├── .gitignore ├── .travis.yml ├── CodeChallenge.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── CodeChallenge.xcscheme │ └── CodeChallengeTests.xcscheme ├── CodeChallenge ├── Base │ ├── CodeChallengeType.swift │ └── ExampleCodeChallenge.swift ├── Challenges │ ├── BulletMatch │ │ ├── BulletMatch.swift │ │ ├── BulletMatch_dataset.json │ │ └── Entries │ │ │ ├── BugKrushaBulletMatchEntry.swift │ │ │ ├── CodesmanBulletMatchEntry.swift │ │ │ ├── FlavioSilverioBulletMatchEntry.swift │ │ │ ├── juliand665BulletMatchEntry.swift │ │ │ └── matthijsBulletMatchEntry.swift │ ├── Clock │ │ ├── Clock.swift │ │ ├── Clock_dataset.json │ │ └── Entries │ │ │ ├── BrandonShegaClockEntry.swift │ │ │ ├── BugKrushaClockEntry.swift │ │ │ ├── EthanSchatzline-ClockEntry.swift │ │ │ ├── FlavioSilverioClockEntry.swift │ │ │ ├── felixdumitClockEntry.swift │ │ │ ├── juliand665ClockEntry.swift │ │ │ └── matthijsClockEntry.swift │ ├── LetterCombinationsOfPhoneNumber │ │ ├── Entries │ │ │ ├── BugKrushaLetterCombinationsOfPhoneNumberEntry.swift │ │ │ ├── LoganWrightEntry.swift │ │ │ └── juliand665LetterCombinationOfPhoneNumberEntry.swift │ │ └── LetterCombinationsOfPhoneNumberChallenge.swift │ ├── LongestSubstringWithoutRepeatingCharacters │ │ ├── Entries │ │ │ └── juliand665LSWRCEntry.swift │ │ └── LongestSubstringWithoutRepeatingCharactersChallenge.swift │ └── TwoSum │ │ ├── Entries │ │ ├── AlexPersian.swift │ │ ├── Aranasaurus.swift │ │ ├── Aryaxt.swift │ │ ├── BugKrusha.swift │ │ ├── IanKeen.swift │ │ ├── Logan.swift │ │ ├── Mosab.swift │ │ ├── Nuudles.swift │ │ └── juliand665TwoSumEntry.swift │ │ └── TwoSumChallenge.swift └── Info.plist ├── CodeChallengeTests ├── Base │ ├── CodeChallengeTestCase.swift │ └── ExampleChallengeTests.swift ├── Challenges │ ├── BulletMatchTests.swift │ ├── ClockTests.swift │ ├── LetterCombinationsOfPhoneNumberTests.swift │ ├── LongestSubstringWithoutRepeatingCharactersTests.swift │ └── TwoSumTests.swift └── Info.plist ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata 19 | 20 | ## Other 21 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | .DS_Store 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode8.2 3 | 4 | script: 5 | - xcodebuild test -scheme CodeChallengeTests -destination 'platform=iOS Simulator,name=iPhone 6,OS=10.1' -------------------------------------------------------------------------------- /CodeChallenge.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1B1F0A4E1BE7EA060030135C /* BugKrushaLetterCombinationsOfPhoneNumberEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B1F0A4D1BE7EA060030135C /* BugKrushaLetterCombinationsOfPhoneNumberEntry.swift */; }; 11 | 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 | 1B9E113F1E005A7C00B9FA5A /* Clock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B9E113E1E005A7C00B9FA5A /* Clock.swift */; }; 16 | 1B9E11411E006A2B00B9FA5A /* BugKrushaClockEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B9E11401E006A2B00B9FA5A /* BugKrushaClockEntry.swift */; }; 17 | 1B9E11461E006F0800B9FA5A /* ClockTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B9E11451E006F0800B9FA5A /* ClockTests.swift */; }; 18 | 1BBAB4801E41D6190038BCB1 /* FlavioSilverioBulletMatchEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BBAB47F1E41D6190038BCB1 /* FlavioSilverioBulletMatchEntry.swift */; }; 19 | 2EB83A801E03290400FAAB32 /* EthanSchatzline-ClockEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EB83A7F1E03290400FAAB32 /* EthanSchatzline-ClockEntry.swift */; }; 20 | 3D00956F1E03200C004E631A /* BrandonShegaClockEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D00956E1E03200C004E631A /* BrandonShegaClockEntry.swift */; }; 21 | 7B1BF2D01E3F9CFA00AEAC0E /* matthijsBulletMatchEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1BF2CF1E3F9CFA00AEAC0E /* matthijsBulletMatchEntry.swift */; }; 22 | 7B925E521E05AFFF0009B0CD /* matthijsClockEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B925E511E05AFFF0009B0CD /* matthijsClockEntry.swift */; }; 23 | 809B704A1BF01B68004131BE /* LoganWrightEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 809B70491BF01B68004131BE /* LoganWrightEntry.swift */; }; 24 | 9272E1AF1BD7F6560030B403 /* CodeChallenge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9272E1A41BD7F6560030B403 /* CodeChallenge.framework */; }; 25 | 9272E1E41BDED71C0030B403 /* LongestSubstringWithoutRepeatingCharactersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9272E1E31BDED71C0030B403 /* LongestSubstringWithoutRepeatingCharactersTests.swift */; }; 26 | 9272E1E61BDED73A0030B403 /* LetterCombinationsOfPhoneNumberTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9272E1E51BDED73A0030B403 /* LetterCombinationsOfPhoneNumberTests.swift */; }; 27 | 94350F5F1BE5D721003592FB /* CodeChallengeTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94350F5E1BE5D721003592FB /* CodeChallengeTestCase.swift */; }; 28 | 94350F611BE5D859003592FB /* ExampleChallengeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94350F601BE5D859003592FB /* ExampleChallengeTests.swift */; }; 29 | 94350F651BE5E836003592FB /* TwoSumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94350F641BE5E836003592FB /* TwoSumTests.swift */; }; 30 | 94350F691BE5EB90003592FB /* Aranasaurus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94350F681BE5EB90003592FB /* Aranasaurus.swift */; }; 31 | 94350F6B1BE5EBD3003592FB /* AlexPersian.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94350F6A1BE5EBD3003592FB /* AlexPersian.swift */; }; 32 | 94350F701BE5EE94003592FB /* Aryaxt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94350F6F1BE5EE94003592FB /* Aryaxt.swift */; }; 33 | 94350F721BE5EF9F003592FB /* BugKrusha.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94350F711BE5EF9F003592FB /* BugKrusha.swift */; }; 34 | 94350F741BE5F04A003592FB /* IanKeen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94350F731BE5F04A003592FB /* IanKeen.swift */; }; 35 | 94350F761BE5F0F6003592FB /* Logan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94350F751BE5F0F6003592FB /* Logan.swift */; }; 36 | 94350F781BE5F174003592FB /* Mosab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94350F771BE5F174003592FB /* Mosab.swift */; }; 37 | 94350F7A1BE5F24A003592FB /* Nuudles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94350F791BE5F24A003592FB /* Nuudles.swift */; }; 38 | 944CFCD81BE72B3C00FD2E41 /* LetterCombinationsOfPhoneNumberChallenge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944CFCD71BE72B3C00FD2E41 /* LetterCombinationsOfPhoneNumberChallenge.swift */; }; 39 | 944CFCDB1BE7310B00FD2E41 /* LongestSubstringWithoutRepeatingCharactersChallenge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944CFCDA1BE7310B00FD2E41 /* LongestSubstringWithoutRepeatingCharactersChallenge.swift */; }; 40 | 9489866A1BE5CFB000D34976 /* CodeChallengeType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948986691BE5CFB000D34976 /* CodeChallengeType.swift */; }; 41 | 948986701BE5D28500D34976 /* ExampleCodeChallenge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9489866F1BE5D28500D34976 /* ExampleCodeChallenge.swift */; }; 42 | 94FB98CA1BE1B5D800228845 /* TwoSumChallenge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94FB98C91BE1B5D800228845 /* TwoSumChallenge.swift */; }; 43 | 953445F81E21ED03008AC0B3 /* BulletMatch_dataset.json in Resources */ = {isa = PBXBuildFile; fileRef = 953445F71E21ED03008AC0B3 /* BulletMatch_dataset.json */; }; 44 | 953445FA1E21ED07008AC0B3 /* Clock_dataset.json in Resources */ = {isa = PBXBuildFile; fileRef = 953445F91E21ED07008AC0B3 /* Clock_dataset.json */; }; 45 | 9572008E1E1F19F9006BB4D6 /* juliand665BulletMatchEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9572008D1E1F19F9006BB4D6 /* juliand665BulletMatchEntry.swift */; }; 46 | 957200991E206A35006BB4D6 /* juliand665LetterCombinationOfPhoneNumberEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 957200981E206A35006BB4D6 /* juliand665LetterCombinationOfPhoneNumberEntry.swift */; }; 47 | 9572009C1E206A4B006BB4D6 /* juliand665LSWRCEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9572009B1E206A4B006BB4D6 /* juliand665LSWRCEntry.swift */; }; 48 | 9572009E1E206A5E006BB4D6 /* juliand665ClockEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9572009D1E206A5E006BB4D6 /* juliand665ClockEntry.swift */; }; 49 | 957200A01E206A65006BB4D6 /* juliand665TwoSumEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9572009F1E206A65006BB4D6 /* juliand665TwoSumEntry.swift */; }; 50 | 957200A21E206A94006BB4D6 /* CodesmanBulletMatchEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 957200A11E206A94006BB4D6 /* CodesmanBulletMatchEntry.swift */; }; 51 | D5D15B361E0C966A00CC9B1C /* felixdumitClockEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D15B351E0C966A00CC9B1C /* felixdumitClockEntry.swift */; }; 52 | /* End PBXBuildFile section */ 53 | 54 | /* Begin PBXContainerItemProxy section */ 55 | 9272E1B01BD7F6560030B403 /* PBXContainerItemProxy */ = { 56 | isa = PBXContainerItemProxy; 57 | containerPortal = 9272E19B1BD7F6560030B403 /* Project object */; 58 | proxyType = 1; 59 | remoteGlobalIDString = 9272E1A31BD7F6560030B403; 60 | remoteInfo = CodeChallange; 61 | }; 62 | /* End PBXContainerItemProxy section */ 63 | 64 | /* Begin PBXFileReference section */ 65 | 1B1F0A4D1BE7EA060030135C /* BugKrushaLetterCombinationsOfPhoneNumberEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BugKrushaLetterCombinationsOfPhoneNumberEntry.swift; sourceTree = ""; }; 66 | 1B31586E1E02FC7E0052ACBD /* FlavioSilverioClockEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FlavioSilverioClockEntry.swift; sourceTree = ""; }; 67 | 1B49C04F1E0850D90094121E /* BugKrushaBulletMatchEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BugKrushaBulletMatchEntry.swift; path = BulletMatch/Entries/BugKrushaBulletMatchEntry.swift; sourceTree = ""; }; 68 | 1B49C0521E0855C90094121E /* BulletMatchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BulletMatchTests.swift; sourceTree = ""; }; 69 | 1B4ECDA41E08267B00767EBD /* BulletMatch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BulletMatch.swift; path = BulletMatch/BulletMatch.swift; sourceTree = ""; }; 70 | 1B9E113E1E005A7C00B9FA5A /* Clock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Clock.swift; sourceTree = ""; }; 71 | 1B9E11401E006A2B00B9FA5A /* BugKrushaClockEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BugKrushaClockEntry.swift; sourceTree = ""; }; 72 | 1B9E11451E006F0800B9FA5A /* ClockTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClockTests.swift; sourceTree = ""; }; 73 | 1BBAB47F1E41D6190038BCB1 /* FlavioSilverioBulletMatchEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FlavioSilverioBulletMatchEntry.swift; path = BulletMatch/Entries/FlavioSilverioBulletMatchEntry.swift; sourceTree = ""; }; 74 | 2EB83A7F1E03290400FAAB32 /* EthanSchatzline-ClockEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "EthanSchatzline-ClockEntry.swift"; sourceTree = ""; }; 75 | 3D00956E1E03200C004E631A /* BrandonShegaClockEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BrandonShegaClockEntry.swift; sourceTree = ""; }; 76 | 7B1BF2CF1E3F9CFA00AEAC0E /* matthijsBulletMatchEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = matthijsBulletMatchEntry.swift; path = BulletMatch/Entries/matthijsBulletMatchEntry.swift; sourceTree = ""; }; 77 | 7B925E511E05AFFF0009B0CD /* matthijsClockEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = matthijsClockEntry.swift; sourceTree = ""; }; 78 | 809B70491BF01B68004131BE /* LoganWrightEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoganWrightEntry.swift; sourceTree = ""; }; 79 | 9272E1A41BD7F6560030B403 /* CodeChallenge.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CodeChallenge.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 80 | 9272E1AE1BD7F6560030B403 /* CodeChallenge.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CodeChallenge.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 81 | 9272E1B51BD7F6560030B403 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 82 | 9272E1E31BDED71C0030B403 /* LongestSubstringWithoutRepeatingCharactersTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LongestSubstringWithoutRepeatingCharactersTests.swift; sourceTree = ""; }; 83 | 9272E1E51BDED73A0030B403 /* LetterCombinationsOfPhoneNumberTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LetterCombinationsOfPhoneNumberTests.swift; sourceTree = ""; }; 84 | 94350F5A1BE5D698003592FB /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 85 | 94350F5E1BE5D721003592FB /* CodeChallengeTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodeChallengeTestCase.swift; sourceTree = ""; }; 86 | 94350F601BE5D859003592FB /* ExampleChallengeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleChallengeTests.swift; sourceTree = ""; }; 87 | 94350F641BE5E836003592FB /* TwoSumTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TwoSumTests.swift; sourceTree = ""; }; 88 | 94350F681BE5EB90003592FB /* Aranasaurus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Aranasaurus.swift; sourceTree = ""; }; 89 | 94350F6A1BE5EBD3003592FB /* AlexPersian.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlexPersian.swift; sourceTree = ""; }; 90 | 94350F6F1BE5EE94003592FB /* Aryaxt.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Aryaxt.swift; sourceTree = ""; }; 91 | 94350F711BE5EF9F003592FB /* BugKrusha.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BugKrusha.swift; sourceTree = ""; }; 92 | 94350F731BE5F04A003592FB /* IanKeen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IanKeen.swift; sourceTree = ""; }; 93 | 94350F751BE5F0F6003592FB /* Logan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logan.swift; sourceTree = ""; }; 94 | 94350F771BE5F174003592FB /* Mosab.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mosab.swift; sourceTree = ""; }; 95 | 94350F791BE5F24A003592FB /* Nuudles.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Nuudles.swift; sourceTree = ""; }; 96 | 944CFCD71BE72B3C00FD2E41 /* LetterCombinationsOfPhoneNumberChallenge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LetterCombinationsOfPhoneNumberChallenge.swift; sourceTree = ""; }; 97 | 944CFCDA1BE7310B00FD2E41 /* LongestSubstringWithoutRepeatingCharactersChallenge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LongestSubstringWithoutRepeatingCharactersChallenge.swift; sourceTree = ""; }; 98 | 948986691BE5CFB000D34976 /* CodeChallengeType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodeChallengeType.swift; sourceTree = ""; }; 99 | 9489866F1BE5D28500D34976 /* ExampleCodeChallenge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleCodeChallenge.swift; sourceTree = ""; }; 100 | 94FB98C91BE1B5D800228845 /* TwoSumChallenge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TwoSumChallenge.swift; sourceTree = ""; }; 101 | 953445F71E21ED03008AC0B3 /* BulletMatch_dataset.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = BulletMatch_dataset.json; path = BulletMatch/BulletMatch_dataset.json; sourceTree = ""; }; 102 | 953445F91E21ED07008AC0B3 /* Clock_dataset.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Clock_dataset.json; sourceTree = ""; }; 103 | 9572008D1E1F19F9006BB4D6 /* juliand665BulletMatchEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = juliand665BulletMatchEntry.swift; path = BulletMatch/Entries/juliand665BulletMatchEntry.swift; sourceTree = ""; }; 104 | 957200981E206A35006BB4D6 /* juliand665LetterCombinationOfPhoneNumberEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = juliand665LetterCombinationOfPhoneNumberEntry.swift; sourceTree = ""; }; 105 | 9572009B1E206A4B006BB4D6 /* juliand665LSWRCEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = juliand665LSWRCEntry.swift; sourceTree = ""; }; 106 | 9572009D1E206A5E006BB4D6 /* juliand665ClockEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = juliand665ClockEntry.swift; sourceTree = ""; }; 107 | 9572009F1E206A65006BB4D6 /* juliand665TwoSumEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = juliand665TwoSumEntry.swift; sourceTree = ""; }; 108 | 957200A11E206A94006BB4D6 /* CodesmanBulletMatchEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CodesmanBulletMatchEntry.swift; path = BulletMatch/Entries/CodesmanBulletMatchEntry.swift; sourceTree = ""; }; 109 | D5D15B351E0C966A00CC9B1C /* felixdumitClockEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = felixdumitClockEntry.swift; sourceTree = ""; }; 110 | /* End PBXFileReference section */ 111 | 112 | /* Begin PBXFrameworksBuildPhase section */ 113 | 9272E1A01BD7F6560030B403 /* Frameworks */ = { 114 | isa = PBXFrameworksBuildPhase; 115 | buildActionMask = 2147483647; 116 | files = ( 117 | ); 118 | runOnlyForDeploymentPostprocessing = 0; 119 | }; 120 | 9272E1AB1BD7F6560030B403 /* Frameworks */ = { 121 | isa = PBXFrameworksBuildPhase; 122 | buildActionMask = 2147483647; 123 | files = ( 124 | 9272E1AF1BD7F6560030B403 /* CodeChallenge.framework in Frameworks */, 125 | ); 126 | runOnlyForDeploymentPostprocessing = 0; 127 | }; 128 | /* End PBXFrameworksBuildPhase section */ 129 | 130 | /* Begin PBXGroup section */ 131 | 1B1F0A4C1BE7E9820030135C /* Entries */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 957200981E206A35006BB4D6 /* juliand665LetterCombinationOfPhoneNumberEntry.swift */, 135 | 1B1F0A4D1BE7EA060030135C /* BugKrushaLetterCombinationsOfPhoneNumberEntry.swift */, 136 | 809B70491BF01B68004131BE /* LoganWrightEntry.swift */, 137 | ); 138 | path = Entries; 139 | sourceTree = ""; 140 | }; 141 | 1B49C0511E0850DD0094121E /* Entries */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 957200A11E206A94006BB4D6 /* CodesmanBulletMatchEntry.swift */, 145 | 1B49C04F1E0850D90094121E /* BugKrushaBulletMatchEntry.swift */, 146 | 9572008D1E1F19F9006BB4D6 /* juliand665BulletMatchEntry.swift */, 147 | 1BBAB47F1E41D6190038BCB1 /* FlavioSilverioBulletMatchEntry.swift */, 148 | 7B1BF2CF1E3F9CFA00AEAC0E /* matthijsBulletMatchEntry.swift */, 149 | ); 150 | name = Entries; 151 | sourceTree = ""; 152 | }; 153 | 1B4ECDA61E0826B000767EBD /* BulletMatch */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | 1B49C0511E0850DD0094121E /* Entries */, 157 | 1B4ECDA41E08267B00767EBD /* BulletMatch.swift */, 158 | 953445F71E21ED03008AC0B3 /* BulletMatch_dataset.json */, 159 | ); 160 | name = BulletMatch; 161 | sourceTree = ""; 162 | }; 163 | 1B9E11421E006A2F00B9FA5A /* Entries */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | 9572009D1E206A5E006BB4D6 /* juliand665ClockEntry.swift */, 167 | 3D00956E1E03200C004E631A /* BrandonShegaClockEntry.swift */, 168 | 1B9E11401E006A2B00B9FA5A /* BugKrushaClockEntry.swift */, 169 | 2EB83A7F1E03290400FAAB32 /* EthanSchatzline-ClockEntry.swift */, 170 | 1B31586E1E02FC7E0052ACBD /* FlavioSilverioClockEntry.swift */, 171 | 7B925E511E05AFFF0009B0CD /* matthijsClockEntry.swift */, 172 | D5D15B351E0C966A00CC9B1C /* felixdumitClockEntry.swift */, 173 | ); 174 | path = Entries; 175 | sourceTree = ""; 176 | }; 177 | 1B9E11471E010A3500B9FA5A /* Clock */ = { 178 | isa = PBXGroup; 179 | children = ( 180 | 1B9E11421E006A2F00B9FA5A /* Entries */, 181 | 1B9E113E1E005A7C00B9FA5A /* Clock.swift */, 182 | 953445F91E21ED07008AC0B3 /* Clock_dataset.json */, 183 | ); 184 | path = Clock; 185 | sourceTree = ""; 186 | }; 187 | 9272E19A1BD7F6560030B403 = { 188 | isa = PBXGroup; 189 | children = ( 190 | 9272E1A61BD7F6560030B403 /* CodeChallenge */, 191 | 9272E1B21BD7F6560030B403 /* CodeChallengeTests */, 192 | 9272E1A51BD7F6560030B403 /* Products */, 193 | ); 194 | sourceTree = ""; 195 | }; 196 | 9272E1A51BD7F6560030B403 /* Products */ = { 197 | isa = PBXGroup; 198 | children = ( 199 | 9272E1A41BD7F6560030B403 /* CodeChallenge.framework */, 200 | 9272E1AE1BD7F6560030B403 /* CodeChallenge.xctest */, 201 | ); 202 | name = Products; 203 | sourceTree = ""; 204 | }; 205 | 9272E1A61BD7F6560030B403 /* CodeChallenge */ = { 206 | isa = PBXGroup; 207 | children = ( 208 | 948986681BE5CEB400D34976 /* Base */, 209 | 94350F591BE5D5C1003592FB /* Challenges */, 210 | 94350F5A1BE5D698003592FB /* Info.plist */, 211 | ); 212 | path = CodeChallenge; 213 | sourceTree = ""; 214 | }; 215 | 9272E1B21BD7F6560030B403 /* CodeChallengeTests */ = { 216 | isa = PBXGroup; 217 | children = ( 218 | 94350F621BE5D89F003592FB /* Base */, 219 | 94350F631BE5E7DD003592FB /* Challenges */, 220 | 9272E1B51BD7F6560030B403 /* Info.plist */, 221 | ); 222 | path = CodeChallengeTests; 223 | sourceTree = ""; 224 | }; 225 | 94350F591BE5D5C1003592FB /* Challenges */ = { 226 | isa = PBXGroup; 227 | children = ( 228 | 1B9E11471E010A3500B9FA5A /* Clock */, 229 | 94350F661BE5EB21003592FB /* TwoSum */, 230 | 944CFCD61BE72AEB00FD2E41 /* LetterCombinationsOfPhoneNumber */, 231 | 944CFCD91BE730A700FD2E41 /* LongestSubstringWithoutRepeatingCharacters */, 232 | 1B4ECDA61E0826B000767EBD /* BulletMatch */, 233 | ); 234 | path = Challenges; 235 | sourceTree = ""; 236 | }; 237 | 94350F621BE5D89F003592FB /* Base */ = { 238 | isa = PBXGroup; 239 | children = ( 240 | 94350F5E1BE5D721003592FB /* CodeChallengeTestCase.swift */, 241 | 94350F601BE5D859003592FB /* ExampleChallengeTests.swift */, 242 | ); 243 | path = Base; 244 | sourceTree = ""; 245 | }; 246 | 94350F631BE5E7DD003592FB /* Challenges */ = { 247 | isa = PBXGroup; 248 | children = ( 249 | 94350F641BE5E836003592FB /* TwoSumTests.swift */, 250 | 1B49C0521E0855C90094121E /* BulletMatchTests.swift */, 251 | 9272E1E51BDED73A0030B403 /* LetterCombinationsOfPhoneNumberTests.swift */, 252 | 1B9E11451E006F0800B9FA5A /* ClockTests.swift */, 253 | 9272E1E31BDED71C0030B403 /* LongestSubstringWithoutRepeatingCharactersTests.swift */, 254 | ); 255 | path = Challenges; 256 | sourceTree = ""; 257 | }; 258 | 94350F661BE5EB21003592FB /* TwoSum */ = { 259 | isa = PBXGroup; 260 | children = ( 261 | 94350F671BE5EB38003592FB /* Entries */, 262 | 94FB98C91BE1B5D800228845 /* TwoSumChallenge.swift */, 263 | ); 264 | path = TwoSum; 265 | sourceTree = ""; 266 | }; 267 | 94350F671BE5EB38003592FB /* Entries */ = { 268 | isa = PBXGroup; 269 | children = ( 270 | 9572009F1E206A65006BB4D6 /* juliand665TwoSumEntry.swift */, 271 | 94350F681BE5EB90003592FB /* Aranasaurus.swift */, 272 | 94350F6A1BE5EBD3003592FB /* AlexPersian.swift */, 273 | 94350F6F1BE5EE94003592FB /* Aryaxt.swift */, 274 | 94350F711BE5EF9F003592FB /* BugKrusha.swift */, 275 | 94350F731BE5F04A003592FB /* IanKeen.swift */, 276 | 94350F751BE5F0F6003592FB /* Logan.swift */, 277 | 94350F771BE5F174003592FB /* Mosab.swift */, 278 | 94350F791BE5F24A003592FB /* Nuudles.swift */, 279 | ); 280 | path = Entries; 281 | sourceTree = ""; 282 | }; 283 | 944CFCD61BE72AEB00FD2E41 /* LetterCombinationsOfPhoneNumber */ = { 284 | isa = PBXGroup; 285 | children = ( 286 | 1B1F0A4C1BE7E9820030135C /* Entries */, 287 | 944CFCD71BE72B3C00FD2E41 /* LetterCombinationsOfPhoneNumberChallenge.swift */, 288 | ); 289 | path = LetterCombinationsOfPhoneNumber; 290 | sourceTree = ""; 291 | }; 292 | 944CFCD91BE730A700FD2E41 /* LongestSubstringWithoutRepeatingCharacters */ = { 293 | isa = PBXGroup; 294 | children = ( 295 | 9572009A1E206A4B006BB4D6 /* Entries */, 296 | 944CFCDA1BE7310B00FD2E41 /* LongestSubstringWithoutRepeatingCharactersChallenge.swift */, 297 | ); 298 | path = LongestSubstringWithoutRepeatingCharacters; 299 | sourceTree = ""; 300 | }; 301 | 948986681BE5CEB400D34976 /* Base */ = { 302 | isa = PBXGroup; 303 | children = ( 304 | 948986691BE5CFB000D34976 /* CodeChallengeType.swift */, 305 | 9489866F1BE5D28500D34976 /* ExampleCodeChallenge.swift */, 306 | ); 307 | path = Base; 308 | sourceTree = ""; 309 | }; 310 | 9572009A1E206A4B006BB4D6 /* Entries */ = { 311 | isa = PBXGroup; 312 | children = ( 313 | 9572009B1E206A4B006BB4D6 /* juliand665LSWRCEntry.swift */, 314 | ); 315 | path = Entries; 316 | sourceTree = ""; 317 | }; 318 | /* End PBXGroup section */ 319 | 320 | /* Begin PBXHeadersBuildPhase section */ 321 | 9272E1A11BD7F6560030B403 /* Headers */ = { 322 | isa = PBXHeadersBuildPhase; 323 | buildActionMask = 2147483647; 324 | files = ( 325 | ); 326 | runOnlyForDeploymentPostprocessing = 0; 327 | }; 328 | /* End PBXHeadersBuildPhase section */ 329 | 330 | /* Begin PBXNativeTarget section */ 331 | 9272E1A31BD7F6560030B403 /* CodeChallenge */ = { 332 | isa = PBXNativeTarget; 333 | buildConfigurationList = 9272E1B81BD7F6560030B403 /* Build configuration list for PBXNativeTarget "CodeChallenge" */; 334 | buildPhases = ( 335 | 9272E19F1BD7F6560030B403 /* Sources */, 336 | 9272E1A01BD7F6560030B403 /* Frameworks */, 337 | 9272E1A11BD7F6560030B403 /* Headers */, 338 | 9272E1A21BD7F6560030B403 /* Resources */, 339 | ); 340 | buildRules = ( 341 | ); 342 | dependencies = ( 343 | ); 344 | name = CodeChallenge; 345 | productName = CodeChallange; 346 | productReference = 9272E1A41BD7F6560030B403 /* CodeChallenge.framework */; 347 | productType = "com.apple.product-type.framework"; 348 | }; 349 | 9272E1AD1BD7F6560030B403 /* CodeChallengeTests */ = { 350 | isa = PBXNativeTarget; 351 | buildConfigurationList = 9272E1BB1BD7F6560030B403 /* Build configuration list for PBXNativeTarget "CodeChallengeTests" */; 352 | buildPhases = ( 353 | 9272E1AA1BD7F6560030B403 /* Sources */, 354 | 9272E1AB1BD7F6560030B403 /* Frameworks */, 355 | 9272E1AC1BD7F6560030B403 /* Resources */, 356 | ); 357 | buildRules = ( 358 | ); 359 | dependencies = ( 360 | 9272E1B11BD7F6560030B403 /* PBXTargetDependency */, 361 | ); 362 | name = CodeChallengeTests; 363 | productName = CodeChallangeTests; 364 | productReference = 9272E1AE1BD7F6560030B403 /* CodeChallenge.xctest */; 365 | productType = "com.apple.product-type.bundle.unit-test"; 366 | }; 367 | /* End PBXNativeTarget section */ 368 | 369 | /* Begin PBXProject section */ 370 | 9272E19B1BD7F6560030B403 /* Project object */ = { 371 | isa = PBXProject; 372 | attributes = { 373 | LastSwiftUpdateCheck = 0710; 374 | LastUpgradeCheck = 0810; 375 | ORGANIZATIONNAME = iosdevelopers; 376 | TargetAttributes = { 377 | 9272E1A31BD7F6560030B403 = { 378 | CreatedOnToolsVersion = 7.0; 379 | LastSwiftMigration = 0810; 380 | }; 381 | 9272E1AD1BD7F6560030B403 = { 382 | CreatedOnToolsVersion = 7.0; 383 | LastSwiftMigration = 0810; 384 | }; 385 | }; 386 | }; 387 | buildConfigurationList = 9272E19E1BD7F6560030B403 /* Build configuration list for PBXProject "CodeChallenge" */; 388 | compatibilityVersion = "Xcode 3.2"; 389 | developmentRegion = English; 390 | hasScannedForEncodings = 0; 391 | knownRegions = ( 392 | en, 393 | Base, 394 | ); 395 | mainGroup = 9272E19A1BD7F6560030B403; 396 | productRefGroup = 9272E1A51BD7F6560030B403 /* Products */; 397 | projectDirPath = ""; 398 | projectRoot = ""; 399 | targets = ( 400 | 9272E1A31BD7F6560030B403 /* CodeChallenge */, 401 | 9272E1AD1BD7F6560030B403 /* CodeChallengeTests */, 402 | ); 403 | }; 404 | /* End PBXProject section */ 405 | 406 | /* Begin PBXResourcesBuildPhase section */ 407 | 9272E1A21BD7F6560030B403 /* Resources */ = { 408 | isa = PBXResourcesBuildPhase; 409 | buildActionMask = 2147483647; 410 | files = ( 411 | 953445F81E21ED03008AC0B3 /* BulletMatch_dataset.json in Resources */, 412 | 953445FA1E21ED07008AC0B3 /* Clock_dataset.json in Resources */, 413 | ); 414 | runOnlyForDeploymentPostprocessing = 0; 415 | }; 416 | 9272E1AC1BD7F6560030B403 /* Resources */ = { 417 | isa = PBXResourcesBuildPhase; 418 | buildActionMask = 2147483647; 419 | files = ( 420 | ); 421 | runOnlyForDeploymentPostprocessing = 0; 422 | }; 423 | /* End PBXResourcesBuildPhase section */ 424 | 425 | /* Begin PBXSourcesBuildPhase section */ 426 | 9272E19F1BD7F6560030B403 /* Sources */ = { 427 | isa = PBXSourcesBuildPhase; 428 | buildActionMask = 2147483647; 429 | files = ( 430 | 957200A21E206A94006BB4D6 /* CodesmanBulletMatchEntry.swift in Sources */, 431 | 94350F7A1BE5F24A003592FB /* Nuudles.swift in Sources */, 432 | 957200991E206A35006BB4D6 /* juliand665LetterCombinationOfPhoneNumberEntry.swift in Sources */, 433 | 94350F6B1BE5EBD3003592FB /* AlexPersian.swift in Sources */, 434 | 1B9E113F1E005A7C00B9FA5A /* Clock.swift in Sources */, 435 | 1B9E11411E006A2B00B9FA5A /* BugKrushaClockEntry.swift in Sources */, 436 | 94350F781BE5F174003592FB /* Mosab.swift in Sources */, 437 | 9572008E1E1F19F9006BB4D6 /* juliand665BulletMatchEntry.swift in Sources */, 438 | 94FB98CA1BE1B5D800228845 /* TwoSumChallenge.swift in Sources */, 439 | 7B925E521E05AFFF0009B0CD /* matthijsClockEntry.swift in Sources */, 440 | 2EB83A801E03290400FAAB32 /* EthanSchatzline-ClockEntry.swift in Sources */, 441 | 957200A01E206A65006BB4D6 /* juliand665TwoSumEntry.swift in Sources */, 442 | 9489866A1BE5CFB000D34976 /* CodeChallengeType.swift in Sources */, 443 | 1B4ECDA51E08267B00767EBD /* BulletMatch.swift in Sources */, 444 | 94350F701BE5EE94003592FB /* Aryaxt.swift in Sources */, 445 | 9572009C1E206A4B006BB4D6 /* juliand665LSWRCEntry.swift in Sources */, 446 | 948986701BE5D28500D34976 /* ExampleCodeChallenge.swift in Sources */, 447 | 1B31586F1E02FC7E0052ACBD /* FlavioSilverioClockEntry.swift in Sources */, 448 | 9572009E1E206A5E006BB4D6 /* juliand665ClockEntry.swift in Sources */, 449 | 1BBAB4801E41D6190038BCB1 /* FlavioSilverioBulletMatchEntry.swift in Sources */, 450 | 944CFCDB1BE7310B00FD2E41 /* LongestSubstringWithoutRepeatingCharactersChallenge.swift in Sources */, 451 | 1B1F0A4E1BE7EA060030135C /* BugKrushaLetterCombinationsOfPhoneNumberEntry.swift in Sources */, 452 | 3D00956F1E03200C004E631A /* BrandonShegaClockEntry.swift in Sources */, 453 | 1B49C0501E0850D90094121E /* BugKrushaBulletMatchEntry.swift in Sources */, 454 | 94350F741BE5F04A003592FB /* IanKeen.swift in Sources */, 455 | 94350F761BE5F0F6003592FB /* Logan.swift in Sources */, 456 | 94350F721BE5EF9F003592FB /* BugKrusha.swift in Sources */, 457 | D5D15B361E0C966A00CC9B1C /* felixdumitClockEntry.swift in Sources */, 458 | 809B704A1BF01B68004131BE /* LoganWrightEntry.swift in Sources */, 459 | 944CFCD81BE72B3C00FD2E41 /* LetterCombinationsOfPhoneNumberChallenge.swift in Sources */, 460 | 94350F691BE5EB90003592FB /* Aranasaurus.swift in Sources */, 461 | 7B1BF2D01E3F9CFA00AEAC0E /* matthijsBulletMatchEntry.swift in Sources */, 462 | ); 463 | runOnlyForDeploymentPostprocessing = 0; 464 | }; 465 | 9272E1AA1BD7F6560030B403 /* Sources */ = { 466 | isa = PBXSourcesBuildPhase; 467 | buildActionMask = 2147483647; 468 | files = ( 469 | 1B9E11461E006F0800B9FA5A /* ClockTests.swift in Sources */, 470 | 1B49C0531E0855C90094121E /* BulletMatchTests.swift in Sources */, 471 | 9272E1E61BDED73A0030B403 /* LetterCombinationsOfPhoneNumberTests.swift in Sources */, 472 | 94350F611BE5D859003592FB /* ExampleChallengeTests.swift in Sources */, 473 | 94350F651BE5E836003592FB /* TwoSumTests.swift in Sources */, 474 | 94350F5F1BE5D721003592FB /* CodeChallengeTestCase.swift in Sources */, 475 | 9272E1E41BDED71C0030B403 /* LongestSubstringWithoutRepeatingCharactersTests.swift in Sources */, 476 | ); 477 | runOnlyForDeploymentPostprocessing = 0; 478 | }; 479 | /* End PBXSourcesBuildPhase section */ 480 | 481 | /* Begin PBXTargetDependency section */ 482 | 9272E1B11BD7F6560030B403 /* PBXTargetDependency */ = { 483 | isa = PBXTargetDependency; 484 | target = 9272E1A31BD7F6560030B403 /* CodeChallenge */; 485 | targetProxy = 9272E1B01BD7F6560030B403 /* PBXContainerItemProxy */; 486 | }; 487 | /* End PBXTargetDependency section */ 488 | 489 | /* Begin XCBuildConfiguration section */ 490 | 9272E1B61BD7F6560030B403 /* Debug */ = { 491 | isa = XCBuildConfiguration; 492 | buildSettings = { 493 | ALWAYS_SEARCH_USER_PATHS = NO; 494 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 495 | CLANG_CXX_LIBRARY = "libc++"; 496 | CLANG_ENABLE_MODULES = YES; 497 | CLANG_ENABLE_OBJC_ARC = YES; 498 | CLANG_WARN_BOOL_CONVERSION = YES; 499 | CLANG_WARN_CONSTANT_CONVERSION = YES; 500 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 501 | CLANG_WARN_EMPTY_BODY = YES; 502 | CLANG_WARN_ENUM_CONVERSION = YES; 503 | CLANG_WARN_INFINITE_RECURSION = YES; 504 | CLANG_WARN_INT_CONVERSION = YES; 505 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 506 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 507 | CLANG_WARN_UNREACHABLE_CODE = YES; 508 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 509 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 510 | COPY_PHASE_STRIP = NO; 511 | CURRENT_PROJECT_VERSION = 1; 512 | DEBUG_INFORMATION_FORMAT = dwarf; 513 | ENABLE_STRICT_OBJC_MSGSEND = YES; 514 | ENABLE_TESTABILITY = YES; 515 | GCC_C_LANGUAGE_STANDARD = gnu99; 516 | GCC_DYNAMIC_NO_PIC = NO; 517 | GCC_NO_COMMON_BLOCKS = YES; 518 | GCC_OPTIMIZATION_LEVEL = 0; 519 | GCC_PREPROCESSOR_DEFINITIONS = ( 520 | "DEBUG=1", 521 | "$(inherited)", 522 | ); 523 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 524 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 525 | GCC_WARN_UNDECLARED_SELECTOR = YES; 526 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 527 | GCC_WARN_UNUSED_FUNCTION = YES; 528 | GCC_WARN_UNUSED_VARIABLE = YES; 529 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 530 | MTL_ENABLE_DEBUG_INFO = YES; 531 | ONLY_ACTIVE_ARCH = YES; 532 | SDKROOT = iphoneos; 533 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 534 | TARGETED_DEVICE_FAMILY = "1,2"; 535 | VERSIONING_SYSTEM = "apple-generic"; 536 | VERSION_INFO_PREFIX = ""; 537 | }; 538 | name = Debug; 539 | }; 540 | 9272E1B71BD7F6560030B403 /* Release */ = { 541 | isa = XCBuildConfiguration; 542 | buildSettings = { 543 | ALWAYS_SEARCH_USER_PATHS = NO; 544 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 545 | CLANG_CXX_LIBRARY = "libc++"; 546 | CLANG_ENABLE_MODULES = YES; 547 | CLANG_ENABLE_OBJC_ARC = YES; 548 | CLANG_WARN_BOOL_CONVERSION = YES; 549 | CLANG_WARN_CONSTANT_CONVERSION = YES; 550 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 551 | CLANG_WARN_EMPTY_BODY = YES; 552 | CLANG_WARN_ENUM_CONVERSION = YES; 553 | CLANG_WARN_INFINITE_RECURSION = YES; 554 | CLANG_WARN_INT_CONVERSION = YES; 555 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 556 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 557 | CLANG_WARN_UNREACHABLE_CODE = YES; 558 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 559 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 560 | COPY_PHASE_STRIP = NO; 561 | CURRENT_PROJECT_VERSION = 1; 562 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 563 | ENABLE_NS_ASSERTIONS = NO; 564 | ENABLE_STRICT_OBJC_MSGSEND = YES; 565 | GCC_C_LANGUAGE_STANDARD = gnu99; 566 | GCC_NO_COMMON_BLOCKS = YES; 567 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 568 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 569 | GCC_WARN_UNDECLARED_SELECTOR = YES; 570 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 571 | GCC_WARN_UNUSED_FUNCTION = YES; 572 | GCC_WARN_UNUSED_VARIABLE = YES; 573 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 574 | MTL_ENABLE_DEBUG_INFO = NO; 575 | SDKROOT = iphoneos; 576 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 577 | TARGETED_DEVICE_FAMILY = "1,2"; 578 | VALIDATE_PRODUCT = YES; 579 | VERSIONING_SYSTEM = "apple-generic"; 580 | VERSION_INFO_PREFIX = ""; 581 | }; 582 | name = Release; 583 | }; 584 | 9272E1B91BD7F6560030B403 /* Debug */ = { 585 | isa = XCBuildConfiguration; 586 | buildSettings = { 587 | CLANG_ENABLE_MODULES = YES; 588 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 589 | DEFINES_MODULE = YES; 590 | DYLIB_COMPATIBILITY_VERSION = 1; 591 | DYLIB_CURRENT_VERSION = 1; 592 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 593 | INFOPLIST_FILE = CodeChallenge/Info.plist; 594 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 595 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 596 | PRODUCT_BUNDLE_IDENTIFIER = com.iosdevelopershq.CodeChallenge; 597 | PRODUCT_NAME = CodeChallenge; 598 | SKIP_INSTALL = YES; 599 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 600 | SWIFT_VERSION = 3.0; 601 | }; 602 | name = Debug; 603 | }; 604 | 9272E1BA1BD7F6560030B403 /* Release */ = { 605 | isa = XCBuildConfiguration; 606 | buildSettings = { 607 | CLANG_ENABLE_MODULES = YES; 608 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 609 | DEFINES_MODULE = YES; 610 | DYLIB_COMPATIBILITY_VERSION = 1; 611 | DYLIB_CURRENT_VERSION = 1; 612 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 613 | INFOPLIST_FILE = CodeChallenge/Info.plist; 614 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 615 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 616 | PRODUCT_BUNDLE_IDENTIFIER = com.iosdevelopershq.CodeChallenge; 617 | PRODUCT_NAME = CodeChallenge; 618 | SKIP_INSTALL = YES; 619 | SWIFT_VERSION = 3.0; 620 | }; 621 | name = Release; 622 | }; 623 | 9272E1BC1BD7F6560030B403 /* Debug */ = { 624 | isa = XCBuildConfiguration; 625 | buildSettings = { 626 | INFOPLIST_FILE = CodeChallengeTests/Info.plist; 627 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 628 | PRODUCT_BUNDLE_IDENTIFIER = com.iosdevelopershq.CodeChallengeTests; 629 | PRODUCT_MODULE_NAME = CodeChallengeTests; 630 | PRODUCT_NAME = CodeChallenge; 631 | SWIFT_VERSION = 3.0; 632 | }; 633 | name = Debug; 634 | }; 635 | 9272E1BD1BD7F6560030B403 /* Release */ = { 636 | isa = XCBuildConfiguration; 637 | buildSettings = { 638 | INFOPLIST_FILE = CodeChallengeTests/Info.plist; 639 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 640 | PRODUCT_BUNDLE_IDENTIFIER = com.iosdevelopershq.CodeChallengeTests; 641 | PRODUCT_MODULE_NAME = CodeChallengeTests; 642 | PRODUCT_NAME = CodeChallenge; 643 | SWIFT_VERSION = 3.0; 644 | }; 645 | name = Release; 646 | }; 647 | /* End XCBuildConfiguration section */ 648 | 649 | /* Begin XCConfigurationList section */ 650 | 9272E19E1BD7F6560030B403 /* Build configuration list for PBXProject "CodeChallenge" */ = { 651 | isa = XCConfigurationList; 652 | buildConfigurations = ( 653 | 9272E1B61BD7F6560030B403 /* Debug */, 654 | 9272E1B71BD7F6560030B403 /* Release */, 655 | ); 656 | defaultConfigurationIsVisible = 0; 657 | defaultConfigurationName = Release; 658 | }; 659 | 9272E1B81BD7F6560030B403 /* Build configuration list for PBXNativeTarget "CodeChallenge" */ = { 660 | isa = XCConfigurationList; 661 | buildConfigurations = ( 662 | 9272E1B91BD7F6560030B403 /* Debug */, 663 | 9272E1BA1BD7F6560030B403 /* Release */, 664 | ); 665 | defaultConfigurationIsVisible = 0; 666 | defaultConfigurationName = Release; 667 | }; 668 | 9272E1BB1BD7F6560030B403 /* Build configuration list for PBXNativeTarget "CodeChallengeTests" */ = { 669 | isa = XCConfigurationList; 670 | buildConfigurations = ( 671 | 9272E1BC1BD7F6560030B403 /* Debug */, 672 | 9272E1BD1BD7F6560030B403 /* Release */, 673 | ); 674 | defaultConfigurationIsVisible = 0; 675 | defaultConfigurationName = Release; 676 | }; 677 | /* End XCConfigurationList section */ 678 | }; 679 | rootObject = 9272E19B1BD7F6560030B403 /* Project object */; 680 | } 681 | -------------------------------------------------------------------------------- /CodeChallenge.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CodeChallenge.xcodeproj/xcshareddata/xcschemes/CodeChallenge.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /CodeChallenge.xcodeproj/xcshareddata/xcschemes/CodeChallengeTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 39 | 40 | 41 | 42 | 48 | 49 | 51 | 52 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /CodeChallenge/Base/CodeChallengeType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CodeChallengeType.swift 3 | // CodeChallenge 4 | // 5 | // Created by Ryan Arana on 10/31/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // MARK: - Challenge Definition 12 | 13 | /** 14 | Protocol for defining a new Challenge. 15 | 16 | This protocol defines the Input/Output types for the Entry's `block` property. HINT: Use a tuple for multiple inputs! It also defines the interface that whatever will run the challenges (currently our tests) uses to run the entries and verify their output. 17 | */ 18 | protocol CodeChallengeType { 19 | /// The type for the input(s) for the challenge. 20 | associatedtype InputType 21 | /// The type that the entry's function will return. 22 | associatedtype OutputType 23 | 24 | /// The heading title for this challenge 25 | var title: String { get } 26 | 27 | /// The entries to be run. Participants will need to add their `CodeChallengeEntry` instance to this array in the challeng's definition. 28 | var entries: [CodeChallengeEntry] { get } 29 | 30 | /** 31 | A function to generate the dataset that the entries will be run against. Each `InputType` in the returned array will be run by each entry multiple times and then averaged in the results. 32 | */ 33 | func generateDataset() -> [InputType] 34 | 35 | /** 36 | A function which verifies the output from running an entry's block with the given input. 37 | 38 | - Returns: True if the output is valid, false if not. 39 | */ 40 | func verifyOutput(_ output: OutputType, forInput input: InputType) -> Bool 41 | } 42 | 43 | /** 44 | Convenient protocol for defining challenges that verify entries using a JSON file. 45 | 46 | Fields required by `JSONBasedChallenge`: 47 | - `fileName` 48 | - `verificationData` 49 | 50 | Fields required by `CodeChallengeType`: 51 | - `title` 52 | - `entries` 53 | - `InputType` 54 | - `OutputType` 55 | 56 | In most cases, this should take over `generateDataset` and `verifyOutput` for you. 57 | The more your types are simple `String`s, the less methods you'll have to implement yourself. 58 | */ 59 | protocol JSONBasedChallenge: class, CodeChallengeType { 60 | 61 | /// The type the output is encoded as in the JSON file. This can usually be inferred from methods you define; you shouldn't have to add it manually. 62 | associatedtype RawOutputType 63 | 64 | /// The name of the JSON file. You shouldn't need to add any path components in here. 65 | /// Recommended placement of the JSON file is in your challenge folder. 66 | var fileName: String { get } 67 | 68 | /// You have to implement this yourself, since protocols can't store anything for you. The types should match those of the JSON file. 69 | var verificationData: [String: RawOutputType] { get set } 70 | 71 | 72 | /// Converts the JSON key into an input for the challenge. (Used for dataset generation.) 73 | /// 74 | /// If your `InputType` is `String`, you don't have to implement this. 75 | /// 76 | /// - Parameter raw: Raw input from the JSON file 77 | /// - Returns: Input to feed into entries 78 | func input(from raw: String) -> InputType 79 | 80 | /// Converts the challenge input back into raw JSON. (Used for output verification.) 81 | /// 82 | /// If your `InputType` is `String`, you don't have to implement this. 83 | /// 84 | /// - Parameter input: Input used for the entry 85 | /// - Returns: Raw input, as in the JSON file, to use for accessing `verificationData` 86 | func raw(from input: InputType) -> String 87 | } 88 | 89 | // Default Implementations 90 | 91 | extension JSONBasedChallenge { 92 | 93 | func generateDataset() -> [InputType] { 94 | // Extract data from JSON file 95 | let bundle = Bundle(for: Self.self) 96 | guard 97 | let dataUrl = bundle.url(forResource: fileName, withExtension: "json"), 98 | let data = try? Data(contentsOf: dataUrl), 99 | let jsonObjects = try? JSONSerialization.jsonObject(with: data, options: .allowFragments), 100 | let vd = jsonObjects as? [String: RawOutputType] else { fatalError() } 101 | 102 | verificationData = vd 103 | 104 | // Map key `String`s to `InputType` 105 | return vd.keys.map { input(from: $0) } 106 | } 107 | } 108 | 109 | extension JSONBasedChallenge where OutputType: Equatable, RawOutputType == OutputType { 110 | 111 | func verifyOutput(_ output: OutputType, forInput input: InputType) -> Bool { 112 | guard let expected = verificationData[raw(from: input)] else { return false } 113 | return expected == output 114 | } 115 | } 116 | 117 | extension JSONBasedChallenge where InputType == String { 118 | 119 | func input(from raw: String) -> InputType { 120 | return raw 121 | } 122 | 123 | func raw(from input: InputType) -> String { 124 | return input 125 | } 126 | } 127 | 128 | // MARK: - Entry Definition 129 | 130 | /// An entry for a `CodeChallengeType`. 131 | struct CodeChallengeEntry { 132 | /// This entry's author's name. 133 | let name: String 134 | 135 | /// The block to be run to evaluate this entry. 136 | let block: (ChallengeType.InputType) -> ChallengeType.OutputType 137 | } 138 | 139 | // MARK: - Test Evaluation 140 | 141 | /// A structure to hold the result of a single run of an Entry's `block`. 142 | struct CodeChallengeResult { 143 | /// The name of the Entry's participant 144 | let name: String 145 | 146 | /// The input that generated the result. 147 | let input: ChallengeType.InputType 148 | 149 | /// The output received from the block. There should be one output in this array for each iteration, and the index will match the corresponding time measurement in the `times` array. NOTE: These should all be the same value, as they are all the result of the entry processing the same input, but we store them all here for just in case. 150 | let outputs: [ChallengeType.OutputType] 151 | 152 | /// The amount of wall-clock time it took to process the input. There should be one time measurment in this array for each iteration, and the index here will match the corresponding output in the `outputs` array. 153 | let times: [TimeInterval] 154 | 155 | /// The number of times the entry was run. 156 | let iterations: Int 157 | 158 | /// The total wall-clock time it took to process input `iterations` times. 159 | var totalTime: TimeInterval { return times.reduce(0) { $0 + $1 } } 160 | 161 | /// The average wall-clock time a single iteration took to process the input. 162 | var averageTime: TimeInterval { 163 | // computers don't like dividing by zero. 164 | guard times.count != 0 else { return TimeInterval.infinity } 165 | return Double(totalTime) / Double(times.count) 166 | } 167 | } 168 | 169 | /// A structure to hold the result of running an Entry's `block` multiple times. 170 | struct AccumulatedChallengeResult { 171 | /// The name of the Entry's participant. 172 | let name: String 173 | 174 | /// How many total runs does this AccumulatedResult represent. 175 | let total: Int 176 | 177 | /// How many of the runs passed verification. 178 | let successes: Int 179 | 180 | /// How many of the runs did not pass verification. 181 | let failures: Int 182 | 183 | /// The ratio of successes to failures (0.0 - 1.0) 184 | let successRate: Double 185 | 186 | /// The array of individual runs' `CodeChallengeResult`s. 187 | let results: [CodeChallengeResult] 188 | 189 | /// The total wall-clock time it took to process all results. 190 | let totalTime: TimeInterval 191 | 192 | /// The average wall-clock time a single iteration took to process its input. 193 | let averageTime: TimeInterval 194 | 195 | /** 196 | Create a new AccumulatedChallengeResult from the given set of results. The time properties will be calculated using the given parameters to this init. 197 | */ 198 | init(name: String, results: [CodeChallengeResult], successes: Int, failures: Int) { 199 | self.name = name 200 | self.results = results 201 | self.successes = successes 202 | self.failures = failures 203 | self.total = successes + failures 204 | self.totalTime = results.reduce(0) { $0 + $1.totalTime } 205 | self.successRate = Double(successes) / Double(total) 206 | 207 | if total == 0 { 208 | self.averageTime = TimeInterval.infinity 209 | } else { 210 | self.averageTime = Double(results.reduce(0) { $0 + $1.averageTime }) / Double(total) 211 | } 212 | } 213 | } 214 | 215 | extension CodeChallengeType { 216 | fileprivate typealias ResultType = CodeChallengeResult 217 | fileprivate typealias OperationType = RunOperation 218 | 219 | typealias AccumulatedResultType = AccumulatedChallengeResult 220 | 221 | /** 222 | Run all of this Challenge's entries using the same generated dataset. 223 | 224 | This function calls `generateDataset()` and then runs each input in the dataset through each entry in the `entries` multiple times, concurrently. It then processes all of the `CodeChallengeResult`s into `AcummulatedChallengeResult`s for each participant and returns them sorted by `totalTime`. 225 | 226 | - Returns: An array of `AcummulatedChallengeResult`s for each participant sorted by `averageTime`. 227 | */ 228 | func runAll() -> [AccumulatedResultType] { 229 | 230 | // Generate the dataset, everybody gets the same one 231 | let dataset = generateDataset() 232 | 233 | // Make a worker queue so that we can run through everything concurrently and save the runner some time. 234 | let workerQueue = OperationQueue() 235 | workerQueue.maxConcurrentOperationCount = 30 236 | var workers = [OperationType]() 237 | let iterations = 10 238 | 239 | // For each entry 240 | for entry in entries { 241 | workers.append(contentsOf: dataset.map { OperationType(entry: entry, input: $0, iterations: iterations) }) 242 | } 243 | 244 | print("Adding \(workers.count) operations to the queue and running them \(min(workerQueue.maxConcurrentOperationCount, workers.count)) at a time") 245 | workerQueue.addOperations(workers, waitUntilFinished: true) 246 | 247 | // Gather up all of the results grouped by Participant name. 248 | var resultsByName = [String: [ResultType]]() 249 | for worker in workers { 250 | if resultsByName[worker.entry.name] == nil { 251 | resultsByName[worker.entry.name] = [] 252 | } 253 | resultsByName[worker.entry.name]?.append(worker.result) 254 | } 255 | 256 | // Generate AccumulatedResults for each participant 257 | var accumulatedResults = [AccumulatedResultType]() 258 | for (name, results) in resultsByName { 259 | var successes = 0 260 | var failures = 0 261 | for result in results { 262 | for output in result.outputs { 263 | if verifyOutput(output, forInput: result.input) { 264 | successes += 1 265 | } else { 266 | failures += 1 267 | } 268 | } 269 | } 270 | let result = AccumulatedResultType(name: name, results: results, successes: successes, failures: failures) 271 | accumulatedResults.append(result) 272 | } 273 | 274 | // Return the accumulated results sorted by average time. 275 | return accumulatedResults.sorted { $0.averageTime < $1.averageTime } 276 | } 277 | } 278 | 279 | private class RunOperation: Operation { 280 | let entry: CodeChallengeEntry 281 | let input: ChallengeType.InputType 282 | let iterations: Int 283 | 284 | var result: CodeChallengeResult! 285 | 286 | init(entry: CodeChallengeEntry, input: ChallengeType.InputType, iterations: Int) { 287 | self.entry = entry 288 | self.input = input 289 | self.iterations = iterations 290 | } 291 | 292 | override func main() { 293 | var outputs = Array() 294 | var times = Array() 295 | for _ in 1...iterations { 296 | let start = Date() 297 | outputs.append(entry.block(input)) 298 | times.append(-start.timeIntervalSinceNow) 299 | } 300 | result = CodeChallengeResult(name: entry.name, input: input, outputs: outputs, times: times, iterations: iterations) 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /CodeChallenge/Base/ExampleCodeChallenge.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleCodeChallenge.swift 3 | // CodeChallenge 4 | // 5 | // Created by Ryan Arana on 10/31/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // Challenge Definition 12 | 13 | struct ExampleCodeChallenge: CodeChallengeType { 14 | typealias InputType = Int 15 | typealias OutputType = String 16 | 17 | let title = "Example Challenge" 18 | 19 | var entries: [CodeChallengeEntry] = [ 20 | // Participants must add their entry instance to this array 21 | noobExampleEntry, 22 | proExampleEntry 23 | ] 24 | 25 | func generateDataset() -> [Int] { 26 | return [Int](1...1000) 27 | } 28 | 29 | func verifyOutput(_ output: String, forInput input: Int) -> Bool { 30 | return output == "\(input)" 31 | } 32 | } 33 | 34 | // Challenge Entries 35 | 36 | let noobExampleEntry = CodeChallengeEntry(name: "Crash Override") { input -> String in 37 | for i in 1...10000 { 38 | // Wait for the Gibson to come online. 39 | } 40 | 41 | guard arc4random_uniform(100) > 20 else { 42 | // Sometimes you gotta stick it to the man, if you _really_ wanna win. 43 | return "\(input-1)" 44 | } 45 | return "\(input)" 46 | } 47 | 48 | let proExampleEntry = CodeChallengeEntry(name: "Acid Burn") { input -> String in 49 | // Just do it. 50 | return "\(input)" 51 | } 52 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/BulletMatch/BulletMatch.swift: -------------------------------------------------------------------------------- 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 | /** 12 | Forensic specialists examine spent cartridges for unique 13 | markings left by parts of a gun. They can then compare 14 | these markings to the ones in any gun to determine if there 15 | is a match. A match means that the bullet was fired from 16 | that gun. 17 | 18 | Given two markings, one from a spent cartridge and the other 19 | from a suspected weapon, both as Strings, return true if they match 20 | and false if they don't. 21 | 22 | EXAMPLES: 23 | Match, returns true 24 | "| ||| | |" and 25 | "| ||| | |" 26 | 27 | Match, returns true though one is rotated. Bullets can be rotated. 28 | Your solution should account for the possible rotation of bullets. 29 | "|| ||| | " and 30 | " | || |||" 31 | 32 | Doesn't match, returns false 33 | "| ||| | |" and 34 | "||| | | |" 35 | 36 | NOTE: Markings cannot be flipped. 37 | "| ||" is not a match for 38 | "|| |" 39 | 40 | Problem adapted from http://bit.ly/2h57Wxe 41 | */ 42 | final class BulletChallenge: JSONBasedChallenge { 43 | typealias InputType = (bulletMarkings: String, gunMarkings: String) 44 | typealias OutputType = Bool 45 | 46 | var title = "Bullet Challenge" 47 | 48 | // no `protected` access level (darn you, swift gods!) 49 | let fileName = "BulletMatch_dataset" 50 | var verificationData: [String : OutputType] = [:] 51 | 52 | var entries: [CodeChallengeEntry] = [ 53 | bugKrushaBulletMatchEntry, 54 | codesmanBulletMatchEntry, 55 | juliand665BulletMatchEntry, 56 | FlavioSilverioBulletMatchEntry, 57 | matthijsBulletMatchEntry 58 | ] 59 | 60 | func input(from raw: String) -> InputType { 61 | let components = raw.components(separatedBy: "#") 62 | let gunMarkings = components[1] 63 | let bulletMarkings = components[0] 64 | return (bulletMarkings: bulletMarkings, gunMarkings: gunMarkings) 65 | } 66 | 67 | func raw(from input: InputType) -> String { 68 | return "\(input.bulletMarkings)#\(input.gunMarkings)" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/BulletMatch/Entries/BugKrushaBulletMatchEntry.swift: -------------------------------------------------------------------------------- 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(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 | } 45 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/BulletMatch/Entries/CodesmanBulletMatchEntry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CodesmanBulletMatchEntry.swift 3 | // CodeChallenge 4 | // 5 | // Created by Tom Holland on 1/6/17. 6 | // Copyright © 2017 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let codesmanBulletMatchEntry = CodeChallengeEntry(name: "codesman") { input in 12 | let weapon = input.0 13 | var cartridge = input.1 14 | 15 | for _ in cartridge.characters { 16 | guard cartridge != weapon else { return true } 17 | // Rotate the cartridge one scratch and try again! 18 | cartridge.insert(cartridge.remove(at: cartridge.startIndex), at: cartridge.endIndex) 19 | } 20 | return false 21 | } 22 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/BulletMatch/Entries/FlavioSilverioBulletMatchEntry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FlavioSilverioBulletMatchEntry.swift 3 | // CodeChallenge 4 | // 5 | // Created by Flávio Silvério on 31/01/17. 6 | // Copyright © 2017 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let FlavioSilverioBulletMatchEntry = CodeChallengeEntry(name: "flaviodsilverio") { input in 12 | 13 | let bulletMarkings = input.0 14 | var gunMarkings = input.1 15 | 16 | for _ in 0...bulletMarkings.characters.count - 1 { 17 | 18 | if bulletMarkings == gunMarkings { 19 | return true 20 | } else { 21 | 22 | gunMarkings.characters.append(gunMarkings.remove(at: gunMarkings.startIndex)) 23 | 24 | //made this second one to try it, it's way slower than the previous one... 25 | // gunMarkings.insert(gunMarkings.remove( 26 | // at: gunMarkings.startIndex), 27 | // at: gunMarkings.endIndex) 28 | } 29 | 30 | } 31 | 32 | return false 33 | 34 | } 35 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/BulletMatch/Entries/juliand665BulletMatchEntry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // juliand665BulletMatchEntry.swift 3 | // CodeChallenge 4 | // 5 | // Created by Julian Dunskus on 06.01.17. 6 | // Copyright © 2017 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let juliand665BulletMatchEntry = CodeChallengeEntry(name: "juliand665", block: compare) 12 | 13 | private func compare(bullet: String, gun: String) -> Bool { 14 | var bul = bullet 15 | 16 | for _ in 1 ... bul.characters.count { 17 | // equate 18 | if bul == gun { 19 | return true 20 | } 21 | // rotate 22 | bul.characters.append(bul.characters.popFirst()!) 23 | } 24 | 25 | return false 26 | } 27 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/BulletMatch/Entries/matthijsBulletMatchEntry.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /* 4 | This is perhaps a bit of a weird solution. :-) 5 | 6 | If gun is || ||| |||| | 7 | 8 | then we glue two of these together to get: 9 | 10 | || ||| |||| | || ||| |||| | 11 | 12 | and then we try to find bullet as a substring: 13 | 14 | | || ||| |||| 15 | 16 | This is a match, yay! 17 | 18 | However, this approach can produce false positives, as in this example: 19 | 20 | |||| || |||| || 21 | | |||| 22 | 23 | There is a matching substring but it's not a valid solution. To deal with 24 | this situation, we remove the parts of the string that match: 25 | 26 | |||| | || 27 | 28 | If this is not identical to the original gun string, then the bullet did 29 | not come from the gun. 30 | 31 | It may sound slow but it's actually a very fast solution! 32 | */ 33 | 34 | let matthijsBulletMatchEntry = CodeChallengeEntry(name: "matthijs") { (bullet, gun) in 35 | let gungun = gun + gun 36 | if let range = gungun.range(of: bullet) { 37 | let leftover = gungun.substring(to: range.lowerBound) + gungun.substring(from: range.upperBound) 38 | return (leftover == gun) 39 | } 40 | return false 41 | } 42 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/Clock/Clock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Clock.swift 3 | // CodeChallenge 4 | // 5 | // Created by Jon-Tait Beason on 12/13/16. 6 | // Copyright © 2016 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Given a time represented as a String, "HH:MM:SS", 13 | calculate the angle the hour hand, minute hand, 14 | and the second hand make clockwise from 12:00:00. 15 | 16 | The angles should be returned in a tuple as follows 17 | (hourHandAngle: Int, minuteHandAngle: Int, secondHandAndle: Int) 18 | 19 | EXAMPLES 20 | "06:00:00" should return (180, 0, 0) 21 | "08:30:00" should return (255, 180, 0) 22 | "10:17:55" should return (308, 107, 330) 23 | 24 | Adapted from http://bit.ly/2gEBhRh 25 | */ 26 | 27 | final class ClockChallenge: JSONBasedChallenge { 28 | typealias InputType = String 29 | typealias OutputType = (hourHandeAngle: Int, minuteHandAngle: Int, secondHandAngle: Int) 30 | 31 | var title = "Clock Challenge" 32 | 33 | // no `protected` access level (darn you, swift gods!) 34 | let fileName = "Clock_dataset" 35 | var verificationData: [String: Int] = [:] 36 | 37 | var entries: [CodeChallengeEntry] = [ 38 | bugKrushaClockEntry, 39 | FlavioSilverioClockEntry, 40 | ethanSchatzlineClockEntry, 41 | brandonShegaClockEntry, 42 | matthijsClockEntry, 43 | felixdumitClockEntry, 44 | juliand665ClockEntry 45 | ] 46 | 47 | // have to declare this explicitly because *of course* tuples are non-nominal and cannot be `Equatable`, despite being able to equate them 48 | func verifyOutput(_ output: (hourHandeAngle: Int, minuteHandAngle: Int, secondHandAngle: Int), forInput input: String) -> Bool { 49 | guard let expected = verificationData[input] else { return false } 50 | return (expected >> 20, expected >> 10 & 0x3ff, expected & 0x3ff) == output 51 | } 52 | } 53 | 54 | /* How I generated the dataset: 55 | 56 | func twoDigitString(from num: Int) -> String { 57 | return num < 10 ? "0\(num)" : "\(num)" 58 | } 59 | 60 | for h in 0...43200 { 61 | if arc4random_uniform(120) == 0 { // strip it down a little 62 | let m = h % 60 63 | let s = m % 60 64 | print("\"\(twoDigitString(from: h / 3600)):\(twoDigitString(from: h / 60 % 60)):\(twoDigitString(from: h % 60))\": \((h * 360 / 43200) << 20 | (m * 360 / 3600) << 10 | s * 360 / 60),") 65 | } 66 | } 67 | 68 | */ 69 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/Clock/Clock_dataset.json: -------------------------------------------------------------------------------- 1 | { 2 | "00:00:01": 6, 3 | "00:01:17": 7270, 4 | "00:05:51": 2133298, 5 | "00:06:05": 3182622, 6 | "00:09:41": 4253942, 7 | "00:10:18": 5305452, 8 | "00:11:12": 5311560, 9 | "00:13:03": 6371346, 10 | "00:14:48": 7430432, 11 | "00:19:25": 9556118, 12 | "00:22:52": 11674936, 13 | "00:22:59": 11674978, 14 | "00:23:18": 11676780, 15 | "00:26:23": 13793418, 16 | "00:28:32": 14855360, 17 | "00:32:38": 16977124, 18 | "00:35:35": 18044114, 19 | "00:38:13": 20157518, 20 | "00:39:40": 20166896, 21 | "00:40:24": 21219472, 22 | "00:45:03": 23345170, 23 | "00:45:17": 23346278, 24 | "00:45:34": 23348428, 25 | "00:46:14": 24400980, 26 | "00:46:54": 24405316, 27 | "00:52:11": 27583554, 28 | "00:56:29": 29706414, 29 | "01:02:02": 32518156, 30 | "01:05:02": 33585164, 31 | "01:05:20": 33587320, 32 | "01:06:33": 34643142, 33 | "01:07:44": 34650376, 34 | "01:08:59": 35706210, 35 | "01:09:16": 35708000, 36 | "01:09:29": 35709102, 37 | "01:09:41": 35711222, 38 | "01:11:16": 36768864, 39 | "01:14:22": 38885508, 40 | "01:19:22": 41013380, 41 | "01:22:39": 43130090, 42 | "01:24:07": 44187690, 43 | "01:24:23": 44189834, 44 | "01:24:41": 44191990, 45 | "01:26:51": 45253938, 46 | "01:26:59": 45253986, 47 | "01:28:48": 46313760, 48 | "01:30:57": 47375702, 49 | "01:32:30": 48434356, 50 | "01:32:47": 48435482, 51 | "01:35:07": 49498154, 52 | "01:35:11": 49499202, 53 | "01:36:36": 50556120, 54 | "01:36:54": 50558276, 55 | "01:38:52": 51619128, 56 | "01:42:56": 53740880, 57 | "01:43:26": 53743772, 58 | "01:43:42": 53745916, 59 | "01:45:09": 54802486, 60 | "01:46:27": 55859362, 61 | "01:51:47": 57989402, 62 | "01:54:38": 60103908, 63 | "01:56:41": 61165814, 64 | "01:59:14": 62229588, 65 | "02:03:38": 63984868, 66 | "02:04:51": 65041714, 67 | "02:06:10": 66098236, 68 | "02:08:58": 67163484, 69 | "02:13:46": 69290260, 70 | "02:15:01": 70346758, 71 | "02:15:02": 70346764, 72 | "02:23:19": 74591346, 73 | "02:23:43": 74594562, 74 | "02:28:05": 77766686, 75 | "02:31:43": 78838018, 76 | "02:32:10": 79889468, 77 | "02:33:32": 79897792, 78 | "02:36:46": 82014484, 79 | "02:38:30": 83074228, 80 | "02:39:45": 83081486, 81 | "02:40:13": 84132942, 82 | "02:42:58": 85198172, 83 | "02:46:59": 87319906, 84 | "02:49:31": 88384698, 85 | "02:49:33": 88384710, 86 | "02:49:45": 88385806, 87 | "02:50:30": 89439412, 88 | "02:51:44": 89446664, 89 | "02:52:58": 90502492, 90 | "02:54:23": 91560074, 91 | "03:01:52": 94383416, 92 | "03:03:00": 95438848, 93 | "03:03:27": 95441058, 94 | "03:06:43": 97558786, 95 | "03:10:23": 99678346, 96 | "03:16:21": 102860926, 97 | "03:16:57": 102864214, 98 | "03:19:26": 103927964, 99 | "03:22:18": 106042476, 100 | "03:24:31": 107105466, 101 | "03:25:01": 107108358, 102 | "03:26:54": 108168516, 103 | "03:31:45": 110295310, 104 | "03:31:54": 110296388, 105 | "03:32:20": 111347832, 106 | "03:36:21": 113469566, 107 | "03:36:26": 113469596, 108 | "03:38:44": 114532616, 109 | "03:40:04": 115589144, 110 | "03:45:24": 117719184, 111 | "03:47:55": 118783306, 112 | "03:48:36": 119835864, 113 | "03:51:19": 120900722, 114 | "03:52:17": 121955430, 115 | "03:53:07": 121960490, 116 | "03:55:22": 123023492, 117 | "03:55:23": 123023498, 118 | "03:57:04": 124082200, 119 | "03:57:44": 124086536, 120 | "04:01:19": 125836402, 121 | "04:01:53": 125840702, 122 | "04:06:05": 129011742, 123 | "04:08:38": 130075876, 124 | "04:09:57": 130084182, 125 | "04:10:08": 131133488, 126 | "04:13:13": 132201550, 127 | "04:15:46": 133265684, 128 | "04:18:00": 135376896, 129 | "04:23:12": 137505864, 130 | "04:24:21": 138561662, 131 | "04:24:49": 138563878, 132 | "04:27:00": 139626496, 133 | "04:28:17": 140682342, 134 | "04:30:22": 141744260, 135 | "04:38:39": 145988842, 136 | "04:39:16": 145992800, 137 | "04:39:53": 145997118, 138 | "04:41:47": 147056922, 139 | "04:42:16": 148108384, 140 | "04:44:28": 149170344, 141 | "04:44:55": 149173578, 142 | "04:45:10": 149175356, 143 | "04:46:21": 150231166, 144 | "04:46:34": 150232268, 145 | "04:47:12": 150236232, 146 | "04:47:23": 150237322, 147 | "04:50:21": 152352894, 148 | "04:53:12": 153418824, 149 | "04:54:01": 154472454, 150 | "04:56:58": 155538780, 151 | "04:58:42": 156598524, 152 | "05:00:59": 157291874, 153 | "05:01:28": 157294760, 154 | "05:01:48": 157296928, 155 | "05:05:04": 159414296, 156 | "05:10:15": 162591834, 157 | "05:15:00": 164718592, 158 | "05:15:36": 164721880, 159 | "05:18:30": 166837428, 160 | "05:19:39": 166843626, 161 | "05:20:45": 167899406, 162 | "05:21:26": 167903388, 163 | "05:22:50": 168961324, 164 | "05:27:18": 171084908, 165 | "05:29:27": 172146850, 166 | "05:31:01": 173205510, 167 | "05:33:44": 174270728, 168 | "05:34:33": 175324358, 169 | "05:36:14": 176383060, 170 | "05:38:15": 177443930, 171 | "05:38:49": 177447206, 172 | "05:40:58": 178509148, 173 | "05:42:57": 179570006, 174 | "05:43:16": 179571808, 175 | "05:44:43": 180629762, 176 | "05:46:44": 181690632, 177 | "05:50:46": 183812372, 178 | "05:51:07": 183814186, 179 | "05:51:47": 183818522, 180 | "05:52:23": 184871050, 181 | "05:58:28": 188053672, 182 | "06:04:52": 190870840, 183 | "06:05:58": 190877020, 184 | "06:11:35": 194057426, 185 | "06:11:48": 194058528, 186 | "06:12:10": 195109948, 187 | "06:16:33": 197233862, 188 | "06:20:02": 199352332, 189 | "06:20:39": 199355626, 190 | "06:20:40": 199356656, 191 | "06:24:06": 201474084, 192 | "06:26:20": 202537080, 193 | "06:26:46": 202539284, 194 | "06:26:49": 202539302, 195 | "06:28:08": 203595824, 196 | "06:29:02": 203601932, 197 | "06:34:26": 206780572, 198 | "06:37:56": 207850832, 199 | "06:38:23": 208902282, 200 | "06:39:08": 208906288, 201 | "06:39:52": 208911672, 202 | "06:40:03": 209960978, 203 | "06:40:22": 209963140, 204 | "06:46:37": 213146846, 205 | "06:49:47": 214214938, 206 | "06:50:44": 215269640, 207 | "06:56:18": 218449004, 208 | "06:57:08": 218454064, 209 | "06:57:16": 218455136, 210 | "06:57:21": 218456190, 211 | "06:59:59": 219520354, 212 | "07:00:12": 220202056, 213 | "07:07:41": 223394038, 214 | "07:08:53": 224449854, 215 | "07:09:17": 224451686, 216 | "07:10:14": 225506388, 217 | "07:11:53": 225516862, 218 | "07:12:25": 226568342, 219 | "07:12:57": 226571606, 220 | "07:13:13": 226573390, 221 | "07:13:56": 226577744, 222 | "07:14:21": 227629182, 223 | "07:15:18": 227634284, 224 | "07:22:49": 231874854, 225 | "07:25:08": 232937520, 226 | "07:25:40": 232941808, 227 | "07:27:17": 233999462, 228 | "07:30:40": 236118256, 229 | "07:31:13": 236121166, 230 | "07:34:30": 238238900, 231 | "07:38:51": 240362802, 232 | "07:39:24": 240365712, 233 | "07:41:12": 241425480, 234 | "07:44:32": 243543232, 235 | "07:45:05": 243546142, 236 | "07:49:59": 245673314, 237 | "07:50:13": 246723662, 238 | "07:54:09": 248844342, 239 | "07:56:19": 249906290, 240 | "08:00:38": 251661540, 241 | "08:05:34": 253789388, 242 | "08:06:35": 254844114, 243 | "08:07:44": 254851336, 244 | "08:10:33": 256965830, 245 | "08:12:15": 258024538, 246 | "08:13:17": 258030694, 247 | "08:17:41": 260155638, 248 | "08:20:25": 262269078, 249 | "08:20:27": 262269090, 250 | "08:21:01": 262273030, 251 | "08:22:55": 263333194, 252 | "08:22:58": 263333212, 253 | "08:28:02": 266510348, 254 | "08:28:14": 266511444, 255 | "08:28:53": 266515774, 256 | "08:33:53": 268643646, 257 | "08:41:59": 272887138, 258 | "08:42:01": 273936390, 259 | "08:42:22": 273938564, 260 | "08:44:50": 275002668, 261 | "08:44:58": 275002716, 262 | "08:44:59": 275002722, 263 | "08:45:24": 275005584, 264 | "08:49:06": 277125156, 265 | "08:51:27": 278188194, 266 | "08:51:33": 278189254, 267 | "08:51:47": 278190362, 268 | "08:52:07": 279240746, 269 | "08:54:39": 280304874, 270 | "08:58:53": 282428734, 271 | "09:00:51": 283120946, 272 | "09:06:24": 286300304, 273 | "09:07:59": 286309730, 274 | "09:10:25": 288422038, 275 | "09:13:01": 289486854, 276 | "09:13:07": 289486890, 277 | "09:21:01": 293730310, 278 | "09:24:39": 295849194, 279 | "09:24:52": 295851320, 280 | "09:26:59": 296912226, 281 | "09:30:03": 299028498, 282 | "09:30:04": 299028504, 283 | "09:32:01": 300089350, 284 | "09:33:48": 300099872, 285 | "09:33:53": 300100926, 286 | "09:38:00": 303271936, 287 | "09:39:35": 303281362, 288 | "09:44:02": 306454540, 289 | "09:46:46": 307519764, 290 | "09:47:17": 307522662, 291 | "09:47:19": 307522674, 292 | "09:49:13": 308583502, 293 | "09:49:41": 308586742, 294 | "09:50:54": 309642564, 295 | "09:51:49": 309647654, 296 | "09:52:11": 310699074, 297 | "09:57:46": 312830228, 298 | "09:59:37": 313890014, 299 | "10:00:59": 314578274, 300 | "10:01:37": 314582238, 301 | "10:01:53": 314584382, 302 | "10:03:27": 315642018, 303 | "10:03:38": 315643108, 304 | "10:03:41": 315644150, 305 | "10:05:21": 316702846, 306 | "10:10:10": 319878204, 307 | "10:12:07": 320938026, 308 | "10:12:57": 320943446, 309 | "10:14:18": 321999980, 310 | "10:14:57": 322004310, 311 | "10:16:26": 323061916, 312 | "10:17:29": 323068078, 313 | "10:17:36": 323069144, 314 | "10:18:58": 324126044, 315 | "10:19:14": 324127828, 316 | "10:21:27": 325189794, 317 | "10:23:12": 326249544, 318 | "10:24:06": 327303204, 319 | "10:29:31": 329434298, 320 | "10:30:48": 330490144, 321 | "10:34:56": 332612944, 322 | "10:35:15": 332614746, 323 | "10:35:48": 332618016, 324 | "10:39:21": 334737534, 325 | "10:40:26": 335792284, 326 | "10:41:58": 335801692, 327 | "10:44:16": 337912928, 328 | "10:47:06": 338978852, 329 | "10:50:35": 341097682, 330 | "10:52:45": 342159630, 331 | "10:53:33": 342164678, 332 | "10:57:14": 344284244, 333 | "11:00:21": 346032254, 334 | "11:08:03": 350273554, 335 | "11:08:42": 350277884, 336 | "11:11:39": 351343850, 337 | "11:17:48": 354527520, 338 | "11:23:42": 357710076, 339 | "11:27:17": 359828582, 340 | "11:29:05": 360888350, 341 | "11:29:31": 360891578, 342 | "11:29:42": 360892668, 343 | "11:32:16": 363005024, 344 | "11:32:43": 363008258, 345 | "11:32:59": 363009378, 346 | "11:34:52": 364070200, 347 | "11:35:20": 364073080, 348 | "11:36:24": 365127824, 349 | "11:39:11": 366193730, 350 | "11:40:20": 367249528, 351 | "11:41:33": 367256774, 352 | "11:47:41": 370440438, 353 | "11:48:40": 371495152, 354 | "11:49:57": 371502422, 355 | "11:50:10": 372552764, 356 | "11:50:31": 372554938, 357 | "11:51:01": 372557830, 358 | "11:51:51": 372563250, 359 | "11:52:26": 373614748, 360 | "11:56:04": 375734296, 361 | "11:57:36": 375743704 362 | } -------------------------------------------------------------------------------- /CodeChallenge/Challenges/Clock/Entries/BrandonShegaClockEntry.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | let brandonShegaClockEntry = CodeChallengeEntry(name: "brandonshega") { input in 4 | let clock = Clock(for: input) 5 | return clock.timeInAngles 6 | } 7 | 8 | fileprivate struct Clock { 9 | let hour: Double 10 | let minute: Double 11 | let second: Double 12 | 13 | init(for date: String) { 14 | let df = DateFormatter() 15 | df.dateFormat = "hh:mm:ss" 16 | guard let date = df.date(from: date) else { fatalError("Bad Time") } 17 | let dateComps = Calendar.current.dateComponents([.hour, .minute, .second], from: date) 18 | guard 19 | let hour = dateComps.hour, 20 | let minute = dateComps.minute, 21 | let second = dateComps.second else { fatalError("Bad Time") } 22 | self.hour = Double(hour) 23 | self.minute = Double(minute) 24 | self.second = Double(second) 25 | } 26 | 27 | var timeInAngles: (Int, Int, Int) { 28 | let hoursToAngle = Int(hour * 30 + (minute/60 * 30)) 29 | let minutesToAngle = Int(minute * 6 + (second/60 * 6)) 30 | let secondsToAngle = Int(second * 6) 31 | return (hoursToAngle, minutesToAngle, secondsToAngle) 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/Clock/Entries/BugKrushaClockEntry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BugKrusha.swift 3 | // CodeChallenge 4 | // 5 | // Created by Jon-Tait Beason on 12/13/16. 6 | // Copyright © 2016 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let bugKrushaClockEntry = CodeChallengeEntry(name: "bugkrusha") { input in 12 | let timeBreakDown = input.components(separatedBy: ":") 13 | 14 | let oneRevolution = 360.0 15 | let numberOfIntervals = 60.0 16 | let degreePerHour = 30.0 17 | let degreePerInterval = oneRevolution / numberOfIntervals 18 | 19 | guard 20 | let seconds = Double(timeBreakDown[2]), 21 | let minutes = Double(timeBreakDown[1]), 22 | let hours = Double(timeBreakDown[0]) 23 | else { fatalError() } 24 | 25 | let secondsAngle = seconds * degreePerInterval 26 | let minutesAngle = minutes * degreePerInterval + (seconds/numberOfIntervals * degreePerInterval) 27 | let hoursAngle = hours * degreePerHour + (minutes/numberOfIntervals * degreePerHour) 28 | 29 | return (Int(hoursAngle), Int(minutesAngle), Int(secondsAngle)) 30 | } 31 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/Clock/Entries/EthanSchatzline-ClockEntry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EthanSchatzline-ClockEntry.swift 3 | // CodeChallenge 4 | // 5 | // Created by Ethan Schatzline on 12/15/16. 6 | // Copyright © 2016 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | private struct Constants { 12 | 13 | static let maxDegrees: Double = 360.0 14 | static let hourTenth: Double = 1.0 / 12.0 15 | static let hourDegrees: Double = 30.0 16 | static let secondMinuteTenth: Double = 1.0 / 60.0 17 | static let minuteDegrees: Double = 6.0 18 | } 19 | 20 | let ethanSchatzlineClockEntry = CodeChallengeEntry(name: "ethan.schatzline") { input in 21 | 22 | let components = input.components(separatedBy: ":") 23 | 24 | guard components.count == 3, 25 | let hour = Double(components[0]), 26 | let minute = Double(components[1]), 27 | let second = Double(components[2]) 28 | else { fatalError("Bad input") } 29 | 30 | let secondPercentage = second * Constants.secondMinuteTenth 31 | let minutePercentage = minute * Constants.secondMinuteTenth 32 | let hourPercentage = hour * Constants.hourTenth 33 | 34 | let secondAngle = Int(secondPercentage * Constants.maxDegrees) 35 | 36 | let minuteDegree = minutePercentage * Constants.maxDegrees 37 | let minuteOffset = secondPercentage * Constants.minuteDegrees 38 | let minuteAngle = Int(minuteDegree + minuteOffset) 39 | 40 | let hourDegree = hourPercentage * Constants.maxDegrees 41 | let hourOffset = minutePercentage * Constants.hourDegrees 42 | let hourAngle = Int(hourDegree + hourOffset) 43 | 44 | return (hourAngle, minuteAngle, secondAngle) 45 | } 46 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/Clock/Entries/FlavioSilverioClockEntry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FlavioSilverioClockEntry.swift 3 | // CodeChallenge 4 | // 5 | // Created by Flávio Silvério on 15/12/16. 6 | // Copyright © 2016 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let FlavioSilverioClockEntry = CodeChallengeEntry(name: "flaviodsilverio") { input in 12 | 13 | let formatter = DateFormatter() 14 | formatter.dateFormat = "hh:mm:ss" 15 | 16 | guard let date = formatter.date(from: input) else { 17 | return (Int(0), Int(0), Int(0)) 18 | } 19 | 20 | let calendar = Calendar.current 21 | 22 | let seconds = calendar.component(.second, from: date) 23 | let minutesAsSeconds = calendar.component(.minute, from: date) * 60 + seconds 24 | let hoursAsSeconds = calendar.component(.hour, from: date) * 3600 + minutesAsSeconds 25 | 26 | let secondsAngle = Int(360 / 60 * seconds) 27 | let minutesAngle = Int((Double(minutesAsSeconds) / Double(3600)) * 360) 28 | let hoursAngle = Int((Double(hoursAsSeconds) / Double(3600 * 12)) * 360) 29 | 30 | return (hoursAngle, minutesAngle, secondsAngle) 31 | } 32 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/Clock/Entries/felixdumitClockEntry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // felixdumitClockEntry.swift 3 | // CodeChallenge 4 | // 5 | // Created by Felix Dumit on 12/22/16. 6 | // Copyright © 2016 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | private var dateFormatter: DateFormatter = { 12 | let df = DateFormatter() 13 | df.dateFormat = "HH:mm:ss" 14 | return df 15 | }() 16 | 17 | let felixdumitClockEntry = CodeChallengeEntry(name: "felix-dumit") { input in 18 | if #available(iOS 10.0, *) { 19 | 20 | guard let date = dateFormatter.date(from: input) else { 21 | fatalError("bad input") 22 | } 23 | 24 | func duration(for component: Calendar.Component) -> Measurement { 25 | let cmp = NSCalendar.current.component(component, from: date) 26 | return Measurement(value: Double(cmp), unit: component.durationUnit!) 27 | } 28 | 29 | let totalDuration = duration(for: .hour) + duration(for: .minute) + duration(for: .second) 30 | 31 | func clockAngle(unit: UnitDuration) -> Int { 32 | let percent = (totalDuration % unit.durationForClockFullTurn) / unit.durationForClockFullTurn 33 | return Int(360 * percent) 34 | } 35 | 36 | return (clockAngle(unit: .hours), clockAngle(unit: .minutes), clockAngle(unit: .seconds)) 37 | 38 | } else { 39 | fatalError("this solution is only available for iOS10") 40 | } 41 | } 42 | 43 | @available(iOS 10.0, *) 44 | private func /(lhs: Measurement, rhs: Measurement) -> Double { 45 | return lhs.converted(to: D.baseUnit()).value / rhs.converted(to: D.baseUnit()).value 46 | } 47 | 48 | @available(iOS 10.0, *) 49 | private func %(lhs: Measurement, rhs: Measurement) -> Measurement { 50 | let value = lhs.converted(to: D.baseUnit()).value 51 | .truncatingRemainder(dividingBy: rhs.converted(to: D.baseUnit()).value) 52 | return Measurement(value: value, unit: D.baseUnit()) 53 | } 54 | 55 | @available(iOS 10.0, *) 56 | private extension UnitDuration { 57 | var durationForClockFullTurn: Measurement { 58 | switch self { 59 | case UnitDuration.hours: 60 | return Measurement(value:12, unit: .hours) 61 | case UnitDuration.minutes: 62 | return Measurement(value:1, unit: .hours) 63 | case UnitDuration.seconds: 64 | return Measurement(value: 1, unit: .minutes) 65 | default: //should not happen 66 | return Measurement(value: 0, unit: .seconds) 67 | } 68 | } 69 | } 70 | 71 | @available(iOS 10.0, *) 72 | private extension Calendar.Component { 73 | var durationUnit: UnitDuration? { 74 | switch self { 75 | case .hour: return .hours 76 | case .minute: return .minutes 77 | case .second: return .seconds 78 | default: return nil 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/Clock/Entries/juliand665ClockEntry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // juliand665ClockEntry.swift 3 | // CodeChallenge 4 | // 5 | // Created by Julian Dunskus on 06.01.17. 6 | // Copyright © 2017 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let juliand665ClockEntry = CodeChallengeEntry(name: "juliand665", block: anglesOfHands) 12 | 13 | private func anglesOfHands(at input: String) -> (Int, Int, Int) { 14 | var time = input.components(separatedBy: ":").map { Int($0)! } 15 | 16 | time[2] *= 6 17 | time[1] *= 6 18 | time[1] += time[2] / 60 19 | time[0] *= 30 20 | time[0] += time[1] / 12 21 | 22 | return (time[0], time[1], time[2]) 23 | } 24 | 25 | private func anglesOfHandsNice(at input: String) -> (Int, Int, Int) { 26 | let secs = input.components(separatedBy: ":").flatMap { Int($0) }.reduce(0) { $0 * 60 + $1 } // @teevee's `scan` would be really nice here 27 | 28 | return (secs * 360 / 43200, (secs % 3600) * 360 / 3600, (secs % 60) * 360 / 60) 29 | } 30 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/Clock/Entries/matthijsClockEntry.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | private extension Array { 4 | // Applies func[i] to self[i] 5 | func mapfuncs(_ funcs: [([Element]) -> Element]) -> [Element] { 6 | precondition(funcs.count == self.count) 7 | var result: [Element] = [] 8 | for i in 0..(name: "matthijs") { input in 16 | 17 | let output = input.components(separatedBy: ":").map({ Int($0)! }).mapfuncs([ 18 | { x in ((x[0]*60 + x[1])*60 + x[2]) / 120 }, 19 | { x in (x[1]*60 + x[2]) / 10 }, 20 | { x in x[2] * 6 }, 21 | ]) 22 | 23 | return (output[0], output[1], output[2]) 24 | } 25 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/LetterCombinationsOfPhoneNumber/Entries/BugKrushaLetterCombinationsOfPhoneNumberEntry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BugKrusha.swift 3 | // CodeChallenge 4 | // 5 | // Created by Jon-Tait Beason on 11/2/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let bugKrushaLetterCombinationOfPhoneNumberEntry = CodeChallengeEntry(name: "bugKrusha") { input in 12 | return getCombinations(digitString: input) 13 | } 14 | 15 | 16 | 17 | 18 | private enum Digit: String { 19 | case Two = "abc" 20 | case Three = "def" 21 | case Four = "ghi" 22 | case Five = "jkl" 23 | case Six = "mno" 24 | case Seven = "pqrs" 25 | case Eight = "tuv" 26 | case Nine = "wxyz" 27 | } 28 | 29 | 30 | private func getCharactersForNumber(number: String) -> Digit? { 31 | switch number { 32 | case "2": return Digit.Two 33 | case "3": return Digit.Three 34 | case "4": return Digit.Four 35 | case "5": return Digit.Five 36 | case "6": return Digit.Six 37 | case "7": return Digit.Seven 38 | case "8": return Digit.Eight 39 | case "9": return Digit.Nine 40 | default: break 41 | } 42 | 43 | return nil 44 | } 45 | 46 | private func getCombinations(digitString: String) -> [String] { 47 | var arrayOfCharacterSets = [String]() 48 | for (index, character) in digitString.characters.enumerated() { 49 | if let charactersForNumber = getCharactersForNumber(number: "\(character)")?.rawValue { 50 | if index == 0 { 51 | arrayOfCharacterSets = charactersForNumber.characters.map { "\($0)" } 52 | } else { 53 | var tempArray = [String]() 54 | for char in charactersForNumber.characters { 55 | for characterSet in arrayOfCharacterSets { 56 | let newString = characterSet + "\(char)" 57 | tempArray.append(newString) 58 | } 59 | } 60 | arrayOfCharacterSets = tempArray 61 | } 62 | } 63 | } 64 | return arrayOfCharacterSets 65 | } 66 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/LetterCombinationsOfPhoneNumber/Entries/LoganWrightEntry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoganWrightEntry.swift 3 | // CodeChallenge 4 | // 5 | // Created by Logan Wright on 11/8/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // MARK: Entry 12 | 13 | typealias PhoneCombinationsTest = CodeChallengeEntry 14 | let LoganWrightLetterCombinationOfPhoneNumberEntry = 15 | PhoneCombinationsTest(name: "LoganWright") { possibleCombinationsForPhoneNumber(phoneNumber: $0) } 16 | 17 | // MARK: Solution 18 | 19 | private let phoneNumberMap: [String : [String]] = [ 20 | "2" : ["a", "b", "c"], 21 | "3" : ["d", "e", "f"], 22 | "4" : ["g", "h", "i"], 23 | "5" : ["j", "k", "l"], 24 | "6" : ["m", "n", "o"], 25 | "7" : ["p", "q", "r", "s"], 26 | "8" : ["t", "u", "v"], 27 | "9" : ["w", "x", "y", "z"] 28 | ] 29 | 30 | func possibleCombinationsForPhoneNumber(phoneNumber: String) -> [String] { 31 | return phoneNumber 32 | .characters 33 | .map { String($0) } 34 | .flatMap { phoneNumberMap[$0] } 35 | .reduce([]) { combinations, nextSet in 36 | guard !combinations.isEmpty else { return nextSet } 37 | return nextSet.flatMap { letter in 38 | return combinations.map { $0 + letter } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/LetterCombinationsOfPhoneNumber/Entries/juliand665LetterCombinationOfPhoneNumberEntry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // juliand665LetterCombinationOfPhoneNumberEntry.swift 3 | // CodeChallenge 4 | // 5 | // Created by Julian Dunskus on 06.01.17. 6 | // Copyright © 2017 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let juliand665LetterCombinationOfPhoneNumberEntry = CodeChallengeEntry(name: "juliand665", block: combinations) 12 | 13 | private func combinations(of input: String) -> [String] { 14 | var combs: [String] = [""] 15 | 16 | let expanded = input.characters.flatMap { numbersToLetters[$0] } 17 | 18 | for letters in expanded { 19 | combs = combs.flatMap { prev in 20 | letters.map { prev.appending($0) } 21 | } 22 | } 23 | 24 | return combs 25 | } 26 | 27 | private let numbersToLetters: [Character: [String]] = [ // explicit declaration reduces compile time 28 | "0": [" "], 29 | "1": [""], 30 | "2": ["a", "b", "c"], 31 | "3": ["d", "e", "f"], 32 | "4": ["g", "h", "i"], 33 | "5": ["j", "k", "l"], 34 | "6": ["m", "n", "o"], 35 | "7": ["p", "q", "r", "s"], 36 | "8": ["t", "u", "v"], 37 | "9": ["w", "x", "y", "z"], 38 | ] 39 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/LetterCombinationsOfPhoneNumber/LetterCombinationsOfPhoneNumberChallenge.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LetterCombinationsOfPhoneNumberChallenge.swift 3 | // CodeChallenge 4 | // 5 | // Created by Ryan Arana on 11/1/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | https://leetcode.com/problems/letter-combinations-of-a-phone-number/ 13 | Letter Combinations of a Phone Number 14 | 15 | Given a digit string, return all possible letter combinations that the number could represent. 16 | 17 | A mapping of digit to letters (just like on the telephone buttons) is given below. 18 | 19 | ![keypad](http://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Telephone-keypad2.svg/200px-Telephone-keypad2.svg.png) 20 | 21 | Input:Digit string "23" 22 | Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]. 23 | */ 24 | struct LetterCombinationsOfPhoneNumberChallenge: CodeChallengeType { 25 | typealias InputType = String 26 | typealias OutputType = [String] 27 | 28 | let title = "Letter Combinations of Phone Number" 29 | 30 | let entries: [CodeChallengeEntry] = [ 31 | bugKrushaLetterCombinationOfPhoneNumberEntry, 32 | LoganWrightLetterCombinationOfPhoneNumberEntry, 33 | juliand665LetterCombinationOfPhoneNumberEntry 34 | ] 35 | 36 | func generateDataset() -> [InputType] { 37 | return ["23"] 38 | } 39 | 40 | func verifyOutput(_ output: OutputType, forInput input: InputType) -> Bool { 41 | guard let expected = verificationDictionary[input] else { return false } 42 | return output.sorted(by: <) == expected.sorted(by: <) 43 | } 44 | 45 | fileprivate let verificationDictionary = [ 46 | "23": ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"] 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/LongestSubstringWithoutRepeatingCharacters/Entries/juliand665LSWRCEntry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // juliand665LSWRCEntry.swift 3 | // CodeChallenge 4 | // 5 | // Created by Julian Dunskus on 06.01.17. 6 | // Copyright © 2017 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let juliand665LSWRCEntry = CodeChallengeEntry(name: "juliand665", block: lswrc) 12 | 13 | private func lswrc(in input: String) -> Int { 14 | var chars: [Character] = [] 15 | var longest = 0 16 | 17 | for char in input.characters { 18 | if chars.contains(char) { 19 | chars.removeFirst(chars.index(of: char)! + 1) 20 | } 21 | chars.append(char) 22 | longest = max(longest, chars.count) 23 | } 24 | 25 | return longest 26 | } 27 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/LongestSubstringWithoutRepeatingCharacters/LongestSubstringWithoutRepeatingCharactersChallenge.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LongestSubstringWithoutRepeatingCharactersChallenge.swift 3 | // CodeChallenge 4 | // 5 | // Created by Ryan Arana on 11/1/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /* 12 | https://leetcode.com/problems/longest-substring-without-repeating-characters/ 13 | Longest Substring Without Repeating Characters 14 | 15 | Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1. 16 | 17 | */ 18 | struct LongestSubstringWithoutRepeatingCharactersChallenge: CodeChallengeType { 19 | typealias InputType = String 20 | typealias OutputType = Int 21 | 22 | let title = "Longest Substring Without Repeating Characters" 23 | 24 | let entries: [CodeChallengeEntry] = [ 25 | juliand665LSWRCEntry 26 | ] 27 | 28 | func generateDataset() -> [InputType] { 29 | return [ 30 | "abcabcbb", 31 | "bbbbb", 32 | "", 33 | "jdjekjaoefeij" 34 | ] 35 | } 36 | 37 | func verifyOutput(_ output: OutputType, forInput input: InputType) -> Bool { 38 | guard let expected = verificationDictionary[input] else { return false } 39 | return output == expected 40 | } 41 | 42 | fileprivate let verificationDictionary = [ 43 | "abcabcbb": 3, 44 | "bbbbb": 1, 45 | "": 0, 46 | "jdjekjaoefeij": 6 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/TwoSum/Entries/AlexPersian.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlexPersian.swift 3 | // CodeChallenge 4 | // 5 | // Created by Ryan Arana on 10/31/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let alexPersianTwoSumEntry = CodeChallengeEntry(name: "AlexPersian") { input in 12 | for i in 0..(name: "Aranasaurus") { input in 12 | 13 | var max = Datum(0, 0) 14 | let mid = input.target / 2 15 | 16 | for (i, number) in input.numbers.enumerated() { 17 | guard number >= 0 && number <= input.target && number >= mid else { continue } 18 | 19 | if number > max.number { 20 | if let diffIndex = input.numbers.index(of: input.target - number) { 21 | return (diffIndex + 1, i + 1) 22 | } 23 | max = Datum(i, number) 24 | } 25 | } 26 | 27 | return .none 28 | } 29 | 30 | private struct Datum { 31 | let index: Int 32 | let number: Int 33 | 34 | init(_ index: Int, _ number: Int) { 35 | self.index = index 36 | self.number = number 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/TwoSum/Entries/Aryaxt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Aryaxt.swift 3 | // CodeChallenge 4 | // 5 | // Created by Ryan Arana on 10/31/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let aryaxtTwoSumEntry = CodeChallengeEntry(name: "Aryaxt") { input in 12 | for i in 0..(name: "Jazbo") { input in 12 | for (index, num) in input.numbers.enumerated() { 13 | for i in index + 1 ..< input.numbers.count { 14 | if calculate(input.numbers[i], numTwo: num, calculation: +) == input.target { 15 | return (index + 1, i + 1) 16 | } 17 | } 18 | } 19 | return nil 20 | } 21 | 22 | private func calculate(_ numOne: Int, numTwo: Int, calculation: (_ a: Int, _ b: Int) -> Int) -> Int { 23 | return calculation(numOne, numTwo) 24 | } 25 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/TwoSum/Entries/IanKeen.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IanKeen.swift 3 | // CodeChallenge 4 | // 5 | // Created by Ryan Arana on 11/1/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let ianKeenTwoSumEntry = CodeChallengeEntry(name: "IanKeen") { input in 12 | for (index, digit) in input.numbers.enumerated() { 13 | if let other = input.numbers.index(of: input.target - digit) { 14 | return (index + 1, Int(other) + 1) 15 | } 16 | } 17 | return nil 18 | } 19 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/TwoSum/Entries/Logan.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Logan.swift 3 | // CodeChallenge 4 | // 5 | // Created by Ryan Arana on 11/1/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let loganTwoSumEntry = CodeChallengeEntry(name: "Logan") { input in 12 | let lastIdx = input.numbers.count - 1 13 | for firstIdx in 0..(name: "Mosab") { input in 12 | var numbers = input.numbers 13 | var dictionary : [Int : Int] = [:] //Dictionary to hold numbers and indices 14 | 15 | for (index, number) in numbers.enumerated() { 16 | dictionary[number] = index 17 | } 18 | 19 | return findIndices(&dictionary, numbers: &numbers, target: input.target) 20 | } 21 | 22 | private func findIndices(_ map : inout [Int:Int], numbers : inout [Int], target : Int) -> (Int, Int)? 23 | { 24 | for (index, number) in numbers.enumerated() 25 | { 26 | if let index2 = map[abs(number - target)] 27 | { 28 | return (index + 1, index2 + 1) //offset by 1 so we're not 0 based 29 | } 30 | } 31 | 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/TwoSum/Entries/Nuudles.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Nuudles.swift 3 | // CodeChallenge 4 | // 5 | // Created by Ryan Arana on 11/1/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let nuudlesTwoSumEntry = CodeChallengeEntry(name: "Nuudles") { input in 12 | var numberToIndex: [Int: Int] = [:] 13 | for (index, number) in input.numbers.enumerated() 14 | { 15 | if let pairIndex = numberToIndex[input.target - number] 16 | { 17 | return (first: pairIndex + 1, second: index + 1) // Why not 0 index? Silly 18 | } 19 | numberToIndex[number] = index 20 | } 21 | return nil 22 | } 23 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/TwoSum/Entries/juliand665TwoSumEntry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // juliand665TwoSumEntry.swift 3 | // CodeChallenge 4 | // 5 | // Created by Julian Dunskus on 06.01.17. 6 | // Copyright © 2017 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let juliand665TwoSumEntryNice = CodeChallengeEntry(name: "juliand665 (swiftier)", block: findPairNice) 12 | 13 | private func findPairNice(in nums: [Int], targeting target: Int) -> (Int, Int)? { // O(log n) 14 | var numbers = nums.enumerated().sorted() { $0.1 < $1.1 } // I assume the closure is making it slower 15 | var i1 = numbers.startIndex 16 | var i2 = numbers.endIndex - 1 17 | 18 | // how to C 19 | while true { // solution guaranteed 20 | let n1 = numbers[i1] 21 | let n2 = numbers[i2] 22 | let sum = n1.element + n2.element 23 | if sum == target { 24 | return (n1.offset + 1, n2.offset + 1) // O(1) 25 | } else if sum < target { 26 | i1 += 1 27 | } else { 28 | i2 -= 1 29 | } 30 | } 31 | } 32 | 33 | let juliand665TwoSumEntryFast = CodeChallengeEntry(name: "juliand665 (swifter)", block: findPairFast) 34 | 35 | private func findPairFast(in nums: [Int], targeting target: Int) -> (Int, Int)? { // O(log n) 36 | 37 | var numbers = nums.sorted() 38 | var i1 = numbers.startIndex 39 | var i2 = numbers.endIndex - 1 40 | 41 | // how to C 42 | while true { // solution guaranteed 43 | let n1 = numbers[i1] 44 | let n2 = numbers[i2] 45 | let sum = n1 + n2 46 | if sum == target { 47 | return (nums.index(of: n1)! + 1, nums.index(of: n2)! + 1) // O(n) 48 | // darn you, indices! sorting .enumerated() instead seems to be slower :( 49 | } else if sum < target { 50 | i1 += 1 51 | } else { 52 | i2 -= 1 53 | } 54 | } 55 | } 56 | 57 | let juliand665TwoSumEntryUgly = CodeChallengeEntry(name: "juliand665 (hardcoded)", block: findPairUgly) 58 | 59 | private func findPairUgly(in nums: [Int], targeting target: Int) -> (Int, Int)? { // O(n) 60 | 61 | var first: Int? 62 | 63 | for (index, num) in nums.enumerated() { 64 | if num > 2 { 65 | if let first = first { 66 | return (first + 1, index + 1) // why would you not want zero-based indices? 67 | } 68 | first = index 69 | } 70 | } 71 | return nil 72 | } 73 | -------------------------------------------------------------------------------- /CodeChallenge/Challenges/TwoSum/TwoSumChallenge.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TwoSumChallenge.swift 3 | // CodeChallenge 4 | // 5 | // Created by Ryan Arana on 10/28/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /* 12 | Given an array of integers, find two numbers such that they add up to a specific target number. 13 | 14 | The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based. 15 | 16 | You may assume that each input would have exactly one solution. 17 | 18 | Input: numbers={2, 7, 11, 15}, target=9 19 | Output: index1=1, index2=2 20 | */ 21 | struct TwoSumChallenge: CodeChallengeType { 22 | typealias InputType = (numbers: [Int], target: Int) 23 | typealias OutputType = (first: Int, second: Int)? 24 | 25 | let title = "Two Sum Challenge" 26 | 27 | let entries: [CodeChallengeEntry] = [ 28 | alexPersianTwoSumEntry, 29 | aranasaurusTwoSumEntry, 30 | aryaxtTwoSumEntry, 31 | bugkrushaTwoSumEntry, 32 | ianKeenTwoSumEntry, 33 | loganTwoSumEntry, 34 | mosabTwoSumEntry, 35 | nuudlesTwoSumEntry, 36 | juliand665TwoSumEntryFast, 37 | juliand665TwoSumEntryUgly 38 | ] 39 | 40 | func generateDataset() -> [InputType] { 41 | return [InputType(numbers: numbers, target: target)] 42 | } 43 | 44 | func verifyOutput(_ output: OutputType, forInput input: InputType) -> Bool { 45 | guard let output = output else { return false } 46 | return (numbers[output.first - 1] + numbers[output.second - 1] == target) 47 | } 48 | } 49 | 50 | private let target = 9 51 | private let numbers: [Int] = { 52 | let count = 1000 53 | var numbers = [Int]() 54 | for _ in 1...count { 55 | // target / 3 so that no 2 of these can add together to make target 56 | numbers.append(Int(arc4random_uniform(UInt32(target/3)))) 57 | } 58 | 59 | let min = (target / 2) 60 | let max = (target - min) 61 | numbers.insert(min, at: Int(arc4random_uniform(UInt32(numbers.count)))) 62 | numbers.insert(max, at: Int(arc4random_uniform(UInt32(numbers.count)))) 63 | return numbers 64 | }() 65 | -------------------------------------------------------------------------------- /CodeChallenge/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /CodeChallengeTests/Base/CodeChallengeTestCase.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CodeChallengeTestCase.swift 3 | // CodeChallenge 4 | // 5 | // Created by Ryan Arana on 10/31/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import CodeChallenge 11 | 12 | class CodeChallengeTestCase: XCTestCase { 13 | /** 14 | Run all of the entries for the given challenge and print the results as nicely as we can to the console. 15 | */ 16 | func runTestsForChallenge(_ challenge: ChallengeType) { 17 | // Do some formatting 18 | let charWidth = 116 19 | var headingText = "Calculating results for '\(challenge.title)'" 20 | let headingTextInnerCount = headingText.characters.count + 2 21 | headingText = headingText.padWithCharacter(" ", toLength: headingTextInnerCount) 22 | headingText = headingText.padWithCharacter("=", toLength: charWidth) 23 | 24 | let footingInnerText = "fin." 25 | var footingText = footingInnerText 26 | footingText = footingText.padWithCharacter(" ", toLength: headingTextInnerCount) 27 | footingText = footingText.padWithCharacter("=", toLength: charWidth) 28 | 29 | print(headingText) 30 | let results = challenge.runAll() 31 | printResults(results) 32 | print(footingText) 33 | } 34 | 35 | fileprivate func printResults(_ results: [AccumulatedChallengeResult]) { 36 | let formatter = NumberFormatter() 37 | formatter.numberStyle = .decimal 38 | formatter.minimumFractionDigits = 5 39 | formatter.maximumFractionDigits = 5 40 | 41 | var names = [String]() 42 | for (i, result) in results.enumerated() { 43 | names.append("\(i+1). \(result.name)") 44 | } 45 | let maxNameLength = names.reduce(0) { max($0, $1.characters.count) } 46 | 47 | for (i, result) in results.enumerated() { 48 | // Add spaces to the name to make the avg column line up with all results 49 | var nameAndNumber = names[i] 50 | while nameAndNumber.characters.count < maxNameLength { 51 | nameAndNumber.append(" ") 52 | } 53 | print("\(nameAndNumber) avg: \(formatter.string(from: NSDecimalNumber(decimal: Decimal(result.averageTime)))!)s\ttotal: \(formatter.string(from: NSDecimalNumber(decimal: Decimal(result.totalTime)))!)s\t[\(result.successRate * 100)% success rate]") 54 | } 55 | } 56 | } 57 | 58 | private extension String { 59 | func padWithCharacter(_ char: Character, toLength length: Int) -> String { 60 | let textLength = characters.count 61 | let paddedCharsCount = (length - textLength) / 2 62 | let paddedChars = String(repeating: String(char), count: paddedCharsCount) 63 | var retValue = "\(paddedChars)\(self)\(paddedChars)" 64 | while retValue.characters.count < length { 65 | retValue.append(char) 66 | } 67 | return retValue 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /CodeChallengeTests/Base/ExampleChallengeTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleChallengeTests.swift 3 | // CodeChallenge 4 | // 5 | // Created by Ryan Arana on 10/31/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | @testable import CodeChallenge 12 | 13 | class ExampleChallengeTests: CodeChallengeTestCase { 14 | func testExampleEntries() { 15 | runTestsForChallenge(ExampleCodeChallenge()) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CodeChallengeTests/Challenges/BulletMatchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BulletMatchTests.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 XCTest 10 | @testable import CodeChallenge 11 | 12 | class BulletMatchTests: CodeChallengeTestCase { 13 | func testBulletMatch() { 14 | runTestsForChallenge(BulletChallenge()) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CodeChallengeTests/Challenges/ClockTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ClockTests.swift 3 | // CodeChallenge 4 | // 5 | // Created by Jon-Tait Beason on 12/13/16. 6 | // Copyright © 2016 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import CodeChallenge 11 | 12 | class ClockTests: CodeChallengeTestCase { 13 | func testClockEntries() { 14 | runTestsForChallenge(ClockChallenge()) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CodeChallengeTests/Challenges/LetterCombinationsOfPhoneNumberTests.swift: -------------------------------------------------------------------------------- 1 | 2 | import XCTest 3 | @testable import CodeChallenge 4 | 5 | class LetterCombinationsOfPhoneNumberTests: CodeChallengeTestCase { 6 | func testLetterCombinationsOfPhoneNumberEntries() { 7 | runTestsForChallenge(LetterCombinationsOfPhoneNumberChallenge()) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /CodeChallengeTests/Challenges/LongestSubstringWithoutRepeatingCharactersTests.swift: -------------------------------------------------------------------------------- 1 | 2 | import XCTest 3 | @testable import CodeChallenge 4 | 5 | class LongestSubstringWithoutRepeatingCharactersTests: CodeChallengeTestCase { 6 | func testLetterCombinationsOfPhoneNumberEntries() { 7 | runTestsForChallenge(LongestSubstringWithoutRepeatingCharactersChallenge()) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /CodeChallengeTests/Challenges/TwoSumTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TwoSumTests.swift 3 | // CodeChallenge 4 | // 5 | // Created by Ryan Arana on 10/31/15. 6 | // Copyright © 2015 iosdevelopers. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | @testable import CodeChallenge 12 | 13 | class TwoSumTests: CodeChallengeTestCase { 14 | func testTwoSumEntries() { 15 | runTestsForChallenge(TwoSumChallenge()) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CodeChallengeTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 iOS Developers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # code-challenges [![Build Status](https://travis-ci.org/iosdevelopershq/code-challenges.svg?branch=master)](https://travis-ci.org/iosdevelopershq/code-challenges) 2 | Weekly(?) code challenges for the community to complete for learning and fun. 3 | 4 | # Submitting an Entry 5 | If you'd like to submit a solution to a challenge you'll do so by creating an instance of `CodeChallengeEntry` which specifies your name and a code block to run with your solution in it. 6 | 7 | Every challenge will have an implementation of `CodeChallengeType` which defines the `InputType` and `OutputType` that your solution block will need to take/return. This `CodeChallengeType` implementation should also include comments in it that describe the challenge itself, so it is your one-stop shop for figuring out what you need to do to successfully complete the challenge. 8 | 9 | Here's step-by-step instructions on how to get an entry submitted: 10 | 11 | 1. Fork the repo and clone it to your machine 12 | 2. Open the Xcode project and navigate to the CodeChallenge -> Challenges folder of the Challenge you'd like to submit an entry for. 13 | 3. Create a new file to put your solution in. Typically it should be named `yourUsername-challengeNameEntry.swift`. 14 | 4. In that file instantiate a `CodeChallengeEntry` object into a global named using the following format: 15 | 16 | ``` 17 | let usernameChallengeNameEntry = CodeChallengeEntry(name: "username") { input in 18 | // Your implementation here, returning the appropriate `OutputType` 19 | } 20 | ``` 21 | 5. Navigate to the `ChallengeNameChallenge.swift` file and add the global instance you created to the `Challenge`'s `entries` array. 22 | 6. To test your implementation and see how it compares to any previously submitted solutions just run the tests (⌘+U)! 23 | 7. Once you're happy with your results commit and push your changes to your fork and submit a Pull-Request back upstream. 24 | 25 | ## Some notes on etiquette 26 | Given that everybody's submissions all run in the same module and namespace it's good to take a few things into account while writing your solution: 27 | 28 | * It's a great idea to have additional `functions` or data structures to use in your implementation but please, if you do, mark them `private` so that they don't pollute the global namespace. 29 | * Don't `print` _anything_. These will probably get flagged when you submit your PR, but save us a step and just don't commit 'em (or use custom breakpoints to do the trick ;) )! Currently we use the debug console from the test runs to output the results of the challenge runs, so the less console noise the better. 30 | 31 | If you're just wanting to submit entries to an existing challenge, you're done! The rest of this README is for folks wanting to create new challenges, if that's you... read on! 32 | 33 | 34 | 35 | --- 36 | 37 | # Submitting a new Challenge 38 | 39 | In order to submit a new challenge you'll need to create an implementation of `CodeChallengeType`. This protocol defines: 40 | * The input and output types for the entries' `block` property 41 | * A title for the challenge 42 | * The Array of entries that will be run (you just have to make an empty array of the appropriate type: `[CodeChallengeEntry]`) 43 | * A function to generate the dataset which is just an array of `InputTypes` which will be fed to each entry over multiple iterations to run the challenge. 44 | * A function to verify the output of the entry for a given input. 45 | 46 | Your implementation should be named using the following format: `FooChallenge` for a Challenge named Foo. You should also include the description of the challenge as comments in this implementation file. 47 | 48 | This Challenge implementation should be created in a subfolder of the Challenges directory and, in this case, the subfolder would be named `Foo` and the file would be `FooChallenge.swift`. 49 | 50 | Check out `CodeChallenge/Base/ExampleCodeChallenge.swift` for a very simple challenge, or the TwoSum challenge for a bit more involved example. 51 | 52 | Last step is you'll need to add a test file for this challenge. The test mostly writes itself. Just create a new test in `CodeChallengeTests/Challenges/FooTests.swift` which will look approximately like this: 53 | 54 | ``` 55 | @testable import CodeChallenge 56 | 57 | class FooTests: CodeChallengeTestCase { 58 | func testFooEntries() { 59 | runTestsForChallenge(FooChallenge()) 60 | } 61 | } 62 | ``` 63 | 64 | That's it! Submit a PR and watch everyone toil over your challenge! 65 | --------------------------------------------------------------------------------