Skip to content

Instantly share code, notes, and snippets.

@jlehikoinen
Created February 27, 2015 05:14
Show Gist options
  • Save jlehikoinen/91ee603b72f254d8c0ea to your computer and use it in GitHub Desktop.
Save jlehikoinen/91ee603b72f254d8c0ea to your computer and use it in GitHub Desktop.
Swift exercise - Pairs
#!/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