Quick actions

cmd+k|ctrl+k

Navigation

Languages

aoc2017-day18-2

Snippet info

Language

Elixir

Visibility

public

Author

christophe.guillon.perso

Created

2017-12-18T16:54:31Z

Updated

2017-12-18T16:54:31Z

getop = fn (state, x) ->                                                                                                                                                                                            
  try do                                                                                                                                                                                                            
    String.to_integer(x)                                                                                                                                                                                            
  rescue                                                                                                                                                                                                            
    _ -> Map.get(state, x, 0)                                                                                                                                                                                       
  end                                                                                                                                                                                                               
end                                                                                                                                                                                                                 
setop = fn (state, x, y) -> Map.put(state, x, y) end                                                                                                                                                                
                                                                                                                                                                                                                    
opadd = fn (state, x, y) -> getop.(state, x) + getop.(state, y) end                                                                                                                                                 
opmul = fn (state, x, y) -> getop.(state, x) * getop.(state, y) end                                                                                                                                                 
opmod = fn (state, x, y) -> rem(getop.(state, x), getop.(state, y)) end                                                                                                                                             
                                                                                                                                                                                                                    
execute = fn (state, pc, inst) ->                                                                                                                                                                                   
#  inst |> IO.inspect                                                                                                                                                                                               
  { op, x, y } = inst                                                                                                                                                                                               
  new =                                                                                                                                                                                                             
    case op do                                                                                                                                                                                                      
      "add" -> setop.(state, x, opadd.(state, x, y))                                                                                                                                                                
      "mul" -> setop.(state, x, opmul.(state, x, y))                                                                                                                                                                
      "mod" -> setop.(state, x, opmod.(state, x, y))                                                                                                                                                                
      "set" -> setop.(state, x, getop.(state, y))                                                                                                                                                                   
    end                                                                                                                                                                                                             
  { new, pc + 1 }                                                                                                                                                                                                   
end                                                                                                                                                                                                                 
                                                                                                                                                                                                                    
execute_and_next = fn {state, pc, prog} ->                                                                                                                                                                          
  inst = Enum.at(prog, pc)                                                                                                                                                                                          
  { state, pc } =                                                                                                                                                                                                   
    case inst do                                                                                                                                                                                                    
      nil -> { state, nil }                                                                                                                                                                                         
      _ -> execute.(state, pc, Enum.at(prog, pc))                                                                                                                                                                   
    end                                                                                                                                                                                                             
  { state, pc, prog }                                                                                                                                                                                               
end                                                                                                                                                                                                                 
                                                                                                                                                                                                                    
runner = fn (state, prog, stop) ->                                                                                                                                                                                  
  gen = Stream.resource(                                                                                                                                                                                            
  fn -> { state, 0, prog } end,                                                                                                                                                                                     
  fn x ->                                                                                                                                                                                                           
    case stop.(x) do                                                                                                                                                                                                
      :halt -> {:halt, x }                                                                                                                                                                                          
      x ->                                                                                                                                                                                                          
        n = execute_and_next.(x)                                                                                                                                                                                    
        { [n], n }                                                                                                                                                                                                  
    end                                                                                                                                                                                                             
  end,                                                                                                                                                                                                              
  fn x -> x end)                                                                                                                                                                                                    
  |> Stream.take(-1)                                                                                                                                                                                                
  |> Enum.to_list                                                                                                                                                                                                   
                                                                                                                                                                                                                    
  elem(Enum.at(gen, 0), 0)                                                                                                                                                                                          
end                                                                                                                                                                                                                 
                                                                                                                                                                                                                    
stop = fn { state, pc, prog } ->                                                                                                                                                                                    
  case Enum.at(prog, pc) do                                                                                                                                                                                         
    nil -> :halt                                                                                                                                                                                                    
    _ -> { state, pc, prog }                                                                                                                                                                                        
  end                                                                                                                                                                                                               
end                                                                                                                                                                                                                 
                                                                                                                                                                                                                    
thread = fn ->        
  receive do x ->                                                                                                                                                                                                   
      send x.parent,                                                                                                                                                                                                
        %{ child: x.state["p"],                                                                                                                                                                                     
           state: runner.(x.state, x.prog, stop) }                                                                                                                                                                  
  end                                                                                                                                                                                                               
end                                                                                                                                                                                                                 
                                                                                                                                                                                                                    
#prog = [ {"set", "a", "1" }, { "add", "a", "2" }, { "set", "b", "a"} ]                                                                                                                                             
prog = :stdio                                                                                                                                                                                                       
|> IO.read(:all)                                                                                                                                                                                                    
|> String.split("\n")                                                                                                                                                                                               
|> Enum.map(&(String.trim(&1)))                                                                                                                                                                                     
|> Enum.filter(&(&1 != ""))                                                                                                                                                                                         
|> Enum.map(&(List.to_tuple(String.split(&1, " "))))                                                                                                                                                                
prog |> IO.inspect                                                                                                                                                                                                  
                                                                                                                                                                                                                    
pid0 = spawn_link thread                                                                                                                                                                                            
pid1 = spawn_link thread                                                                                                                                                                                            
                                                                                                                                                                                                                    
send pid0, %{ parent: self(), state: %{"p" => 0}, prog: prog}                                                                                                                                                       
send pid1, %{ parent: self(), state: %{"p" => 1}, prog: prog}                                                                                                                                                       
                                                                                                                                                                                                                    
receive do x -> x end                                                                                                                                                                                               
|> IO.inspect                                                                                                                                                                                                       
receive do x -> x end                                                                                                                                                                                               
|> IO.inspect
INFO