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

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...
............

*)