DEV Community

Marco Servetto
Marco Servetto

Posted on

Advent of code Day 20

Finally a day where I can feel satisfied with my code results.
I explain this code in the detail on my youtube channel, (https://www.youtube.com/watch?v=lqA_XT0U4ng)

reuse [L42.is/AdamsTowel]

Fs = Load:{reuse[L42.is/FileSystem]}

Point = Data.AddList:Data:{ I x, I y
  method Point +(Point that) =
    \(x=this.x()+that.x(),y=this.y()+that.y())
  method Point max(Point that)=(
    (x0,y0) = this
    (x1,y1) = that
    Point(x=x0.max(x1),y=y0.max(y1))
    )
  method Point min(Point that) = 
    this.with(x=\x.min(that.x()))<:This.with(y=\y.min(that.y()))
  }

Map = Data:{
  M = Collection.map(key=Point,val=Bool)
  mut M map=\()
  var Bool outer=Bool.false()
  var Point topLeft = Point(x=0I,y=0I)
  var Point bottomRight = Point(x=0I,y=0I)

  mut method Void put(Point key, Bool val) = (
    \#map.put(key=key,val=val)
    \topLeft(\topLeft.min(key))
    \bottomRight(\bottomRight.max(key))
    )
  read method Bool val(Point key) =
    \map.val(key=key).val(orElse=this.outer())

  read method I nearBin(Point that) = 0I.acc()((
    var n = 512I
    for xi in Range(I"-1" to=2I), for yi in Range(I"-1" to=2I) (
      n/=2I
      if this.val(key=Point(x=xi,y=yi)+that) \add(n)
      )
    ))
  read method mut This step(Key that) = (
    mut This new = This()
    (x0,y0) = \topLeft
    (x1,y1) = \bottomRight
    for x in Range(x0-1I to=x1+2I), for y in Range(y0-1I to=y1+2I) (
      key=Point(x=x,y=y)
      i=\nearBin(key)
      X[i.isInRange(0I to=512I)] // is my binary conversion correct?
      new.put(key=key,val=that.val(i))
      )
    new.outer(if this.outer() that.right() else that.left())
    new
    )
  }
Key = Collection.list(Bool)

Main=(
  input = Fs.Real.#$of().read(\"input").split(S.nl()++S.nl())
  imm key = Key()( for i in input().split() \add(i==S"#") )
  X[key.size()==512I]
  var map = Map()
  for line in input().split(S.nl()), li in Range.unbounded() (
    for c in line.split(), ci in Range.unbounded() (
      map.put(key=\(x=li,y=ci),val=c==S"#")
      )
    )
  for i in Range(2I) ( map:=map.step(key) )  //50I
  tot = 0I.acc()(for (val) in map.map() \addIf(val))
  Debug(tot)
  )
Enter fullscreen mode Exit fullscreen mode

Discussion (0)