Xah Talk Show 2023-12-11 Advent of Code Day 3, Live Coding, in WolframLang
Advent of Code 2023, Day 3, Problem Description
your input
467..114.. ...*...... ..35..633. ......#... 617*...... .....+.58. ..592..... ......755. ...$.*.... .664.598..
sum up all numbers that have one or more symbols adjacent to it, and adjacency include diagonal direction. Symbol is any character not period and not digit.
in this example, 114 and 58 are not adjacent to a symbol. Others are. Answer is 4361
Part 2
Find all asterisks, such that the asterisk has 2 and only 2 numbers that are adjacent. Multiply these 2 numbers together, you get a product.
sum all the products.
In sample input, there are two such asterisks. One the top left, with numbers 467 and 35. Product is 16345. One the lower right, with numbers 755 and 598. Product is 451490. sum is 467835
Solution
(* Advent of Code 2023, Day 3, part 1. solution. *) input = "467..114.. ...*...... ..35..633. ......#... 617*...... .....+.58. ..592..... ......755. ...$.*.... .664.598.."; input = ReadString[ "c:/Users/xah/web/xahlee_info/talk_show/i/advent_of_code_2023_day_3_input.txt" ]; xCharPerLine = StringPosition[ input, "\n", 1 ][[1,1]]-1; paddedLine= StringRepeat[".", xCharPerLine+2 ]; paddedInput = paddedLine <> StringReplace[ "."<> input <> "." , {"\n" -> "..",RegularExpression[ "[^\\d.]" ]->"x"} ] <> paddedLine; numPositions = StringPosition[ paddedInput , DigitCharacter.., Overlaps->False ]; Map[ Function[positionPair, Module[{beginPos, endPos, charCount, prevLineNeighbor, nextLineNeighbor, charNeighbors}, beginPos = positionPair[[1]]; endPos = positionPair[[2]]; charCount = beginPos - endPos + 1; prevLineNeighbor = StringTake[ paddedInput, {(beginPos-(xCharPerLine+2)-1), (endPos-(xCharPerLine+2)+1)} ]; nextLineNeighbor = StringTake[ paddedInput, {(beginPos+(xCharPerLine+2)-1), (endPos+(xCharPerLine+2))+1} ]; charNeighbors = StringTake[ paddedInput, {beginPos-1, endPos+1} ]; If[ Or@@ StringContainsQ[ {prevLineNeighbor, nextLineNeighbor, charNeighbors}, "x"], StringTake[ paddedInput, { beginPos, endPos } ]//ToExpression, 0] ] ], numPositions ]//Total (* toy input answer: 4361 my input answer: 535235 *)
thoughts on novel approach
- gah. been thinking on the advent day 3 problem in past 3 hours.
- need a break
- get some to eat.
- goal is simple. produce the shortest code on earth.
- bonus, unusual, never seen, approach, demo the power of wolframlang.
- currently 2 approach. one, pure regex match. no rely on any string position info at all.
- the other, is some kinda a mask stamp. this would be extreme. but still dunno feasibility.
- 3rd approach is rely on position. this would still produce shortest code, but the approach is not novel. every solution does this.
- How's Shortest Code Solution Defined?
- Shortest Code in WolframLang May be Most Inefficient
- Programing Trick to Avoid Checking Out of Bounds Index for 2d Array
cookie stamp approach
- let me explain the cookie stamp approach
- consider the input string a 2d matrix.
- each entry is a single char.
- u need to find all numbers that has a symbol char adjacent to it, including diagonal.
- the cookie stamp approach, is consider something like a bitmask, but a matrix mask, that u just stamp on it and get the nums u want. all rest entries become null or 0.
- in order to create this mask, u do need some kinda pattern... lol omg, i got a idea.
- consider this as a height field, or heat map.
- numbers has high heat. and symbols too.
- when symbols r near number, they increase the height of the number
- how to computer the distance? easy 2d geometry
- and also neighborhood.
- omg great, turned this from string to matrix to a geometry.
scratchpad
input = "467..114.. ...*...... ..35..633. ......#... 617*...... .....+.58. ..592..... ......755. ...$.*.... .664.598.."; (* input = ReadString[ "c:/Users/xah/web/xahlee_info/talk_show/i/advent_of_code_2023_day_3_input.txt" ]; *) xCharPerLine = StringPosition[ input, "\n", 1 ][[1,1]]-1 (* xCharPerLine = StringSplit[ input, "\n", 2 ][[1]] //StringLength *) (* 10 *) (* 140 *) xLineCount = StringCount[ input, "\n" ]+1; xTotalChars = StringLength[ input ] (* 109 *) xUniqueSymChars = DeleteDuplicates @ Characters @ StringReplace[input, {DigitCharacter .., "." .., "\n"} -> ""] (* {@, *, $, &, /, =, -, +, #, %} *) xNumPositions = StringPosition[ StringReplace[input,"\n"->""], num:(DigitCharacter..) , Overlaps -> False ]; xSymPositions = StringPosition[ input, StringExpression[ xUniqueSymChars ], Overlaps -> False ]; (* symbols are never consecutive *) (* And@@(SameQ /@ xSymPositions ) *) xmatrix = Partition[ Characters@ StringReplace[input, "\n"->"" ] , xLineCount ] ArrayPad[xmatrix, 1, t] (* Pick[ Range @ Length @ input, StringMatchQ[patt] @ input ] *) (* StringCases[ input, StringExpression[ (d:Except@Character@"@*$&/=-+#%"../; (True) ) ] :> ToExpression@d ] *) (* Character@"@*$&/=-+#%" *) (* StringCases[ input, StringExpression[ (d:DigitCharacter../; (True) ) ] :> ToExpression@d ] *) (* check, if there is a symbol in front, or after, the number. then check, if there is a symbol, above the line. then check, if there is a symbol, after the line. suppose beginning and end pos of a num is {x , y} so we check is pos (x -1) a symbol? is (y+1) a symbol? (also make sure, the number is at the beginning of line or end of line) is pos (x -lineCharCount -1) a symbol? is pos (y + lineCharCount +1) a symbol? (also make sure, the number not at first line or last line. special need to do for out of boundary.) validNumberQ = Function[ {pos}, True]; *)
input = "467..114.. ...*...... ..35..633. ......#... 617*...... .....+.58. ..592..... ......755. ...$.*.... .664.598.."; (* input = ReadString[ "c:/Users/xah/web/xahlee_info/talk_show/i/advent_of_code_2023_day_3_input.txt" ]; *) xCharPerLine = StringPosition[ input, "\n", 1 ][[1,1]]-1; (* paddedInput = input yy= StringRepeat[".",xCharPerLine+2 ]; xx= yy <> StringReplace[ "."<> input <> "." , {"\n" -> "..",RegularExpression[ "[^\\d.]" ]->"t"} ] <> yy xt= "ttt"<> StringRepeat[ ".", xCharPerLine-4 ]<>"ttt" *) xUniqueSymChars = DeleteDuplicates @ Characters @ StringReplace[DigitCharacter ..|"."..|"\n"->""]@input sym=StringRiffle[xUniqueSymChars , "" ] (* sym= Characters@"@*$&/=-+#%" *) StringCases[input, RegularExpression @StringTemplate["((.|\n){0,``})(\\d+)((.|\n){0,``})"][xCharPerLine+2,xCharPerLine+2] :> {"$1", "$3", "$5"}, Overlaps->True] StringCases[input, RegularExpression @StringTemplate["((.|\n){0,``})(\\d+)((.|\n){0,``})"][xCharPerLine+2,xCharPerLine+2] :> {"$1", "$2", "$3", "$4", "$5"}] StringCases[ input, b:(xUniqueSymChars..~~"."...) ~~n:(NumberString)~~a:("."..~~xUniqueSymChars...)/; Or@@@ ((StringLength@# < 10+2 && StringContainsQ[ #, "t" ]) &)/@ {a,b} :> n ] StringCases[ input, /;(StringLength@d === 4) b:Except@DigitCharacter... ~~n:(DigitCharacter..)~~a:Except@DigitCharacter... :> {b, n, a } ] (* b:(sym..~~"."...) ~~n:(NumberString)~~a:(sym...~~"."..~~sym...) :> n StringCases[ input, b:(sym..~~"."...) ~~n:(NumberString)~~a:("."..~~sym...)/; Or@@@ ((StringLength@# < 10+2 && StringContainsQ[ #, "t" ]) &)/@ {a,b} :> n ] *) Characters@"0123456789.\n" CharacterRange["0","9"]|"."|"\n" StringCases[ xx, b:("t"..~~"."...) ~~n:(DigitCharacter..)~~a:("."..~~"t"...)/; , Overlaps -> False ] StringPartition[xx, 12]//TableForm StringPosition[ xx, RegularExpression[ "ttt........t\\dt........ttt" ] , Overlaps -> False ] (* RegularExpression@"t\\dt" "t"~~DigitCharacter~~"t" ............ .467..114... ....t....... ...35..633.. .......t.... .617t....... ......t.58.. ...592...... .......755.. ....t.t..... ..664.598... ............ *)