1
1
import ArgumentParser
2
2
import Foundation
3
3
4
- struct Card {
5
- var count = 1
6
- var score = 0
4
+ struct MapKey : Hashable {
5
+ let first : String
6
+ let second : String
7
+ }
8
+
9
+ struct Seen : Hashable {
10
+ let type : String
11
+ let coord : Int
12
+ }
13
+
14
+ struct MapEntry {
15
+ let input : Range < Int >
16
+ let output : Range < Int >
7
17
}
8
18
9
19
@main
10
- struct Day05b : ParsableCommand {
20
+ struct Day05a : ParsableCommand {
11
21
@Option ( help: " Specify the input " )
12
22
public var input : String
13
23
@@ -20,23 +30,70 @@ struct Day05b: ParsableCommand {
20
30
print ( " Failed to open file \( input) " )
21
31
return
22
32
}
23
- var cards = [ Int: Card] ( )
24
- for line in filecontent. components ( separatedBy: . newlines) {
25
- let split = line. components ( separatedBy: [ " : " , " | " ] )
26
- let card = Int ( split [ 0 ] . substring ( from: 4 ) . trimmingCharacters ( in: [ " " ] ) ) !
27
- let winning = Set < Int > ( numbers ( fromString: split [ 1 ] ) )
28
- let chosen = Set < Int > ( numbers ( fromString: split [ 2 ] ) )
29
- let winningCount = winning. intersection ( chosen) . count
30
- cards [ card] = Card ( count: 1 , score: winningCount)
33
+
34
+ let lines = filecontent. components ( separatedBy: . newlines)
35
+ let s = numbers ( fromString: lines [ 0 ] . substring ( from: 7 ) )
36
+ var seeds = [ Range < Int > ] ( )
37
+ for i in 0 ..< s. count / 2 {
38
+ seeds. append ( s [ i*2] ..< s [ i*2] + s[ i*2+ 1 ] )
31
39
}
32
40
33
- var result = 0
34
- for card in cards. keys. sorted ( ) {
35
- let c = cards [ card] !
36
- result += c. count
37
- if c. score > 0 {
38
- for i in 1 ... c. score {
39
- cards [ card + i] !. count += c. count
41
+ var mappings = [ String: String] ( )
42
+ var almanac = [ MapKey: [ MapEntry] ] ( )
43
+
44
+ var key : MapKey ?
45
+ for idx in 2 ..< lines. count {
46
+ if lines [ idx] == " " {
47
+ key = nil
48
+ continue
49
+ }
50
+
51
+ if key == nil {
52
+ let split = lines [ idx] . components ( separatedBy: [ " - " , " " ] )
53
+ key = MapKey ( first: split [ 0 ] , second: split [ 2 ] )
54
+ mappings [ split [ 0 ] ] = split [ 2 ]
55
+ almanac [ key!] = [ ]
56
+ } else {
57
+ let entry = numbers ( fromString: lines [ idx] )
58
+ almanac [ key!] !. append ( MapEntry ( input: entry [ 1 ] ..< entry [ 1 ] + entry[ 2 ] , output: entry [ 0 ] ..< entry [ 0 ] + entry[ 2 ] ) )
59
+ }
60
+ }
61
+
62
+ // print(seeds)
63
+ // print(mappings)
64
+ // print(almanac)
65
+
66
+ var result = Int . max
67
+ var seen = [ String : Set < Int > ] ( )
68
+ mappings. values. forEach ( { seen [ $0] = Set < Int > ( ) } )
69
+ for seed in seeds {
70
+ for i in seed {
71
+ var what = i
72
+ var first = " seed "
73
+ var skip = false
74
+ while let second = mappings [ first] {
75
+ // if !seen[second]!.insert(what).inserted {
76
+ // skip = true
77
+ // break
78
+ // }
79
+ if let entries = almanac [ MapKey ( first: first, second: second) ] {
80
+ for entry in entries {
81
+ if entry. input. contains ( what) {
82
+ what = entry. output. lowerBound + ( what - entry. input. lowerBound)
83
+ break
84
+ }
85
+ }
86
+ } else {
87
+ assert ( false )
88
+ }
89
+ first = second
90
+ }
91
+ // if (skip) {
92
+ // continue
93
+ // }
94
+ if what < result {
95
+ print ( " New best: \( what) from \( i) " )
96
+ result = what
40
97
}
41
98
}
42
99
}
0 commit comments