diff --git a/day_04/common.nim b/day_04/common.nim new file mode 100644 index 0000000..16f1a1d --- /dev/null +++ b/day_04/common.nim @@ -0,0 +1,33 @@ +import std/[math, sequtils, setutils, strformat, strmisc, strutils] + +# ASSUMPTION: lottery numbers are < 128 +type + Card* = ref object + idx*: int + play, pot: set[int8] + +proc value*(card: Card): int = + (card.play * card.pot).len + +proc points*(card: Card): int = + result = case card.value: + of 0: 0 + of 1: 1 + else: 2 ^ (card.value - 1) + +proc `$`*(card: Card): string = + return &"Card {card.idx+1}: {card.play}, {card.pot} => {card.value}" + +proc parseNumberSet(s: string): set[int8] = + s.strip.splitWhitespace().mapIt(it.parseInt.int8).toSet + +proc parseInput*(s: string): seq[Card] = + let lines = s.strip.splitLines + for i, line in lines: + let card = new Card + let (left, _, right) = line.split(":")[1].partition("|") + card.idx = i + card.play = parseNumberSet(left) + card.pot = parseNumberSet(right) + echo card + result.add(card) diff --git a/day_04/solution_04a.nim b/day_04/solution_04a.nim index c97ab51..19cba85 100644 --- a/day_04/solution_04a.nim +++ b/day_04/solution_04a.nim @@ -1,37 +1,11 @@ -import std/[cmdline, math, sequtils, setutils, strformat, strscans, strutils] +import std/[cmdline, math, sequtils, strformat] + +import common -var result = 0 var fn = if paramCount() > 0: paramStr(1) else: "input_04.txt" -var lines = readFile(fn).strip.splitLines - -# ASSUMPTION: lottery numbers are < 128 -type - Card = ref object - play, pot: set[int8] -var cards: seq[Card] - -proc points(card: Card): int = - let matches = (card.play * card.pot).len - if matches == 1: - result = 1 - elif matches > 1: - result = 2 ^ (matches - 1) - else: - result = 0 - - -for line in lines: - var cardno: int - let cardspec = line.split(":", 1) - - if scanf(cardspec[0].strip, "Card$s$i", cardno): - let card = new Card - card.play = cardspec[1].split("|")[0].strip.splitWhitespace().mapIt(it.strip).mapIt(it.parseInt).mapIt(it.int8).toSet - card.pot = cardspec[1].split("|")[1].strip.splitWhitespace().mapIt(it.strip).mapIt(it.parseInt).mapIt(it.int8).toSet - echo &"Card {cardno}: {card.play}, {card.pot} => {card.points}" - cards.add(card) - result += card.points +var cards = parseInput(readFile(fn)) +var result = sum(cards.mapIt(it.points)) echo &"Cards processed: {cards.len}" echo &"Result: {result}" diff --git a/day_04/solution_04b.nim b/day_04/solution_04b.nim index e41922f..0bfe48e 100644 --- a/day_04/solution_04b.nim +++ b/day_04/solution_04b.nim @@ -1,36 +1,12 @@ -import std/[cmdline, sequtils, setutils, strformat, strscans, strutils] +import std/[cmdline, strformat] + +import common -var result = 0 var fn = if paramCount() > 0: paramStr(1) else: "input_04.txt" -var lines = readFile(fn).strip.splitLines - -# ASSUMPTION: lottery numbers are < 128 -type - Card = ref object - idx: int - play, pot: set[int8] -var cards: seq[Card] - -proc value(card: Card): int = - (card.play * card.pot).len - -#proc `$`(card: Card): string = -# return &"Card idx={card.idx}: value={card.value}" - - -for i, line in lines: - var cardno: int - let cardspec = line.split(":", 1) - - if scanf(cardspec[0].strip, "Card$s$i", cardno): - let card = new Card - card.idx = i - card.play = cardspec[1].split("|")[0].strip.splitWhitespace().mapIt(it.strip).mapIt(it.parseInt).mapIt(it.int8).toSet - card.pot = cardspec[1].split("|")[1].strip.splitWhitespace().mapIt(it.strip).mapIt(it.parseInt).mapIt(it.int8).toSet - #echo &"Card {card.idx}: {card.play}, {card.pot} => {card.value}" - cards.add(card) - +var cards = parseInput(readFile(fn)) var stack = cards +var result = 0 + while stack.len > 0: result += len(stack) var extra_cards: seq[Card] @@ -41,7 +17,7 @@ while stack.len > 0: stack = extra_cards -#echo &"Cards processed: {cards.len}" +echo &"Cards processed: {cards.len}" echo &"Result: {result}" case fn: