Created
February 27, 2015 05:14
-
-
Save jlehikoinen/91ee603b72f254d8c0ea to your computer and use it in GitHub Desktop.
Swift exercise - Pairs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env xcrun swift | |
// pairs.swift | |
// | |
// Created by Lehikoinen Janne on 06/10/14. | |
// Copyright (c) 2014 FMC. All rights reserved. | |
// | |
// Note! This script runs for 5+ minutes! | |
// Works with Xcode 6.1 Beta | |
// Answer: Total number of (99%) matches: 5553 | |
// Links: | |
// http://reaktor.fi/careers/rakkauden-fast-track/ | |
// http://reaktor.fi/wp-content/uploads/2014/08/fast_track_generoitu_nimilista.txt | |
/* | |
Combination stuff: | |
How many different pairs (2 people) can be formed from 1001 people? | |
Combination (1001,2) => 1001!/(2!(1001-2)!) => 500500 | |
Smaller examples: | |
Combination (5,2) => 5!/(2!(5-2)!) => 10 | |
Combination (10,2) => 10!/(2!(10-2)!) => 45 | |
*/ | |
/* | |
PAIRS addition logic | |
[[P: 0], [A: 2], [I: 3], [R: 1], [S: 1]] => 5 numbers | |
[0 + 2 = 2, 2 + 3 = 5, 3 + 1 = 4, 1 + 1 = 2] => 4 numbers | |
[2 + 5 = 7, 5 + 4 = 9, 4 + 2 = 6] => 3 numbers | |
[7 + 9 = 16 => 1 + 6 = 7, 7 + 6 = 13 => 1 + 3 = 4] => 2 numbers | |
[7, 4] => 74% | |
*/ | |
import Cocoa | |
import Foundation | |
// Helper funcs | |
// This function downloads 'names' text file and puts names to an array, | |
// copies names from original array to a new array and skips empty strings | |
// Returns an array of strings (names), e.g ["Emmi-Maria Airamo", "Kössi Kalervo", ...] | |
func namesUrlToArray() -> [String] { | |
// URL variables | |
let namesUrlString = "http://reaktor.fi/wp-content/uploads/2014/08/fast_track_generoitu_nimilista.txt" | |
let url = NSURL(string: namesUrlString) | |
let request = NSURLRequest(URL: url!) | |
var enc: NSStringEncoding = NSUTF8StringEncoding | |
var content = "" | |
var error: NSError? | |
var response: NSURLResponse? | |
// Use NSURLConnection to make a test connection to target URL | |
var responseData = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: nil) as NSData? | |
// Check if target URL can be found | |
if let httpResponse = response as? NSHTTPURLResponse { | |
let statusCode = httpResponse.statusCode | |
if (statusCode == 200) { | |
// Fetch names list | |
content = String(contentsOfURL: url!, usedEncoding:&enc, error:&error)! | |
} else { | |
println("Download failed! HTTP status code: \(statusCode)") | |
exit(1) | |
} | |
} | |
// Put names to an array | |
let namesArray: [String] = content.componentsSeparatedByString("\n") | |
// Create new empty Array | |
var newArray = [String]() | |
for name in namesArray { | |
if !(name.isEmpty) { | |
newArray.append(name) | |
} | |
} | |
return newArray | |
} | |
// This function calculates number of PAIRS characters in two names | |
// Returns dictionary like ["P": 1, "A": 2, "I": 3, "R": 4, "S": 5] | |
func numberOfPairsChars(name: String) -> Dictionary<String, Int> { | |
// PAIRS counters | |
var pCounter = 0, aCounter = 0, iCounter = 0, rCounter = 0, sCounter = 0 | |
// Default counter | |
var defaultCounter = 0 | |
// Create empty PAIRS dict | |
var pairsDict = ["P": 0, "A": 0, "I": 0, "R": 0, "S": 0] | |
for char in name { | |
switch char { | |
case "p": | |
pCounter += 1 | |
pairsDict["P"] = pCounter | |
case "a": | |
aCounter += 1 | |
pairsDict["A"] = aCounter | |
case "i": | |
iCounter += 1 | |
pairsDict["I"] = iCounter | |
case "r": | |
rCounter += 1 | |
pairsDict["R"] = rCounter | |
case "s": | |
sCounter += 1 | |
pairsDict["S"] = sCounter | |
default: | |
defaultCounter += 1 | |
} | |
} | |
return pairsDict | |
} | |
// This function divides two digit number into parts which is between 10 and 18 and | |
// calculates the sum of those two numbers (e.g. 15 => 1 + 5 = 6) | |
// Returns the sum of two numbers (Int) | |
func calculateSumOfTwoDigits(originalNumber: Int) -> Int { | |
// Supposition: number IS between 10 and 18 | |
let firstDigit = 1 // Always 1 | |
let secondDigit = originalNumber - 10 | |
return firstDigit + secondDigit | |
} | |
// This function takes an array as a parameter and calculates sum of two adjacent numbers (Int) | |
// Returns an array which contains (array.count - 1) numbers (Int) | |
func createSumOfFactorsArray(charNumbers: [Int]) -> [Int] { | |
var sumOfTwo = 0 | |
var returnArray: Array = [Int]() | |
let charNumbersCount = charNumbers.count - 1 | |
for index in 0..<charNumbersCount { | |
sumOfTwo = charNumbers[index] + charNumbers[index + 1] | |
if sumOfTwo < 10 { | |
returnArray.insert(sumOfTwo, atIndex: index) | |
} else { | |
// Call helper function for calculation | |
sumOfTwo = calculateSumOfTwoDigits(sumOfTwo) | |
returnArray.insert(sumOfTwo, atIndex: index) | |
} | |
} | |
return returnArray | |
} | |
// Main logic | |
func mainHook () { | |
// Put all names to an array | |
var namesArray = namesUrlToArray() | |
// Helper index for array iteration and element removal | |
var helperIndex = 0 | |
// Final counters | |
var matchCounter = 0 | |
var totalCounter = 0 | |
// Go through the names array with enumeration | |
for (index, firstName) in enumerate(namesArray) { | |
// Go through the names array 2nd time to go through all combinations | |
for secondName in namesArray { | |
// ...but skip the original (identical) name | |
if (firstName != secondName) { | |
// Concatenate two strings for PAIRS calculation | |
let catName = firstName + secondName | |
// Get PAIRS numbers in dictionary | |
let pairsChars = numberOfPairsChars(catName) | |
// println("Pairs chars: \(pairsChars)") | |
// Put PAIRS dictionary (values) numbers to a new array | |
// for iteration => [1, 2, 3, 2, 1] | |
var iterationArray = Array(pairsChars.values) | |
// Three array iterations | |
for i in 1...3 { | |
iterationArray = createSumOfFactorsArray(iterationArray) | |
// Result: an array with only two numbers e.g [7, 3] | |
} | |
// Concatenate previous two numbers | |
let finalPercentage = String(iterationArray[0]) + String(iterationArray[1]) | |
let finalPercentageInt: Int! = finalPercentage.toInt() | |
// Print only name pairs with 99% match | |
if finalPercentageInt == 99 { | |
println("\(firstName) & \(secondName) => \(finalPercentage)%") | |
// Count only 99% combinations | |
matchCounter += 1 | |
} | |
// Count every combination | |
totalCounter += 1 | |
} | |
} | |
// helperIndex needed for removing elements from array | |
namesArray.removeAtIndex(helperIndex - index) | |
helperIndex += 1 | |
} | |
// Print summary | |
println("Total number of combinations: \(totalCounter)") // 500500 | |
println("Total number of (99%) matches: \(matchCounter)") // 5553 | |
} | |
// Run mainHook | |
mainHook() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment