Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Swift 6]: Update secret agent #829

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
"higher-order-functions"
],
"prerequisites": [
"basics"
"optionals"
],
"status": "active"
},
Expand Down
18 changes: 10 additions & 8 deletions exercises/concept/secret-agent/.docs/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,35 @@ Your mission, should you choose to accept it, is to write a pair of tools to hel

Once you have the secret plans, you will need to protect it so that only those who know the password can recover them.

In order to do this, you will need to implement the function
`protectSecret(_ secret: String, withPassword password: String) -> (String) -> String`. This function will return another function that takes possible password strings as input. If the entered password is correct the new function returns the hidden secret, but if it is the incorrect password the function returns "Sorry. No hidden secrets here."
In order to do this, you will need to implement the function `protectSecret(_ secret: String, withPassword password: String) -> (String) -> String`.
This function will return another function that takes possible password strings as input.
If the entered password is correct the new function returns the hidden secret, but if it is the incorrect password the function returns "Sorry. No hidden secrets here."

```swift
let secretFunction = protectSecret("Steal the world's supply of french fries!", withPassword: "5up3r53cr37")

secretFunction("Open sesame")
// => "Sorry. No hidden secrets here."
// returns "Sorry. No hidden secrets here."

secretFunction("5up3r53cr37")
// => "Steal the world's supply of french fries!"
// returns "Steal the world's supply of french fries!"
```

## 2. Generate a combination to open their safe

We have learned that UMBRA bases all of their safe combinations on the number of the room they are located in. The safe combinations are generated by repeatedly applying a special function to the room number. So the first number of the combination will come from applying the function to the room number, the second will come from applying the function to the first number, and the third from applying the function to the second number.
We have learned that UMBRA bases all of their safe combinations on the number of the room they are located in.
The safe combinations are generated by repeatedly applying a special function to the room number.
So the first number of the combination will come from applying the function to the room number, the second will come from applying the function to the first number, and the third from applying the function to the second number.

However, UMBRA regularly changes the function used to generate the combinations, so your tool will need to take both a room number and the appropriate function in order to generate the combination.

Implement the function
`generateCombination(forRoom room: Int, usingFunction f: (Int) -> Int) -> (Int, Int, Int)` to generate the combination you will need.
Implement the function `generateCombination(forRoom room: Int, usingFunction f: (Int) -> Int) -> (Int, Int, Int)` to generate the combination you will need.

```swift
func makeCombo(_ x: Int) -> Int {
(x * 13) % 256
}

generateCombination(forRoom: 227, usingFunction: makeCombo)
// => (135, 219, 31)
// returns (135, 219, 31)
```
44 changes: 22 additions & 22 deletions exercises/concept/secret-agent/Package.swift
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
// swift-tools-version:5.3
// swift-tools-version:6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "SecretAgent",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "SecretAgent",
targets: ["SecretAgent"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "SecretAgent",
dependencies: []),
.testTarget(
name: "SecretAgentTests",
dependencies: ["SecretAgent"]),
]
name: "SecretAgent",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "SecretAgent",
targets: ["SecretAgent"])
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "SecretAgent",
dependencies: []),
.testTarget(
name: "SecretAgentTests",
dependencies: ["SecretAgent"]),
]
)
Original file line number Diff line number Diff line change
@@ -1,37 +1,33 @@
import XCTest
import Foundation
import Testing

@testable import SecretAgent

final class SecretAgentTests: XCTestCase {
let runAll = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false
let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false

@Suite struct SecretAgentTests {
let protected = protectSecret(
"UMBRA will fill everyone's sugar bowls with salt!", withPassword: "P455w0rd")

@Test("password success")
func testPasswordSuccess() {
XCTAssertEqual(protected("P455w0rd"), "UMBRA will fill everyone's sugar bowls with salt!")
#expect(protected("P455w0rd") == "UMBRA will fill everyone's sugar bowls with salt!")
}

func testPasswordFail() throws {
try XCTSkipIf(true && !runAll) // change true to false to run this test
XCTAssertEqual(protected("hunter2"), "Sorry. No hidden secrets here.")
@Test("password fail", .enabled(if: RUNALL))
func testPasswordFail() {
#expect(protected("hunter2") == "Sorry. No hidden secrets here.")
}

func testCombination1() throws {
try XCTSkipIf(true && !runAll) // change true to false to run this test
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct
// results.
@Test("combination 1", .enabled(if: RUNALL))
func testCombination1() {
let combo = generateCombination(forRoom: 1, usingFunction: { ($0 * 127 + 19) % 256 })
XCTAssertTrue(combo == (146, 129, 18))
#expect(combo == (146, 129, 18))
}

func testCombination2() throws {
try XCTSkipIf(true && !runAll) // change true to false to run this test
let combo = generateCombination(
forRoom: 1,
usingFunction: {
($0 * 73 + 161) % 256
})
XCTAssertTrue(combo == (234, 91, 148))
@Test("combination 2", .enabled(if: RUNALL))
func testCombination2() {
let combo = generateCombination(forRoom: 1, usingFunction: { ($0 * 73 + 161) % 256 })
#expect(combo == (234, 91, 148))
}
}