Skip to content

Instantly share code, notes, and snippets.

@erica
Last active December 12, 2017 22:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erica/8f35b8f37768b50d6a756f6a09ee0bb7 to your computer and use it in GitHub Desktop.
Save erica/8f35b8f37768b50d6a756f6a09ee0bb7 to your computer and use it in GitHub Desktop.
func day1(_ string: String) -> Int {
return string
.indices
.filter({ idx in
guard idx != string.index(before: string.endIndex)
else { return string[string.startIndex] == string[idx] }
return string[idx] == string[string.index(after: idx)] })
.map({ Int(String(string[$0])) ?? 0 })
.reduce(0, +)
}
["57276274387944537823652626177853384411146325384494935924454336611953119173638191671326254832624841593421667683474349154668177743437745965461678636631863541462893547616877914914662358836365421198516263335926544716331814125295712581158399321372683742773423626286669759415959391374744214595682795818615532673877868424196926497731144319736445141728123322962547288572434564178492753681842244888368542423832228211172842456231275738182764232265933625119312598161192193214898949267765417468348935134618964683127194391796165368145548814473129857697989322621368744725685183346825333247866734735894493395218781464346951777873929898961358796274889826894529599645442657423438562423853247543621565468819799931598754753467593832328147439341586125262733737128386961596394728159719292787597426898945198788211417854662948358422729471312456437778978749753927251431677533575752312447488337156956217451965643454445329758327129966657189332824969141448538681979632611199385896965946849725421978137753366252459914913637858783146735469758716752765718189175583956476935185985918536318424248425426398158278111751711911227818826766177996223718837428972784328925743869885232266127727865267881592395643836999244218345184474613129823933659422223685422732186536199153988717455568523781673393698356967355875123554797755491181791593156433735591529495984256519631187849654633243225118132152549712643273819314433877592644693826861523243946998615722951182474773173215527598949553185313259992227879964482121769617218685394776778423378182462422788277997523913176326468957342296368178321958626168785578977414537368686438348124283789748775163821457641135163495649331144436157836647912852483177542224864952271874645274572426458614384917923623627532487625396914111582754953944965462576624728896917137599778828769958626788685374749661741223741834844643725486925886933118382649581481351844943368484853956759877215252766294896496444835264357169642341291412768946589781812493421379575569593678354241223363739129813633236996588711791919421574583924743119867622229659211793468744163297478952475933163259769578345894367855534294493613767564497137369969315192443795512585"].forEach {
print("Answer for \($0) is \(day1($0))")
}
// Part II
import Foundation
func day1(_ string: String) -> Int {
let halfcount = string.count / 2
return string
.indices
.filter({ idx in
let lastIdx = string.index(before: string.endIndex)
guard idx != lastIdx
else {
return string[lastIdx] == string[string.index(string.startIndex, offsetBy: halfcount - 1)] }
let offset = (idx.encodedOffset + halfcount) % string.count
return string[idx] == string[string.index(string.startIndex, offsetBy: offset)] })
.map({ Int(String(string[$0])) ?? 0 })
.reduce(0, +)
}
["1212", "1221", "123425", "123123", "12131415"].forEach {
print("Answer for \($0) is \(day1($0))")
}
import Foundation
let path = Bundle.main.path(forResource: "test", ofType: "txt")!
let str = try! String(contentsOfFile: path)
let lines = str
.components(separatedBy: .newlines)
.filter({ !$0.isEmpty })
let numberLines = lines.map({ (line: String) -> [Int] in
return line.components(separatedBy: .whitespaces)
.filter({ !$0.isEmpty })
.map({ Int($0) ?? .max })
})
print(numberLines.map({ $0.max()! - $0.min()! })
.reduce(0, +))
// Part II
import Foundation
let path = Bundle.main.path(forResource: "test", ofType: "txt")!
let str = try! String(contentsOfFile: path)
let lines = str
.components(separatedBy: .newlines)
.filter({ !$0.isEmpty })
let numberLines = lines.map({ (line: String) -> [Int] in
return line.components(separatedBy: .whitespaces)
.filter({ !$0.isEmpty })
.map({ Int($0) ?? .max })
})
func division(_ line: [Int]) -> Int {
guard line.count > 1 else { fatalError("Logic error") }
let (first, rest) = (line.first!, Array(line.dropFirst()))
for each in rest {
if first % each == 0 { return first / each }
if each % first == 0 { return each / first }
}
return division(rest)
}
print(numberLines.map(division)
.reduce(0, +))
for n in [1024, 12, 23, 312051] {
for i in sequence(first: 1, next: { $0 + 2 }) {
// Find least bounding square that contains number
let boundingSize = i * i
if boundingSize >= n {
// Start of the outer edge sequence
let firstValue = (i - 2) * (i - 2) + 1
// Calculate distance to center
let radius = (i - 1) / 2
// The first number is always positioned at the
// bottom right, one up from the bottom
var current = radius - 1
// The `direction` differential is the basis of
// the triangle wave generator. It flips at the
// minimum (-radius) and maximum (radius) offsets
var direction = -1
// One trip through the outer edge will be
// sufficient to find the value
for value in firstValue ... boundingSize {
if value == n {
print("Result for \(n) is \(radius + abs(current))")
break
}
// Generate the next value in the triangle
// wave pattern to determine the distance
// from the center
current += direction
if abs(current) == radius { direction *= -1 }
}
break
}
}
}
// Part II
let side = 9 // any odd number that's big enough
let middle: Int = (side - 1) / 2
var narray = Array(repeating: Array(repeating: 0, count: side), count: side)
var (nx, ny) = (side - 1, side - 1)
var (minx, maxx) = (0, side - 1)
var (miny, maxy) = (0, side - 1)
var (dx, dy) = (-1, 0)
enum Sides { case top , right, bottom, left }
var whichSide = Sides.bottom
narray[(side - 1) / 2][(side - 1) / 2] = 1
for n in stride(from: side * side, through: 1, by: -1) {
narray[ny][nx] = n
switch (nx, ny, whichSide) {
case (minx, _, .bottom):
(dx, dy, whichSide) = (0, -1, .left)
case (_, miny, .left):
(dx, dy, whichSide) = (1, 0, .top)
case (maxx, _, .top):
(dx, dy, whichSide) = (0, 1, .right)
case (_, maxy - 1, .right):
(dx, dy, whichSide) = (-1, 0, .bottom)
(minx, miny) = (minx + 1, miny + 1)
(maxx, maxy) = (maxx - 1, maxx - 1)
default:
break
}
(nx, ny) = (nx + dx, ny + dy)
}
func locationOf(_ targetValue: Int, in array: [[Int]]) -> (y: Int, x: Int)? {
for (lineNumber, line) in array.enumerated() {
if line.contains(targetValue) {
return (lineNumber, line.index(of: targetValue)!)
}
}
return nil
}
var array = Array(repeating: Array(repeating: 0, count: side), count: side)
array[middle][middle] = 1
let topValue = 312051
for idx in stride(from: 2, through: side * side, by: 1) {
let (y, x) = locationOf(idx, in: narray)!
// print(idx, y, x)
var sum = 0
for j in stride(from: -1, through: 1, by: 1) {
for i in stride(from: -1, through: 1, by: 1) {
if (y + j) < side && (y + j) >= 0 &&
(x + i) < side && (x + i) >= 0
{
sum += array[y + j][x + i]
}
}
}
array[y][x] = sum
if (sum > topValue) {
print("SOLUTION: \(sum)")
break
}
}
import Foundation
func test(_ words: [String]) -> String? {
guard !words.isEmpty else { return "OK" }
var words = words
let word = words.removeFirst()
if words.contains(word) { return nil }
return test(words)
}
var tests = ["aa bb cc dd ee", "aa bb cc dd aa", "aa bb cc dd aaa"]
print(tests.map({ $0.components(separatedBy: .whitespaces)}).flatMap(test).count)
let path = Bundle.main.path(forResource: "test", ofType: "txt")!
let str = try! String(contentsOfFile: path)
tests = str
.components(separatedBy: .newlines)
.filter({ !$0.isEmpty })
print(tests.map({ $0.components(separatedBy: .whitespaces)}).flatMap(test).count)
// print(tests)
// Part II
import Foundation
func findAnagram(_ word: String, _ array: [String]) -> Bool {
for eachString in array {
if word.count != eachString.count { continue }
var characterBag = Array(eachString.characters)
for c in word {
if let idx = characterBag.index(of: c) {
characterBag.remove(at: idx)
}
}
if characterBag.isEmpty { return true }
}
return false
}
func test(_ words: [String]) -> String? {
guard !words.isEmpty else { return "Yep" }
var words = words
let word = words.removeFirst()
if findAnagram(word, words) { return nil }
return test(words)
}
var tests = ["abcde fghij", "abcde xyz ecdab", "a ab abc abd abf abj", "iiii oiii ooii oooi oooo", "oiii ioii iioi iiio"]
print(tests.map({ $0.components(separatedBy: .whitespaces)}).flatMap(test).count)
let path = Bundle.main.path(forResource: "test", ofType: "txt")!
let str = try! String(contentsOfFile: path)
tests = str
.components(separatedBy: .newlines)
.filter({ !$0.isEmpty })
print(tests.map({ $0.components(separatedBy: .whitespaces)}).flatMap(test).count)
// print(tests)
import Foundation
// var array = [0, 3, 0, 1, -3]
var array = [1, 2, -1, -2, 1, -3, -1, 1, 0, -4, -8, -7, -2, 0, -2, -11, 1, -2, 0, 0, -11, -17, -18, -1, -12, -21, -15, -24, -8, -5, 0, -17, -8, -5, -24, -16, -16, -21, -5, -7, -13, -11, -2, -27, -29, -38, -2, 2, -27, -10, -9, -32, -3, -1, -6, -50, -21, -47, -47, -16, -48, -19, -53, -25, -57, -42, -64, -21, -59, -3, -51, -66, -44, -42, -45, -6, -18, -28, -18, -48, -21, -15, -4, -10, -49, -72, -56, -47, -41, -74, -38, -60, -28, -10, -32, -1, -9, -40, -10, -6, -58, -92, -8, -94, -99, -93, -33, -31, -84, -28, -39, -105, -23, -76, -35, -71, -100, -102, -29, -86, -70, -30, -8, 0, -109, 1, -22, -24, -92, -21, -103, -127, -67, 0, -68, -31, -71, -111, -26, -123, -39, -116, -15, -86, -85, -137, -127, -134, -145, -29, -123, -19, -43, -152, -122, -148, -129, -97, -39, -28, -49, -93, -110, -103, -130, 1, -114, -146, -99, -128, -118, -32, -48, -115, -155, -26, -37, -65, -48, -71, -6, -137, -178, -111, -139, -127, -160, -172, -98, -38, -156, -11, -62, -187, -53, 2, -117, -3, -31, -143, -41, -47, -169, -162, -158, -12, -69, -114, -180, -155, -125, -64, -176, -184, -202, -116, -74, -98, -205, -84, -152, -54, -102, -165, -138, -140, -180, -96, -98, -109, -81, -199, -137, -56, -74, -179, -175, -114, -124, -15, -234, -219, -51, -41, -144, -134, -161, -59, -128, -71, -22, -165, -222, -70, -65, -51, -43, -86, -198, -238, -119, -31, -195, -87, -102, -30, -73, -76, -153, -238, -8, -73, -63, -148, -42, -16, -228, -243, -235, -160, -107, -235, -29, -188, -202, -42, -215, -159, -134, -172, -263, -188, -124, -34, -206, -15, -138, -184, -20, -32, -271, -103, -203, -129, -177, -69, -107, -265, -68, -299, -161, -148, -182, 0, -207, -106, -68, -92, -53, -52, -288, -3, -211, -143, -204, -126, -152, -106, -232, -153, -234, -62, -124, -131, -42, -297, -332, -188, -115, -100, -173, -52, -115, -296, -301, -312, -292, -2, -321, -178, -174, -244, -309, -161, -346, -251, -157, -325, -292, -159, -95, 0, -124, -69, -324, -223, -89, -359, -242, -239, 1, -39, -204, -287, -142, -123, -363, -218, -197, -136, -20, -304, -281, -83, -7, -129, -315, -76, -349, -141, -318, -369, -346, -161, -141, -110, -279, -5, -86, -348, -59, -255, -266, -355, -110, -14, -339, -109, -44, -38, -10, -164, -214, -265, -412, -72, -413, -271, -343, -124, -352, -304, -124, -381, -258, -8, -235, -288, -27, -296, -179, -392, -336, -255, -114, -15, -407, -296, -29, -352, -419, -190, -308, -2, -430, -157, -379, -220, -179, -77, -337, -61, -48, -64, -197, -408, -284, -84, -409, -243, -316, -77, -77, -428, -432, -182, -437, -254, -50, -260, -301, -28, -33, -335, -348, -240, -287, -436, -225, -221, -198, -190, -50, -87, -161, -408, 0, -14, -225, -105, -188, -290, -349, -57, -45, -20, -384, -36, -264, -359, -52, -21, -328, -194, -432, -113, -475, -391, -86, -407, -18, -435, -206, -317, -254, -369, -373, -127, -405, -309, -154, -480, -271, -71, -306, -381, -252, -253, -420, -40, -349, -403, -44, -256, -33, -429, -10, -461, -405, -216, -329, -201, -498, -392, -149, -419, -85, -408, -248, -88, -322, -438, -381, -100, -445, -412, -215, -220, -83, -436, -411, -555, -372, -232, -309, -151, -214, -219, -268, -123, -90, -241, -508, -134, -74, -296, -505, -240, -161, -477, -63, -118, -293, -69, -197, -88, -520, -170, -37, -114, -234, -36, -225, -116, -36, -195, -363, -75, -137, -7, -506, -124, -556, -15, -327, -74, -367, -505, -29, -296, -281, -180, -420, -119, -449, -502, -204, -294, -484, -515, -74, -337, -256, -479, -471, -27, -614, -354, -369, -607, -244, -578, -195, -215, -407, -552, -247, -514, -434, -291, -521, -99, -598, -292, -400, -594, -381, -602, -260, -79, -441, -444, -146, -451, -502, -215, -81, -577, -652, -507, -264, -588, -431, -401, -103, -282, -125, -259, -615, -321, -271, -84, -84, -323, -650, -79, -289, -522, -129, -343, -441, -186, -561, -244, -186, -296, -272, -258, -308, -390, -677, -367, -186, -604, -104, -481, -394, -31, -663, -493, -608, -142, -86, -356, -581, -131, -11, -92, -258, -552, -176, -244, -208, -564, -9, -558, -256, -439, -460, -641, -457, -715, -328, -291, -172, -380, -406, 0, -123, -286, -301, -375, -358, -607, -599, -670, -94, -143, -65, -201, -486, -394, -405, -671, -673, -564, -137, -200, -148, -644, -589, -643, -155, -714, -602, -54, -746, -403, -520, -446, -646, -680, -474, -431, -762, -712, -554, -187, -242, -242, -595, -66, -610, -378, -430, -595, -485, -467, -434, -663, -375, -81, -503, -688, -651, -17, -10, -184, -361, -165, -785, -61, -211, -140, -740, -126, -549, -222, -611, -557, -786, -525, -431, -111, -287, -131, -574, -212, -733, -223, -734, -275, -524, -295, -541, -240, -162, -750, -350, -486, -672, -579, -410, -737, -544, -728, -516, -163, -227, -249, -177, -522, -363, -190, -613, -148, -810, -593, -702, -545, -187, -27, -332, -611, -510, -214, -56, -219, -696, -593, -720, -479, -155, -278, -517, -691, -314, -638, -748, -232, -737, -46, -138, -192, -631, -224, -691, -628, -613, -324, -185, -365, -259, -219, -462, -290, -783, -710, -444, -271, -117, -469, -609, -105, -602, -465, -260, -323, -544, -493, -458, -261, -102, -198, -221, -321, -694, -614, -147, -511, -592, -335, -738, -198, -274, -780, -598, -281, -686, -25, -682, -827, -491, -312, -540, -304, -293, 2, -238, -614, -22, -380, -194, -167, -167, -569, -170, -184, -104, -327, -401, -654, -926, -571, -181, -809, -552, -767, -579, -823, -620, -660, -853, -448, -720, -872, -898, -45, -154, -409, -399, -950, -393, -782, -376, -65, -644, -654, -523, -24, -767, -419, -183, -143, -98, -792, -485, -923, -360, -173, -879, -847, -732, -962, -643, -392, -117, -4, -932, -253, -298, -381, -339, -796, -274, -79, -586, -567, -425, -541, -329, -800, -878, -519, -111, -224, -304, -560, -183, -604, -952, -229, 2, -115, -748, -262, -54, -533, -139, -785, -583, -634, -164, -836, -77, -578, -593, -561, -596, -611, -440, -27, -848, -998, -56, -947, -740, -737, -612, -655, -845, -812, -925, -197, -236, -37, -753, -747, -286, -641, -43, -348, -33, -713, -610, -777, -899, -1005, -264, -193, -928, -193, -412, -213, -228, -1012, -920, -702, -420, -496, -1019, -386, -645, -804, -795, -12, -810, -117, -454, -266, -1059, -321, -674, -647]
var current = 0
var step = 0
// print(step, array)
while current >= 0 && current < array.count {
step = step + 1
let next = current + array[current]
array[current] += 1
current = next
// print(step, array)
}
print(step)
// Part II
var current = 0
var step = 0
// print(step, array)
while current >= 0 && current < array.count {
step = step + 1
let offset = array[current]
let next = current + offset
array[current] += (offset >= 3) ? (-1) : 1
current = next
// print(step, array)
}
print(step)
import Foundation
var array = [2, 8, 8, 5, 4, 2, 3, 1, 5, 5, 1, 2, 15, 13, 5, 14]
var seen = [array]
public func redistribute(_ array: inout [Int]) {
let x = array.max()!
let count = array.count
let idx = array.index(of: x)!
let banks = array[idx]
array[idx] = 0
for n in 1 ... banks {
let i = (idx + n) % count
array[i] += 1
}
}
public func find() {
var count = 0
while true {
redistribute(&array)
count += 1
for item in seen {
if item == array {
print("Done: \(count)")
return
}
}
seen.append(array)
}
}
// Part II
import Foundation
var array = [2, 8, 8, 5, 4, 2, 3, 1, 5, 5, 1, 2, 15, 13, 5, 14]
// var array = [2, 4, 1, 2]
var seen = [array]
public func redistribute(_ array: inout [Int]) {
let x = array.max()!
let count = array.count
let idx = array.index(of: x)!
let banks = array[idx]
array[idx] = 0
for n in 1 ... banks {
let i = (idx + n) % count
array[i] += 1
}
}
public func find() {
var count = 0
while true {
redistribute(&array)
count += 1
for (idx, item) in seen.enumerated() {
if item == array {
print("II:", seen.dropFirst(idx).count)
return
}
}
seen.append(array)
}
}
import Foundation
class Node {
var parent: Node? = nil
var children: [Node] = []
let name: String
init(name: String) {
self.name = name
}
}
let path = Bundle.main.path(forResource: "test", ofType: "txt")!
let str = try! String(contentsOfFile: path)
let cs = CharacterSet.lowercaseLetters.union(CharacterSet.whitespaces)
let lines = str
.components(separatedBy: .newlines)
.filter({ !$0.isEmpty })
.map({ $0.filter({
cs.contains(String($0).unicodeScalars.first!)
})
})
.map({ $0.components(separatedBy: .whitespaces) })
.map({ $0.map({
$0.trimmingCharacters(in: .whitespaces)})
.filter({ !$0.isEmpty })
})
var nodedict: [String: Node] = [:]
for line in lines {
guard !line.isEmpty else { continue }
let name = line[0]
let node = Node(name: name)
nodedict[name] = node
}
for line in lines {
guard !line.isEmpty else { continue }
var line = line
let name = line.removeFirst()
let node = nodedict[name]!
for child in line {
if let childnode = nodedict[child] {
node.children.append(childnode)
childnode.parent = node
} else {
print("Error: \(child) node not found in dict")
}
}
}
for (name, node) in nodedict {
guard node.parent == nil else { continue } // child
print("\(name) is unparented")
}
// Part II
import Foundation
class Node {
var parent: Node? = nil
var children: [Node] = []
let name: String
let weight: Int
var sumWeight: Int = 0
init(name: String, weight: Int) {
self.name = name
self.weight = weight
}
}
let path = Bundle.main.path(forResource: "test", ofType: "txt")!
let str = try! String(contentsOfFile: path)
let cs = CharacterSet.alphanumerics
.union(CharacterSet.whitespaces)
let lines = str
.components(separatedBy: .newlines)
.filter({ !$0.isEmpty })
.map({ $0.filter({
cs.contains(String($0).unicodeScalars.first!)
})
})
.map({ $0.components(separatedBy: .whitespaces) })
.map({ $0.map({
$0.trimmingCharacters(in: .whitespaces)})
.filter({ !$0.isEmpty })
})
var nodedict: [String: Node] = [:]
// print(lines)
for line in lines {
guard !line.isEmpty else { continue }
let name = line[0]
let weight = Int(line[1])!
let node = Node(name: name, weight: weight)
nodedict[name] = node
}
for line in lines {
guard !line.isEmpty else { continue }
var line = line
let name = line.removeFirst() // name
let _ = line.removeFirst() // weight
let node = nodedict[name]!
for child in line {
if let childnode = nodedict[child] {
node.children.append(childnode)
childnode.parent = node
} else {
print("Error: \(child) node not found in dict")
}
}
}
var root: String? = nil
for (name, node) in nodedict {
guard node.parent == nil else { continue } // child
print("Root: \(name)\n")
root = name
}
func balance(_ name: String) {
guard let node = nodedict[name] else {
print("Missing node: \(name)")
fatalError()
}
for child in node.children {
balance(child.name)
node.sumWeight += (child.sumWeight + child.weight)
}
}
balance(root!)
let (star, nothing) = ("*", "")
for (name, node) in nodedict {
guard !node.children.isEmpty else { continue }
if Set(node.children.map({ $0.weight + $0.sumWeight })).count != 1 {
print("\(name) is unbalanced")
for child in node.children {
print(" \(child.name), \(child.weight + child.sumWeight) \(child.children.isEmpty ? star : nothing)")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment