Skip to content
This repository was archived by the owner on Aug 17, 2022. It is now read-only.

Commit 4761eb8

Browse files
authored
Merge pull request #11 from iosdevelopershq/bullet_match
Bullet match
2 parents 47b224d + 3d3c875 commit 4761eb8

File tree

5 files changed

+3177
-0
lines changed

5 files changed

+3177
-0
lines changed

CodeChallenge.xcodeproj/project.pbxproj

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
/* Begin PBXBuildFile section */
1010
1B1F0A4E1BE7EA060030135C /* BugKrushaLetterCombinationsOfPhoneNumberEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B1F0A4D1BE7EA060030135C /* BugKrushaLetterCombinationsOfPhoneNumberEntry.swift */; };
1111
1B31586F1E02FC7E0052ACBD /* FlavioSilverioClockEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B31586E1E02FC7E0052ACBD /* FlavioSilverioClockEntry.swift */; };
12+
1B49C0501E0850D90094121E /* BugKrushaBulletMatchEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B49C04F1E0850D90094121E /* BugKrushaBulletMatchEntry.swift */; };
13+
1B49C0531E0855C90094121E /* BulletMatchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B49C0521E0855C90094121E /* BulletMatchTests.swift */; };
14+
1B4ECDA51E08267B00767EBD /* BulletMatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B4ECDA41E08267B00767EBD /* BulletMatch.swift */; };
15+
1B5C1BC51E1EB242002E9254 /* markings_short.json in Resources */ = {isa = PBXBuildFile; fileRef = 1B5C1BC41E1EB242002E9254 /* markings_short.json */; };
1216
1B9E113F1E005A7C00B9FA5A /* Clock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B9E113E1E005A7C00B9FA5A /* Clock.swift */; };
1317
1B9E11411E006A2B00B9FA5A /* BugKrushaClockEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B9E11401E006A2B00B9FA5A /* BugKrushaClockEntry.swift */; };
1418
1B9E11461E006F0800B9FA5A /* ClockTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B9E11451E006F0800B9FA5A /* ClockTests.swift */; };
@@ -51,6 +55,10 @@
5155
/* Begin PBXFileReference section */
5256
1B1F0A4D1BE7EA060030135C /* BugKrushaLetterCombinationsOfPhoneNumberEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BugKrushaLetterCombinationsOfPhoneNumberEntry.swift; sourceTree = "<group>"; };
5357
1B31586E1E02FC7E0052ACBD /* FlavioSilverioClockEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FlavioSilverioClockEntry.swift; sourceTree = "<group>"; };
58+
1B49C04F1E0850D90094121E /* BugKrushaBulletMatchEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BugKrushaBulletMatchEntry.swift; path = BulletMatch/Entries/BugKrushaBulletMatchEntry.swift; sourceTree = "<group>"; };
59+
1B49C0521E0855C90094121E /* BulletMatchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BulletMatchTests.swift; sourceTree = "<group>"; };
60+
1B4ECDA41E08267B00767EBD /* BulletMatch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BulletMatch.swift; path = BulletMatch/BulletMatch.swift; sourceTree = "<group>"; };
61+
1B5C1BC41E1EB242002E9254 /* markings_short.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = markings_short.json; sourceTree = "<group>"; };
5462
1B9E113E1E005A7C00B9FA5A /* Clock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Clock.swift; sourceTree = "<group>"; };
5563
1B9E11401E006A2B00B9FA5A /* BugKrushaClockEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BugKrushaClockEntry.swift; sourceTree = "<group>"; };
5664
1B9E11451E006F0800B9FA5A /* ClockTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClockTests.swift; sourceTree = "<group>"; };
@@ -111,6 +119,23 @@
111119
path = Entries;
112120
sourceTree = "<group>";
113121
};
122+
1B49C0511E0850DD0094121E /* Entries */ = {
123+
isa = PBXGroup;
124+
children = (
125+
1B49C04F1E0850D90094121E /* BugKrushaBulletMatchEntry.swift */,
126+
);
127+
name = Entries;
128+
sourceTree = "<group>";
129+
};
130+
1B4ECDA61E0826B000767EBD /* BulletMatch */ = {
131+
isa = PBXGroup;
132+
children = (
133+
1B49C0511E0850DD0094121E /* Entries */,
134+
1B4ECDA41E08267B00767EBD /* BulletMatch.swift */,
135+
);
136+
name = BulletMatch;
137+
sourceTree = "<group>";
138+
};
114139
1B9E11421E006A2F00B9FA5A /* Entries */ = {
115140
isa = PBXGroup;
116141
children = (
@@ -133,6 +158,13 @@
133158
path = Clock;
134159
sourceTree = "<group>";
135160
};
161+
1BB33E9E1E15BA5200C83E3F /* Resources */ = {
162+
isa = PBXGroup;
163+
children = (
164+
);
165+
path = Resources;
166+
sourceTree = "<group>";
167+
};
136168
9272E19A1BD7F6560030B403 = {
137169
isa = PBXGroup;
138170
children = (
@@ -174,10 +206,13 @@
174206
94350F591BE5D5C1003592FB /* Challenges */ = {
175207
isa = PBXGroup;
176208
children = (
209+
1B5C1BC41E1EB242002E9254 /* markings_short.json */,
210+
1BB33E9E1E15BA5200C83E3F /* Resources */,
177211
1B9E11471E010A3500B9FA5A /* Clock */,
178212
94350F661BE5EB21003592FB /* TwoSum */,
179213
944CFCD61BE72AEB00FD2E41 /* LetterCombinationsOfPhoneNumber */,
180214
944CFCD91BE730A700FD2E41 /* LongestSubstringWithoutRepeatingCharacters */,
215+
1B4ECDA61E0826B000767EBD /* BulletMatch */,
181216
);
182217
path = Challenges;
183218
sourceTree = "<group>";
@@ -195,6 +230,7 @@
195230
isa = PBXGroup;
196231
children = (
197232
94350F641BE5E836003592FB /* TwoSumTests.swift */,
233+
1B49C0521E0855C90094121E /* BulletMatchTests.swift */,
198234
9272E1E51BDED73A0030B403 /* LetterCombinationsOfPhoneNumberTests.swift */,
199235
1B9E11451E006F0800B9FA5A /* ClockTests.swift */,
200236
9272E1E31BDED71C0030B403 /* LongestSubstringWithoutRepeatingCharactersTests.swift */,
@@ -345,6 +381,7 @@
345381
isa = PBXResourcesBuildPhase;
346382
buildActionMask = 2147483647;
347383
files = (
384+
1B5C1BC51E1EB242002E9254 /* markings_short.json in Resources */,
348385
);
349386
runOnlyForDeploymentPostprocessing = 0;
350387
};
@@ -371,12 +408,14 @@
371408
7B925E521E05AFFF0009B0CD /* matthijsClockEntry.swift in Sources */,
372409
2EB83A801E03290400FAAB32 /* EthanSchatzline-ClockEntry.swift in Sources */,
373410
9489866A1BE5CFB000D34976 /* CodeChallengeType.swift in Sources */,
411+
1B4ECDA51E08267B00767EBD /* BulletMatch.swift in Sources */,
374412
94350F701BE5EE94003592FB /* Aryaxt.swift in Sources */,
375413
948986701BE5D28500D34976 /* ExampleCodeChallenge.swift in Sources */,
376414
1B31586F1E02FC7E0052ACBD /* FlavioSilverioClockEntry.swift in Sources */,
377415
944CFCDB1BE7310B00FD2E41 /* LongestSubstringWithoutRepeatingCharactersChallenge.swift in Sources */,
378416
1B1F0A4E1BE7EA060030135C /* BugKrushaLetterCombinationsOfPhoneNumberEntry.swift in Sources */,
379417
3D00956F1E03200C004E631A /* BrandonShegaClockEntry.swift in Sources */,
418+
1B49C0501E0850D90094121E /* BugKrushaBulletMatchEntry.swift in Sources */,
380419
94350F741BE5F04A003592FB /* IanKeen.swift in Sources */,
381420
94350F761BE5F0F6003592FB /* Logan.swift in Sources */,
382421
94350F721BE5EF9F003592FB /* BugKrusha.swift in Sources */,
@@ -392,6 +431,7 @@
392431
buildActionMask = 2147483647;
393432
files = (
394433
1B9E11461E006F0800B9FA5A /* ClockTests.swift in Sources */,
434+
1B49C0531E0855C90094121E /* BulletMatchTests.swift in Sources */,
395435
9272E1E61BDED73A0030B403 /* LetterCombinationsOfPhoneNumberTests.swift in Sources */,
396436
94350F611BE5D859003592FB /* ExampleChallengeTests.swift in Sources */,
397437
94350F651BE5E836003592FB /* TwoSumTests.swift in Sources */,
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//
2+
// BulletMatch.swift
3+
// CodeChallenge
4+
//
5+
// Created by Jon-Tait Beason on 12/19/16.
6+
// Copyright © 2016 iosdevelopers. All rights reserved.
7+
//
8+
9+
import Foundation
10+
/**
11+
Forensic specialists examine spent cartridges for unique
12+
markings left by parts of a gun. They can then compare
13+
these markings to the ones in any gun to determine if there
14+
is a match. A match means that the bullet was fired from
15+
that gun.
16+
17+
Given two markings, one from a spent cartridge and the other
18+
from a suspected weapon, both as Strings, return true if they match
19+
and false if they don't.
20+
21+
EXAMPLES:
22+
Match, returns true
23+
"| ||| | |" and
24+
"| ||| | |"
25+
26+
Match, returns true though one is rotated. Bullets can be rotated.
27+
Your solution should account for the possible rotation of bullets.
28+
"|| ||| | " and
29+
" | || |||"
30+
31+
Doesn't match, returns false
32+
"| ||| | |" and
33+
"||| | | |"
34+
35+
NOTE: Markings cannot be flipped.
36+
"| ||" is not a match for
37+
"|| |"
38+
39+
Problem adapted from http://bit.ly/2h57Wxe
40+
*/
41+
42+
final class BulletChallenge: CodeChallengeType {
43+
typealias InputType = (bulletMarkings: String, gunMarkings: String)
44+
typealias OutputType = Bool
45+
46+
var title = "Bullet Challenge"
47+
private let separator = "#"
48+
49+
var entries: [CodeChallengeEntry<BulletChallenge>] = [
50+
bugKrushaBulletMatchEntry
51+
]
52+
53+
func generateDataset() -> [InputType] {
54+
let bundle = Bundle(for: BulletChallenge.self)
55+
guard
56+
let dataUrl = bundle.url(forResource: "markings_short", withExtension: "json"),
57+
let data = try? Data(contentsOf: dataUrl),
58+
let jsonObjects = try? JSONSerialization.jsonObject(with: data, options: .allowFragments),
59+
let vd = jsonObjects as? [String: Bool]
60+
else { fatalError() }
61+
62+
verificationData = vd
63+
let markings = verificationData.keys.map { key -> (String, String) in
64+
let components = key.components(separatedBy: self.separator)
65+
let gunMarkings = components[1]
66+
let bulletMarkings = components[0]
67+
return (bulletMarkings: bulletMarkings, gunMarkings: gunMarkings)
68+
}
69+
70+
return Array(markings)
71+
}
72+
73+
func verifyOutput(_ output: Bool, forInput input: (bulletMarkings: String, gunMarkings: String)) -> Bool {
74+
return verificationData[input.bulletMarkings + separator + input.gunMarkings] == output
75+
}
76+
}
77+
78+
private var verificationData = [String: Bool]()
79+
80+
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//
2+
// BugKrushaBulletMatchEntry.swift
3+
// CodeChallenge
4+
//
5+
// Created by Jon-Tait Beason on 12/19/16.
6+
// Copyright © 2016 iosdevelopers. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
let bugKrushaBulletMatchEntry = CodeChallengeEntry<BulletChallenge>(name: "bugKrusha") { input in
12+
let count = input.0.characters.count
13+
14+
guard
15+
count == input.1.characters.count
16+
else { return false }
17+
18+
var resets = count
19+
var bulletIndex = 0
20+
var gunIndex = 0
21+
var matches = 0
22+
23+
let bulletMarks = input.0.characters.flatMap { String($0) }
24+
var gunMarks = input.1.characters.flatMap { String($0) }
25+
26+
while resets >= 0 && gunIndex < count {
27+
if bulletMarks[bulletIndex] == gunMarks[gunIndex] {
28+
gunIndex += 1
29+
matches += 1
30+
bulletIndex += 1
31+
} else {
32+
let last = gunMarks.removeLast()
33+
gunMarks = [last] + gunMarks
34+
gunIndex = 0
35+
bulletIndex = 0
36+
matches = 0
37+
38+
resets -= 1
39+
}
40+
41+
if matches == count { return true }
42+
}
43+
return false
44+
}

0 commit comments

Comments
 (0)