Skip to content

Instantly share code, notes, and snippets.

@bkyrlach
Created December 10, 2019 20:45
Show Gist options
  • Select an option

  • Save bkyrlach/10fe80669c5b14c64367aedda9239b19 to your computer and use it in GitHub Desktop.

Select an option

Save bkyrlach/10fe80669c5b14c64367aedda9239b19 to your computer and use it in GitHub Desktop.
case class ComputerState(memory: Vector[Int], ptr: Int)
type IntCodeError[A] = Either[String,A]
type IntCodeProgram[A] = StateT[IntCodeError,ComputerState,A]
def pure[A](a: A): IntCodeProgram[A] = StateT.pure(a)
def inspect[A](f: ComputerState => A): IntCodeProgram[A] = StateT.inspect(f)
def mod(f: ComputerState => ComputerState): IntCodeProgram[Unit] = StateT.modify(f)
def error[A](msg: String): IntCodeProgram[A] = StateT.liftF(Left(msg))
def read: IntCodeProgram[Int] = for {
ptr <- inspect(_.ptr)
next <- readAt(ptr)
_ <- mod(s => s.copy(ptr = ptr + 1))
} yield {
next
}
def readAt(ptr: Int): IntCodeProgram[Int] = inspect(s => s.memory(ptr))
def write(value: Int)(ptr: Int): IntCodeProgram[Unit] = mod(s => s.copy(memory = s.memory.updated(ptr, value)))
def run_(opCode: Int): IntCodeProgram[Unit] = FlatMap[IntCodeProgram].tailRecM(opCode) {
case 1 => for {
op1 <- read >>= readAt
op2 <- read >>= readAt
_ <- read >>= write(op1 + op2)
next <- read
} yield { Left(next) }
case 2 => for {
op1 <- read >>= readAt
op2 <- read >>= readAt
_ <- read >>= write(op1 * op2)
next <- read
} yield { Left(next) }
case 99 => pure(Right())
case _ => error("Unrecognized op code")
}
def run: IntCodeProgram[Unit] = read >>= run_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment