packages feed

swarm-0.7.0.0: data/scenarios/Challenges/_flower-count/solution.sw

def doN : Int -> Cmd a -> Cmd Unit = \n. \c.
  if (n == 0) {} {c; doN (n-1) c}
end

def abs : Int -> Int = \n.
  if (n < 0) {-n} {n}
end

def λmatch = \f. \p. match p f end
def λcase = \f. \g. \s. case s f g end

// Go to the given absolute coordinates.  End facing east.
def goto : Int * Int -> Cmd Unit = λmatch \destx. \desty.
  cur <- whereami;
  match cur \x. \y.
  let dx = destx - x in
  let dy = desty - y in
  if (dx < 0) {turn west} {turn east};
  doN (abs dx) move;
  if (dy < 0) {turn south} {turn north};
  doN (abs dy) move;
  turn east;
end

def liftA2 : (a -> b -> c) -> Cmd a -> Cmd b -> Cmd c = \f. \ca. \cb.
  a <- ca;
  b <- cb;
  pure (f a b)
end

def add : Cmd Int -> Cmd Int -> Cmd Int = liftA2 (\x. \y. x + y) end

def countCell : Cmd Int =
  s <- scan down;
  pure $ case s
    (\_. 0)
    (\t. if (t == "flower") {1} {0})
end

tydef List a = rec l. Unit + (a * l) end

def sum : List Int -> Int = λcase
  (\_. 0)
  (λmatch \hd. \tl. hd + sum tl)
end

def for : Int -> (Int -> Cmd a) -> Cmd (List a) = \n. \k.
  if (n == 0) {pure (inl ())} {a <- k n; b <- for (n-1) k; pure (inr (a,b))}
end

def countRow : Int -> Cmd Int = \w.
  ns <- for (w-1) (\_. n <- countCell; move; pure n);
  last <- countCell;
  pure (sum ns + last)
end

def isEven : Int -> Bool = \n. (n / 2) * 2 == n end

def around : Dir -> Cmd Unit = \d. turn d; move; turn d end

// countFlowers (w,h) (x,y) counts the number of flowers
// in the w by h rectangle with lower-left corner at (x,y)
def countFlowers : Int * Int -> Int * Int -> Cmd Int = \size. \ll.
  goto ll;
  match size \w. \h.
  cnts <- for (h-1) (\i.
    cnt <- countRow w;
    if (isEven i) { around right } { around left };
    pure cnt
  );
  last <- countRow w;
  pure (sum cnts + last)
end

def acquire : Cmd Text =
  thing <- atomic (b <- isempty; if b {pure ""} {grab});
  if (thing == "") {acquire} {pure thing}
end

def countAndReport : Int * Int -> Int * Int -> Cmd Unit = \size. \ll.
  cnt <- countFlowers size ll;
  goto (0,0);
  paper <- acquire;
  let soFar = read @Int paper in
  erase paper;
  newPaper <- print "paper" (format (soFar + cnt));
  place newPaper;
end

def until : Cmd Bool -> Cmd a -> Cmd Unit = \test. \body.
  b <- test; if b {} {body; until test body}
end

def acquireFlower : Cmd Unit =
  until (ishere "flower") move; grab; pure ()
end

def go =
  for 4 (\r.
    for 3 (\c.
      build {countAndReport (40,10) (-59 + 40*(c-1), -19 + 10*(r-1))}
    )
  );
  print "paper" "0";
  turn left; move; place "paper: 0";
  wait 1024;
  acquireFlower;
  turn back;
  goto (20,0);
  res <- meet;
  case res (\_. pure ()) (\truelove. give truelove "flower")
end;

go;