Skip to content

Instantly share code, notes, and snippets.

@masak
Created April 24, 2012 21:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save masak/2484152 to your computer and use it in GitHub Desktop.
Save masak/2484152 to your computer and use it in GitHub Desktop.
Solving the apples-and-guards problem symbolically
# <masak> a boy wants to give an apple to a girl. to get to her, he has to pass through
# five gates, each with a guard. he bribes each guard with half of his apples,
# plus one. after he's given the apple to the girl, he has no apples left. how
# many did he have to begin with?
use v6;
role Expr {
}
class Var does Expr {
method code() { -> $x { $x } }
}
class Op does Expr {
has &.op;
has $.l;
has $.r;
method code() { -> $x { &!op($.l.code()($x), $.r) } }
}
multi infix:</>(Expr $l, $r) { Op.new: :op(&[/]), :$l, :$r }
multi infix:<->(Expr $l, $r) { Op.new: :op(&[-]), :$l, :$r }
sub guard($x) {
$x / 2 - 1
}
sub replace-var(Expr $_, Expr $inner) {
when Op { Op.new( :op(.op), :l(replace-var(.l, $inner)), :r(.r) ) }
when Var { $inner }
}
sub solve(Expr $_) {
when Op {
my ($l, $r) = .l, .r;
my $inv = do given .op {
when $_ === &infix:</> { Op.new: :op(&[*]), :l(Var.new), :$r }
when $_ === &infix:<-> { Op.new: :op(&[+]), :l(Var.new), :$r }
};
replace-var(solve($l), $inv);
}
when Var {
Var.new
}
}
my &id = -> $x { $x };
multi infix:<**>(&code, 0) { &id }
multi infix:<**>(&code, Int $n where * > 0) {
-> $x { &code((&code ** ($n - 1))($x)) }
}
my &anti-guard = solve( guard(Var.new) ).code;
say (&anti-guard ** 5)(1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment