[
  {
    "path": ".git-hooks/install-hooks",
    "content": "#!/usr/bin/env zsh\n\nemulate -R zsh\n\ncd ${0%/*}\n\nhooks_dir=\"$(git rev-parse --git-dir)/hooks\"\n\nfor hook in *; do\n    if [[ $hook = ${0:t} ]]; then\n        continue\n    fi\n\n    target=\"$hooks_dir/$hook\"\n\n    if [[ ! -f $target ]]; then\n        print \"Linking $hook...\"\n        ln -fs ${hook:a} $target\n    elif [[ -h $target ]]; then\n        print \"$hook already linked.\"\n    else\n        print \"[ERROR] $hook already exists!\"\n        return 1\n    fi\ndone\n"
  },
  {
    "path": ".git-hooks/prepare-commit-msg",
    "content": "#!/usr/bin/env zsh\nemulate -LR zsh\nsetopt extendedglob\n\nfiles=(\"${(@f)$(git diff --cached --name-only)}\")\n\ncase $files[1] in\n    (#b)other/clrs/([0-9][0-9])/([0-9][0-9]|problems)/([0-9][0-9]).*)\n        prefix=${files[1]%%.*}\n\n        # The filenames are sorted. If the first and the last have the same prefix,\n        # then every element in the file has this prefix.\n        if [[ $files[-1] != $prefix.* ]]; then\n            return 0\n        fi\n\n        # Don't do anything if a commit message is already present\n        if [[ -n $(head -n 1 $1) ]]; then\n            return 0\n        fi\n\n        chapter=${match[1]#0}\n        section=${match[2]#0}\n        exercise=${match[3]#0}\n\n        if [[ $section = 'problems' ]]; then\n            title=$(head -n 1 $prefix.markdown)\n            message=\"clrs; problem $chapter.$exercise - ${(L)title##\\#\\# }\"\n        else\n            message=\"clrs; exercise $chapter.$section.$exercise - \"\n        fi\n\n        sed -i -e \"1i\\\\\n        $message\\\\\n        \" $1\n        ;;\n\n    (#b)scheme/eopl/([0-9][0-9])/([0-9][0-9]).scm)\n        chapter=${match[1]}\n        exercise=${match[2]}\n\n        # Abort if files are not for the same exercise\n        for file in $files; do\n            [[ $file != scheme/eopl/$chapter(/$exercise|/tests/${exercise}-tests).scm ]] && return 0\n        done\n\n        # Abort if commit message already enetered\n        [[ -n $(head -n 1 $1) ]] && return 0\n\n        sed -i -e \"1i\\\\\n        eopl; exercise ${chapter#0}.$exercise - \\\\\n        \" $1\n        ;;\n\n    *)\n        ;;\nesac\n"
  },
  {
    "path": ".gitignore",
    "content": "java/**/bin/**\njava/*/.classpath\njava/*/.project\njava/*/.settings/\n"
  },
  {
    "path": "README",
    "content": "You should probably not care about this project. It contains various code I decided to keep for various reason, none of them actually worth sharing.\n"
  },
  {
    "path": "Rakefile",
    "content": "desc 'Install git hooks'\ntask :hooks do\n  Dir['git-hooks/*'].each do |file|\n    name = file.split('/').last\n    sh \"ln -s ../../#{file} .git/hooks/#{name}\"\n  end\nend\n"
  },
  {
    "path": "advent-of-code/2020/01.1.pl",
    "content": "use strict;\nuse v5.32;\n\nopen INPUT, '<', 'inputs/1.1';\n\nmy @numbers;\n\nwhile (<INPUT>) {\n  chomp $_;\n  push @numbers, $_;\n}\n\nfor my $a (@numbers) {\n  for my $b (@numbers) {\n    if ($a + $b == 2020) {\n      say \"$a + $b = 2020; a * b = @{[$a * $b]}\";\n    }\n  }\n}\n"
  },
  {
    "path": "advent-of-code/2020/01.2.pl",
    "content": "use strict;\nuse v5.32;\n\nopen INPUT, '<', 'inputs/1.1';\n\nmy @numbers;\n\nwhile (<INPUT>) {\n  chomp $_;\n  push @numbers, $_;\n}\n\nfor my $a (@numbers) {\n  for my $b (@numbers) {\n    for my $c (@numbers) {\n      if ($a + $b + $c == 2020) {\n        say \"$a + $b + $c = 2020; a * b = @{[$a * $b * $c]}\";\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "advent-of-code/2020/02.1.pl",
    "content": "use v5.32;\nuse warnings;\n\nopen INPUT, '<', 'inputs/2' or die;\n\nmy $valid = 0;\n\nwhile (<INPUT>) {\n  /^(\\d+)-(\\d+) (\\w): (.*)$/ or die(\"Unmatched input: $_\");\n  my ($low, $high, $char, $password) = ($1, $2, $3, $4);\n  my $count = () = ($password =~ /$char/g);\n  $valid++ if ($low <= $count && $count <= $high);\n}\n\nsay $valid;\n"
  },
  {
    "path": "advent-of-code/2020/02.2.pl",
    "content": "use v5.32;\nuse warnings;\n\nopen INPUT, '<', 'inputs/2' or die;\n\nmy $valid = 0;\n\nmy $count = 0;\nwhile (<INPUT>) {\n  $count++;\n  /^(\\d+)-(\\d+) (\\w): (.*)$/ or die(\"Unmatched input: $_\");\n  my ($first, $second, $char, $password) = ($1, $2, $3, $4);\n  $valid++ if substr($password, $first - 1, 1) eq $char xor substr($password, $second - 1, 1) eq $char;\n}\n\nsay $valid;\n"
  },
  {
    "path": "advent-of-code/2020/03.1.pl",
    "content": "use v5.32;\nuse warnings;\n\nopen INPUT, '<', 'inputs/3' or die;\n\nmy $input = [map { chomp; $_ } <INPUT>];\nmy $width = length($input->[0]);\nmy $height = @$input;\n\nmy @directions = (3, 1);\n\nmy ($x, $y) = (0, 0);\nmy $trees = 0;\n\nwhile ($y < $height) {\n  $trees++ if substr($input->[$y], $x, 1) eq '#';\n  $y += $directions[1];\n  $x += $directions[0];\n  $x %= $width;\n}\n\nsay $trees;\n"
  },
  {
    "path": "advent-of-code/2020/03.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse List::Util qw( reduce );\n\nopen INPUT, '<', 'inputs/3' or die;\n\nsub collisions {\n  my ( $input, $directions ) = @_;\n  my $width = length($input->[0]);\n  my $height = @$input;\n\n  my ($x, $y) = (0, 0);\n  my $trees = 0;\n\n  while ( $y < $height ) {\n    $trees++ if substr( $input->[$y], $x, 1 ) eq '#';\n    $y += $directions->[1];\n    $x += $directions->[0];\n    $x %= $width;\n  }\n\n  $trees;\n}\n\nmy $input = [map { chomp; $_ } <INPUT>];\n\nmy $directions = [\n  [1, 1],\n  [3, 1],\n  [5, 1],\n  [7, 1],\n  [1, 2],\n];\n\nmy @numbers;\nfor my $direction (@$directions) {\n  my $trees = collisions( $input, $direction );\n  say \"right $direction->[0], left $direction->[1] = $trees\";\n  push @numbers, $trees;\n}\n\nsay \"product = \" . reduce { $a * $b } @numbers;\n"
  },
  {
    "path": "advent-of-code/2020/04.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse Set::Scalar;\n\nopen INPUT, '<', 'inputs/4';\n\nmy $required = Set::Scalar->new(qw(byr iyr eyr hgt hcl ecl pid));\nmy $count;\n\nlocal $/ = \"\\n\\n\";\nwhile (<INPUT>) {\n  chomp;\n\n  my $record = $_;\n  my %fields;\n\n  $fields{$1} = $2 while $record =~ /(\\S+):(\\S+)/g;\n\n  my $keys = Set::Scalar->new(keys(%fields));\n\n  $count++ if $required->difference($keys)->is_empty;\n}\n\nsay $count;\n"
  },
  {
    "path": "advent-of-code/2020/04.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse Set::Scalar;\nuse Data::Dump qw(dump);\n\nopen INPUT, '<', 'inputs/4';\n\nmy $required = Set::Scalar->new(qw(byr iyr eyr hgt hcl ecl pid));\nmy $count;\n\nlocal $/ = \"\\n\\n\";\nwhile ( <INPUT> ) {\n  chomp;\n\n  my $record = $_;\n  my %fields;\n\n  $fields{$1} = $2 while $record =~ /(\\S+):(\\S+)/g;\n\n  my $keys = Set::Scalar->new( keys( %fields ) );\n\n  next unless $required->difference( $keys )->is_empty;\n\n  my ( $height, $unit ) = ( $fields{hgt} =~ /(\\d+)(cm|in)/ );\n\n  next unless 1920 <= $fields{byr} and $fields{byr} <= 2002;\n  next unless 2010 <= $fields{iyr} and $fields{iyr} <= 2020;\n  next unless 2020 <= $fields{eyr} and $fields{eyr} <= 2030;\n  next unless defined $unit;\n  next unless ( $unit eq 'cm' and 150 <= $height and $height <= 193 ) or\n              ( $unit eq 'in' and 59 <= $height and $height <= 76);\n  next unless $fields{hcl} =~ /^#[0-9a-f]{6}$/;\n  next unless $fields{ecl} =~ /^(amb|blu|brn|gry|grn|hzl|oth)$/;\n  next unless $fields{pid} =~ /^\\d{9}$/;\n\n  $count++;\n}\n\nsay $count;\n"
  },
  {
    "path": "advent-of-code/2020/05.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse List::Util qw(max);\n\nmy $line = 'BFFFBBFRRR';\n\nopen INPUT, '<', 'inputs/5';\n\nsub seat {\n  $_ = shift;\n\n  s/[BR]/1/g;\n  s/[FL]/0/g;\n\n  my ( $row, $column ) = (m/(\\d{7})(\\d{3})/);\n  $row = oct( \"0b$row\" );\n  $column = oct( \"0b$column\" );\n\n  [ $row, $column ];\n}\n\nsub seat_id {\n  my ($row, $column) = seat($_[0])->@*;\n\n  return $row * 8 + $column;\n}\n\nmy @ids;\npush @ids, seat_id($_) while <INPUT>;\n\nsay max(@ids);\n"
  },
  {
    "path": "advent-of-code/2020/05.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse Array::Utils qw(array_minus);\nuse List::Util qw(min max);\n\nmy $line = 'BFFFBBFRRR';\n\nopen INPUT, '<', 'inputs/5';\n\nsub seat {\n  $_ = shift;\n\n  s/[BR]/1/g;\n  s/[FL]/0/g;\n\n  my ( $row, $column ) = (m/(\\d{7})(\\d{3})/);\n  $row = oct( \"0b$row\" );\n  $column = oct( \"0b$column\" );\n\n  [ $row, $column ];\n}\n\nsub seat_id {\n  my ( $row, $column ) = seat( $_[0] )->@*;\n\n  return $row * 8 + $column;\n}\n\nmy @ids;\npush @ids, seat_id($_) while <INPUT>;\n\nmy @range = ( min(@ids) .. max(@ids) );\n\nsay array_minus(@range, @ids);\n\n"
  },
  {
    "path": "advent-of-code/2020/06.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse Data::Dump qw( dump );\nuse List::Util qw( reduce );\nuse List::MoreUtils qw( uniq );\n\nopen INPUT, '<', 'inputs/6' or die;\n\n$_ = do { local $/; <INPUT> };\n\nmy @chunks = split /\\n\\n/;\nchomp @chunks;\ns/\\n//g for @chunks;\n\ndump reduce { $a + $b }\n     map { scalar uniq split '' }\n     @chunks;\n\n"
  },
  {
    "path": "advent-of-code/2020/06.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse Data::Dump qw( dump );\nuse List::Util qw( reduce );\nuse List::MoreUtils qw( uniq );\nuse Set::Scalar;\n\nopen INPUT, '<', 'inputs/6' or die;\n\n$_ = do { local $/; <INPUT> };\n\nmy @chunks = split /\\n\\n/;\nchomp @chunks;\n\ndump reduce { $a + $b }\n     map { scalar $_->elements }\n     map { reduce { $a->intersection($b) } map { Set::Scalar->new(split '') } split \"\\n\" }\n     @chunks;\n"
  },
  {
    "path": "advent-of-code/2020/07.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse Data::Dump qw(dump);\n\nmy %bags;\n\nopen INPUT, '<', 'inputs/7' or die;\n\nwhile (<INPUT>) {\n  /^(.*)? bags contain (.*)\\.$/ or die;\n  my $color = $1;\n\n  if ( $2 eq 'no other bags' ) {\n    $bags{ $color } = [];\n    next;\n  }\n\n  my @options = split ', ', $2;\n\n  for ( @options ) {\n    /^(\\d+) (.*?) bags?$/ or die;\n    my ( $count, $inner_color ) = ( $1, $2 );\n    push @{ $bags{$color} }, $inner_color;\n  }\n}\n\nsub can_contain {\n  my ( $outer, $inner ) = @_;\n\n  my @stack = ( $outer );\n\n  while ( @stack ) {\n    my $key = shift @stack;\n    return 1 if ( $key eq $inner );\n    push @stack, $bags{$key}->@*;\n  }\n\n  0;\n}\n\nmy $count;\n\nfor ( keys %bags ) {\n  next if $_ eq 'shiny gold';\n  $count++ if can_contain( $_, 'shiny gold' );\n}\n\nsay $count;\n"
  },
  {
    "path": "advent-of-code/2020/07.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse List::Util qw( reduce );\nuse Data::Dump qw(dump);\n\nmy %bags;\n\nopen INPUT, '<', 'inputs/7' or die;\n\nwhile (<INPUT>) {\n  /^(.*)? bags contain (.*)\\.$/ or die;\n  my $color = $1;\n\n  if ( $2 eq 'no other bags' ) {\n    $bags{ $color } = [];\n    next;\n  }\n\n  my @options = split ', ', $2;\n\n  for ( @options ) {\n    /^(\\d+) (.*?) bags?$/ or die;\n    my ( $count, $inner_color ) = ( $1, $2 );\n    push @{ $bags{$color} }, { count => $count, color => $inner_color };\n  }\n}\n\n\nsub number_of_bags {\n  my ( $color ) = @_;\n\n  return 0 unless $bags{ $color }->@*;\n\n  reduce { $a + $b }\n    map { $_->{count} + $_->{count} * number_of_bags($_->{color}) }\n    $bags{ $color }->@*;\n}\n\n\nsay number_of_bags( 'shiny gold' );\n"
  },
  {
    "path": "advent-of-code/2020/08.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse experimental qw( switch );\n\nmy @instructions;\n\nopen INPUT, '<', 'inputs/8';\n\nwhile ( <INPUT> ) {\n  my ( $op, $arg ) = split ' ';\n  push @instructions, { op => $op, arg => $arg };\n}\n\nmy @executed;\n\nmy $ip = 0;\nmy $reg = 0;\n\nwhile (1) {\n  my ( $op, $arg ) = $instructions[$ip]->@{'op', 'arg'};\n\n  last if $executed[$ip];\n\n  $executed[$ip] = 1;\n  $ip++;\n\n  given ( $op ) {\n    when('nop') { }\n    when('jmp') { $ip += $arg - 1 }\n    when('acc') { $reg += $arg }\n  }\n\n}\n\nsay $reg;\n"
  },
  {
    "path": "advent-of-code/2020/08.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse experimental qw( switch );\n\nuse Storable qw( dclone );\n\nmy @instructions;\n\nopen INPUT, '<', 'inputs/8';\n\nwhile ( <INPUT> ) {\n  my ( $op, $arg ) = split ' ';\n  push @instructions, { op => $op, arg => $arg };\n}\n\nuse Data::Dump qw(dump);\n\nsub evaluate {\n  my ( $instructions ) = @_;\n\n  my @executed;\n  my $infinite = 0;\n  my $ip = 0;\n  my $reg = 0;\n\n  while ( $ip <= $#instructions ) {\n    my ( $op, $arg ) = $instructions->[$ip]->@{'op', 'arg'};\n\n    if ( $executed[$ip] ) {\n      $infinite = 1;\n      last;\n    }\n\n    $executed[$ip] = 1;\n    $ip++;\n\n    given ( $op ) {\n      when('nop') { }\n      when('jmp') { $ip += $arg - 1 }\n      when('acc') { $reg += $arg }\n    }\n  }\n\n  return { reg => $reg, infinite => $infinite };\n}\n\nuse Data::Dump qw(dump);\n\nfor my $i (0..$#instructions) {\n  my $modified = dclone( \\@instructions );\n\n  if ( $modified->[$i]{op} eq 'nop' ) {\n    $modified->[$i]{op} = 'jmp';\n  } elsif ( $modified->[$i]{op} eq 'jmp' ) {\n    $modified->[$i]{op} = 'nop';\n  } else {\n    next\n  }\n\n  my $result = evaluate( $modified );\n\n  if ( ! $result->{infinite} ) {\n    say $result->{reg};\n  }\n}\n\n\n\n__DATA__\nnop +0\nacc +1\njmp +4\nacc +3\njmp -3\nacc -99\nacc +1\njmp -4\nacc +6\n"
  },
  {
    "path": "advent-of-code/2020/09.1.pl",
    "content": "use v5.32;\nuse warnings;\n\nuse Data::Dump qw(dump);\n\nopen INPUT, '<', 'inputs/9';\n\nmy $preamble = 25;\n\nmy $consume = $preamble;\nmy @window;\nmy %counts;\n\nsub is_sum_of_two {\n  my ( $number, $counts ) = @_;\n\n  for my $key ( %$counts ) {\n    next unless $counts->{$key};\n\n    my $difference = $number - $key;\n\n    return 1 if $counts->{$difference} and ($difference != $key or $counts->{$difference} >= 2);\n  }\n\n  0\n}\n\nwhile (<INPUT>) {\n  chomp;\n\n  if ( $consume ) {\n    push @window, $_;\n    $counts{$_}++;\n    $consume--;\n\n    next;\n  }\n\n  unless (is_sum_of_two( $_, \\%counts )) {\n    say \"invalid: $_\";\n    last;\n  }\n\n  my $removed = shift @window;\n  $counts{$removed}--;\n\n  push @window, $_;\n  $counts{$_}++;\n}\n"
  },
  {
    "path": "advent-of-code/2020/09.2.pl",
    "content": "use v5.32;\nuse warnings;\n\nuse List::Util qw( min max );\nuse Data::Dump qw(dump);\n\nopen INPUT, '<', 'inputs/9';\nmy $preamble = 25;\n\nsub is_sum_of_two {\n  my ( $number, $counts ) = @_;\n\n  for my $key ( %$counts ) {\n    next unless $counts->{$key};\n\n    my $difference = $number - $key;\n\n    return 1 if $counts->{$difference} and ($difference != $key or $counts->{$difference} >= 2);\n  }\n\n  0\n}\n\nsub weakness {\n  my ( $number, $numbers ) = @_;\n\n\n  for my $i ( 0 .. $#$numbers ) {\n    my $sum = 0;\n    my $j;\n\n    for ( $j = $i; $j <= $#$numbers; $j++ ) {\n      $sum += $numbers->[$j];\n      last if $sum >= $number;\n    }\n\n    next unless $sum == $number;\n\n    my @subrange = @{$numbers}[ $i .. $j ];\n    my $min = min @subrange;\n    my $max = max @subrange;\n    my $weakness = $min + $max;\n\n    return $weakness;\n  }\n}\n\nmy $consume = $preamble;\nmy @numbers;\nmy @window;\nmy %counts;\n\nwhile (<INPUT>) {\n  chomp;\n\n  push @numbers, $_;\n\n  if ( $consume ) {\n    push @window, $_;\n    $counts{$_}++;\n    $consume--;\n\n    next;\n  }\n\n  unless ( is_sum_of_two( $_, \\%counts ) ) {\n    pop @numbers;\n    my $weakness = weakness( $_, \\@numbers );\n    say \"invalid: $_\";\n    say \"weakness: $weakness\";\n\n    last;\n  }\n\n  my $removed = shift @window;\n  $counts{$removed}--;\n\n  push @window, $_;\n  $counts{$_}++;\n}\n"
  },
  {
    "path": "advent-of-code/2020/10.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse List::Util qw( max );\n\nopen INPUT, '<', 'inputs/10';\n\nmy @numbers = ( 0 );\n\nwhile (<INPUT>) {\n  chomp;\n  push @numbers, $_;\n}\n\n@numbers = sort { $a <=> $b } @numbers;\npush @numbers, max( @numbers ) + 3;\n\nmy %diffs;\n\nfor my $i ( 0 .. $#numbers - 1 ) {\n  my $diff = $numbers[$i + 1] - $numbers[$i];\n  $diffs{$diff}++\n}\n\nsay $diffs{1} * $diffs{3}\n"
  },
  {
    "path": "advent-of-code/2020/10.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse List::Util qw( max reduce );\n\nopen INPUT, '<', 'inputs/10';\n\nmy @numbers;\n\nwhile (<INPUT>) {\n  chomp;\n  push @numbers, $_;\n}\n\n@numbers = sort { $a <=> $b } @numbers;\npush @numbers, max( @numbers ) + 3;\n\nmy %diffs;\n\nfor my $i ( 0 .. $#numbers - 1 ) {\n  my $diff = $numbers[$i + 1] - $numbers[$i];\n  $diffs{$diff}++\n}\n\nmy @count = (1);\n\nfor my $i ( @numbers ) {\n  my $possible = reduce { ($a // 0) + ($b // 0) } @count[max($i - 3, 0) .. $i - 1];\n  $count[$i] = $possible;\n}\n\nsay $count[max(@numbers)];\n"
  },
  {
    "path": "advent-of-code/2020/11.1.pl",
    "content": "use v5.32;\nuse warnings;\n\nopen INPUT, '<', 'inputs/11';\n\nmy $plan;\n\nwhile ( <INPUT> ) {\n  chomp;\n  push @$plan, [ split '' ];\n}\n\nsub neighbours {\n  my ( $x, $y, $h, $w ) = @_;\n\n  my @result;\n\n  for my $a ( $x - 1 .. $x + 1 ) {\n    for my $b ( $y - 1 .. $y + 1 ) {\n      push @result, [ $a, $b ] if ( 0 <= $a and $a < $h and 0 <= $b and $b < $w and ( $a != $x or $b != $y ) );\n    }\n  }\n\n  @result;\n}\n\nsub iterate {\n  my $plan = shift;\n  my $height = @$plan;\n  my $width = @{$plan->[0]};\n\n  my $result = [];\n\n  for my $i ( 0 .. $height - 1 ) {\n    for my $j ( 0 .. $width - 1 ) {\n      my @neighbours = neighbours( $i, $j, $height, $width );\n      my $seat = $plan->[ $i ][ $j ];\n      my $taken = 0;\n\n      for ( @neighbours ) {\n        $taken++ if $plan->[ $_->[0] ][ $_->[1] ] eq '#';\n      }\n\n      if ( $seat eq 'L' and $taken == 0 ) {\n        $seat = '#';\n      } elsif ( $seat eq '#' and $taken >= 4 ) {\n        $seat = 'L';\n      }\n\n      $result->[ $i ][ $j ] = $seat;\n    }\n  }\n\n  $result;\n}\n\nfor ( 0 .. 100000 ) {\n  my $before = join \"\\n\", map { join '', @$_ } @$plan;\n\n  $plan = iterate( $plan );\n\n  my $after = join \"\\n\", map { join '', @$_ } @$plan;\n\n  if ( $before eq $after ) {\n    my $count = () = $after =~ /#/g;\n    say $count;\n    last;\n  }\n}\n\n"
  },
  {
    "path": "advent-of-code/2020/11.2.pl",
    "content": "use v5.32;\nuse warnings;\n\nopen INPUT, '<', 'inputs/11';\n\nmy $plan;\n\nwhile ( <INPUT> ) {\n  chomp;\n  push @$plan, [ split '' ];\n}\n\nsub neighbours {\n  my ( $x, $y, $h, $w ) = @_;\n\n  my @result;\n\n  for my $a ( $x - 1 .. $x + 1 ) {\n    for my $b ( $y - 1 .. $y + 1 ) {\n      push @result, [ $a, $b ] if ( 0 <= $a and $a < $h and 0 <= $b and $b < $w and ( $a != $x or $b != $y ) );\n    }\n  }\n\n  @result;\n}\n\nsub iterate {\n  my $plan = shift;\n  my $height = @$plan;\n  my $width = @{$plan->[0]};\n\n  my $result = [];\n\n  for my $i ( 0 .. $height - 1 ) {\n    for my $j ( 0 .. $width - 1 ) {\n      my $seat = $plan->[ $i ][ $j ];\n      my $taken = visible_occupied( $plan, $i, $j );\n\n      if ( $seat eq 'L' and $taken == 0 ) {\n        $seat = '#';\n      } elsif ( $seat eq '#' and $taken >= 5 ) {\n        $seat = 'L';\n      }\n\n      $result->[ $i ][ $j ] = $seat;\n    }\n  }\n\n  $result;\n}\n\nsub first_in_direction {\n  my ( $plan, $x, $y, $direction ) = @_;\n  my $height = @$plan;\n  my $width = @{$plan->[0]};\n\n  $x += $direction->[0];\n  $y += $direction->[1];\n\n  while ( 0 <= $x and $x < $height and 0 <= $y and $y < $width ) {\n    my $seat = $plan->[ $x ][ $y ];\n    if ( $seat ne '.' ) {\n      return $seat;\n    }\n\n    $x += $direction->[0];\n    $y += $direction->[1];\n  }\n\n  return '.';\n}\n\nsub visible_occupied {\n  my ( $plan, $x, $y ) = @_;\n\n  my @directions = ( [0, 1], [0, -1], [1, 0], [-1, 0], [1, 1], [-1, 1], [1, -1], [-1, -1] );\n  my @seen = map { first_in_direction( $plan, $x, $y, $_ ) } @directions;\n  my $count = 0;\n  for ( @seen ) {\n    $count++ if $_ eq '#';\n  }\n\n  $count;\n}\n\nfor ( 0 .. 100000 ) {\n  my $before = join \"\\n\", map { join '', @$_ } @$plan;\n\n  $plan = iterate( $plan );\n\n  my $after = join \"\\n\", map { join '', @$_ } @$plan;\n\n  if ( $before eq $after ) {\n    my $count = () = $after =~ /#/g;\n    say $count;\n    last;\n  }\n}\n"
  },
  {
    "path": "advent-of-code/2020/12.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse experimental qw(smartmatch switch);\n\nopen INPUT, '<', 'inputs/12';\n\nmy @pos = ( 0, 0 );\nmy @dir = ( 0, 1 );\n\nsub rotate {\n  my ( $deg, $a, $b ) = @_;\n  my @dir = $deg > 0 ? ( 1, -1 ) : ( -1, 1 );\n  my $steps = abs($deg) / 90;\n\n  for ( 1..$steps ) {\n    ( $a, $b ) = ( $b * $dir[0], $a * $dir[1] );\n  }\n\n  ( $a, $b );\n}\n\nwhile (<INPUT>) {\n  /^([NSEWLRF])(\\d+)$/;\n\n  my ( $cmd, $d ) = ( $1, $2 );\n  my ( $x, $y, $a, $b ) = ( @pos, @dir );\n\n  given ( $cmd ) {\n    when('F') { @pos = ( $x + $a * $d, $y + $b * $d ) }\n    when('L') { @dir = rotate(-$d, $a, $b) }\n    when('R') { @dir = rotate($d, $a, $b) }\n    when('N') { @pos = ( $x - $d, $y ) }\n    when('S') { @pos = ( $x + $d, $y ) }\n    when('W') { @pos = ( $x, $y - $d ) }\n    when('E') { @pos = ( $x, $y + $d ) }\n  }\n\n}\n\nsay abs($pos[0]) + abs($pos[1]);\n\n__END__\nF10\nN3\nF7\nR90\nF11\n"
  },
  {
    "path": "advent-of-code/2020/12.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse experimental qw(smartmatch switch);\n\nopen INPUT, '<', 'inputs/12';\n\nmy @pos = ( 0, 0 );\nmy @wp = ( -1, 10 );\n\nsub rotate {\n  my ( $deg, $a, $b ) = @_;\n  my @dir = $deg > 0 ? ( 1, -1 ) : ( -1, 1 );\n  my $steps = abs($deg) / 90;\n\n  for ( 1..$steps ) {\n    ( $a, $b ) = ( $b * $dir[0], $a * $dir[1] );\n  }\n\n  ( $a, $b );\n}\n\nwhile (<INPUT>) {\n  chomp;\n  /^([NSEWLRF])(\\d+)$/;\n\n  my ( $cmd, $d ) = ( $1, $2 );\n  my ( $x, $y, $a, $b ) = ( @pos, @wp );\n\n  say \"$_: [$x, $y] // [$a, $b]\";\n\n  given ( $cmd ) {\n    when('F') { @pos = ( $x + $a * $d, $y + $b * $d ) }\n    when('L') { @wp = rotate(-$d, $a, $b) }\n    when('R') { @wp = rotate($d, $a, $b) }\n    when('N') { @wp = ( $a - $d, $b ) }\n    when('S') { @wp = ( $a + $d, $b ) }\n    when('W') { @wp = ( $a, $b - $d ) }\n    when('E') { @wp = ( $a, $b + $d ) }\n  }\n\n}\n\nsay abs($pos[0]) + abs($pos[1]);\n"
  },
  {
    "path": "advent-of-code/2020/13.1.pl",
    "content": "use v5.32;\nuse warnings;\n\nopen INPUT, '<', 'inputs/13';\nmy $contents = do { local $/; <INPUT> };\n\nmy ( $time, $schedule ) = split \"\\n\", $contents;\n\nmy @ids = grep { $_ ne 'x' } split ',', $schedule;\n\nmy $min = 10_000_000_000;\nmy $answer = 0;\n\nfor my $id ( @ids ) {\n  my $wait = ($id - $time % $id);\n  if ( $wait < $min ) {\n    $min = $wait;\n    $answer = $wait * $id;\n  }\n}\n\nsay $answer;\n__END__\n939\n7,13,x,x,59,x,31,19\n"
  },
  {
    "path": "advent-of-code/2020/13.2.pl",
    "content": "use v5.32;\nuse warnings;\n\nuse Math::Utils qw( gcd );\n\nopen INPUT, '<', 'inputs/13';\nmy $contents = do { local $/; <INPUT> };\n\nmy ( $time, $schedule ) = split \"\\n\", $contents;\n\nmy @ids = split ',', $schedule;\n\nmy $start = shift @ids;\nmy $offset = 0;\nmy $step = $start;\n\nfor my $id ( @ids ) {\n  $offset += 1;\n  next if $id eq 'x';\n  $start += $step until ( $start + $offset ) % $id == 0 and $start >= $id ;\n  $step = ($step * $id) / gcd( $step, $id );\n}\n\nsay $start;\n"
  },
  {
    "path": "advent-of-code/2020/14.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse experimental \"switch\";\nuse bigint;\nuse List::Util qw( sum );\n\nopen INPUT, '<', 'inputs/14';\n\nsub bin { oct \"0b$_[0]\" }\n\nsub mask {\n  my ( $mask, $num ) = @_;\n\n  ( $num & bin( $mask =~ s/X/1/rg ) ) | bin( $mask =~ s/X/0/rg );\n}\n\n\nmy $mask;\nmy %mem;\n\nwhile (<INPUT>) {\n  given ($_) {\n    when(/^mask = ([X01]+)$/) {\n      $mask = $1;\n    }\n    when(/^mem\\[(\\d+)\\] = (\\d+)$/) {\n      $mem{$1} = mask( $mask, $2 );\n    }\n    default { say \"OH NON NON ON ON O\" }\n  }\n}\n\nsay sum values(%mem);\n"
  },
  {
    "path": "advent-of-code/2020/14.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse experimental \"switch\";\nuse bigint;\nuse List::Util qw( sum );\nuse List::MoreUtils qw( uniq zip6 );\n\nopen INPUT, '<', 'inputs/14';\n\nsub bin { oct \"0b$_[0]\" }\n\nsub mask {\n  my ( $mask, $addr ) = @_;\n  my @mask = split '', $mask;\n  my @addr = split '', sprintf( \"%036b\", $addr );\n\n  variants( join \"\", map { $_->[0] == 1 ? '1' : $_->[0] eq 'X' ? 'X' : $_->[1] } zip6( @mask, @addr ) );\n}\n\nsub variants {\n  my ( $mask ) = @_;\n  my @result;\n\n  return ( $mask ) unless $mask =~ m/^([01]*)(?:(X)(.*))$/;\n\n  my ( $prefix, $suffix ) = ( $1, $3 );\n\n  map { ( \"${prefix}0$_\", \"${prefix}1$_\" ) } variants( $suffix );\n}\n\nmy $mask;\nmy %mem;\n\nwhile (<INPUT>) {\n  given ($_) {\n    when(/^mask = ([X01]+)$/) {\n      $mask = $1;\n    }\n    when(/^mem\\[(\\d+)\\] = (\\d+)$/) {\n      my ( $x, $y ) = ( $1, $2 );\n      my @addrs = mask( $mask, $1 );\n\n      $mem{$_} = $y for ( @addrs );\n    }\n    default { say \"OH NON NON ON ON O\" }\n  }\n}\n\nsay sum values(%mem);\n"
  },
  {
    "path": "advent-of-code/2020/15.1.pl",
    "content": "use v5.32;\nuse warnings;\n\nmy @numbers = ( 15, 12, 0, 14, 3, 1 );\n\nmy %spoken;\nmy $next = shift @numbers;\nmy $turn = 1;\n\nfor my $number ( @numbers ) {\n  $spoken{$next} = $turn++;\n  $next = $number;\n}\n\nwhile ( $turn < 2020 ) {\n  my $said;\n\n  if ( $spoken{$next} ) {\n    $said = $turn - $spoken{$next};\n  } else {\n    $said = 0;\n  }\n\n  $spoken{$next} = $turn;\n  $turn++;\n  $next = $said;\n}\n\nsay $next;\n"
  },
  {
    "path": "advent-of-code/2020/15.2.pl",
    "content": "use v5.32;\nuse warnings;\n\nmy @numbers = ( 15, 12, 0, 14, 3, 1 );\n\nmy %spoken;\nmy $next = shift @numbers;\nmy $turn = 1;\n\nfor my $number ( @numbers ) {\n  $spoken{$next} = $turn++;\n  $next = $number;\n}\n\nwhile ( $turn < 30000000 ) {\n  my $said;\n\n  if ( $spoken{$next} ) {\n    $said = $turn - $spoken{$next};\n  } else {\n    $said = 0;\n  }\n\n  $spoken{$next} = $turn;\n  $turn++;\n  $next = $said;\n}\n\nsay $next;\n"
  },
  {
    "path": "advent-of-code/2020/16.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse List::Util qw( none );\n\nopen INPUT, '<', 'inputs/16';\n\nmy $contents = do { local $/; <INPUT> };\nmy @parts = split \"\\n\\n\", $contents;\n\nmy %rules;\nmy @ticket;\nmy @nearby;\n\nfor ( split \"\\n\", $parts[0] ) {\n  /^([^:]+): (\\d+)-(\\d+) or (\\d+)-(\\d+)$/ or die $_;\n\n  my ( $name, $a, $b, $c, $d ) = ( $1, $2, $3, $4, $5 );\n\n  $rules{$name} = sub { my $x = $_[0]; $a <= $x and $x <= $b or $c <= $x and $x <= $d };\n}\n\n@ticket = ( split \",\", ( split(\"\\n\", $parts[1]) )[1] );\n\n$parts[2] =~ s/^nearby tickets:\\n//sg;\n\nfor ( split \"\\n\", $parts[2] ) {\n  push @nearby, [ split \",\" ];\n}\n\nmy $sum;\n\nfor my $ticket ( @nearby ) {\n  for my $number ( @$ticket ) {\n    $sum += $number if none { $_->($number) } (values %rules);\n  }\n}\n\nsay $sum;\n"
  },
  {
    "path": "advent-of-code/2020/16.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse List::Util qw( none );\nuse Set::Scalar;\n\nopen INPUT, '<', 'inputs/16';\n\nmy $contents = do { local $/; <INPUT> };\nmy @parts = split \"\\n\\n\", $contents;\n\nmy %rules;\nmy @ticket;\nmy @nearby;\n\nfor ( split \"\\n\", $parts[0] ) {\n  /^([^:]+): (\\d+)-(\\d+) or (\\d+)-(\\d+)$/ or die $_;\n\n  my ( $name, $a, $b, $c, $d ) = ( $1, $2, $3, $4, $5 );\n\n  $rules{$name} = sub { my $x = $_[0]; $a <= $x and $x <= $b or $c <= $x and $x <= $d };\n}\n\n@ticket = ( split \",\", ( split(\"\\n\", $parts[1]) )[1] );\n\n$parts[2] =~ s/^nearby tickets:\\n//sg;\n\nfor ( split \"\\n\", $parts[2] ) {\n  push @nearby, [ split \",\" ];\n}\n\nsub is_valid {\n  my $ticket = shift;\n\n  for my $number ( @$ticket ) {\n    return 0 if none { $_->($number) } (values %rules);\n  }\n\n  1;\n}\n\nmy @valid = grep { is_valid($_) } @nearby;\n\nmy @possible = map { Set::Scalar->new( keys(%rules) ) } ( 1 .. %rules );\n\nfor my $ticket ( @valid ) {\n  my @numbers = @$ticket;\n  for my $i ( 0 .. $#numbers ) {\n    while ( my ( $name, $fn ) = each %rules ) {\n      if ( ! $fn->( $numbers[$i] ) ) {\n        $possible[$i]->delete( $name );\n      }\n    }\n  }\n}\n\nfor ( 0 .. $#possible ) {\n  my $remove = Set::Scalar->new( map { $_->elements } grep { $_->size == 1 } @possible );\n\n  for my $set ( @possible ) {\n    $set -= $remove if ( $set->size > 1 );\n  }\n}\n\nmy %positions;\n\nfor ( 0 .. $#possible ) {\n  my $set = $possible[$_];\n  die \"collision\" if $set->size != 1;\n  $positions{ ($set->members)[0] } = $_;\n}\n\nmy $result = 1;\n\nwhile ( my ( $name, $pos ) = each %positions ) {\n  next unless $name =~ /^departure /;\n  $result *= $ticket[$pos];\n}\n\nsay $result;\n"
  },
  {
    "path": "advent-of-code/2020/17.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse Hash::MultiKey;\nuse List::Util qw( sum uniq );\n\nmy %game;\ntie %game, 'Hash::MultiKey';\n\nmy $x = 0;\n\nopen INPUT, '<', 'inputs/17';\n\nwhile (<INPUT>) {\n  my @chars = split '';\n\n  for my $y ( 0 .. $#chars ) {\n    if ( $chars[$y] eq '#' ) {\n      $game{ [ $x, $y, 0] } = 1;\n    }\n  }\n\n  $x++;\n}\n\nsub neighbours {\n  my ( $x, $y, $z ) = $_[0]->@*;\n\n  my @result;\n\n  for my $dx ( -1 .. 1 ) {\n    for my $dy ( -1 .. 1 ) {\n      for my $dz ( -1 .. 1 ) {\n        next unless $dx || $dy || $dz;\n        push @result, [ $x + $dx, $y + $dy, $z + $dz ];\n      }\n    }\n  }\n\n  @result;\n}\n\nfor ( 1 .. 6 ) {\n  my %next;\n  tie %next, 'Hash::MultiKey';\n\n  my @space;\n\n  while ( my ( $cube, $alive ) = each %game ) {\n    next unless $alive;\n    for my $neighbour ( neighbours( $cube ) ) {\n      push @space, join(',', @$neighbour);\n    }\n  }\n\n  @space = map { [ split ',' ] } uniq @space;\n\n  for my $cube ( @space ) {\n    my $count = sum( grep { defined $_ } @game{ neighbours( $cube ) } );\n    my $alive = $game{ $cube } // 0;\n    $next{ $cube } = 1 if  $count == 3 || ( $alive && $count == 2 ) ;\n  }\n\n  %game = %next;\n}\n\nsay sum values( %game );\n"
  },
  {
    "path": "advent-of-code/2020/17.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse Hash::MultiKey;\nuse List::Util qw( sum uniq );\n\nmy %game;\ntie %game, 'Hash::MultiKey';\n\nmy $x = 0;\n\nopen INPUT, '<', 'inputs/17';\n\nwhile (<INPUT>) {\n  my @chars = split '';\n\n  for my $y ( 0 .. $#chars ) {\n    if ( $chars[$y] eq '#' ) {\n      $game{ [ $x, $y, 0, 0 ] } = 1;\n    }\n  }\n\n  $x++;\n}\n\nsub neighbours {\n  my ( $x, $y, $z, $w ) = $_[0]->@*;\n\n  my @result;\n\n  for my $dx ( -1 .. 1 ) {\n    for my $dy ( -1 .. 1 ) {\n      for my $dz ( -1 .. 1 ) {\n        for my $dw ( -1 .. 1 ) {\n          next unless $dx || $dy || $dz || $dw;\n          push @result, [ $x + $dx, $y + $dy, $z + $dz, $w + $dw ];\n        }\n      }\n    }\n  }\n\n  @result;\n}\n\nfor ( 1 .. 6 ) {\n  my %next;\n  tie %next, 'Hash::MultiKey';\n\n  my @space;\n\n  while ( my ( $cube, $alive ) = each %game ) {\n    next unless $alive;\n    for my $neighbour ( neighbours( $cube ) ) {\n      push @space, join(',', @$neighbour);\n    }\n  }\n\n  @space = map { [ split ',' ] } uniq @space;\n\n  for my $cube ( @space ) {\n    my $count = sum( grep { defined $_ } @game{ neighbours( $cube ) } ) // 0;\n    my $alive = $game{ $cube } // 0;\n    $next{ $cube } = 1 if $count == 3 || ( $alive && $count == 2 ) ;\n  }\n\n  %game = %next;\n}\n\nsay sum values( %game );\n"
  },
  {
    "path": "advent-of-code/2020/18.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse experimental 'switch';\n\nopen INPUT, '<', 'inputs/18';\n\nsub evaluate {\n  my $tokens = shift;\n  my $op = sub { $_[1] };\n  my $result = 0;\n\n  while (my $next = shift( @$tokens )) {\n    given ( $next ) {\n      when( /(\\d)/ ) { $result = $op->( $result, $1 ) }\n      when( '+' ) { $op = sub { $_[0] + $_[1] } }\n      when( '*' ) { $op = sub { $_[0] * $_[1] } }\n      when( '(' ) { $result = $op->( $result, evaluate( $tokens ) ) }\n      when( ')' ) { return $result }\n      default { die \"unexpected token: $next\"; }\n    }\n  }\n\n  $result;\n}\n\nsub parse {\n  $_ = shift;\n  s/ //g;\n  chomp;\n  my @tokens = split '';\n\n  evaluate( \\@tokens );\n}\n\nmy $result = 0;\n\nwhile (<INPUT>) {\n  $result += parse( $_ );\n}\n\nsay $result;\n\n__DATA__\n1 + (2 * 3) + (4 * (5 + 6))\n2 * 3 + (4 * 5)\n5 + (8 * 3 + 9 + 3 * 4 * 3)\n5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))\n((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2\n"
  },
  {
    "path": "advent-of-code/2020/18.2.pl",
    "content": "use v5.32;\nuse warnings;\n\nmy $parse = qr{\n  (?&MULT) (?{ $_ = $^R->[1] })\n\n  (?(DEFINE)\n    (?<NUMBER> ( \\d ) (?{ [$^R, eval $^N] }) )\n\n    (?<ATOM> ( (?&NUMBER) | \\( (?&MULT) \\) ) )\n\n    (?<MULT>\n      (?&ADD) (?{ [ $^R->[0], $^R->[1] ] })\n      (?: \\* (?&ADD) (?{ [ $^R->[0][0], $^R->[0][1] * $^R->[1] ] }) )*\n    )\n\n    (?<ADD>\n      (?&ATOM) (?{ [ $^R->[0], $^R->[1] ] })\n      (?: \\+ (?&ATOM) (?{ [ $^R->[0][0], $^R->[0][1] + $^R->[1] ] }) )*\n    )\n  )\n}xms;\n\n\nsub parse {\n  local $_ = shift;\n  local $^R;\n\n  s/ //g;\n  eval { m{\\A$parse\\z} } and return $_;\n\n  die $@;\n}\n\nopen INPUT, '<', 'inputs/18';\n\nmy $result;\n$result += parse($_) while (<INPUT>);\nsay $result;\n"
  },
  {
    "path": "advent-of-code/2020/19.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse experimental 'switch';\n\nopen INPUT, '<', 'inputs/19';\nmy $contents = do { local $/; <INPUT> };\nmy @parts = split \"\\n\\n\", $contents;\n\nmy %definitions;\n\nfor ( split \"\\n\", $parts[0] ) {\n  m/^(\\d+): (.*)$/;\n  $definitions{ $1 } = $2;\n}\n\nmy %compiled;\n\nsub compile {\n  my $n = shift;\n  return $compiled{ $n } if exists $compiled{ $n };\n\n  my $compiled;\n  given ( $definitions{ $n } ) {\n    when(/^ \" (\\w) \" $/x) {\n      $compiled = $1\n    }\n    when(/^ (\\d+) ( \\s+ ( \\d+ | \\| ) )* $/x) {\n      $compiled = '(' . ( join '|', map { s/(\\d+)\\s*/compile( $1 )/eg; $_ } split /\\s*\\|\\s*/ ) . ')';\n    }\n    default {\n      die \"can't compile: $_\",\n    }\n  }\n\n  $compiled{ $n } = $compiled;\n}\n\nmy $pattern = compile( 0 );\nmy $regex = qr/^$pattern$/;\n\nmy $count = 0;\n\nfor ( split \"\\n\", $parts[1] ) {\n  $count++ if $_ =~ $regex;\n}\n\nsay $count;\n"
  },
  {
    "path": "advent-of-code/2020/19.2.pl",
    "content": "use v5.32;\nuse warnings;\n\nopen STDIN, '<', 'inputs/19';\n\n$/ x= 2;\n$_ = <>;\ns/^8: .*$/8: 42 | 42 8/m;\ns/^11: .*$/11: 42 31 | 42 11 31/m;\ns/^(\\d+): (.*)$/\"(?<g$1> (\" . ( $2 =~ s#(\\d+)#(?&g$1)#gr ) . \") )\"/gem;\ns/\\(\"(\\w)\"\\)/$1/g;\nmy $pattern = qr/^(?&g0) (?(DEFINE) $_)$/x;\nsay scalar grep { m/$pattern/ } split \"\\n\", <>;\n"
  },
  {
    "path": "advent-of-code/2020/20.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse List::Util qw( first min max reduce );\n\nopen STDIN, '<', 'inputs/20';\n\nmy @tiles;\n\nsub bin {\n  $_ = shift;\n  s/\\./0/g;\n  s/#/1/g;\n  oct \"0b$_\";\n}\n\nsub rotate {\n  my ( $t, $r, $b, $l ) = @_;\n\n  return ( scalar reverse( $l ), $t, scalar reverse( $r ), $b );\n}\n\nsub hpose {\n  my ( $t, $r, $b, $l ) = @_;\n\n  return ( $b, scalar reverse( $r ), $t, scalar reverse( $l ) );\n}\n\n$/ x= 2;\nwhile (<>) {\n  m/Tile (\\d+):/ or die $_;\n\n  my $id = $1;\n  my ( $first , @lines ) = split \"\\n\";\n\n  my ( $top, $bottom ) = ( $lines[0], $lines[-1] );\n  my $left = join '', map { substr $_, 0, 1 } @lines;\n  my $right = join '', map { substr $_, -1, 1 } @lines;\n\n  my @row = ( $top, $right, $bottom, $left );\n\n  my @variants;\n  push @variants, [ @row ], [ hpose( @row ) ];\n  @row = rotate( @row );\n  push @variants, [ @row ], [ hpose( @row ) ];\n  @row = rotate( @row );\n  push @variants, [ @row ], [ hpose( @row ) ];\n  @row = rotate( @row );\n  push @variants, [ @row ], [ hpose( @row ) ];\n\n  push @tiles, {\n    id => $id,\n    lines => [ @lines ],\n    left => $left,\n    right => $right,\n    top => $top,\n    bottom => $bottom,\n    variants => [ map { [ map { bin( $_ ) } @$_ ] } @variants ]\n  };\n}\n\n$tiles[0]{pos} = [0, 0];\n$tiles[0]{rotation} = $tiles[0]{variants}[0];\n\nmy @unchecked = ( $tiles[0] );\n\nwhile ( @unchecked ) {\n  my $tile = shift @unchecked;\n  my ( $top, $right, $bottom, $left ) = $tile->{rotation}->@*;\n  my ( $x, $y ) = $tile->{pos}->@*;\n\n  for my $other ( @tiles ) {\n    next if exists $other->{pos};\n\n    for my $variant ( $other->{variants}->@* ) {\n      if ( $top == $variant->[2] ) {\n        $other->{pos} = [ $x - 1, $y ];\n        $other->{rotation} = $variant;\n        push @unchecked, $other;\n      } elsif ( $right == $variant->[3] ) {\n        $other->{pos} = [ $x, $y + 1 ];\n        $other->{rotation} = $variant;\n        push @unchecked, $other;\n      } elsif ( $bottom == $variant->[0] ) {\n        $other->{pos} = [ $x + 1, $y ];\n        $other->{rotation} = $variant;\n        push @unchecked, $other;\n      } elsif ( $left == $variant->[1] ) {\n        $other->{pos} = [ $x, $y - 1 ];\n        $other->{rotation} = $variant;\n        push @unchecked, $other;\n      }\n    }\n  }\n}\n\nmy $top = min map { $_->{pos}[0] } @tiles;\nmy $bottom = max map { $_->{pos}[0] } @tiles;\nmy $left = min map { $_->{pos}[1] } @tiles;\nmy $right = max map { $_->{pos}[1] } @tiles;\n\nmy @corners = (\n (first { $_->{pos}[0] == $top && $_->{pos}[1] == $left } @tiles)->{id},\n (first { $_->{pos}[0] == $top && $_->{pos}[1] == $right } @tiles)->{id},\n (first { $_->{pos}[0] == $bottom && $_->{pos}[1] == $left } @tiles)->{id},\n (first { $_->{pos}[0] == $bottom && $_->{pos}[1] == $right } @tiles)->{id},\n);\n\nsay reduce { $a * $b } @corners;\n"
  },
  {
    "path": "advent-of-code/2020/20.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse List::Util qw( first min max reduce );\nuse List::MoreUtils qw( all );\nuse Hash::MultiKey;\n\nuse experimental 'switch';\n\nopen STDIN, '>&', DATA;\nopen STDIN, '<', 'inputs/20';\n\nmy @tiles;\n\nsub bin {\n  $_ = shift;\n  s/\\./0/g;\n  s/#/1/g;\n  oct \"0b$_\";\n}\n\nsub rotate {\n  my ( $t, $r, $b, $l ) = @_;\n\n  return ( scalar reverse( $l ), $t, scalar reverse( $r ), $b );\n}\n\nsub hpose {\n  my ( $t, $r, $b, $l ) = @_;\n\n  return ( $b, scalar reverse( $r ), $t, scalar reverse( $l ) );\n}\n\n$/ x= 2;\nwhile (<>) {\n  m/Tile (\\d+):/ or die $_;\n\n  my $id = $1;\n  my ( $first , @lines ) = split \"\\n\";\n\n  my ( $top, $bottom ) = ( $lines[0], $lines[-1] );\n  my $left = join '', map { substr $_, 0, 1 } @lines;\n  my $right = join '', map { substr $_, -1, 1 } @lines;\n\n  my @row = ( $top, $right, $bottom, $left );\n\n  my @images;\n  push @images, [ @row ], [ hpose( @row ) ];\n  @row = rotate( @row );\n  push @images, [ @row ], [ hpose( @row ) ];\n  @row = rotate( @row );\n  push @images, [ @row ], [ hpose( @row ) ];\n  @row = rotate( @row );\n  push @images, [ @row ], [ hpose( @row ) ];\n\n  push @tiles, {\n    id => $id,\n    image => [ map { [split ''] } @lines ],\n    left => $left,\n    right => $right,\n    top => $top,\n    bottom => $bottom,\n    variants => [ map { [ map { bin( $_ ) } @$_ ] } @images ]\n  };\n}\n\n$tiles[0]{pos} = [0, 0];\n$tiles[0]{rotation} = $tiles[0]{variants}[0];\n$tiles[0]{orientation} = 0;\n\nmy @unchecked = ( $tiles[0] );\n\nsub orient {\n  my ( $image, $index ) = @_;\n\n  my $s = $#{$image->[0]};\n\n  my $pick;\n\n  given ($index) {\n    when(0) { $pick = sub { my ( $a, $b ) = @_; $image->[$a][$b] } }\n    when(1) { $pick = sub { my ( $a, $b ) = @_; $image->[$s - $a][$b] } }\n    when(2) { $pick = sub { my ( $a, $b ) = @_; $image->[$s - $b][$a] } }\n    when(3) { $pick = sub { my ( $a, $b ) = @_; $image->[$s - $b][$s - $a] } }\n    when(4) { $pick = sub { my ( $a, $b ) = @_; $image->[$s - $a][$s - $b] } }\n    when(5) { $pick = sub { my ( $a, $b ) = @_; $image->[$a][$s - $b] } }\n    when(6) { $pick = sub { my ( $a, $b ) = @_; $image->[$b][$s - $a] } }\n    when(7) { $pick = sub { my ( $a, $b ) = @_; $image->[$b][$a] } }\n  }\n\n  my @result;\n  for my $x ( 0 .. $s ) {\n    my @line;\n    for my $y ( 0 .. $s ) {\n      push @line, $pick->( $x, $y );\n    }\n    push @result, [ @line ];\n  }\n\n  \\@result;\n}\n\nwhile ( @unchecked ) {\n  my $tile = shift @unchecked;\n  my ( $top, $right, $bottom, $left ) = $tile->{rotation}->@*;\n  my ( $x, $y ) = $tile->{pos}->@*;\n\n  for my $other ( @tiles ) {\n    next if exists $other->{pos};\n\n    for my $i ( 0..$#{$other->{variants}} ) {\n      my $variant = $other->{variants}[$i];\n\n      use Data::Dump qw(dump);\n\n      if ( $top == $variant->[2] ) {\n        $other->{pos} = [ $x - 1, $y ];\n        $other->{rotation} = $variant;\n        $other->{orientation} = $i;\n        push @unchecked, $other;\n      } elsif ( $right == $variant->[3] ) {\n        $other->{pos} = [ $x, $y + 1 ];\n        $other->{rotation} = $variant;\n        $other->{orientation} = $i;\n        push @unchecked, $other;\n      } elsif ( $bottom == $variant->[0] ) {\n        $other->{pos} = [ $x + 1, $y ];\n        $other->{rotation} = $variant;\n        $other->{orientation} = $i;\n        push @unchecked, $other;\n      } elsif ( $left == $variant->[1] ) {\n        $other->{pos} = [ $x, $y - 1 ];\n        $other->{rotation} = $variant;\n        $other->{orientation} = $i;\n        push @unchecked, $other;\n      }\n    }\n  }\n}\n\nmy $top = min map { $_->{pos}[0] } @tiles;\nmy $bottom = max map { $_->{pos}[0] } @tiles;\nmy $left = min map { $_->{pos}[1] } @tiles;\nmy $right = max map { $_->{pos}[1] } @tiles;\n\nmy %positions;\ntie %positions, 'Hash::MultiKey';\n\nfor my $tile ( @tiles ) {\n  $positions{ $tile->{pos} } = $tile;\n}\n\nmy @complete;\n\nfor my $x ( $top .. $bottom ) {\n  my @images;\n\n  for my $y ( $left .. $right ) {\n    my $tile = $positions{ [$x, $y] };\n    my $image = orient( $tile->{image}, $tile->{orientation} );\n    push @images, $image;\n  }\n\n  for my $i ( 1 .. 8 ) {\n    my @line;\n\n    for my $image ( @images ) {\n      push @line, @{$image->[$i]}[1..8];\n    }\n\n    push @complete, [ @line ];\n  }\n}\n\nmy $pattern = <<END;\n                  #\n#    ##    ##    ###\n #  #  #  #  #  #\nEND\n\nsub patternize {\n  my @dots;\n  my $pattern = shift;\n  my @lines = split \"\\n\", $pattern;\n\n  for my $x ( 0..$#lines ) {\n    my $line = $lines[$x];\n    my @chars = split \"\", $line;\n    for my $y ( 0..$#chars ) {\n      my $char = $chars[$y];\n      if ( $char eq '#' ) {\n        push @dots, [$x, $y];\n      }\n    }\n  }\n\n  return @dots;\n}\n\nmy @dots = patternize( $pattern );\n\nmy $size = $#complete;\n\nfor my $orientation ( 0 .. 7 ) {\n  my $h = max map { $_->[0] } @dots;\n  my $w = max map { $_->[1] } @dots;\n\n  my $image = orient( \\@complete, $orientation );\n\n  my $found = 0;\n\n  for my $x ( 0 .. $size - $h ) {\n    for my $y ( 0 .. $size - $w ) {\n      if ( all { $image->[$x + $_->[0]][$y + $_->[1]] eq '#' } @dots ) {\n        $found = 1;\n\n        for ( @dots ) {\n          $image->[$x + $_->[0]][$y + $_->[1]] = '.';\n        }\n      }\n    }\n  }\n\n  if ( $found ) {\n    say scalar grep { $_ eq '#' } map { @$_ } @$image;\n    last;\n  }\n}\n"
  },
  {
    "path": "advent-of-code/2020/21.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse Set::Scalar;\nuse List::Util qw( uniq );\nuse Array::Utils qw( array_diff );\n\nopen STDIN, '<', 'inputs/21';\n\nmy %possible;\nmy @foods;\n\nwhile (<>) {\n  m/^(.*) \\(contains (.*)\\)$/;\n\n  my @ingredients = split ' ', $1;\n  my @allergens = split ', ', $2;\n  my $set = Set::Scalar->new( @ingredients );\n\n  push @foods, { ingredients => [ @ingredients ], allergens => [ @allergens ] };\n\n  for ( @allergens ) {\n    $possible{ $_ } ||= $set;\n    $possible{ $_ } = $possible{ $_ }->intersection( $set );\n  }\n}\n\n\nfor ( 0 .. scalar keys %possible ) {\n  my @sets = values %possible;\n  my $remove = Set::Scalar->new( map { $_->elements } grep { $_->size == 1 } @sets );\n\n  for ( keys %possible ) {\n    $possible{ $_ } -= $remove if ( $possible{ $_ }->size > 1 );\n  }\n}\n\nmy @all = uniq map { $_->{ingredients}->@* } @foods;\nmy @allergens = uniq map { $_->elements } values %possible;\nmy $safe = Set::Scalar->new( array_diff @all, @allergens );\n\nmy $count = 0;\n\nfor ( @foods ) {\n  for ( $_->{ingredients}->@* ) {\n    $count++ if ( $safe->has( $_ ) );\n  }\n}\n\nsay $count;\n"
  },
  {
    "path": "advent-of-code/2020/21.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse Set::Scalar;\nuse List::Util qw( uniq );\nuse Array::Utils qw( array_diff );\n\nopen STDIN, '<', 'inputs/21';\n\nmy %possible;\nmy @foods;\n\nwhile (<>) {\n  m/^(.*) \\(contains (.*)\\)$/;\n\n  my @ingredients = split ' ', $1;\n  my @allergens = split ', ', $2;\n  my $set = Set::Scalar->new( @ingredients );\n\n  push @foods, { ingredients => [ @ingredients ], allergens => [ @allergens ] };\n\n  for ( @allergens ) {\n    $possible{ $_ } ||= $set;\n    $possible{ $_ } = $possible{ $_ }->intersection( $set );\n  }\n}\n\n\nfor ( 0 .. scalar keys %possible ) {\n  my @sets = values %possible;\n  my $remove = Set::Scalar->new( map { $_->elements } grep { $_->size == 1 } @sets );\n\n  for ( keys %possible ) {\n    $possible{ $_ } -= $remove if ( $possible{ $_ }->size > 1 );\n  }\n}\n\nmy %allergens;\n\nfor ( keys %possible ) {\n  my $name = ( $possible{ $_ }->elements )[0];\n  $allergens{ $name } = $_;\n}\n\nmy @all = uniq map { $_->{ingredients}->@* } @foods;\nmy @allergens = uniq map { $_->elements } values %possible;\nmy $safe = Set::Scalar->new( array_diff @all, @allergens );\n\nmy $count = 0;\n\nfor ( @foods ) {\n  for ( $_->{ingredients}->@* ) {\n    $count++ if ( $safe->has( $_ ) );\n  }\n}\n\nsay join ',', sort { $allergens{ $a } cmp $allergens{ $b } } @allergens;\n"
  },
  {
    "path": "advent-of-code/2020/22.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse List::MoreUtils qw( zip );\n\nopen STDIN, '<', 'inputs/22';\n\n$_ = do { local $/; <> };\nm/^Player 1:\\n(.*)\\n\\nPlayer 2:\\n(.*)\\n$/sm;\n\nmy @a = split \"\\n\", $1;\nmy @b = split \"\\n\", $2;\n\nwhile ( @a and @b ) {\n  my ( $a, $b ) = ( shift @a, shift @b );\n\n  if ( $a > $b ) {\n    push @a, $a, $b;\n  } else {\n    push @b, $b, $a;\n  }\n}\n\nmy $i = @a + @b;\nmy $sum = 0;\n\n$sum += $_ * $i-- for ( @a, @b );\n\nsay $sum;\n"
  },
  {
    "path": "advent-of-code/2020/22.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse List::MoreUtils qw( zip );\n\nopen STDIN, '<', 'inputs/22';\n\n$_ = do { local $/; <> };\nm/^Player 1:\\n(.*)\\n\\nPlayer 2:\\n(.*)\\n$/sm;\n\nmy @a = split \"\\n\", $1;\nmy @b = split \"\\n\", $2;\n\nsub round {\n  my @a = $_[0]->@*;\n  my @b = $_[1]->@*;\n\n  my %seen;\n\n  while ( @a and @b ) {\n    my $signature = join( ' ', @a ) . ' | ' . join( ' ', @b );\n    return { winner => 1, a => \\@a, b => \\@b } if $seen{ $signature };\n    $seen{ $signature } = 1;\n\n    my ( $a, $b ) = ( shift @a, shift @b );\n\n    my $a_wins;\n\n    if ( $a <= @a and $b <= @b ) {\n      my $result = round( [ @a[ 0 .. $a - 1] ], [ @b[ 0 .. $b - 1 ] ] );\n      $a_wins = ($result->{winner} == 1);\n    } elsif ( $a > $b ) {\n      $a_wins = 1;\n    } else {\n      $a_wins = 0;\n    }\n\n    if ( $a_wins ) {\n      push @a, $a, $b;\n    } else {\n      push @b, $b, $a;\n    }\n  }\n\n  return {\n    winner => ( @a ) ? 1 : 2,\n    a => [ @a ],\n    b => [ @b ],\n  }\n}\n\nmy $result = round( [ @a ], [ @b ] );\n\nmy $i = $result->{a}->@* + $result->{b}->@*;\nmy $sum = 0;\n\n$sum += $_ * $i-- for ( $result->{a}->@*,$result->{b}->@* );\n\nsay $sum;\n"
  },
  {
    "path": "advent-of-code/2020/23.1.pl",
    "content": "use v5.32;\nuse warnings;\n\nuse List::Util qw( any );\nuse constant INPUT => '784235916';\n\npackage Ring {\n  use List::MoreUtils qw( firstidx );\n\n  sub new {\n    my ( $package, $pointer, @elements ) = @_;\n\n    bless { pointer => $pointer, elements => [ @elements ] }, $package;\n  }\n\n  sub show {\n    my $self = shift;\n\n    use Data::Dump qw(dump);\n    warn dump $self->{elements};\n  }\n\n  sub pick_three {\n    my $self = shift;\n    my $ring = $self->normalize;\n\n    my @three = splice $ring->{elements}->@*, 1, 3;\n\n    ( $ring, @three );\n  }\n\n  sub normalize {\n    my $self = shift;\n    my @elements = $self->{elements}->@*;\n    my @prefix = splice @elements, 0, $self->{pointer};\n\n    Ring->new( 0, @elements, @prefix );\n  }\n\n  sub current {\n    my $self = shift;\n    $self->{elements}[ $self->{pointer} ];\n  }\n\n  sub insert_after {\n    my ( $self, $destination, @items ) = @_;\n    my @elements = ( $self->{elements}->@* );\n    my $i = firstidx { $_ == $destination } @{$self->{elements}};\n    splice @elements, $i + 1, 0, @items;\n\n    Ring->new( $self->{pointer}, @elements );\n  }\n\n  sub select_next {\n    my $self = shift;\n    my ( $pointer, @elements ) = ( $self->{pointer}, $self->{elements}->@* );\n\n    $pointer = $pointer + 1 % scalar( @elements );\n\n    Ring->new( $pointer, @elements );\n  }\n\n  sub cannonical {\n    my $self = shift;\n    my $i = firstidx { $_ == 1 } $self->{elements}->@*;\n    my $ring = Ring->new( $i, $self->{elements}->@* )->normalize;\n\n    join '', $ring->{elements}->@[1..8];\n  }\n}\n\nsub destination {\n  my @numbers = @_;\n\n  my $n = $numbers[0];\n\n  while ( any { $_ == $n } @numbers ) {\n    $n--;\n    $n = 9 if $n == 0;\n  }\n\n  $n;\n}\n\nmy $ring = Ring->new( 0, split( '', INPUT ) );\n\nfor ( 1 .. 100 ) {\n  say \"-- move $_ --\";\n  say \"cups: \" . join( ' ', $ring->{elements}->@* );\n  ( $ring, my @pick ) = $ring->pick_three;\n  say \"pick up: \" . join( ' ', @pick );\n  my $destination = destination $ring->current, @pick;\n  say \"destination: \" . $destination;\n  $ring = $ring->insert_after( $destination, @pick );\n  $ring = $ring->select_next;\n  say \"\";\n}\n\nsay $ring->cannonical;\n"
  },
  {
    "path": "advent-of-code/2020/23.2.pl",
    "content": "use v5.32;\nuse warnings;\n\nuse List::Util qw( any );\nuse constant INPUT => '784235918';\nuse constant LIMIT => 1_000_000;\nuse constant MOVES => 10_000_000;\n\nmy ( $n, @numbers ) = split '', INPUT;\nmy @index;\n\nmy $first = { number => $n, next => undef };\n@index[ $n ] = $first;\nmy $current = $first;\n\nfor ( @numbers ) {\n  my $next = { number => $_, next => undef };\n  @index[$_] = $next;\n  $current->{next} = $next;\n  $current = $next;\n}\n\n\nfor ( my $i = 10; $i <= LIMIT; $i++ ) {\n  my $next = { number => $i, next => undef };\n  push @index, $next;\n  $current->{next} = $next;\n  $current = $next;\n}\n\n$current->{next} = $first;\n\n$current = $first;\n\nsub take {\n  my $n = shift;\n  my $first = $current->{next};\n  my $last = $first;\n  my @result;\n\n  while ( $n-- ) {\n    push @result, $last;\n    $last = $last->{next};\n  }\n\n  $current->{next} = $last;\n  $result[-1]->{next} = undef;\n\n  @result;\n}\n\nsub destination {\n  my @numbers = @_;\n\n  my $n = $numbers[0];\n\n  while ( any { $_ == $n } @numbers ) {\n    $n--;\n    $n = LIMIT if $n == 0;\n  }\n\n  $n;\n}\n\nsub insert {\n  my ( $destination, @elements ) = @_;\n\n  my $after = $destination->{next};\n  $destination->{next} = $elements[0];\n  $elements[-1]->{next} = $after;\n}\n\nfor ( my $c = 1; $c <= MOVES; $c++ ) {\n  my @pick = take 3;\n  my $destination = destination $current->{number}, map { $_->{number} } @pick;\n  insert $index[ $destination ], @pick;\n  $current = $current->{next};\n}\n\nsay $index[1]->{next}{number} * $index[1]->{next}{next}{number};\n"
  },
  {
    "path": "advent-of-code/2020/24.1.pl",
    "content": "use v5.32;\nuse warnings;\nuse experimental 'switch';\n\nuse Hash::MultiKey;\n\nopen STDIN, '<', 'inputs/24';\n\nsub coordinates {\n  my ( $x, $y ) = 0, 0;\n\n  while ( $_[0] =~ /([ns])?([we])/g ) {\n    given ( ($1 // '') . $2 ) {\n      when('e') { $y += 1 }\n      when('w') { $y -= 1 }\n      when('ne') { $x -= 1; $y += ( $x + 1 ) % 2 }\n      when('nw') { $x -= 1; $y -= $x % 2 }\n      when('se') { $x += 1; $y += ( $x + 1 ) % 2 }\n      when('sw') { $x += 1; $y -= $x % 2 }\n      default { die \"unknown $_\" }\n    }\n  }\n\n  ( $x, $y )\n}\n\nmy %grid;\ntie %grid, 'Hash::MultiKey';\n\nwhile (<>) {\n  chomp;\n  my $c = [ coordinates( $_ ) ];\n  $grid{ $c } = ! ( $grid{ $c } // 0 );\n}\n\nsay scalar grep { $_ } values( %grid );\n"
  },
  {
    "path": "advent-of-code/2020/24.2.pl",
    "content": "use v5.32;\nuse warnings;\nuse experimental 'switch';\n\nuse List::Util qw( uniq );\nuse Hash::MultiKey;\n\nopen STDIN, '<', 'inputs/24';\n\nsub coordinates {\n  my ( $x, $y ) = 0, 0;\n\n  while ( $_[0] =~ /([ns])?([we])/g ) {\n    given ( ($1 // '') . $2 ) {\n      when('e') { $y += 1 }\n      when('w') { $y -= 1 }\n      when('ne') { $x -= 1; $y += ( $x + 1 ) % 2 }\n      when('nw') { $x -= 1; $y -= $x % 2 }\n      when('se') { $x += 1; $y += ( $x + 1 ) % 2 }\n      when('sw') { $x += 1; $y -= $x % 2 }\n      default { die \"unknown $_\" }\n    }\n  }\n\n  ( $x, $y )\n}\n\nsub neighbours {\n  my ( $x, $y ) = $_[0]->@*;\n\n  my $offset = $x % 2 || -1;\n\n  (\n    [ $x - 1, $y ], [ $x - 1, $y + $offset ],\n    [ $x, $y - 1 ], [ $x, $y + 1 ],\n    [ $x + 1, $y ], [ $x + 1, $y + $offset ],\n  )\n}\n\nmy %grid;\ntie %grid, 'Hash::MultiKey';\n\nwhile (<>) {\n  chomp;\n  my $c = [ coordinates( $_ ) ];\n  $grid{ $c } = ! ( $grid{ $c } // 0 );\n}\n\nfor ( 1 .. 100 ) {\n  my %new;\n  tie %new, 'Hash::MultiKey';\n\n  my @check =\n    map { [ split ',' ] }\n    uniq\n    map { join ',', @$_ }\n    map { ( $_, neighbours( $_ ) ) }\n    grep { $grid{ $_ } }\n    keys %grid;\n\n  for ( @check ) {\n    my $black = $grid{ $_ };\n    my $count = scalar grep { $grid{ $_ } } neighbours $_;\n\n    $new{ $_ } = 1 if $count == 2 or $black and $count == 1;\n  }\n\n  %grid = %new;\n}\n\nsay scalar grep { $_ } values( %grid );\n"
  },
  {
    "path": "advent-of-code/2020/25.1.pl",
    "content": "use v5.32;\nuse warnings;\n\nuse constant MOD => 20201227;\n\nsub transform {\n  my ( $loop, $subject ) = @_;\n  my $result = 1;\n\n  for ( 1 .. $loop ) {\n    $result *= $subject;\n    $result %= MOD;\n  }\n\n  $result;\n}\n\nsub find_loop_size {\n  my ( $key, $subject ) = @_;\n\n  my $n = 1;\n  my $i = 0;\n  while (1) {\n    $i++;\n    $n *= $subject;\n    $n %= MOD;\n\n    return $i if $n == $key;\n  }\n\n  return undef;\n}\n\nsub hack {\n  transform( find_loop_size( $_[0], 7 ), $_[1] ) ;\n}\n\n#say hack 5764801, 17807724;\nsay hack 2069194, 16426071;\n"
  },
  {
    "path": "advent-of-code/2020/25.2.pl",
    "content": ""
  },
  {
    "path": "advent-of-code/2020/inputs/1.1",
    "content": "1028\n1987\n1938\n1136\n1503\n1456\n1107\n1535\n1946\n1986\n855\n1587\n1632\n1548\n1384\n1894\n1092\n1876\n1914\n1974\n1662\n1608\n2004\n1464\n1557\n1485\n1267\n1582\n1307\n1903\n1102\n1578\n1421\n1184\n1290\n1786\n1295\n1930\n1131\n1802\n1685\n1735\n1498\n1052\n1688\n990\n1805\n1768\n1922\n1781\n1897\n1545\n1591\n1393\n1186\n149\n1619\n1813\n1708\n1119\n1214\n1705\n1942\n1684\n1460\n1123\n1439\n1672\n1980\n1337\n1731\n1203\n1481\n2009\n1110\n1116\n1443\n1957\n1891\n1595\n1951\n1883\n1733\n1697\n1321\n1689\n1103\n1300\n1262\n1190\n1667\n1843\n1544\n1877\n1718\n1866\n1929\n1169\n1693\n1518\n1375\n1477\n1222\n1791\n1612\n1373\n1253\n1087\n1959\n1970\n1112\n1778\n1412\n1127\n1767\n1091\n1653\n1609\n1810\n1912\n1917\n935\n1499\n1878\n1452\n1935\n1937\n968\n1905\n1077\n1701\n1789\n1506\n1451\n1125\n1686\n1117\n1991\n1215\n1776\n1976\n846\n1923\n1945\n1888\n1193\n1146\n1583\n1315\n1372\n1963\n1491\n1777\n1799\n1363\n1579\n1367\n1863\n1983\n1679\n1944\n1654\n1953\n1297\n530\n1502\n1738\n1934\n1185\n1998\n1764\n1856\n1207\n1181\n1494\n1676\n1900\n1057\n339\n1994\n2006\n1536\n2007\n644\n1173\n1692\n1493\n1756\n1916\n1890\n1908\n1887\n1241\n1447\n1997\n1967\n1098\n1287\n1392\n1932\n"
  },
  {
    "path": "advent-of-code/2020/inputs/10",
    "content": "84\n60\n10\n23\n126\n2\n128\n63\n59\n69\n127\n73\n140\n55\n154\n133\n36\n139\n4\n70\n110\n97\n153\n105\n41\n106\n79\n145\n35\n134\n146\n148\n13\n77\n49\n107\n46\n138\n88\n152\n83\n120\n52\n114\n159\n158\n53\n76\n16\n28\n89\n25\n42\n66\n119\n3\n17\n67\n94\n99\n7\n56\n85\n122\n18\n20\n43\n160\n54\n113\n29\n130\n19\n135\n30\n80\n116\n91\n161\n115\n141\n102\n37\n157\n129\n34\n147\n142\n151\n68\n78\n24\n90\n121\n123\n33\n98\n1\n40\n"
  },
  {
    "path": "advent-of-code/2020/inputs/11",
    "content": "LLLLLLL.LLLLLLLLLLLL.LL.L.LLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLLLL.LLLLLLLLLLLLL\nLLLLLLL.LLLLLLLLLLLL.LLL..LLLLLLLLLLLLLLLLLLLLLLL..LLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLL\nLLLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLL.LLLLLLLLL.LLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLL\nLLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLL.LLLL.LLLLLLLLLLL.LLLLLLLLLLLLLLLL.LLLLL.LLLLLLLL.LLLL\nLLLLLLL.LLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLL\nLLLLLLL.LLLLLL.L.LLLLLLLL.L.LLLLLL.LLLLLL.LL.LLLLL.LLLLLLLLLLLLLLLLL.LLLL.LLLLL.LLLLLLLLLLLLL\n.L.....L...L.....LL..L...LLL.L.LL..LLL..LL.LLL...LLLL..L......L..........L...L..LL..LLL.L...L\nLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLLLL.LLLLLLL.LLLLL\nLLLLLLL.LLLLLL.LLLLL.L.LLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLL.LLLLLLL.LL.LLLLLLLLLLLLL\nLLLL.LL.LLLLLL.LLLL.LLLLL.LLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLL.LL.LLLLL.LLLLLLLLL.LLLL.\nLLLLLLL.LLLLLL.LLLLL..LLL.LLLLLL.L.LLLLLLLLL.LLLL..LLLLLLL.L.L.LLLLL.LLLLLLLLLL.LLLLLLLLLLLLL\nLLL.LLL.LLLLLLLLLL.L.LLLL..LLLLLLLLLL.LL.LL.LLLLLL.LLLLL.LLLLLLLLLLL.LLLL.LLLLL.LLLLLLL.LLLLL\nLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLL.L.LLLLL.LLLLLLL.LL.LLLLLLLLLLL.LLLLL.LLLLLLLLLLLL.\nLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLL\nL...L..LLL.....L.LL..L.LLLL....LLLL.....L.L.LLL..L.L...LL.LL....L..LLLL..L..L.LL...L.L.....L.\nLLLLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLLLL.LLL.L.LLLLLLLLLLLLLLLLL.LLLL.LLLLL.LLLLLLL.LLLLL\nLLLLLLL.LLLLLL.LLLLL.LLLL.LLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLL.LLL.LLLLLLL.LLLLLLLLLL.LLLLL\nLLLLLLL.LLLLLLLLLLLL.LLLL.LLLL.LLL.LLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.L.LL.LLLLL.LLLLLLLLLLLLL\nLLLLLLL..LLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLL\n.........LL..LL..LL..LL.....L..L..LL.............L...L....LLLL...LL...LLL..L...LLL.....L....L\nLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLL..LLLLLL.L.LLL\nLLLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLL.LLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL\nLLLLLLL.LL.LLL.LLLLL.LLLL.LLLLLLLL.LLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLL.LLL.LLLLLLLLLL\nLLLLLLL.LLLLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLL.LLLL.LL.LL..LLLLLLLLLLLL\nLLLLLLL.LLLLLLLLLLLL.LLLL.LLLLLLLLLL.LLLLLLL.LLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLLLL.LLLLLLL.LLLLL\nLLLLLLLLLLL.L.LLLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL\n...L.L..L.L.L....L....L.LLL.L.L.L..L..L...L....L......L.......L..L.L.L..L..LL...L....L....LL.\nLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLL.L.LL.LL.LL.LLLLLLLLLLLLL\nLLLLLLL.LLLLLL.LLLLL.LLLL.LLLLLLLL.LLLLLLL.L.LLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLLLL.LLLLLLL.LLLLL\nLLLLLLLLLLLLLL.LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL..LLL..LLLL.LLLL.LL.LLLLL\nLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLL.LLLLLLLLL.LLLLL.L.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL\nLLLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLLLLLLLLLLLL..LLLL\nLLLLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLL.LL.LLLLLLLLLL.LLLLLLLLL.LLLLLLLLLL.LLLLLLL.LLLLL\n..LLLLL...LL...L..L.....L.LL.L....L.L..LL.L......L.L.L..L...L.L..L..L..L.LL..L.L.L..L.....L..\nLLLLLLL.LLLLLL.LLL.L.LLLL.LLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLL\nLLLLLLL.LLL.LL.LLLLL.LLLL.LLLLLLLL.LLLLLL.LL.LLLL..LLLLLL.LLLLLLLLLL.LLLL..LLLL.LLLLLLL.LLLLL\nLLLLLLLLLLLLLL.LLLLL.LLLL.LLLLLLLL.LLLLLLLLL.LLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLLL.LLLLLLL.LLLLL\n.LLLLLL.LLLLLL.LLLLL.LLLLLLLLL.LLL.LLLLLLL.L.LLLLLLLLLLLLLLLL.LLLLLL.LLLL.LLLLL.LLLLLLL.LLLLL\nLLLLLLL.LLLLLL.LLLLLLLLLL.LLLLLLLL.LLLLLLLLL.LLLL.LLLLLLLL.LLLLLLLLL.LLLL.LLLLL.LLLLLLLLLLLLL\nLLLLLLL.LLL.LL.LLLLLLLLLL.LLLLLLLL.LLLLLLLLL.LLLLL.LLLL.LL.LL.LLLLLLLLLLLLLL.LL.LLLL.LL.LLLL.\nLLLLLLL.LLLLLL.LLLLLLLLLL.L..LLLLLLLLLLLLLLL.LLLLLLLLLLLL.LLLLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLL\nLL......LLL...L.LL...LL..LLLL.L..L.........L..L.....L..L......L..L...LLL.....LL.......LL.....\nLLLLLLL.LLLLLL.LLLLL.L.LL.LLLLLLLL.LLLL.LLLLL.L.LLLLLLLLLL.LLLLLLLLL.LLLLLLLLL..LLLLLLLLLLLLL\nLLLLLLL.L.LLLL.LLLLL.LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLL.LLLL.LL.LL.LLLLLLLLLLLLL\nLLLLLLL.LLLLLL.LLLLLLLLLL..LLLLLLLLLLLLLLLLLLLLLLL.L.LLLLL.LLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL\nLLLLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLLLL.L.LLLLLLLLLLL\nLLLLLLL.LLLLLL.LLLLL.LLLL.LLL.LLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL\nLLLLLLL.LLLLLL.LLLLL.LLLL.LLLLLLLLL.LLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.LLL.LLLLLLLLLLLLLLLLLLLL\nLLLLLLL.LLLLLL.LLL.L.LLLL.LLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLL.LLLL.LLLLL.LLLLLLLLLLLLL\nL....L.L..L.L....L..L.L...L.....L..LL...L.L.L.L.LL..L....LL..LL....L.L.......LLL..LLL...LL..L\nLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLL.LLLLLLL.LLLLLLLLLLLLLL..LLLLLLLLL.LLLL..LLLL.LLLLLLLLLLLLL\nLLLLLLLLLLLLLL.LLLLL.LLLL.LLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLLLLLLL.LLLLLLLLL.LLLLLLL.LLLLL\nLLLLLLL.LLLLL..LLLLL.LLLLLLLLLLLLL.LLLLLL.LL..LLLLLLLLLLLLLLLLLLLLLL.LLLL.LLLLL.LLLLLLLLL.LLL\nL.L.LLLLLLLLLL.LLLLL.LLLL.LLLLL.LL.LLLLLLLLL.LLLLL.LLLLLLL.LLLLL.LLL.LLLL.LLLLLLLLLLLLLLLLLLL\nLLLLLLL.LLLLLL.LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLL.LLLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLL\nLLLLLLL.LLLLLLLLLLLL.LLLL.LLLLLLLL.LLLLLLLLL.LLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLLLLLLLLLLLL.LLLLL\nLLLLLLLLLLLLLL.LLLLL.LLLL.LLLLLLLL.LLLLLLLLL.LLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLLLL.LLLLLLL.LLLLL\nLLLLLLL.L.LLLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLL.LLLL.LLLL.LLLLLLLLLLLLLLLLLL.\nLL.L.LLLLLLLLL.LLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLLLLLLLLLLLL.LLLLL\n...L..L..L..L....LLL..L.LL....L........L.......L.L.LL.L........L...LLLL....LL.......L.LL..L.L\nLLLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLL\nLLLLLLL.LLLLLL.LL.LL.LLLLLLLLLL.LL.LLLLLLLLL.LLLLL.LLL..LLLLLLLLLLLL.LLLL..LL.L.LLLLLLL.LLLLL\nLLLLLLL.LLLLLLLLLLLL.LLLL.LLLLLLLL.LLLLLLL.L.LL.LL.LLLLLLL.LLLLLLLLLL.LLL.LLLLL.LLLLLLL.LLLLL\nLLLLLLLLLLL.LL.L.LLL.LLLL.LLLLLLL..LLLLLLLLL.LLLLLL.LLLLLLLLLLLLLLLL.LLLL..LLLLLLLLLLLL.LLLLL\nLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLLLLLLLLLLLLL.LLLLL.L.LLLLL\nLLLLLLL.LLLLLL.LLLLLLLLLL.LLLLLLLL.L.LLLLLLL.LLLLLLLLLLLLL.LLLLLLLLL.LLLL.LLLLL.LLLLLLLLLLLLL\nLLLLLLLLLLLLLL.LLLLL.LLLL.LLLLLLLL.LLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLL.L.LLL.LLLLLLL..LLLL\nLLLLLLL.LLLLLL.LLLLL.LLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.L.LL.L.LLL.LLLLLLL.LLLL.\n....LLLL.L..L....LL..L.....LL..........LL.....L.L..LL.LL......L.L.L.L....L.LL.L.L..L......L..\nLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLL.LLLLLLL\nLLLLLLLLLLL.LLLLLLLL.LLLL.LLLLLLLL.LLL.LLLLL.LLLL..LLLLLLLLLLLLLLLLL.LLLL.LLLLL..LLLLLL.LLLLL\nLLLLLLLLLLLLLL.LLLLL.LLLL.LLLLLLLLLLLLLLL.LL.LLLLL.LLLLLLLLLLLLLLLLLLLLLL.LLLLL.LLLLLLL.LL.LL\nLLLLLLL.LLLLLL.LLLLL.LLLL.LLLLLLLL.LLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLLLLLL.LLLLLLLLLL.\nLLLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLL..LLLLLL.LLLLLLL.LL.LLLLLLLLLLLLLLLLLLLLLLLLL.L.LLLLL..LLLL\nLLL.LLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLL.LL.LLLLLLL.LLLLLLL.L.LLLL.LLLLL.LLLLLLL.LLLLL\nLLLLLLLLLLLLLL.LLLLL.LLLL.LLLLLLLL.LLLL.LLLL.LLLLL.LLLL.LLLLLLLLLLLL.LLLLLLLLLL.LLLLLLL.LLLLL\nLLLLLL..LLLLLLLLLL.L.LLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLL.LLLLLLLLL.LLLLLLLLLL.LLLLLLL.L.LLL\nLLLLLLLLLL.LLLLLLLLL.LL.L.LLLLLLLL.LLLLLLLLL.LLLLLLLLLLLLL.LLLLLLLLL.LLLL.LLLLL.LLL.LLL.LLLLL\nL.L...L....LL.L....LL..L...L...LL.L.............LLLLL..LL........LLL.L....L.L...L.L...LLL.LL.\nLLLLLLL.LLLLLL.LLLLLLLLLL.LLLLLLLL.LLLLLLLLL.LLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLLLLL.LLLLLL.LLLLL\nLL.LLLL.LLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLL.LLLLL.LLLLLLL.L.LLL.LLLLLLLLLLLLLLLLLLLLLLLLLLLL\nLLLLLLL.LLLLLL.LLLLL.LLLLLLLLLLLLL.LLLLLLLLL.LLLLL.LLLLLLLLLLLLLLLLL.LLLL.LLLLL.LLLLLLLLLLLLL\nLLLLLLL.LLLLLL.LLLLLLLLLL.LLLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLL.LLLL.LLL.LLLLLLLLLLL.LLL\n.LLL..LL.L.LL.L...L.L..L...L....L.L................L....L.......L..L.....L...LLL....L....LL..\nLLLLL.LLLLLLLL.LLLLL.L.LL.LLLLLLLL.LLLLLLLLL..LLLLLLLLLLLL.LLLLLLLLL.LLLL.LLLLL.LLLLLLL.LLLLL\nLLLLLLL.LLLLLL.LLLLLLLLLL.LL.L.LLL.LLLLLL.LL.LLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLL.LLLLLLLLL.LLLLL\nLLLLLLL.LLLLLL.LLLLL.LLLL.LLLLLLLLLL.L.LLLLL.LLLLLLLLLLLLLLLLLLLLLLL.LLLLLLLLLLLLLLLLLL.LLLLL\nLLLLLL..LLLLLLLLLLLLLLLLL.LLLLLLLL.L.LLL.LLL.LLLLL.LLLLLLLLLLLLLLLLL.LLLLLLLLLL.LLLLLLLLLLLLL\nLLLLLLL.LLLL.L.LLL.LLLLLLLLLLLLLLL.LLLLLLLLL.LLLLL.LLLLLLL.LLLLLLLLL.LLLL.LLLLL.LLLL.LLLLLLLL\nLLLLLLL.LLLLLLLLLLLL..LLL.LLLLLLLL..LLLLLLLLLLLLLL.LLLLLLLLLLL.LLLLLLL.LLLLLLLL.LLLLLLL.LLLLL\n"
  },
  {
    "path": "advent-of-code/2020/inputs/12",
    "content": "F29\nE5\nL90\nW1\nR90\nE1\nR90\nW5\nF32\nE2\nS3\nR270\nF61\nR180\nR180\nE2\nF13\nR180\nF18\nL180\nF15\nN2\nS2\nR270\nN2\nF81\nW4\nN2\nE1\nN5\nF5\nN3\nR90\nW5\nS1\nF20\nL90\nS2\nR90\nF81\nS2\nE1\nF59\nN1\nL180\nW3\nR90\nE5\nF2\nR90\nF28\nR90\nF70\nL180\nS4\nL90\nF97\nW2\nR180\nS5\nF12\nN4\nL90\nF47\nR90\nF20\nW3\nS2\nE2\nF29\nS2\nL90\nS1\nL180\nF92\nL90\nS4\nW3\nL90\nW5\nF56\nN3\nL90\nS4\nF83\nS2\nF82\nW4\nF34\nR90\nN5\nF85\nR90\nF17\nR90\nF15\nW1\nL90\nF55\nS3\nF38\nW1\nF38\nS3\nW1\nN1\nF77\nR180\nS5\nF89\nL90\nF62\nN4\nR90\nE3\nL180\nE2\nF44\nS4\nR90\nW2\nL180\nS4\nR90\nN5\nF30\nS5\nR90\nF88\nR90\nF10\nL90\nN5\nF45\nE5\nF51\nW5\nN3\nE3\nF93\nE5\nF85\nN5\nL90\nF6\nW4\nN3\nF25\nL90\nE2\nS4\nW1\nR180\nE4\nS3\nE2\nF26\nN3\nE3\nF32\nN3\nL90\nF25\nL180\nE3\nF46\nF12\nN3\nW4\nL90\nS2\nL90\nF31\nW4\nF75\nL180\nE3\nF79\nR90\nN5\nL270\nW5\nL180\nS5\nF19\nN2\nF90\nL180\nW3\nS4\nE2\nF85\nN1\nF62\nW4\nF77\nL180\nW1\nN2\nL90\nF86\nR90\nW5\nF34\nE1\nF72\nR90\nE3\nF5\nN2\nR90\nS2\nR270\nW4\nF58\nF19\nR180\nR90\nW4\nF60\nN1\nE1\nR90\nF27\nW4\nL90\nF35\nE1\nF11\nE4\nR90\nW5\nF68\nL90\nS2\nW3\nF2\nL90\nF24\nW4\nN4\nR90\nF32\nL90\nL90\nF22\nF91\nR90\nW1\nF23\nW2\nS1\nW3\nS2\nF97\nW4\nL90\nW1\nF16\nS4\nL180\nW4\nF48\nE5\nF21\nN3\nF2\nE2\nF75\nN5\nE2\nL90\nE3\nF76\nL90\nN1\nL90\nN5\nE1\nL90\nE2\nR90\nF40\nL90\nS5\nE1\nF8\nS1\nL90\nE4\nN3\nF10\nL180\nF68\nR90\nF89\nR90\nW1\nL180\nE2\nF48\nS2\nL90\nF61\nN3\nL90\nL180\nW2\nN2\nF32\nR90\nE2\nF74\nW4\nN5\nF78\nN2\nF62\nS1\nR180\nS2\nE1\nL90\nN4\nF85\nR90\nW4\nR90\nE1\nR180\nW3\nS5\nE1\nR270\nN4\nF89\nN4\nR90\nN1\nE2\nN3\nF89\nN5\nE1\nF17\nR270\nF58\nE1\nL90\nF38\nW4\nS1\nE2\nR90\nE2\nW2\nL90\nW5\nL90\nE2\nF1\nE1\nF34\nS4\nF16\nW5\nL180\nF31\nL90\nE2\nF46\nL180\nN5\nF64\nR90\nF58\nL90\nF15\nL90\nS4\nE3\nF74\nF26\nS2\nW2\nS4\nF81\nS4\nL180\nE1\nF21\nF53\nE5\nF55\nL270\nW2\nS2\nE1\nS2\nE3\nN2\nF24\nL180\nN1\nE5\nF60\nS1\nF54\nN1\nF9\nN3\nL90\nE3\nL90\nE3\nL90\nN1\nF28\nN4\nR180\nN5\nF44\nN2\nE3\nR90\nW4\nR180\nF69\nW3\nS2\nR180\nE3\nR270\nS4\nW2\nR90\nF69\nE3\nF44\nL90\nF87\nE4\nF21\nE1\nS2\nR90\nE5\nL90\nW5\nR90\nE1\nF66\nW4\nF51\nS3\nS4\nW3\nL90\nE1\nR90\nW1\nR180\nW1\nN1\nL180\nN3\nL180\nE2\nF14\nN2\nE5\nF95\nL270\nN4\nR90\nN1\nR90\nN1\nE4\nF90\nN3\nF35\nN5\nF74\nR90\nN3\nF64\nN1\nF28\nN2\nW2\nF7\nW4\nN2\nF37\nE3\nF100\nR90\nF36\nL90\nF41\nE1\nL90\nL90\nW1\nN3\nW2\nW3\nL90\nW5\nF100\nR90\nN2\nL180\nF7\nW2\nE2\nF77\nL180\nN2\nR180\nF60\nL90\nN5\nL90\nF72\nL270\nW1\nL180\nN5\nR90\nF54\nS3\nF70\nN1\nF72\nE4\nN5\nR90\nS1\nW1\nN3\nR90\nF45\nE4\nF32\nW5\nF78\nW3\nR90\nW4\nF58\nR90\nE5\nL90\nF3\nR90\nN1\nR90\nW1\nN4\nE1\nW3\nN5\nR90\nW5\nS3\nF25\nW4\nN3\nF55\nW2\nR90\nN1\nF98\nL90\nW3\nL270\nE1\nN3\nN2\nR90\nS1\nF39\nL90\nW2\nL90\nN3\nE3\nF80\nW1\nN1\nW4\nF25\nR90\nE3\nL180\nF21\nS4\nF75\nL90\nF76\nW5\nN4\nE2\nR90\nF44\nE3\nN1\nW3\nF49\nN2\nL180\nS4\nL90\nF55\nS4\nR90\nF14\nR90\nW5\nL90\nF85\nN2\nL90\nL90\nE3\nR90\nN3\nE4\nS5\nF75\nL90\nF60\nN2\nR180\nE2\nL90\nE2\nL180\nF27\nE4\nN4\nL90\nN2\nL180\nF91\nN4\nF47\nW2\nN2\nF63\nF63\nW4\nF28\nL90\nN1\nF57\nS1\nE2\nL90\nE5\nL180\nN3\nE4\nF70\nR90\nW5\nL90\nW1\nE3\nF18\nE3\nF15\nN1\nE4\nL90\nW1\nF49\nE3\nR90\nF61\nN3\nE2\nF69\nE1\nF7\nL90\nS1\nF73\nR90\nS5\nE2\nL90\nN1\nS4\nR180\nF8\nS1\nE5\nF44\nN1\nF39\nL90\nS1\nF83\nL90\nE4\nF59\nN4\nW2\nS3\nW2\nR90\nL270\nE4\nR90\nN5\nE4\nF22\nE1\nS3\nR90\nW5\nR270\nN1\nS4\nF39\nN4\nF78\nN4\nW3\nF34\nE5\nF31\nL90\nN3\nR180\nF75\nS2\nE1\nR180\nF89\nE5\nR180\nS1\nW3\nF97\nR180\nF54\nW2\nF6\nW5\nN3\nF58\nR90\nN2\nL180\nF2\nW3\nE3\nN3\nR180\nW1\nE3\nS3\nE2\nF87\nW5\nE3\nR90\nF63\nF30\nR90\nS3\nF69\nE2\nF87\nN1\nF95\nS4\nL90\nF52\n"
  },
  {
    "path": "advent-of-code/2020/inputs/13",
    "content": "1006726\n23,x,x,x,x,x,x,x,x,x,x,x,x,41,x,x,x,x,x,x,x,x,x,647,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,13,19,x,x,x,x,x,x,x,x,x,29,x,557,x,x,x,x,x,37,x,x,x,x,x,x,x,x,x,x,17\n"
  },
  {
    "path": "advent-of-code/2020/inputs/14",
    "content": "mask = 11110100010101111011001X0100XX00100X\nmem[17610] = 1035852\nmem[55284] = 229776690\nmem[16166] = 12685380\nmem[8340] = 16011\nmask = 0X1X0X010101011X10X101000X0001110100\nmem[968] = 15992\nmem[32758] = 7076\nmem[30704] = 1701\nmem[33719] = 58012\nmem[20818] = 25927237\nmem[16718] = 46485\nmask = 111001111X0X0X101X111X1X001XX0011010\nmem[2115] = 14848\nmem[42753] = 617\nmem[56076] = 9933868\nmem[19106] = 43503\nmem[10073] = 32909\nmem[40830] = 1959686\nmask = X11X00000XX1011X10000X01110000X0001X\nmem[41605] = 13245557\nmem[6571] = 7973763\nmem[46231] = 28527162\nmem[44901] = 163334644\nmask = 0101XXX1X10XX1101011110000000010010X\nmem[53492] = 357272\nmem[32816] = 35015\nmem[6965] = 11280352\nmem[27745] = 160101\nmem[26728] = 1260\nmask = 1XXX0100XX1X0X10101100011101101X0111\nmem[22010] = 28123044\nmem[42154] = 82539\nmem[54914] = 22078\nmem[7185] = 436\nmem[58583] = 25334197\nmask = 11110010X001011010X1XX010XX0110001XX\nmem[62397] = 9570559\nmem[49595] = 15491062\nmem[21644] = 9478776\nmem[19853] = 31023\nmask = 001110000101011X1111100XX1111000X111\nmem[62345] = 1200300\nmem[34309] = 115943357\nmem[23144] = 873\nmem[36010] = 954\nmem[6857] = 645222\nmask = 0011X101110X10101111000X010X00100000\nmem[12284] = 570\nmem[44849] = 48293\nmem[48549] = 489763617\nmem[51371] = 1151\nmask = 01X0X10101000XXX10111010011010XX0X10\nmem[17699] = 14190020\nmem[32796] = 84255743\nmem[62003] = 1426\nmem[18906] = 353\nmem[38218] = 615297\nmask = 0X0101010111XXX01011010111XX01100010\nmem[26389] = 62531634\nmem[12404] = 1034263\nmem[49398] = 1006\nmem[22929] = 313056\nmem[16164] = 1694664\nmem[19077] = 53452\nmask = 0X1XXX0X010101101X1110XX101010X01010\nmem[38381] = 18385\nmem[2319] = 552\nmem[60857] = 1931\nmem[41219] = 19301038\nmem[9073] = 85077\nmask = 00010000010XX1X01000110101100X000111\nmem[10385] = 227941\nmem[31042] = 151514106\nmem[22360] = 168649336\nmask = 0110010X0100XX10001X11X1X11100XX0X11\nmem[40411] = 8140928\nmem[3859] = 2742\nmem[45449] = 4317450\nmem[17740] = 1337381\nmem[19338] = 6605990\nmem[22407] = 53051\nmem[42292] = 550664\nmask = X1110XX00X0101101011XX0X101110001111\nmem[59509] = 304929\nmem[43817] = 14977\nmem[39410] = 439\nmem[38730] = 34567670\nmem[31862] = 8027039\nmem[60857] = 5209\nmask = X11X0000X1X101X010110XX011111011X011\nmem[28472] = 14882\nmem[50099] = 1135\nmem[58921] = 980796\nmem[50737] = 36974\nmem[54167] = 22140347\nmem[2139] = 22934\nmem[13202] = 136157\nmask = X1X001X1010001X0X0111100101110X0X101\nmem[911] = 8925\nmem[652] = 183714641\nmem[58633] = 5186611\nmem[41763] = 29030\nmask = 011X01010010001110110X0X1100000000X1\nmem[47324] = 8124\nmem[31660] = 355290\nmem[19624] = 1760\nmem[32635] = 27873924\nmem[45190] = 439446159\nmem[1090] = 428\nmask = XX10000X00011X1X1011010X0001110X0101\nmem[40622] = 1839170\nmem[45103] = 108379641\nmem[29222] = 187252\nmem[42753] = 2592089\nmem[46615] = 4466791\nmem[22416] = 6619543\nmask = X0X101X10X000010XXX10110111011011101\nmem[42154] = 3271203\nmem[10355] = 89584861\nmem[14447] = 383415\nmask = 1X000X001X100X10X0X1X01X1101X0110101\nmem[40691] = 1490354\nmem[6162] = 601597339\nmem[62819] = 15727\nmem[48596] = 8589566\nmem[46732] = 56337\nmem[35437] = 1568988\nmask = 00X0X10X01010110X0111X0XX01100001111\nmem[43285] = 75734\nmem[41605] = 46442\nmem[7672] = 667983\nmem[29222] = 9835\nmem[34949] = 3945167\nmask = 01X00101X101001010X1100X0X11X110X101\nmem[8617] = 182201\nmem[33667] = 11585659\nmem[57414] = 235257\nmask = 0111010001010XX01X11XX1011XX101X1011\nmem[19633] = 3970\nmem[10580] = 6454804\nmem[22445] = 12328278\nmem[22131] = 70709\nmem[31438] = 870851666\nmem[46279] = 638924631\nmem[20402] = 311245\nmask = 0110000101X1X11010111X001111X1000111\nmem[2405] = 733626\nmem[27649] = 150996\nmem[45000] = 13156617\nmask = 01X10X0X01X10110101101X1X1X00100011X\nmem[44304] = 5130\nmem[25804] = 264101480\nmem[896] = 1445\nmem[20949] = 386031115\nmem[24951] = 9889\nmem[51040] = 3708234\nmask = 00100X01010101101111100010XX0100X1XX\nmem[31907] = 15551\nmem[1218] = 1034\nmem[17073] = 359232\nmask = 010100010101X1101X11011X010001XXXXX0\nmem[11137] = 1499158\nmem[59509] = 262392\nmem[6988] = 14863\nmem[28213] = 554\nmem[7044] = 68\nmask = 01100101X1XX0X10X01110X1001X00X00X11\nmem[22674] = 3230\nmem[35891] = 3585\nmem[3551] = 15928515\nmem[36206] = 104461320\nmem[22167] = 1161073\nmask = 01X1X00X01010X1010111X010XX00011X101\nmem[17360] = 494\nmem[34415] = 3766044\nmem[8898] = 846638\nmem[48368] = 500781\nmask = 011001010X0X001X0X101X010X100101100X\nmem[60679] = 10414\nmem[34463] = 11\nmask = 01100100010XX11X1X0X0000001111010011\nmem[40952] = 1659\nmem[27502] = 2916485\nmem[7436] = 211741\nmem[58641] = 944726\nmem[58633] = 46218913\nmask = 010110000101011X101101X0111110X00X11\nmem[3042] = 13844\nmem[49701] = 56163826\nmask = 011001X00101011010X1100010X11X011X11\nmem[38067] = 7299191\nmem[31130] = 116061\nmem[2139] = 63458254\nmem[4521] = 1237\nmask = 0111X000X1010110101X011100100100011X\nmem[21329] = 642\nmem[41123] = 28058\nmem[29555] = 4111\nmem[15009] = 3801745\nmem[49595] = 317\nmem[56642] = 126724425\nmem[29388] = 19214321\nmask = 1101X1X0X11X101011X01X11X0111X001X01\nmem[20118] = 21164480\nmem[39432] = 508\nmem[39859] = 958\nmem[36851] = 196470\nmem[26907] = 97849565\nmask = XX10000011110X001011XX0010X110100001\nmem[34234] = 17652327\nmem[16028] = 80890944\nmem[54559] = 64040\nmem[25194] = 41593756\nmask = 001110000101X1101XX1000X10110000110X\nmem[33667] = 916652067\nmem[2405] = 1244\nmem[63718] = 292918\nmem[29526] = 711465\nmem[24951] = 1884\nmem[22360] = 167190303\nmask = 1100000000111X11101X0110X00010X00100\nmem[6620] = 2734891\nmem[64584] = 215747822\nmask = 01X00X000100101000X11000X01110100X01\nmem[56211] = 3278176\nmem[40364] = 340370\nmem[23555] = 27655\nmem[42471] = 227213\nmask = 1X10X1111101X110X011X000X0X0X10011X0\nmem[6829] = 110833304\nmem[15624] = 23686\nmem[59705] = 5391933\nmem[10724] = 32064\nmem[14827] = 6939\nmask = X1X1100001010X111011101X00110X000010\nmem[50595] = 719945\nmem[1480] = 39227195\nmem[52615] = 124668762\nmask = 01100XX1110X011XX01100001011X1X10X10\nmem[58924] = 3492\nmem[16850] = 584\nmem[61283] = 289490093\nmem[20396] = 55247\nmem[12216] = 9844180\nmem[12216] = 14974951\nmask = 00X00101010101X010111000101XX0100001\nmem[4778] = 4486654\nmem[24826] = 1334889\nmem[30412] = 685\nmem[424] = 40892660\nmem[19019] = 87071\nmem[58641] = 13743890\nmask = 011100XXX10101101X0X00010001011100X0\nmem[10355] = 392450\nmem[20082] = 23264\nmem[25220] = 1800190\nmem[59108] = 141835\nmem[58233] = 543\nmem[48973] = 863\nmem[54167] = 28960\nmask = 1110X0000001X11010110000X1011XXX1010\nmem[52783] = 2071776\nmem[60857] = 108259027\nmem[37356] = 2641268\nmem[21950] = 47481758\nmem[52557] = 7700825\nmask = 0X11010XX10X001011110010111000101001\nmem[58111] = 244589936\nmem[41399] = 42658\nmem[27306] = 237040\nmem[4122] = 1592\nmask = X1X00X0111110110101XX1001001X0010X10\nmem[6801] = 34789897\nmem[59447] = 10675177\nmem[28987] = 666686\nmask = X110000X000110X11011111000X11100010X\nmem[424] = 2927\nmem[30920] = 894899\nmem[1670] = 305032596\nmask = 0111X01000X1X1101011001X111000011010\nmem[29811] = 632621\nmem[40046] = 51323\nmem[55593] = 6182\nmask = 01100011100XX11X00X110X011110XX10101\nmem[58803] = 484311\nmem[49237] = 12281\nmem[46823] = 1332\nmem[24356] = 1277234\nmem[42561] = 1938\nmem[14991] = 8909\nmask = 0111X00000X101101X11101010111X001111\nmem[8482] = 2735\nmem[36657] = 64651206\nmem[3842] = 157\nmem[60137] = 483271\nmem[5610] = 709\nmask = XX1X00X00X01X11010111X001101110X1111\nmem[22416] = 27971815\nmem[19192] = 7861\nmem[51678] = 25016\nmask = 011XX1111101XX101111001X001110010000\nmem[64535] = 155\nmem[38057] = 669\nmem[8482] = 29767095\nmask = 00100X000X010X10X111100X11100110X101\nmem[38067] = 10211\nmem[37762] = 11637\nmem[34706] = 44902\nmask = 0X11001100110XXX1011011X10X10X01100X\nmem[26809] = 2100865\nmem[60446] = 25094\nmem[43745] = 461971\nmem[24321] = 28927\nmem[7984] = 355769146\nmem[9488] = 1910\nmask = 0X1001X1X10X0X1010111X10X011X01X1111\nmem[51678] = 2889\nmem[46700] = 214866595\nmem[40992] = 4945733\nmem[25409] = 172376952\nmask = 0110011111X100101X11000XX110X0001X0X\nmem[11587] = 9651\nmem[41265] = 61660\nmem[1822] = 6155\nmem[29303] = 250909900\nmem[59145] = 51920318\nmask = 01X1X0X0X1010110101100101111100X0001\nmem[33719] = 2071728\nmem[24951] = 108\nmem[12284] = 369552742\nmem[55012] = 53272268\nmem[31862] = 3576\nmem[5950] = 460151\nmem[55978] = 53697916\nmask = XX1100000X01011010X1100011X01000X110\nmem[61606] = 1036\nmem[6477] = 81209\nmem[2187] = 6526467\nmask = 111000X011110100X011X0XXX11X10110X01\nmem[25194] = 7338343\nmem[16563] = 225968\nmem[51983] = 30985431\nmask = 0X000100010101101X11100X00011X111011\nmem[34309] = 434429\nmem[16850] = 476433401\nmem[63015] = 181118\nmask = X110001011X1010X1011010X1011X01100X0\nmem[19081] = 237103716\nmem[24300] = 10640\nmem[23963] = 430607\nmask = 0111XXXX001101101011000011XX00X01XX1\nmem[26941] = 27590\nmem[31862] = 20472\nmem[4020] = 3134353\nmem[55543] = 1761762\nmem[45048] = 1024489921\nmask = 11100111X10X111XX0X1000010111110101X\nmem[48596] = 3587524\nmem[2018] = 451398\nmem[54298] = 121634159\nmem[26371] = 5517119\nmem[57585] = 1825\nmask = 0111X00X0011X11010X10X100100X1100000\nmem[44281] = 1515553\nmem[36633] = 1289\nmem[30077] = 12046281\nmem[55362] = 226809\nmem[48993] = 794317\nmem[58968] = 241\nmask = X110010101100X10101110100011000XX001\nmem[22929] = 2072990\nmem[22931] = 336\nmem[31880] = 119168961\nmem[3859] = 49656496\nmem[45103] = 296484159\nmask = XX11000001011110100101100X0X01100101\nmem[41219] = 826\nmem[38539] = 22527609\nmem[40238] = 29540\nmem[34813] = 4305171\nmem[51640] = 4302332\nmem[44070] = 1373134\nmask = 011X0000X101011010011111X01X10101011\nmem[40884] = 256867181\nmem[56234] = 2181222\nmem[5950] = 68826\nmem[1760] = 88028804\nmem[50704] = 5302105\nmem[24366] = 442\nmem[10147] = 127227597\nmask = 0110X1100101X1101011X111100X0X0XX010\nmem[21956] = 121736133\nmem[25007] = 3174\nmem[42616] = 925004\nmem[1670] = 3018\nmem[46932] = 2981988\nmask = X1110011001XXXX01011011X1X1100011X01\nmem[61283] = 521975\nmem[27640] = 322\nmem[62514] = 153670214\nmem[23951] = 14226595\nmem[9549] = 2336533\nmem[11888] = 827772\nmask = 1101X100XXX1X010111000XX0001000X10X1\nmem[16797] = 22808\nmem[48021] = 2258240\nmem[12370] = 185157105\nmask = 01110X0X00XX0X1X10110100X10X01000010\nmem[4594] = 93\nmem[57388] = 665641765\nmem[1345] = 361710791\nmem[37543] = 1730\nmem[57136] = 388716965\nmem[42524] = 553\nmem[13403] = 637623155\nmask = 0110X1X0X101011X10110110100101011110\nmem[16512] = 3631\nmem[11337] = 203803846\nmem[2504] = 336583240\nmem[12269] = 4069068\nmask = 01XX001111001110101100001X01000100X0\nmem[33661] = 6490\nmem[30704] = 128919282\nmem[41797] = 22490\nmem[8134] = 38294563\nmem[63208] = 12103\nmask = 11X00X0000X1XX1X101100010000010011XX\nmem[24951] = 3275742\nmem[23998] = 1551\nmem[19972] = 5727596\nmem[17337] = 205937438\nmem[41952] = 53261\nmem[64651] = 26734\nmask = X11001111101XX101X110X001011100X0X1X\nmem[57388] = 441426\nmem[11337] = 336\nmem[8515] = 381065399\nmem[49625] = 1066556272\nmem[54274] = 7650\nmem[8575] = 15426\nmem[18302] = 216253866\nmask = 1X0X00X000X11X1110110100110111X1X101\nmem[6256] = 17076091\nmem[7973] = 5554062\nmem[39859] = 1429203\nmask = 0X110001011101101X1111101001XX000110\nmem[38807] = 351\nmem[28213] = 22387\nmem[26591] = 76518875\nmem[15712] = 12048675\nmask = 01X1XX00010101101011X111XX1010XX1011\nmem[9073] = 789\nmem[39859] = 919291385\nmem[18302] = 347\nmem[41224] = 4579691\nmem[41167] = 19132842\nmem[424] = 158741911\nmask = X110010X0100X010X0100X00XX111001X011\nmem[28822] = 66019\nmem[46209] = 2719\nmem[35264] = 1826\nmem[60137] = 389000\nmask = 01010001X101X11010110X111111X1000001\nmem[16591] = 62860121\nmem[10737] = 1180\nmem[31130] = 16000\nmem[34880] = 584\nmem[6800] = 39\nmask = 0111X000X1XX11101001010X00110010011X\nmem[5501] = 31780835\nmem[31862] = 6009\nmem[49129] = 91037\nmem[7935] = 15099\nmem[44839] = 31518815\nmask = 0101000101011110X1110111000001XXX000\nmem[14827] = 1206371\nmem[62398] = 1062\nmem[50952] = 1253562\nmem[32584] = 22533969\nmem[9662] = 2590\nmask = 01100X111X0X1110XX111X000X1101000001\nmem[40142] = 107915\nmem[10580] = 4884244\nmem[2187] = 1020\nmask = 11X100XX1001X1X0101X01X1001X11111100\nmem[19551] = 54829\nmem[18208] = 627039\nmem[18032] = 3423\nmem[24162] = 301557348\nmem[35891] = 1206\nmask = 01100111110100X0XX1X1011XXX100101000\nmem[9695] = 368318059\nmem[9916] = 30083984\nmem[9903] = 866066456\nmem[3360] = 434642\nmem[3609] = 2437\nmask = 0XX1X000010XX1X0100X1010X10100X00111\nmem[64662] = 5845\nmem[20000] = 2302117\nmem[21056] = 11248\nmem[641] = 200833516\nmem[46678] = 3506929\nmask = 0X100111111100101111110X01110X00010X\nmem[59199] = 1984963\nmem[43784] = 7811709\nmem[49701] = 3967\nmem[11888] = 790487\nmask = 111X00000101111010010X10001101XX11X0\nmem[51082] = 222096294\nmem[50595] = 121297\nmem[27424] = 268132\nmem[9473] = 200971\nmem[42941] = 1604\nmask = 0X11010X1X00X01011110010111XX010X00X\nmem[44304] = 31572\nmem[14907] = 1066531\nmem[34745] = 91393\nmem[1617] = 124090\nmem[25898] = 49692\nmask = X11X01000X010X111X1X10100000010X10X0\nmem[12953] = 62465686\nmem[24718] = 15597133\nmem[20124] = 4930329\nmask = 0X11010000X10X1010110111XX00X1XX101X\nmem[12426] = 694\nmem[2226] = 70693\nmem[6332] = 3693756\nmask = 0111100000110XX010X11000X1X111011010\nmem[42447] = 86599788\nmem[62694] = 50365\nmem[59239] = 4355782\nmem[12523] = 14292673\nmem[52756] = 2685769\nmem[54978] = 207845\nmem[17699] = 366567692\nmask = 011001011111X0XX101100000X10X0X01011\nmem[8186] = 1183\nmem[6181] = 8087\nmem[61605] = 3505\nmem[46678] = 85544\nmem[40046] = 5212041\nmem[28835] = 3272650\nmask = 011100000101X11010X1011X10X1XX00X011\nmem[55012] = 105058\nmem[52202] = 26295\nmem[59657] = 2809\nmask = X1X10100X101XXX0X110001110001XX01001\nmem[45682] = 323588\nmem[49237] = 58065\nmem[41032] = 27927\nmem[35647] = 280\nmem[47892] = 252817\nmem[29350] = 15075\nmask = X11100X0010X01X010111101001100000010\nmem[34234] = 10472\nmem[14531] = 102821\nmem[49081] = 3626197\nmem[62940] = 630043\nmem[4115] = 453716952\nmask = 0111010001XX0110111X0101100X1X10101X\nmem[911] = 198069\nmem[5550] = 42378\nmem[27566] = 13692\nmem[13890] = 46764242\nmem[11669] = 66225421\nmem[54529] = 652599152\nmask = X11X01X00X01011X10110110X00X100X10X0\nmem[7236] = 3301\nmem[10580] = 971\nmem[51284] = 232016\nmem[13784] = 33278200\n"
  },
  {
    "path": "advent-of-code/2020/inputs/16",
    "content": "departure location: 26-724 or 743-964\ndeparture station: 33-845 or 864-954\ndeparture platform: 26-472 or 482-967\ndeparture track: 27-140 or 158-956\ndeparture date: 25-884 or 894-952\ndeparture time: 37-924 or 941-949\narrival location: 48-311 or 335-972\narrival station: 39-703 or 724-950\narrival platform: 40-108 or 114-950\narrival track: 30-101 or 108-967\nclass: 33-386 or 399-949\nduration: 44-444 or 452-956\nprice: 27-220 or 234-974\nroute: 42-774 or 790-959\nrow: 48-900 or 918-956\nseat: 42-165 or 178-949\ntrain: 45-831 or 842-965\ntype: 49-522 or 548-974\nwagon: 32-565 or 588-964\nzone: 27-608 or 617-953\n\nyour ticket:\n101,71,193,97,131,179,73,53,79,67,181,89,191,137,163,83,139,127,59,61\n\nnearby tickets:\n818,269,901,814,631,821,607,127,247,636,755,762,559,670,189,249,499,273,565,463\n470,472,597,259,345,370,827,520,595,92,204,52,104,248,688,500,99,694,659,803\n432,251,666,518,217,469,791,304,139,724,516,522,702,496,804,142,408,518,82,823\n333,471,429,58,129,754,304,879,459,288,268,386,217,138,284,554,762,370,769,161\n242,255,344,634,710,124,813,241,697,342,600,637,202,421,75,195,496,470,806,554\n464,948,755,334,662,493,251,948,286,472,562,400,774,790,385,263,100,689,681,83\n511,796,756,593,637,647,377,277,178,642,588,695,591,495,678,682,346,318,417,84\n762,238,803,343,290,80,558,216,806,157,821,359,654,661,870,552,503,604,200,754\n613,290,370,761,595,899,743,868,289,162,303,653,810,311,95,468,588,456,772,342\n352,332,559,813,443,243,881,75,522,245,190,61,488,755,341,489,219,671,642,875\n884,60,949,97,626,597,472,371,273,464,942,254,497,443,50,555,692,286,557,445\n159,512,555,651,88,237,71,259,76,639,727,356,519,93,696,644,872,117,160,655\n897,767,193,255,485,702,370,160,597,651,918,444,831,160,67,107,768,140,163,282\n523,415,900,125,409,75,335,512,807,507,769,73,108,427,269,826,817,434,946,80\n114,60,239,55,73,122,619,799,754,795,497,792,835,311,594,767,821,267,812,597\n795,291,757,746,626,752,220,649,269,918,75,895,895,369,310,794,638,900,712,619\n740,295,117,790,364,344,900,921,884,896,809,382,189,944,165,92,878,791,827,212\n256,293,876,370,159,678,669,512,755,185,430,489,515,457,467,312,384,219,380,830\n186,130,560,633,920,457,59,766,305,835,642,813,68,453,656,429,427,256,364,296\n281,488,117,820,159,444,923,325,805,801,91,698,631,343,131,287,560,831,495,661\n132,875,622,812,308,880,160,830,668,238,445,454,410,685,64,413,428,799,55,656\n261,772,752,829,367,947,71,194,66,254,102,812,280,455,90,744,823,460,205,406\n656,347,472,489,419,355,693,250,221,75,302,492,83,617,691,556,687,99,773,520\n208,365,163,0,181,820,403,844,343,347,557,124,945,599,699,439,75,800,745,115\n278,228,294,803,372,759,239,384,80,243,99,456,378,367,668,703,762,288,758,689\n89,198,186,409,123,279,100,367,275,399,470,163,752,215,659,342,69,916,467,875\n624,551,663,437,441,753,807,638,373,881,108,377,229,367,769,691,79,254,409,456\n661,553,822,674,435,55,800,139,749,800,158,368,402,521,321,842,285,439,673,417\n218,363,786,191,694,117,130,95,701,284,159,308,802,400,826,284,158,462,405,234\n887,763,452,724,336,882,818,377,400,681,674,814,511,470,260,433,97,653,62,744\n690,606,756,361,283,670,501,621,519,325,764,239,137,501,62,454,241,237,368,507\n61,283,521,131,751,521,696,181,214,766,762,503,190,336,311,345,74,600,617,789\n297,375,215,56,675,695,825,125,277,84,656,181,563,790,828,694,343,710,744,298\n412,359,842,243,520,876,696,555,620,190,668,487,274,238,599,54,633,297,727,637\n690,556,264,384,369,18,190,808,344,603,767,90,695,219,63,896,484,255,483,799\n122,877,512,905,254,495,692,751,369,675,625,640,355,879,604,627,457,70,878,78\n942,121,807,564,919,431,768,675,65,619,461,336,247,623,527,493,133,283,237,404\n84,384,876,444,880,403,675,114,632,255,21,205,339,253,62,372,404,683,292,88\n185,348,472,400,63,444,80,883,373,336,426,563,675,561,305,516,449,456,514,872\n648,82,604,650,697,825,462,813,306,94,814,597,879,795,461,294,213,511,331,487\n488,761,215,264,421,492,695,191,205,753,918,639,162,317,769,212,123,202,591,795\n842,127,163,78,765,180,236,87,235,462,60,800,871,364,217,614,924,597,247,409\n807,423,611,589,759,629,192,471,456,118,77,760,94,82,882,429,60,462,499,898\n772,503,822,287,342,458,918,633,624,216,280,75,328,125,352,685,520,769,508,655\n212,386,347,829,752,482,690,521,136,687,991,899,244,798,562,424,354,554,654,61\n558,252,63,674,882,420,693,273,604,269,812,621,266,338,697,479,58,295,659,204\n351,426,373,683,869,621,815,263,685,244,804,435,446,461,353,764,762,815,403,760\n590,469,920,421,125,382,650,844,694,602,493,746,372,874,243,990,198,486,745,100\n249,668,621,369,630,216,242,752,588,10,125,216,675,162,162,352,462,242,296,771\n161,81,595,194,61,359,300,379,339,696,58,485,282,696,11,265,302,621,678,439\n256,944,238,602,599,184,410,229,244,899,509,289,119,488,159,75,79,269,607,809\n992,802,308,271,58,520,201,64,164,748,551,123,371,122,602,403,361,205,820,443\n662,601,606,596,57,757,160,687,139,215,783,72,444,440,365,298,511,654,56,237\n460,302,355,632,824,664,760,210,924,673,692,688,763,358,488,419,709,275,663,206\n595,420,202,434,454,550,274,745,453,195,314,374,682,372,695,249,65,245,57,680\n247,877,682,187,743,288,884,509,281,341,355,499,296,178,310,289,651,659,231,250\n601,421,558,658,641,884,104,483,865,647,255,945,439,286,821,697,693,820,700,115\n608,944,870,617,414,271,440,404,378,426,714,295,791,89,792,280,654,243,193,273\n639,183,837,439,161,696,494,653,86,215,58,550,67,758,355,435,507,214,251,403\n757,216,644,124,775,382,159,84,599,381,202,946,672,744,443,426,219,490,246,360\n406,214,643,589,107,521,819,124,425,774,339,74,608,654,399,444,624,623,943,250\n696,291,829,514,696,472,235,751,602,823,259,416,160,24,250,439,743,164,949,762\n807,652,337,772,876,685,899,190,459,358,429,831,125,206,834,655,53,422,453,208\n837,881,335,774,884,690,588,441,302,864,53,607,81,140,897,470,258,693,355,507\n450,471,55,235,307,383,623,488,662,208,302,844,344,622,137,492,604,633,685,745\n244,140,457,495,381,558,264,509,69,703,337,756,774,593,824,361,627,513,899,110\n588,675,747,751,348,687,310,212,88,711,433,665,947,247,493,941,182,564,242,803\n131,809,52,243,229,244,265,212,282,248,441,246,210,701,506,348,812,52,354,791\n195,800,417,404,746,683,488,558,53,625,520,774,201,377,143,73,417,457,556,820\n879,365,346,239,821,924,843,844,662,648,828,251,374,78,17,768,453,108,245,265\n217,286,600,281,408,676,265,5,311,433,236,134,67,463,380,684,123,292,420,690\n753,453,500,898,487,556,185,839,361,521,282,674,617,399,946,100,647,941,874,297\n509,403,121,483,371,672,768,181,894,109,486,765,308,55,94,196,400,947,551,665\n284,628,619,764,673,117,140,649,275,279,347,696,949,668,479,234,186,125,807,658\n159,179,808,697,270,948,744,702,588,878,178,600,466,502,189,513,313,219,844,813\n794,89,798,897,762,943,632,181,753,637,113,358,236,882,280,680,67,466,299,873\n687,211,824,97,459,945,159,521,517,201,252,355,359,303,635,429,643,135,824,738\n366,522,355,949,490,500,425,119,517,212,75,301,636,658,188,635,660,115,838,308\n67,693,297,257,461,604,287,92,75,601,773,240,193,292,881,916,694,128,603,594\n684,486,773,235,386,773,896,401,894,766,551,632,87,196,462,763,103,417,299,867\n601,369,703,467,497,74,420,516,235,450,197,198,820,806,370,942,161,813,943,303\n565,669,213,604,349,499,203,553,549,690,590,379,89,649,513,517,420,345,366,317\n250,514,752,810,520,254,276,692,90,865,458,657,694,4,117,89,519,158,643,248\n809,868,194,665,315,99,504,826,211,335,410,512,701,131,879,797,593,204,509,419\n89,666,249,808,190,195,991,186,812,353,188,774,65,700,700,457,498,273,745,879\n192,299,357,829,601,455,263,123,245,807,594,139,130,98,103,453,645,400,163,919\n757,291,511,756,659,640,878,749,408,452,621,598,128,262,365,805,726,252,159,639\n998,361,517,654,745,73,799,64,261,243,618,265,806,416,945,84,686,430,452,702\n193,686,757,225,206,358,509,552,522,606,592,748,372,375,507,871,501,99,693,373\n800,433,423,244,75,399,822,357,866,613,489,598,405,218,772,100,421,374,812,428\n232,658,918,309,335,250,271,237,756,115,514,74,254,220,242,130,120,260,691,429\n516,135,63,608,68,366,260,827,599,687,433,381,192,464,75,640,890,132,590,592\n293,790,666,369,497,824,195,882,100,63,894,386,872,703,511,679,684,639,82,477\n112,54,444,68,946,797,370,343,685,588,759,791,499,249,241,941,374,434,239,443\n347,666,104,948,623,826,680,277,341,57,411,624,443,455,51,548,290,668,693,502\n465,270,252,463,253,434,128,595,774,256,598,64,67,307,348,213,478,348,809,262\n278,381,798,768,516,825,831,426,114,181,74,274,772,187,750,799,374,161,3,60\n489,340,296,553,96,805,239,648,791,309,484,88,484,797,363,829,128,120,868,977\n275,902,677,688,488,867,751,98,874,443,236,379,203,486,200,895,431,241,251,617\n187,511,602,442,301,631,876,793,510,623,75,56,101,407,805,164,772,302,608,910\n341,194,268,818,450,467,82,262,260,874,185,92,943,436,164,287,644,672,190,949\n521,644,922,869,471,467,134,209,878,249,805,259,640,140,820,868,680,867,797,888\n696,92,208,819,197,486,240,70,114,697,768,922,52,182,227,414,659,216,745,921\n360,764,235,823,822,195,498,290,677,989,811,666,876,872,666,418,484,310,268,206\n806,773,119,191,642,746,417,125,946,770,68,386,639,484,847,819,91,452,264,67\n894,420,617,399,594,921,811,679,869,642,403,350,816,671,703,279,612,745,271,766\n452,724,361,759,428,754,626,410,190,210,217,306,879,51,829,936,603,165,80,279\n135,93,678,283,624,488,326,755,240,384,56,641,502,50,790,99,756,816,57,899\n468,89,447,490,129,650,796,802,617,403,75,598,827,470,136,826,924,599,510,69\n11,519,284,210,795,452,503,701,666,878,300,865,689,632,132,456,269,341,640,289\n274,299,214,499,693,677,430,499,427,280,415,554,304,126,509,740,724,823,287,498\n702,401,94,647,999,340,100,682,210,412,348,762,625,864,64,661,403,97,697,384\n697,695,226,292,556,658,771,802,515,309,797,588,652,509,379,508,115,365,285,452\n184,672,373,894,697,699,489,630,269,455,749,352,208,412,512,648,231,295,517,648\n116,341,746,199,120,372,89,782,656,620,417,199,379,820,94,668,873,385,818,482\n71,437,428,588,87,129,797,604,308,942,148,127,455,252,180,335,343,373,121,774\n743,193,820,873,595,357,819,305,409,747,228,763,872,506,84,562,180,809,670,661\n943,442,899,309,767,137,199,407,679,944,304,357,792,979,190,198,278,419,214,798\n460,413,257,872,134,666,943,446,644,160,549,359,129,684,344,341,633,335,517,662\n122,277,89,487,684,358,550,722,97,643,72,361,495,370,919,124,651,651,900,697\n817,802,682,797,412,649,506,495,644,897,51,821,471,683,696,384,160,52,112,828\n899,483,853,804,384,607,82,91,656,815,624,687,554,820,125,188,78,289,183,656\n713,408,672,270,350,123,159,879,746,654,53,506,249,804,259,132,374,128,384,84\n51,746,949,761,697,518,884,649,426,99,124,924,631,255,293,633,701,798,21,376\n483,294,192,212,455,359,337,814,949,495,164,766,281,799,729,211,515,96,257,754\n820,368,756,16,657,651,797,422,601,674,187,234,443,765,883,52,644,262,399,277\n374,182,140,695,504,620,617,675,363,52,615,380,878,268,441,756,672,72,352,195\n302,201,406,506,483,499,198,120,689,560,411,57,506,622,931,698,188,865,282,597\n149,813,402,366,896,264,499,99,68,502,804,923,798,866,882,161,646,193,666,688\n773,827,126,773,948,553,808,482,336,990,165,384,821,831,870,62,750,118,814,55\n402,669,320,258,631,271,876,201,129,311,373,98,486,666,596,806,949,114,638,252\n511,878,125,191,340,868,349,813,100,444,517,303,746,288,670,623,59,664,86,835\n58,652,898,548,501,122,644,561,591,379,660,513,751,367,893,750,826,560,867,826\n760,799,874,623,304,759,880,946,211,947,180,617,671,215,654,343,161,383,267,148\n554,649,296,248,807,69,335,703,371,943,139,456,944,763,772,845,465,549,638,106\n382,339,199,347,351,96,864,165,125,65,464,650,820,87,827,199,110,287,922,307\n854,408,123,371,134,798,756,278,923,283,492,864,385,563,565,190,252,486,482,630\n383,592,2,484,65,922,644,345,793,386,423,679,348,817,471,281,880,415,179,623\n306,452,549,877,132,81,454,553,179,343,94,502,72,204,139,678,289,9,413,804\n629,424,490,307,695,433,64,95,949,693,378,191,296,72,198,434,485,445,256,89\n755,809,606,499,74,259,94,649,315,667,297,88,254,425,241,52,255,352,685,657\n768,828,654,691,254,461,241,108,63,661,817,617,17,602,771,753,180,307,635,441\n490,699,275,651,456,681,432,335,552,377,279,124,594,869,53,872,788,98,63,769\n297,625,382,211,694,408,897,510,196,195,455,339,351,807,760,802,910,71,649,828\n483,555,88,691,442,868,289,643,74,403,260,633,561,437,665,460,419,277,154,549\n520,411,599,807,278,486,555,165,900,218,500,752,828,250,68,791,200,103,124,188\n506,841,843,244,375,303,158,487,134,759,235,763,558,597,805,257,469,274,877,50\n628,192,375,975,517,138,180,677,305,60,276,134,817,691,551,214,284,794,51,67\n352,642,494,845,634,746,71,619,402,227,808,360,819,920,617,753,643,491,812,492\n381,296,293,139,455,643,140,294,245,505,921,201,378,443,800,369,976,879,92,267\n918,268,63,181,372,78,264,63,638,236,837,266,644,399,702,257,946,824,869,138\n509,206,617,373,55,321,662,376,664,692,458,218,211,560,399,459,163,421,289,483\n104,724,435,627,120,348,123,272,304,199,423,190,865,749,234,204,942,894,770,493\n180,764,752,135,212,630,554,427,607,621,811,212,362,347,239,777,634,900,455,877\n644,946,151,844,220,288,608,385,159,278,370,491,362,949,680,281,871,179,75,386\n878,820,458,92,289,195,66,814,362,137,461,127,770,412,916,453,98,797,668,370\n385,770,241,744,555,809,268,443,119,132,470,377,74,184,253,122,141,746,197,201\n384,667,617,103,869,871,799,257,792,488,127,384,269,680,551,505,280,431,269,254\n482,702,159,489,830,123,215,204,872,56,514,260,456,108,368,229,242,191,53,799\n602,558,864,268,802,434,160,644,102,592,945,411,607,360,493,796,468,384,386,404\n164,371,220,434,628,418,82,588,190,560,608,131,916,694,884,198,765,703,358,82\n491,490,263,825,565,509,53,670,416,703,877,126,161,944,76,486,747,784,288,266\n679,419,626,341,588,364,758,594,671,51,913,795,261,827,651,633,386,115,626,648\n264,621,203,521,366,96,881,431,818,557,356,590,236,383,344,941,655,628,382,227\n901,499,378,762,488,671,350,255,876,239,406,556,683,521,158,421,829,373,158,72\n624,900,869,467,444,820,247,280,291,234,896,747,899,654,184,471,622,13,871,471\n799,683,279,131,663,678,225,676,430,65,345,98,138,193,188,267,505,257,689,588\n766,305,865,416,60,516,771,462,165,105,483,555,883,761,498,665,660,696,617,506\n469,431,658,439,267,163,505,194,698,681,494,258,408,107,669,294,809,136,549,288\n417,440,178,259,816,193,502,90,945,991,307,465,343,564,488,118,139,798,441,824\n946,683,592,182,813,74,864,872,408,640,460,948,77,263,692,467,402,202,11,108\n607,214,949,219,466,431,486,280,635,342,254,405,793,374,256,94,692,552,615,261\n497,681,195,924,877,92,198,186,308,403,250,372,484,301,111,187,56,201,401,193\n549,608,490,811,549,284,335,648,2,684,920,165,277,866,749,400,604,278,461,202\n122,826,658,844,270,817,896,340,656,784,876,340,306,383,589,647,797,296,220,605\n671,804,653,297,61,340,239,772,373,688,291,755,92,240,371,65,21,604,607,642\n994,381,193,868,76,495,943,403,415,84,423,626,99,675,214,344,805,588,115,410\n646,276,478,845,116,947,564,462,407,689,91,284,257,59,64,596,287,292,214,286\n250,668,109,239,701,646,347,278,440,210,108,185,670,238,556,884,180,415,405,310\n56,159,267,821,744,435,762,658,657,262,827,196,870,352,713,873,682,73,71,724\n677,494,594,700,597,551,767,138,749,430,124,560,339,386,278,200,896,94,139,712\n938,73,489,383,346,635,638,747,821,345,408,758,800,431,765,183,842,263,186,745\n5,125,769,508,404,250,747,818,458,757,54,875,651,803,896,250,797,589,293,636\n642,342,361,132,598,83,629,443,336,213,77,829,208,295,811,379,269,192,449,235\n303,794,376,117,198,874,88,284,241,565,632,425,240,57,768,398,606,685,516,212\n291,819,947,878,829,423,410,880,7,101,379,761,595,867,384,559,64,896,92,664\n263,654,441,635,564,661,914,640,668,268,290,344,286,757,490,588,818,765,421,305\n655,622,797,562,414,85,179,375,867,801,418,460,69,276,158,109,140,302,212,381\n466,217,763,790,486,202,57,124,878,122,239,520,774,628,502,749,357,604,862,92\n479,549,68,134,238,687,796,368,817,209,252,301,495,918,682,161,409,247,897,81\n254,451,894,681,618,437,509,791,592,454,349,258,456,282,793,254,793,56,820,158\n800,185,138,434,291,19,134,140,759,765,288,178,268,621,218,439,291,502,496,52\n373,810,255,509,189,84,756,746,498,364,216,824,774,656,392,765,370,199,771,304\n650,443,845,605,900,340,189,124,259,820,608,810,761,370,242,555,834,800,752,507\n441,757,425,831,636,139,448,746,98,249,895,184,454,442,756,685,432,553,120,634\n115,563,74,562,841,823,501,945,671,354,680,279,604,772,279,194,286,257,258,272\n414,455,515,162,53,505,165,554,441,422,369,367,297,220,755,516,849,554,191,132\n620,139,813,95,354,241,493,880,652,901,408,98,431,866,695,66,119,664,80,202\n589,373,596,461,340,335,286,695,766,423,695,626,470,550,882,367,897,838,382,943\n374,339,518,555,212,409,511,109,687,592,338,77,831,588,897,164,163,508,603,416\n634,767,376,844,749,803,383,53,752,274,96,116,628,549,126,450,465,179,865,554\n115,821,821,383,605,275,619,654,564,819,799,644,651,431,430,114,804,165,907,482\n649,452,253,493,680,366,761,677,794,501,207,806,822,92,683,811,618,229,881,435\n421,489,178,459,402,436,216,103,272,498,675,341,811,369,875,758,418,702,246,344\n429,805,100,604,420,436,465,304,342,818,126,517,65,552,899,858,67,270,634,483\n186,98,22,429,795,453,774,58,924,431,753,266,827,65,627,667,797,140,805,116\n645,692,67,515,189,455,820,195,872,54,750,63,442,806,614,71,818,134,697,265\n644,209,487,486,751,68,243,494,744,810,351,431,72,621,61,584,266,411,470,99\n824,790,625,384,96,629,195,749,440,557,633,83,211,983,354,655,178,195,646,73\n309,342,684,275,288,621,430,347,135,84,549,203,631,428,755,472,588,386,786,472\n805,455,309,139,845,992,702,353,621,307,123,68,694,404,516,755,699,122,620,192\n814,880,192,466,68,645,119,509,337,671,238,813,134,894,896,298,469,263,254,858\n197,634,618,115,559,180,632,831,772,497,234,342,92,517,130,562,935,499,347,899\n253,104,423,752,278,341,339,108,459,193,829,671,670,603,752,374,751,497,430,793\n273,80,79,101,69,442,381,472,117,118,747,76,633,108,446,634,554,291,306,400\n86,245,132,135,101,420,262,664,442,765,551,703,820,293,703,890,460,899,434,264\n789,748,257,799,680,696,350,604,92,362,679,260,336,842,468,924,490,262,191,131\n208,941,258,823,87,11,746,419,364,492,440,66,405,245,211,182,376,257,287,829\n842,807,739,773,633,411,471,595,659,50,464,276,867,266,122,767,290,866,494,406\n519,696,438,924,430,287,444,265,245,608,415,120,77,642,878,99,60,309,104,125\n81,62,295,220,284,286,590,414,651,16,240,873,279,629,270,78,698,560,754,796\n501,378,589,256,724,206,698,873,383,404,443,628,633,245,652,838,829,628,651,192\n101,943,695,519,359,865,132,246,206,767,871,922,85,288,645,533,629,462,133,601\n755,632,54,459,801,69,24,63,367,81,770,680,235,688,414,210,747,409,761,632\n18,434,493,136,114,368,452,503,379,687,671,80,640,422,256,641,299,560,666,135\n129,347,747,259,435,436,64,100,403,416,453,415,92,468,194,120,486,111,218,628\n374,381,708,99,404,372,502,99,648,945,624,919,461,792,81,469,116,744,60,690\n208,131,218,115,658,695,756,184,599,159,820,138,472,667,779,137,276,680,196,506\n594,761,703,487,67,218,84,67,790,470,130,750,383,687,380,900,199,610,242,594\n364,501,597,753,130,619,220,69,520,404,945,415,556,439,552,716,811,756,62,459\n595,179,510,773,606,647,518,55,998,256,830,617,413,433,688,127,139,805,186,845\n243,472,648,340,911,201,415,460,432,516,793,416,884,799,800,83,949,62,758,50\n118,89,942,439,340,278,137,908,135,699,453,383,287,194,403,501,829,242,54,879\n462,461,655,114,504,463,256,362,340,414,463,416,769,808,864,127,565,373,662,615\n266,706,116,219,246,69,620,75,600,50,553,831,440,342,919,99,271,76,680,215\n899,344,676,979,372,270,274,201,84,161,409,593,250,194,514,206,380,309,352,399\n"
  },
  {
    "path": "advent-of-code/2020/inputs/17",
    "content": "#####..#\n#..###.#\n###.....\n.#.#.#..\n##.#..#.\n######..\n.##..###\n###.####\n"
  },
  {
    "path": "advent-of-code/2020/inputs/18",
    "content": "2 * 9 + 5 + ((8 + 6 + 5) * (2 + 3 * 9 + 3) + 5) * (7 + 9 + 7 + 3 * 7) * 5\n7 + (2 + 8 * 8 * 2 + (4 * 3 * 9 + 4 * 4)) + 4 * 3\n6 + 9 * 2 * 2 + (2 + (7 * 6 * 6) + 4 * (7 * 8 * 2 + 4) * 7) + 7\n2 + ((3 * 6 * 5 * 4 + 7 * 7) + 5 * 4 * 5 * (8 * 7 + 9) + 8) * (4 + 6 * 5)\n(7 * 6 * 3 + 4 * 3 * 9) + (6 * 6 * (4 + 6 + 4) + 7 + 2 + (9 * 8 * 9 + 9 * 7 * 4)) + (3 * 4 + 3 + 2) * 8\n(3 + (7 * 7 + 9 * 9 * 6)) * 3 * 5 + 4 * 8\n8 + 9 * (2 + 2 * 5 + 9 * 2) * 2 + ((6 + 4) * 4 + (4 * 7 + 3 * 3 + 7) * (4 * 5 + 8 + 8 + 7 * 6) + (6 + 2) + 5)\n(2 + 2 * 9 * 7) * ((9 + 8) * 3 * 6 + 6 + (5 * 4 * 4 * 3)) + 9 + (3 + 2)\n2 + 7 * 3 + ((7 + 7 * 3) * 6 + 8)\n2 + 7 + 6 + (4 + 7 * 7) + 9 * 2\n(9 * 2 * 4 * 4) + 4\n8 + (8 + 8 + 7) * (5 * 4 + 4 + 5 * 5) * 9 + 8\n(6 * (4 * 2 + 4 + 7 + 4) + 4 * 7 + (7 + 5 + 3 + 3 * 7) * 6) * 6 + 3 + 6 + 5\n5 + ((7 * 3 * 2) + 9 * (9 + 2) * 6)\n(3 * (2 * 2 * 3 * 7 * 2) * 8) * 8\n((3 + 2) + 5 + 7 + 3 * (8 + 4 + 5 * 8 * 9)) + 7 * 3 * 6\n7 * 6 + 8 * 4 + ((7 + 5 + 2 + 4 * 9 + 9) * 7 + 5)\n6 * (6 * (4 + 8 + 6) * 6)\n4 + 3 + (6 * (2 * 8))\n(2 * 8 * (3 + 8 + 3 + 2) * (8 * 4 + 2 + 8) * 9 + 7) * 8\n4 * (3 + 9) + 9 + 4 + 8 + 4\n((6 + 3 + 5 + 6 + 6) * 9 * (2 + 7 * 4 * 9 + 3 * 7) + 6) * (3 * 9 + 2 + 7 * 3) * 6\n8 * (5 + 4 * 3) + 3 * 7 + 6 * 4\n4 + 6 + 6 + (4 + 9 + 3 + 3 + 3) + (2 + 6 * 2 + 3 + 4) * (2 * 4 + 9 + 3)\n7 + (3 + 2 * 4 + 4 * 9 + 2) * 2 * ((8 * 6 + 6 * 2 + 7 + 7) + (2 + 8 * 7 + 6 * 9) + 7 * 6) * 7 + 8\n3 * (8 * 7 * (5 + 2 + 8 * 9))\n6 * 9 + 2 + 8 + (4 * 3 * 4 + 6)\n(2 * 6) + 7 * 9 + (3 * 9 + 8 * 4 * 3 * 5) * (9 * 7)\n5 * 2 + (3 + 5 * (5 + 7 + 7 + 4) * 2)\n9 + 4 * (8 + 3 * 2 + 9 * 6 * 4) * 9 * 6\n6 + (6 * (2 * 5 * 4 * 7 * 3) * 9 + 4 + 6 * 3) + 4 * 8\n(6 + (4 * 7) + 6 * 5) + 4 + 7 + 2\n3 + 4 * 9 + 9 * 8 + (3 * 4 + (9 * 6 * 9 * 2) * 5 + 8)\n8 + (3 + (9 * 3) + (6 * 4) + 8 * 6 + 8) + 5\n(7 + 6 * 3) * 2 + 5\n6 + 6 + ((6 + 7) * 9 + 5) * 2\n(3 * 3 * 2 * 5) + 9 * 9 + 3\n(8 * (6 + 2) + 4) * 9\n(4 * 6 * 6 * 3) * 9 * 4 + 4 * 4 * 9\n5 * 5 + ((8 * 9 * 2 + 5) + (3 + 7 * 5 + 2) + 2 + 8 + 5)\n9 + 8 * (6 + 2 * 2) + 7 + 4 * 9\n7 * 8 + (9 + (9 + 4 + 6 * 6 * 9 * 6)) * 8 * 5\n9 * 7 + 8 + 7 * (4 * 2 + (6 + 3 * 4 + 6 * 6 + 6) * 2) + 9\n8 + 2 + (4 * 3) + (2 + 8) * 5 * 7\n2 * 7 * 7 * 8 + (3 * 4 * (7 * 4) + 5 * 8)\n2 * ((6 + 7 + 6 + 2) * 4 + (9 + 4 * 5) + 8 + 6 * 7)\n(6 + 4 * 4 + 9 * (4 + 9 * 5 + 9 + 9 * 9) + 7) * 2\n8 + 9 * (4 + (6 + 4 * 3 * 6 * 6) + 7 + (6 * 2 * 8) + (9 + 5 * 3 + 3 * 3) * 9) * 9 * 4\n(8 + 8 * 9 + 9 + (7 + 8 * 3)) * (6 + 4 * 7)\n2 + (6 * 3 * 5 * 5) + 4 + 9 + (4 + 9 + 9) + 4\n8 + 3 + 8 + (4 + 6 * 6 * 2 * 5) + 5 * 5\n2 * 4 + (7 + 6 + 9 + 5 + 9 + 2)\n(5 * 5 + (5 + 7 + 4 + 3 + 7) * 4) + ((6 * 4) + 2 * (8 + 8 + 4 * 4) * (7 * 7 * 2 + 3) + (8 + 6 + 8 * 2 * 8 + 8)) * 7\n3 * 4 * (7 + 6 * 4 + 6 * 3) * 4 + 4 + ((8 * 6 + 2 + 5 + 7 + 6) + 6)\n9 + (9 * 7 + 2 * 9) + 8 + 6\n4 + 6 + 7 + 6 * 3\n5 * ((4 + 4) + 4 + 7 * 9) * 6\n9 * 6 + 6 + (4 + (5 + 9 + 2 + 9 * 5 + 8) * 4 * 8 * (3 * 4 + 7 * 6 * 3) + 7) * (4 + 4 * (6 + 7 * 6 * 7 * 9)) * 5\n6 + (2 + 4 + 6 + 6 + (8 * 7 * 2 + 6)) + 5 + 9 + 2 + (8 * 7 * (9 + 8 * 6 * 6 * 7 * 3))\n6 + 9 + 7 + 8 + (8 * 6 * (5 + 5 * 7 + 3) * 8 * (4 + 8 * 2 + 9))\n(9 + 3 + 8 + 4 + 8 + 4) * 6 * 3 * 6\n5 * ((5 + 7 + 2 * 3 + 4 + 3) + 3) + 6 + 4\n2 * (8 * 4 + (9 * 3) * (7 + 2 + 3 * 4) * 7) * (6 + 9 + 7) + 5 + 4 + 7\n9 * (9 * (8 * 9 + 5 * 3 * 2) + (9 + 7 + 8 * 8) * (9 * 7 + 6)) * 3 * 3 + 8 * 6\n5 * ((2 + 5) * (8 + 2 * 6 + 6 + 3) + 9 + 3 + 9) * (7 * 4) + (3 * 7 + 8 + 5 + 2 + (7 * 7 + 6)) + 4 * 7\n(2 + 8 + 6 + 6 + 8 + 3) + 5 + (5 + 7 * 8 * 5 + 5 * (2 * 4 * 2 + 2 + 6))\n5 + 6 + (9 * 7 * (6 * 8 * 4 + 7 * 2 * 4) + 3 * 5) + 4 + (2 * 4 * 6 * (9 + 6 + 7))\n5 + 6 * (7 + 5 * (4 * 3 * 9))\n6 * 8 + 4 + (2 + 8 * 6 * 2 + (5 + 9) * 3) + 6\n(7 + 5) * 7 + 5 * (6 + 4 * 9 + 6 * 2)\n9 * (9 + (5 + 9 * 7 + 7 * 2 + 2) * 9 + 8 + 5 * 6) + (5 + 5 * (2 + 4 + 7 + 9 + 6) + 2) * 9 * (3 + 5 + (8 + 2 * 2 + 7 * 7 * 6))\n7 * (7 + 3 * 8 * 9 * 9 + (5 * 2)) + 5\n9 * 9 * (8 + 3 + (2 + 9 + 6 + 6)) * 4 + 2 + (2 + 9 + 6)\n((9 * 4 * 9 * 3 + 2 * 5) + (7 + 2 * 4 * 3 * 6 * 8) * 7) * 3 * 9\n(3 + (8 + 6 * 6 * 5) + (3 * 5 + 8 * 5) + 7 * (2 + 3 * 7)) + (8 * (6 * 8 * 5 + 8 * 2)) + 8\n4 * 4 + 5 * 8 * (2 * 2 + 8) * 8\n7 * 8 + (5 * 4) * 7 + 2 + 9\n((4 * 9) * 4 * 8 * (4 * 6 * 5 * 2) * 5 + 9) + 7 * 2 + 8\n((4 * 3 * 9 + 7 * 7) * (7 + 3 + 7) + 9 + 6 + 8 + (3 + 2 * 6 * 2 * 9)) * 2 + (7 + (9 * 9) + 6) * 3 + 6\n8 + (9 * 8 + (2 + 3 * 3) + 4 + 4 + 4) + 4 * (5 * 4 + 4 * 6) * 7 + 8\n9 + 8 * ((2 * 5 + 7 * 2) + 3 * 4 * 3 * 8 * (2 * 6 + 6 + 3 * 5 + 6)) + (8 + 9 * 8 * 2 * 3 * 9)\n8 + (9 * (8 * 5))\n(5 * 4 * 9 * 3) + 7 + (3 + 7)\n3 * (2 * 8 + 2 * (8 * 3 * 8 + 8)) * 7 + (6 + 7)\n3 + 4\n2 * 8 + ((8 + 9 + 6 * 7 * 4 + 5) + 2 + (5 * 2 + 8)) * 4 + 2\n2 + 5 * 7 * 4 * (3 + 9 * (4 + 5 * 7) + 4) + 5\n5 + 7 * (6 * 9 + 9 + 5 * 3) + 8\n4 + (8 + 6 + 5 + 5 * (2 + 6) * 5)\n5 * 4 + 3 + ((4 * 5 * 7 * 6) + (7 * 7 + 6 + 8 * 9 + 4) + 5 + 2 * 7 * 5)\n9 * (8 + (4 + 9 * 8 + 7 * 3) + 3 * 9) + (7 * 7 + 5 * (5 + 7 + 3 * 9))\n4 * 6 + (2 + 6)\n6 + 2 * 2 + 4\n4 + 9 * 7 * (2 + 5 * 4) * 9\n(2 + 4 * (2 * 9 * 4 * 8 + 5 + 4)) + 4 + (8 * 7) + 7 + (3 + 5 * 7)\n9 * 8 * 8 * (6 + 6 * 2 + 5 * 7 + 3) + 6 + 8\n(3 + 9 + (7 * 2 + 2 + 3 + 2)) + (4 * 6)\n((6 + 3) + 3 * 8 + 7 * 7 + 8) + (9 + (8 * 6 + 7) + 2 + 5 * 4) + 5 + 3\n8 * ((5 + 2 * 9 + 2 + 7) * 7 * 7 + 7) * 4 + 8 + (4 * (3 * 9 + 3) + (2 * 9 * 4 * 9 * 7 + 6) + 6) * (8 + (2 + 5 * 3 + 8) + 4 + 8)\n5 + 4 + 7 * (4 + (5 * 5 + 3 * 3 + 8 + 7) + 3 + 8 * 6)\n((9 + 5 * 5 * 6 + 4) + (2 + 2) * 2) * (9 * 9 + 7 * 7 * 6) + 9 + 6 + 2 + (9 * (5 * 9) + 3 * 5 * (5 * 2 * 4 * 7))\n2 * (9 * (5 + 9 * 2 * 9) * 9 + 6) * (2 * 6) * 5 + (3 + 9 + 4 + 6 + (4 * 5 * 7 + 6) + (6 + 7)) * 7\n3 * 8 * 8 * 9 * 2 + 3\n6 * 8 * 6 + (2 + 7) + 5\n(6 * (3 * 4 + 6 + 9) * (2 + 8 + 3 * 8 + 3 * 2)) * 7 * 9 * 7\n8 + (4 + 9 + 2 + 9 * 2 + 9)\n5 + 7 + 6 + ((2 * 2 + 7 + 3 + 9) + 2 + 8) * 7\n(3 * 2) * 2 * 7 * 5\n9 + ((4 * 3 + 3 * 6 * 2 * 9) * 5 * 7 * 3) * 4 * 7 * 2\n(2 * 2 + 9 + 7) + (6 + 4 * 9 * 5) + 6 * 8 * 3 + 8\n8 * 8 + (7 * 9 + 6 * 7 * (2 * 2) * (4 + 2 + 8 * 2 * 3)) + 4\n(3 * (7 * 9 * 6) + 2 + (2 * 6)) * (4 * 3 * 7)\n2 + (2 * (6 + 9 + 9 * 6)) * (7 + 7 * 3 + 8) + 7 + 3\n9 + (5 * 2 + (8 * 4) * 7 * 5) + 9 + 4\n2 + 4 * 4 + 8 * 3 + 5\n8 * 2 * (8 * (7 * 3 * 5 + 7) * 5 + 6 * 4 + 9) * 8 * 2 * 8\n((7 + 4) + 7 * 3 + 6 * (3 + 6 + 8) * (5 + 4)) * 2 * (7 + (2 + 3 * 5) * 5 + 3 + 6) * ((6 + 3 + 4 + 2 + 3) + 4 * (3 * 7 + 2))\n(2 + (3 * 8 * 2)) + 2 * ((3 + 6 + 3 + 7) * 5 * (9 * 2 + 6 + 7 + 3))\n(6 + (7 * 2 + 4 * 9 + 5 * 2) + 4 + 8 * (4 * 8 * 5 + 7) + 9) * 7 + 2 * 9\n2 + (6 + 4 * 2 + (7 * 2)) * (8 * 6 + 6 * 4 + 5 * (5 * 4 + 9))\n(6 * 3 + (5 * 8 * 4 + 7)) + 7 * 7 + 9 + 9 + 7\n(2 * 9 * 7 * 5 * 7 + 5) * 8 + (8 * (9 + 9 * 8) * 7) * 4 + 5\n6 + (3 + 8 + 4 + 9 * 7)\n4 * 8 + 2\n((8 * 8 + 4 + 9) + 9 * 7 + 8) * 8 * (5 + 7 * 5) * 2 + ((3 * 2 + 6 + 6 * 3) * 8 + 9 * 9 * (9 * 6)) + (4 * 8 * (5 + 8 * 5 * 8) * 6 * 9 + 8)\n(3 * 6 * 7) * (4 + 8) + 9\n6 * ((9 * 3 * 4 + 9 * 2) + 7 + 2 * 6)\n6 + (7 + 8 + 2 * 5 * 2) * 7 + (5 + 3) * 7\n7 + ((6 * 8 * 6 * 3) * 9 * 3) + 9 + ((3 + 4 * 2 * 6) * 4 * 3) + 5 + 3\n(4 + 3 * (5 * 2 * 2)) + 5\n4 * 3 * (6 * (4 + 3 + 9 * 3)) + (4 * 2 * 5 + (9 * 2) * (6 + 8 + 9 + 6 * 8 + 8) + 2) + 6 + 8\n7 * 5 * 9 + 7 + (5 * (9 + 8 + 3 * 6 * 3)) * ((3 + 5) * (7 + 9 + 3 + 6 * 2) * 3 + 9)\n((3 + 3 * 9 + 4 * 8 * 2) + 6) + 2 * (5 * (2 * 5 * 7 + 8 + 6) * 2 + 8 + 3 + 6) + (4 + 6 + 4)\n(2 * 8 + 8 + 4 + 3 + 5) + 7\n6 + (6 * 5 * 9 * 6)\n8 + 2 + 6 + 3 + (9 + 6 + (7 * 3) + 5 + 4 + 8)\n6 + 7 * (3 * 7 * 5 + (9 + 6 + 6) * 7) * (3 + 4 + 7 * 4 + 6) * 4 * 4\n9 * 9 * (4 * 4 * (3 * 2 * 2 + 4 + 7 * 3) * 7 * 5 + (7 * 4)) + 5\n9 * ((6 + 3 * 6 + 2) + 4 * (9 * 8 + 8)) + 5 * 6 * 4 + 4\n(8 * 9 + (8 + 5 + 8 + 5 + 3)) + 3 + 6 * 4 * 2 * 4\n8 + (3 * 6 * 7) * 4 * 4 * 3\n(6 * 8 + (2 * 2 + 3 * 8) + 6 * (4 * 9)) * 6 * (2 * 8 + 7 * (8 + 9 + 6 * 9 + 3 + 3))\n3 + 8 * 2 + (8 * 3)\n4 + 3 * 2 * (5 + 3 + 5 + (6 * 5 * 3 * 6 * 6)) + 9 + 7\n(3 + 5 + (3 + 9 + 9 + 7) * 7 * 6) + 7 * 5 * (5 + 3)\n2 + ((7 + 2 + 9 + 2 + 6) * 3 * 2 * 5 * 5 + 2) + 2\n6 * 8 * (2 + 4 * 9 * 5) + 9 + 3\n4 * (6 + 9)\n5 * 2 + 3 * 2 * (5 * 3 * 9 * 7 + (6 + 4 * 5 + 6) * (6 * 2 * 2)) * (9 + 6 + 9 + (8 + 9 + 9))\n5 + (4 * 4 * 5 * (4 * 2 * 4 * 2) * 7) * 2\n3 * 2 + ((4 * 6 * 8) + 9 * (3 * 9 * 8 * 2))\n(3 * 5 + 6 * 8) + 5 + ((2 + 9) + (3 + 4 * 2 * 5 * 3) + 4 + (3 * 7)) * 6\n6 + 3 + 2 + 4 + (6 * 2 + 6 + 4) * 2\n(5 + (5 + 6 + 7 * 2) + 7 + 4 * 5) + 5 * 6 * 9\n4 * 7 * (3 * 2) + 4\n(5 + 4 + (8 + 3 + 7 * 2)) * (6 + (5 + 7 + 3 * 8 + 4) * 5 + 6 * 6 * 5) + 7\n2 * 5 + (5 + 4 + 3) + (9 * 3 + (7 * 6 * 9 * 4 * 3 * 2)) * 3 + 2\n(8 * 2 + 3) + 5 * 2 * 9 + 9 + (3 + 4)\n9 + 6 * ((4 * 7 * 9 * 5 * 4 * 5) + 8 * 8 * 7) * 7\n5 * 4 + ((3 + 2 * 5 * 6 + 7) + 7) + 2\n3 * 9 + 4 * 9\n9 + 7 + (7 + 5 + 3 * (5 + 7 * 8 * 7 + 5 + 7)) + (7 * 6 + 5 * 8) + (8 + (2 + 3 * 3 + 4) + (6 * 9 * 9) * 8) * 6\n8 * (2 * 7 * 3 * 4) + 9 * 3 + 7\n6 + (8 + (7 + 5 * 8 * 5) + 5 * 6 + (8 * 6) + 6) * 3\n7 + 3 * 4 * 6 + 9\n8 + 8 + ((8 * 9 + 6 + 3 * 9) + 3 + 4 * 8)\n9 + 4 + 6 + 3 + 2 + (2 * 6 + 8 + 3)\n(5 * 2) + 4 + 7 * 9 + (5 + 5 + 3 * 5)\n5 * 5 * 2 * 5 + (9 + 7 + 5)\n(2 * 5) + 7\n5 + 7 * 9 + 3 * 5\n(8 * 7 + 9 * 5) + 3 * (6 * 5 + (2 * 7 * 2 * 7 + 7 * 2) + 4) + 3\n(6 + 6 + 6 + 9) + 9 + (3 * 5 + 4 + (6 * 3) * 4) * 3 + (8 + 7 * 5 * (3 * 3) + 6) * 3\n((2 * 8 * 3 + 2 * 6 * 5) * 5 + (7 * 3 + 5 + 6 * 9 * 4) * (5 * 6 + 8 + 4 * 7 * 5)) + 6 + (9 * (9 + 7 * 8 * 3) + 7 * (5 * 9 + 6 + 5 + 4 + 8) * 8 + 8) * 5\n2 * (5 + 2 * 2 * 3 + (4 + 3)) * (6 + 6 + 2 * 9 + 9 * 3) * 8 * 8\n9 * (9 + 3 + 8 + 5) * (2 * 5 * (6 + 8) * 9) * (4 + 3 * 8 * 9 * 4 + 4) * (3 * 9 * 8 + (6 * 6 + 9 + 5) + 2 * (8 + 2 * 7))\n2 * 5 * 9 * 8 * ((7 * 2 * 3) + 3)\n2 * (6 * 7 * 2 * 4 + (5 * 4 + 7 + 3 + 7) + 5) * (7 + (6 + 3) * (8 + 8) * 3 * (5 + 2)) * 3 * 8 * 7\n2 * 5 * (4 * 9 + 2 + 5 * 2) + 6 * 5 + (6 * 6 * 4 * 8 * 4)\n4 + 8 * 4 + 4 * 3 + (7 + 2 * 2 * 5 * 2 + 8)\n(8 * (4 + 5 + 9 * 9 + 8) * 4 + (8 + 7 + 9 * 4 * 4 + 3)) * 7 * 8 * 3\n8 * 9 + ((2 + 5 + 8 * 9 + 5) + 2) * 7 * 4 + 5\n3 + (5 * 8 * 6 * (7 + 4 * 2 + 2 * 4 * 2) + (9 + 6) * 9) + 4\n9 * 7 + 4 + (7 + 9 + (9 * 9 + 8 * 4 * 5 * 8) + 5) + 3\n2 * 2 + 6 + (3 * 9 + 6 + (4 * 4 * 6 + 2 * 5)) * 5\n6 * 3 * (3 + 8 * 7) + 9\n7 * 2 * 6 * (3 * 3 * 8 * (2 + 7 * 9 + 8))\n9 * 7 + 6 * (7 * (3 + 6 + 7) + 3) + (9 * 6 + (2 + 9 * 3) + (7 * 8 * 8 + 6 * 3 * 5) * 9)\n3 * 4 * 4 * 6 + 2 + (6 * 3)\n4 * (5 + 7) + 8\n5 * 3 * 9 + 9 + 9 * 2\n8 + (8 * 9) * 7 + 6 * 9\n9 + 9 * (3 * 8) * 3 + 2\n6 + (8 + 6 + 2) * (9 * 9 * 8)\n5 + 4 * 3 + (2 * 2 * (2 + 3 + 4 + 7 * 3) + 5 + 3) + 6\n9 * 2 + 3 * 8 * 9\n5 * 2 * 7 * ((5 + 6 * 4 + 6 + 3 + 5) * 7 + 9 + 4) * (7 + 3 * 7)\n2 + ((5 + 3 * 4 + 2) * 2 * 6 + (8 * 8 + 8) * 3 * (3 * 8 * 5 * 6 + 5))\n5 + (6 + 9 + 4 + (3 * 7)) * (4 + 6 * 5 * (7 + 8 * 3 + 3 * 9) + (9 + 8 + 3))\n4 * 2 + 9 + (9 * 6 * 9 * (9 * 4 + 3 * 2 * 6 + 8) + 7 + 9) * (5 + 7 * 9 * 5) + (8 + 9 + 4 * 5 * 8)\n7 + 8 * 3 + (5 + 2 * 2 + 6 * 8) + 7\n8 + ((9 * 7 + 5 * 8 + 3 + 6) * 4) + 6 * 4 + 4 + 3\n(6 + 2 + 4 + 7) * (2 + 6 * 7 * (4 * 3 + 9 + 5 * 5) + 5 + (2 + 3 * 5 * 5 * 6)) * 2\n(6 + 9) + 4 * 9\n4 * (4 * 5 + 9 * (9 + 5 * 7 * 6 * 7 + 9))\n2 * 5 + ((7 + 3 * 3 * 9 + 8 + 4) * 4 * 6) + 3 + 6 + (4 + (2 * 7) + 5)\n(7 + (4 * 5 + 2 + 2 * 2 + 8)) * 5 + 5 + (3 + 8 + 6 * 6) * 9\n5 + 4 + 4 + 7 * (2 + 6 + (3 + 6 + 7) + 6 * 9) * (2 + 8)\n8 + ((4 * 3 * 2) + 4) + 5 * 7 * 3 * 5\n4 * 4 + 9 + (8 + (6 * 5 * 2 + 8 * 3 + 8) + 4 * (2 + 6 * 2 + 4 + 3 + 2) * (4 + 5))\n(9 + 8 * 8 + (5 * 8 * 7 * 8 + 9 * 6)) * 9 + 5 * 2\n7 + 8 * (2 + (5 + 7 + 3 + 9 * 8 + 8) * (2 * 9 * 7) + 3 + 4) * 8 + 5 + 2\n5 + 2 * (5 * 7 * 6 * 4 * 2 + (7 + 2 + 7 + 9 + 4))\n6 * 8 * 7 * 8 * 9 + 9\n5 + 8 + 7 * 5 * (8 * 8 * 5 + 7 + 9) + 6\n9 + 2 * 3 * 5\n8 * 5 + (2 + (4 + 9 + 5 * 6 + 8) + 9 * (4 + 4 * 5 * 3) * (5 * 7 * 8 + 3 * 3 + 3) + 5)\n7 + 3 + (2 * 2 + 5 * 8 + 3) + (8 + 3 + (6 * 5 + 4 * 5))\n6 * ((2 * 6 + 6 * 2 + 5 + 4) * 8 + 8 * 9) * (5 * 2 + 4 + 6 * 3) + ((6 + 8 + 8 + 6 + 7 * 6) + 8 * 9 * 2 * 2 * (8 + 3 + 7 * 5 * 3)) * ((5 + 9) * 4) + 4\n(3 * 8 * 5) + 8 + (3 + 7 + 2 * 3 * 8) * 5\n7 + 3 * 9 + (2 * (2 + 9 + 9 + 8 + 9) * (8 * 6)) * 4 * 9\n7 + 9 + (3 + 7 + 2 + 6)\n4 * (6 + (3 + 6 + 3) * (9 * 7 * 4 + 3 + 4) + 8 * 7 + 4)\n((9 + 6) * 3 + 2 * 5) + (6 * 5 + 4 + 3)\n3 + (4 * (2 + 4 + 4 + 2)) * 4 * 7 + 5 + 5\n(5 * 9 * 2 * (7 * 9 * 8) + 2) + 6 + 2 + 8 + 9\n5 + 4 * 4 + (2 * 3 + 8 + 8) * 6 * (9 * 8 + (8 * 9 * 5) + 9)\n3 * 5 * (8 + 3 + 7) + 4 + 6\n6 + 7 * (9 + (2 + 7 + 2 * 2)) * 3\n(9 * (4 * 3)) + 9 * 4 + (9 * 5 + 5 * (6 * 2 + 8 * 8) + 2) + 9 + 8\n6 * 7 + 7\n7 + (9 * 6 * 8 + 9 * 2) * 4 * (9 * 4 * 6 + (8 * 5 * 8)) * 7\n8 + 5 + ((8 + 2 * 6) + (9 * 3 * 8)) + 7\n4 * 8 * (6 + (4 + 5) + 5 * 3)\n(3 * 2 + 6) + 3 + 3 + 8 * 6 * 7\n9 * 3 * 3 + (4 * (6 + 3) * 4) + 2 * 9\n5 + 9 + 7 + 4 * (9 * 3)\n((8 * 9) + (7 + 5 + 6) + 3 * (5 + 7 + 6)) + 5 + (3 * 8 * 3) * 2\n9 + 6 * 5 * ((4 * 4) + 7 * 3) + (3 * 6)\n7 + (8 + 7) + 4 * (3 + 3) * 7 * 9\n((6 + 7 + 4 + 7) * 7 + 9 + (9 * 7 + 5 + 7 + 7) + 9 + (7 + 3 + 2 * 6 + 9)) + 2 + (4 * 7 + 9 * 3 * 2 * (5 + 9 + 3)) * 5\n9 * (3 + (9 * 9)) + 9 * 8 + 4 * 2\n(8 * 8 + 6 + 9 + 8 + 2) + 6 * 5 + 5 * 4\n3 + 3 + 4 * (6 * 6) + 2 * 8\n(5 * 9) * (8 * (2 + 6 * 9) * 7 + 7)\n8 * 5 + (8 + 8 + 8 * 4) + 3 * 8 * (8 + 6 * 3 + 4)\n4 * 9 + (5 * (8 * 3) + 4) * 5 + (3 * 3)\n(2 + 2 * 4 * 3) + 8 * ((2 * 6 + 5 + 6 * 2) * 3) + 2\n((5 * 4 + 2 + 7 * 6) + (7 * 5 + 4) + 9 + 7 + 7) + 3\n2 + 3 + 9 * 9 + (9 * (2 + 8 + 7) * 3)\n3 * 7\n(4 + 2 * 5) + 2\n5 * 5 * (5 + (8 + 8 + 8) + 3 * 2 * 4) * 9 * 2 + 8\n4 + 5 * 3 * 5 + (4 + (3 + 8 + 4) + 7) + 7\n(4 + 7 + 6 + 2 * 7) + 7\n4 * 2 * 4\n(4 * 4 + (6 * 6 * 7 * 2) * 4 * 6 * 7) * ((9 + 5 + 9) + 8) * (5 + 8 + 2 + (9 + 8 * 2 + 9 * 8) * 8 + 3) * 6\n5 + 8 * 9 + ((7 * 9 * 3 * 7) * 2 + (2 + 2 + 3 * 6 + 6) + 5 + 4)\n3 * 8 + 2 + (7 + 8 + (8 + 7 + 7 * 6 + 2) + (3 + 2) + 5)\n4 + 4 * 6 * 5\n4 * 9 * ((9 + 2) + 4 + 2 * 5) * ((6 * 9 * 5 + 8) * (7 + 7)) * (8 * 7 + 9 + 7 * (2 + 9 + 9 + 4 + 8) + 9) * 6\n(8 * (2 + 3 + 7 * 3 + 2) * 2 * 4 + 7) + 4 + 3 * 2\n(6 + (2 * 5 + 3 * 2 * 4 * 7)) * 6 + 4 + 6 + 9 + 9\n(8 + 8 * 6 * (4 + 3 + 4 + 8 * 2 * 4) + 7) + 2\n8 + 9\n8 + 8 * 4 + 4 * ((9 * 2) + 2)\n(3 + 3 + 9 * 9 + 5 * 2) + 5 + 7\n2 + (7 * 5 * 2)\n8 + (5 + 3 + 8 * (3 + 2) * 6) + 9 * 9 * 8 * 9\n8 + (2 * 5 + (9 * 7 * 4 * 2) * (7 * 4) * 4 * 6) * 9 + 3\n4 * 7 + 4 * 4 * (2 + (2 * 8 + 2 * 5 + 2) * 7)\n8 * 5 + 8 + (6 * 9 * 8 * 2 + 5 + (4 * 5 + 4 + 3 + 3)) + 4\n9 + 9 * 2 * 9 + (5 + 2 + 6 + 3 * (5 * 2 + 8 * 9 + 6 + 7))\n4 * 9 + 2\n4 + 4 * (3 + (4 + 9 * 8 * 7 * 3 * 3) * 2 + 9) + (2 * 7) + 8\n((5 + 8 + 5 * 2 * 5 * 3) * 5 * 6 + 2) + (5 * 9 * 6 + 2 * (4 + 8 + 9 * 9 * 8 * 3) * 2) + (8 * 6 + 2)\n3 + 7 + (9 * (2 * 6 + 3) + 4) * (3 + 4 * 8)\n((2 * 2 + 5 * 6 + 7 * 2) * 5 + 9 + 6) * 5\n(8 * 6 * (3 + 8) + 9 + 7 * 5) * 3 * 2 * 3 * 5 * 5\n((2 + 9 * 4 + 8) * (5 + 5 + 6) * 6 + 9 * 8 + (6 + 9)) * (9 + 8) * 6 * 6 + 9 + 7\n(6 * 5 * 6 * 5 * 3) * 6 * 9 * 9\n(5 * 4 * (5 * 3 * 3) * (5 + 6 + 2 + 2 * 9 * 3)) + (3 + 6 * 3 * 3 + 3 * (8 * 5 + 3)) * (9 + 3 * 9) + (7 + 4 + 3 * 8 * 8)\n(4 + (9 + 2 * 3 + 9 + 6) + 2) + 2 * 7 * 5\n9 + 8 + (3 + (7 * 7 + 2 * 8 + 6 * 2) * 8 * 6 * (9 + 7 + 4))\n(7 + 3) * 7 * (4 + 4 * (2 + 3 + 4 + 6) + 7) + 6 + 2\n(8 * (5 * 9 * 6) * 3 * (7 * 5)) + 5 + 3\n(2 * 6 + (7 + 5) * 7 + 3) * 5 + 3 * 2\n((9 + 4) * 6 * 2 * 3 + 6) * ((2 + 6 + 4 * 7 + 4 * 7) * (7 + 9 + 2) * 2) + 7 * 2\n3 * (9 + 9 + 5 + (9 + 7 * 7 + 8 + 2 + 6) + (9 * 8 + 8 * 8 * 7) * 3) + (7 + 9 * 4 + (6 + 4) + 2) + 9\n9 + (2 * 5 + 9) + 9 + 7\n3 * 9 + ((2 + 4 * 4) * 3 + 5 * 3 * 5 + (4 + 8 * 3 * 4)) + 6 * 5\n3 + (7 * 2 + (4 + 6 * 6)) * 2 + (4 * 5 + 2 + 6 + (7 * 6 + 6 + 7)) * 6 + 9\n6 + 5 * (3 + 5 + 2 + (9 + 6 * 3) + 3 + 7) * 3\n4 * ((4 + 4 * 8 + 7 + 2 + 4) * (4 + 4 + 8 * 4 + 4 + 3) + 9 * (6 * 4 * 9 * 9) * 2 * (6 + 6 * 9 * 3 + 4)) + 7\n9 + 8\n7 + (9 + (5 * 6 * 5 * 3 * 3))\n7 * 9 + 4 + 6 + ((9 * 2 + 9) * 7 * 9) + 6\n((8 + 7 * 8 * 6 * 9 + 2) + 4 + 6 * 9 * (5 * 6 * 9 * 8) * 7) * 5 + 5\n2 + 2 * (4 + 3 + 6 + 4 + 5) * (7 * 5 * 5 * 6 + 4 + (6 * 8 * 4 + 7))\n(3 + (9 + 2 * 3)) + 2 * 7\n(5 + 8 * 5 * (9 * 6 + 4 * 6 + 5)) + 5 * ((3 * 9 + 7) + 9 + (2 * 6 * 4 * 3 + 4 * 4) + 7 + (5 * 4 * 9 + 9 * 7) * 5)\n((7 + 2 * 5 * 3) + 4) * 8\n6 * (3 + 7 * (2 + 6) + 6 + (9 * 8 * 7) * (5 * 4 + 7 + 8 * 8)) + 6 * 6\n(6 + 9 * (2 + 2 * 2 * 3 * 7 + 8) * 3 * 5 * 4) + 2\n5 + 2 + (9 + 4 * 7 + 3 + 8) * (4 + 8 * (3 + 2 * 7 * 4)) + 8 + (4 + 5)\n(8 * 9 + 9 + 4 * 5) + 2 * 2 * 9 + (3 + 9) + 5\n4 * 7 + ((5 + 7) * 3) * 9 * 9\n6 + 6 * 4 * ((8 + 9 * 7 * 3 + 9 * 8) + 4) * 3 * 4\n4 * (6 * (9 * 9 + 4 * 2 * 3) * 2) + 8 * 5 * 3\n7 + 4 * (8 * 2 * 2 * 3 * 8 * 8) * 7 + 2 + 5\n8 * ((2 * 3 * 5 * 9 * 2 + 6) * 4 * (7 + 3 * 4 + 7 * 5 + 5) * 3) * 7 + ((9 + 8 + 5) * 8 * (5 * 8 * 9 + 3 + 9) * 5)\n5 * (7 + 2 + 9) + 9 * (5 + 8) + 3 * 6\n6 * ((9 * 5 + 7) * (8 + 9 + 9 * 7 + 3 + 4))\n((7 + 2 * 6 * 5) * 7 + 2) * 8 * 7\n9 + ((7 + 8 * 9 * 4 * 4 + 6) + 8) * (9 + (7 + 2 + 6 * 3))\n(3 + 6 * (6 * 9 * 4)) + 6 + 5 * 9 + (4 * 6 * 8) * ((7 + 2 * 9 * 4 + 4) + 9 + (6 + 2) + 5)\n2 + 4 + 6 + 2 * ((8 * 3 * 2 + 7 * 6 + 3) + 4 + 5 + 5 * 5)\n6 + ((6 * 5 * 3 + 9) + (7 + 7 * 8 + 9 * 7 + 6))\n(9 + 3 * 3 + (6 * 4 * 2 * 9 + 7 + 4) * 2) * 9 * 2\n4 * ((8 + 4) * 2) * (7 + 6 + 3)\n9 * 2 + (9 + (7 * 4) * 9 + 8 + (4 + 4) + 7) + (6 * 6 * 3 * 3) * ((9 * 4) * 5 * (6 + 3 + 8) + 5 * 7) + 2\n5 + ((9 + 3 + 4 + 2) + (5 + 3) + (4 * 2)) * 7\n(8 * 7) + 9 + 6 + 7 * 9 * ((5 + 8 + 5 * 5 + 7 + 2) * 2 + 6)\n(9 * 3 * 6) * 4 + 5 * 4 * 3\n5 * ((7 + 4 * 5 + 8) + 2) * 9 + 3\n2 * 2 + ((2 * 2) * (7 * 5 * 6 + 9)) * 2\n4 + ((5 * 5 + 2 + 2) * 3 * 6 + (4 * 3 * 3 + 4 + 7)) * 3 + 3 + (4 + (6 + 9) + 4 + 6 * (2 * 3) * (5 + 8 * 2 * 8)) + 9\n2 * 9 + 5\n2 + ((6 + 7 + 9) * 9 + 9) + 9 * 5\n2 + 7 * (9 * 7 + (6 + 5 + 2)) + 8 + 5\n3 * (7 * 4 + 8 * 8 * 6 * 8) + 5 + 2\n8 + (5 * 2 * 3 + 5 + 8 * 3) * 3 * (9 * (2 + 8) * (7 + 3 + 5 + 4 * 9) * 6 + 5 + (8 + 9)) + 4 + 3\n4 + 7 * ((8 * 5 * 2) + 3) + 2\n4 + 6\n(5 * (7 * 6 + 3 + 4) + 9 + (8 + 9) + (5 * 6) * 4) * 8\n6 + ((7 + 5 + 7 * 3 + 8 + 3) * 5 * 2 * 4 + 5 + 4)\n5 + 4 + ((6 + 6 + 5 + 7 * 8) * (2 + 4 * 3 * 8 + 3) + (4 + 3) + 2) + 9\n7 * 3 + 6 + 6 * 4 * 6\n(4 * 9 + 2 + 4 + 9) * 6 + 6 * (4 * 9 * (6 * 9 * 3 * 6 * 2 * 7) + 5 + 3 * 3) + 3 * 8\n(5 + (4 * 8) + (5 * 5)) + (2 + 5 * 8)\n9 + 3 * 3 * 8 + (3 + 4 * 2 + (6 * 7 * 2 + 4 + 6 * 9) * 4) * 3\n3 * 6 + 2 + (8 * 6 * 6 + 8 + 8) * ((7 + 3 * 4 * 5) * 4 + 9 * (7 + 4 + 5 * 9 + 8 + 3) * (7 * 8 * 5 + 5 + 7 + 6)) + 4\n6 + 4 + (5 + 7 * 6)\n5 + 3 * 8 + 6 + 3\n6 + 2 + 9 + 8 + (7 + (8 + 2 * 8 + 3 + 8) * 8) * (8 * 8 * (7 + 9 * 2 + 7 * 4) * 4 + (7 + 6 + 7 * 4 + 5))\n3 + 8 + 4 + (8 + 7) * ((7 + 5) + 8 + 4 + (9 * 7 * 8 * 6) + (7 + 6 + 8 * 3)) + 5\n4 + 2 + 6 * (8 + 2 * 2 * 7) * 2 * 8\n2 + 6 * 4 + 6 + (8 + 4 + 6 * 8 + (6 + 4 * 9 * 8 * 3 + 6) * (3 * 5 * 2 + 2 + 7 * 2)) * 3\n6 + 6 * 4 + ((9 * 8 * 5) * 4 * 9 * (2 + 9 * 4 + 8 * 8) * 7)\n3 * 3 + (2 + 9 * 6 + 3) * ((3 + 2 * 2 + 8 * 8 * 3) + 8 * 9) * 4 + 9\n(2 * 7 + 2 * 2) * 8 + 6\n5 + (3 + 9 + 3 + 9 * 4 + 6) + 3 * 7 * 5 * 5\n((9 + 7 * 4 * 5 + 6 * 8) + 5 * 3 * (2 * 7 + 3 + 5 * 4 + 9)) * 5 * 8\n7 + 2 + (5 + (8 + 2 * 2 * 9 + 6) * 4 + 2 * 5) * 3 + 5\n7 + (8 + 6 * (9 + 6 * 3 * 9 * 8 + 7))\n7 + 2 + 7 * (9 + 4 + 3 * 3 + 9)\n7 + ((5 + 7 * 4 * 3) + 4 * (9 * 5 + 2 * 5 * 6 + 2)) * 3 * ((3 + 3 + 4 + 8) * (4 * 5 * 7 * 4 + 9) + 8 + 3) * 7\n(3 * 9 * 8 + 8 + (5 * 3 + 6 * 3 + 2) + (8 + 9 + 3)) * 5 * 4 * 4 * 3\n9 * 6 + (9 * 6 + 3 * (7 * 4 * 2 + 9) + 3)\n(3 + 6 * (6 * 5 * 8 * 9) + (7 + 5 * 5 + 5 + 8 * 8)) * 6 + (9 + 8 + 7 * 5 + (8 + 3 * 4 + 8 * 9) * 7) * 8 + 6\n(9 * 7 + (4 * 8 + 9 + 6) * 3 * 7 * (9 * 7)) + (5 * 9 * (3 * 4 * 7 + 6) * (8 * 9 + 5 + 2 + 9))\n5 * (8 * 3) + 9 * ((8 * 3 * 4) * (6 * 2) * 3 + 6 * 6 * 8) * ((2 * 3 * 6 + 4 * 2 + 5) * 8 * 6 * 2)\n3 + (4 * (6 + 5 * 3 + 9 + 3) * 2 * (8 + 7 * 8 * 7 + 5) * (8 + 8)) + (8 * 5 + 8 + 6 * 9 * 4) + 8 * 4 + 3\n(3 * 6 * 7 * (3 + 7 * 4) * 8 * 8) * 5 + 6 * 6 + (4 * (9 + 5 * 8 * 9 * 6 * 6) * 3) + ((7 * 8 * 6 + 2 + 5 * 6) * 2 + 3 + 5 * (3 * 8) + 6)\n(2 + 4 * 9) + (7 + 2 + 7 * 7 * (3 + 8 * 4 + 2) * (7 + 5)) * 9 * 7\n4 + (8 + 2 + 5 + 2 + 9 + 4) + 7 + 6 * 4\n3 * 8 + (8 + 5) * (7 + 5 + 6)\n5 + (5 + (7 + 5)) * 8 * 6 * ((9 + 3 * 2 * 5 + 2 + 9) * 2 + 5 + 3 * 6) * ((2 + 2 * 9) * 6 * 8 * 7 * (4 * 5) * 6)\n7 + 3 * 6 + ((5 + 2 + 6 + 5 + 5 * 4) * 4 * 9)\n5 * 4 + 8 * 3\n(8 + 6 * 6 + 5) + 9 + (6 + 3) + 7 + 6\n"
  },
  {
    "path": "advent-of-code/2020/inputs/19",
    "content": "2: 12 16 | 41 26\n55: 92 16 | 84 26\n107: 48 26 | 29 16\n91: 16 86 | 26 120\n56: 19 16 | 30 26\n33: 69 16 | 127 26\n65: 112 16 | 76 26\n23: 16 16 | 44 26\n102: 16 116 | 26 132\n39: 16 26 | 26 26\n40: 23 26 | 76 16\n108: 16 53 | 26 51\n22: 110 26 | 55 16\n42: 1 16 | 47 26\n14: 112 26 | 46 16\n117: 115 26 | 76 16\n120: 26 6 | 16 59\n72: 26 130 | 16 66\n131: 102 26 | 20 16\n93: 16 16 | 26 16\n58: 97 26 | 104 16\n69: 26 88 | 16 46\n54: 76 16 | 116 26\n1: 26 64 | 16 28\n48: 13 26 | 61 16\n92: 85 26 | 117 16\n49: 124 26 | 98 16\n6: 44 44\n24: 112 26\n17: 112 16 | 116 26\n115: 44 16 | 16 26\n113: 16 128 | 26 89\n106: 26 132 | 16 6\n16: \"b\"\n67: 44 16 | 26 26\n104: 44 88\n41: 26 132 | 16 76\n38: 16 59 | 26 46\n89: 16 24 | 26 62\n80: 18 26 | 35 16\n98: 46 26\n101: 16 132 | 26 46\n85: 16 59\n126: 16 67 | 26 59\n9: 26 49 | 16 80\n10: 26 67 | 16 59\n34: 26 93 | 16 23\n4: 70 26 | 107 16\n100: 123 26 | 63 16\n109: 118 16 | 54 26\n77: 16 50 | 26 99\n88: 26 26 | 16 16\n81: 67 26\n18: 16 115 | 26 88\n123: 57 16 | 103 26\n60: 26 18 | 16 43\n94: 26 23 | 16 59\n0: 8 11\n57: 46 16 | 125 26\n110: 26 58 | 16 60\n20: 44 76\n15: 56 26 | 33 16\n114: 26 132 | 16 23\n7: 16 6 | 26 115\n28: 16 3 | 26 25\n51: 112 16 | 23 26\n43: 88 16 | 116 26\n111: 26 6 | 16 93\n62: 26 132 | 16 112\n76: 16 26 | 26 16\n27: 96 26 | 45 16\n50: 26 93 | 16 76\n132: 16 26\n35: 16 115 | 26 132\n53: 16 46 | 26 116\n75: 104 26 | 81 16\n82: 26 9 | 16 100\n78: 26 116 | 16 125\n19: 16 39 | 26 132\n37: 26 41 | 16 127\n45: 91 16 | 108 26\n59: 26 26 | 26 16\n116: 26 16\n84: 7 16 | 94 26\n86: 16 6 | 26 88\n63: 94 26 | 17 16\n103: 115 26 | 59 16\n130: 16 34 | 26 20\n99: 39 26 | 6 16\n26: \"a\"\n64: 16 15 | 26 21\n97: 67 16 | 23 26\n83: 105 26 | 27 16\n21: 75 16 | 52 26\n30: 26 125 | 16 112\n3: 16 121 | 26 74\n105: 26 73 | 16 113\n125: 16 16\n13: 16 88 | 26 39\n32: 72 26 | 122 16\n122: 16 77 | 26 2\n90: 4 26 | 32 16\n12: 26 6 | 16 39\n29: 68 26 | 101 16\n79: 106 26 | 111 16\n61: 132 16 | 46 26\n31: 83 26 | 90 16\n96: 16 87 | 26 5\n118: 26 93 | 16 116\n44: 26 | 16\n25: 37 16 | 71 26\n52: 10 26 | 7 16\n124: 125 16 | 6 26\n66: 26 36 | 16 14\n127: 16 116 | 26 39\n68: 26 46 | 16 6\n70: 79 26 | 109 16\n128: 126 16 | 40 26\n8: 42\n71: 26 114 | 16 78\n73: 129 16 | 131 26\n5: 16 65 | 26 118\n11: 42 31\n119: 16 112 | 26 6\n95: 16 88 | 26 59\n87: 119 16 | 14 26\n121: 35 26 | 95 16\n47: 22 26 | 82 16\n46: 16 16 | 16 26\n129: 12 16 | 17 26\n112: 26 26\n36: 67 26 | 125 16\n74: 16 10 | 26 38\n\naaaaaababbaaababaaaabbbb\naabbabbabbbbbaaaababbbbbaaabbaabababbaaabababbab\nbaabaabaaabbaaaaaaabaabb\naabaaababababbbaabababaaaaaaabba\nbabbaabaaaabbabbabbaabba\naabbabbbaaaaaaabaabaabaa\naaabaabbaaabaabbaaaaababaabaabbabbabaaababaabaabbaabaabbaabaaaabbabababa\nabbabaabbbaabbbbaabaababaabbaabbbabbbabbaabbabbaabaabbbbbaaabaababbabbba\nabaaabaababaaabbbaaabbbb\nbaabbabbaaababbbabaabaab\nabababbabbabbbaabaaaaaab\nbbabbaababbbbbbbbaababba\nabaaaaaaabbaaaaabbaabbba\nabbbbaabbabbbaabbabbbbbbaaababbaabaaaababaaabbbabaaaaabbbababaabbbaababb\naabaaabbaaabbbaababbbaaaaabbaaababbbababbbabaabbabbaabbbbbabbbbbaaaababbabbabaaa\naaabbbababbbabababbaabba\nbabbbbabbbaabaabbbbaabba\nababbbbbbbbaaabababbaaaabbaabaaabbbabbab\nbbabaaaaabababaababaabaaabababbb\nbbabbabbabbaaaabbbaababbbaaaabaabbaaaaaa\nbaaaabaabbabbabbabbbbbbaabbbbbbbbbaababbbbabbaabaabababb\nbabbaaaabaababaabaababab\nbbbababaababaabbbabaabbb\nbaaababbbbbbbababbabbabaaaaabbaa\nbaababaababbabbbabbababaabbaaabababbaaab\nbbbaaabbbabbbaaaaaabaabaabbbbaabbaaabbba\naabbabaaaaaabaabababaabbbbbaabbaaababbbb\naaababbbaabaabbababaababbbaaabbabaaaabab\nbbbbbbbbabbbaaaabbbbaaaa\nabbbbaaaaabaababbbbaabba\nabbbbaaaaabbbabbbbbaabbbaaabbabbabbababaababbaaa\nbababbabaaabbaaaaabaabaababababa\naabaabbabbabaabaaaabbaaabbbbbbbabbbbbabbabbbbabb\nabbaaabaaaaaaaaabaaabbbaabbbaaabbaaaaabaaaabbbbaaaabbaab\naabaaababbaaabbbaabbbaaabaabbbbabbbaaabaabbaababababaaba\naaaaaabaabbaaaababbaabba\naaaaaaaabaaabbaabaabaaabbbababaaabbabbab\nbbabbabaaabbababaabababb\naabbbbabbaaabbbabaababaaaaabbbba\nbaaaaaaabbbababbabbaaabaaabababbaababaaaababaaabaababaaa\nbbbaabbbabaaaabaaaabbbaa\nbaaaabaabbababaabaabaaaa\nbbbbbaabbaaaaaaabbaaabaa\naabbbbabbbbaaabbabbbbaab\nbabaababbabbabbabbababbbaaabbbbb\nbabbbbabbbaabaaabbbaabaa\nabbbbaaaabbaaaaabbabbbaaabbbaababaababbbaaaababbaaabbbbbaabaaaaa\nbaabbbbabbbbbaabbbaabbba\naabbabbbaaabaaaabbaabbbb\nbabaabaabaaaabbaabababbb\naabbabbbbabbaababbaaaaaa\nbbaababbababbbbbbbbbaaab\nbbbbbbabaaabbabbabaababbbbbbbbaa\nbaabbaaabbabaabbbbbababb\nabbbbbbaaabaaabbaababbbb\nbababbbabbabaabbbabbaabaaabbbabaababbababbababab\naababbababbbbbaabaababab\nbabbbaaaaaaaaaabbbabaaba\nabbbaaabbaaaabaaababaabbaabaaaaaabbaabbaabaabababbabaaaa\naababaabaabbaaaabababaab\nbabababbaaaaaabaabababababbbabbbbbababaabaababba\nbbbbbabbbbaababaabaabbbbbababababaabbaba\nbaabbbbabbabaabbbaababbb\nabbbbbabbababbbbbbaaabbabababbabaabbaabbabaaabbaaaaabababaabbaababbbabbaaaabaaaa\naababababaaaabbbaaaabbbaaaaabbbb\nababbaabbbaaaabaaaabaaab\nabbbbbbaaababaabbabbabbababbbaaabbaababa\nbbaabaabbbbaabbbbbaaabbbabbababbbbbbaabb\nabbababbabababbbaabaaaaa\nabbbaaaaaaaaabaabababbab\nbbaababbabababbaababaabbabbbbbabbbabbbbb\nbabbabbabaabbaabaababbbb\nbbbbbaaaaabbabbabbaaaaab\naaababababbbabaababbabab\nbaababbbaaabbaababaaaabbabbaabbb\naababaabaabaaaabbbbabaabbbbbbbabaabbbbaa\naaaaaaaabbbbaabbbbbababaabbaabbbaaababba\nbbbababbbbaabbabbbababbaabababababbaaabaababaaab\nbaababaaaabbbabbabbbabbababbababbabbaaab\nbaabbbbaaabbbababbaaaabb\nbbababbbabbbbaaaabbabbab\nbabbabbbabbbabaabaabbbbb\naabaabbabbababaabbbbaaaa\naabbbabbbbababaabaaaaaab\naaabaaaabbbabaabaabbabaabbbabbbb\naababaabbbbbabaaaaaaabba\nbabaabbabbababbbbaabbbaabbbbbaababbbbabbbbabbbab\nabaaabbbbbababbbbabbbbba\nabbbbaaaaabbbabaaababbaa\nababbbaaabbbabbbbabbaabb\naaaaaaabaaaaabaababbbbabbabbbbababaabbaa\naaaabbabbaaababbbbbabababbabaabaaabbbabbbbbbbabbaaabbbbbbabbabab\nbbbaaabbbbbbaabbaaabbbba\nbbbaaababbabbabbbaabaabb\nabbbbbbbaababbbbbbbbabbaabaabbaababbbaba\naaaaaabbbbbbbababbaababbbaabbbba\nbaaaabaaabbababaabaabaaaababbbbbbababaaabbbbbabb\nbbabbbaabbbaabbbbabaaabbbabaaabaabbbbbbbaaaaabba\naaaaaabaabababbabbbbabba\nababbaababababbaaaaabbba\naabaababbabbbbabbbbaabbbabaaaaaaaabaaababaabbbbb\nbaabbabbbbaaabbabababbaaaaaababb\naaabbaabababbabaababaaab\nabbaaaabaaaaaabbaaabbbaa\nababbababbabbabababbaaaababbabbabbbabaabbababaabbbabbbbaabbbbabbabbabbbb\nbaaaaaaabbababbababaabbabaaaabbaaabababaabaaaaabaabbbbaa\naabbaaaabbaaababbbaaabbaabbbababababaaaa\naaaaabbbaaabababbaabbaabbaaaaaba\nbbababaabaaabaabbbbbabbb\naababaabaaaaabbbabaaabaaabababbb\nbbbabababbaaaabbabaaabbabbabaaba\nbababbaaabaaaaaababbaabb\naaaaaabbaaabaaaabaababab\nbaaabaabbabaababaabbbbabaabaabbbbbbabbbabbaabbaa\naaaaabaaaaabbabbbbbbbabb\nbabbabaaaaabaaaaabbbbabb\nbbbbbaababbbbbbabbbaaabbabbbabbbbabbaabbbababbbb\naaabababbbabbabbaaaabaababbaabbbaabababb\nbbaaababaaaaabaabaabbbbabbabbabbbabbbbbabaaabbba\naabaaabbababbbbbbbbbaaaa\naababbabbbaabaaabbabbaabaabbababbabbbbbb\nbababaaabbbbbaabbbbabaabbaabaaba\naaaabaaaaaaaaababbaaaaabbbbababbbabbbaab\naabaaaabbaaabaabaababbaa\naabaababbbbabaabbaaabbba\nbbbbababbbabaaabbabbaabbababaaabbbbbabba\naabbaaaaabbaaaababbbaabb\naaabaaaaaaaaaaaabaaababaabbbabbbaababaabbaabaabbbbaabbabbbbabbaa\nabaaaaaaabbbabbbababbbaabaabaabb\nabbaaaaaaabbaaaababbbaab\nbbabaabbaaaaaabbabaabbba\nbbabaabbabbbabaababbbbba\nbaabbbbaaaabaabaaabaabaa\nbbabbbbbbbaabbbaaabbaabbbbaabbabbabbbabbbbabbbab\naaabababbbabbaababababababbbbabaabababaaaaaaabba\naabbbaaaaababbabbbaaabbabbaaaabaabbbbaaaabbaabba\nababaabbaabbbabaabaaaabbbbabbbbbbaaabbbb\nbaababbbabbbabbbaababaaa\nbbbbbaaaabababababbabaab\nbbbbbaabbbabbaabbaaaaaba\nabaaabbbbabaababbabaaababbaababa\naabbbbabbabaaabbbbababaaabaaaabbbabaabaa\nbabbabbbababbbbbbaabbbbaabbabbab\nabababababbaaaaaaaabbbba\naabbbabbbbabaaabbabbbbabaabaaaabbbbabaaaaaabbbba\naabbbabbbbaababbbbbbbaab\nbbaaaababbbababaaaabbbbaabbbaaabbababbbb\nabbabbaabaaaabababaabababaaabbaaababbbbaababbabbaaabbabaababbaab\naaabababaaaabaabaaaaaaabbbababbababbabbababbaaab\nbabaabbabaabbabbbbbaabaa\nbabbabbbbbaabaaabbbbbabaabbbabbabbaaaabbabbbabaabbbaaaaa\nbbbababaaabaaabbabababaabaaababbbabaaaaaabbaabba\nbaabbabbababbbaaaaaabbaa\naabaabababbbbbaabaababba\nababbbaaababbbaaaaabbbaa\nabbabbbabbaababbaababbbb\naababaababaabaaabbabaaababaabababbabbbab\naaaabaaaaabbbbabaabbbabbbbaababbbbbbaaab\nbbbbababbbbbababaaaabbaa\nabbbaaaabbbaaabaabbbaaab\nbbabaaabbbbbabaababbaaaabbbaaabbbaaaaabaabbbabbbbbabbbbbbaaaaabbaaabbbabbbbaabababaaabaa\naaabbaabaabbababaaaaabba\nbbabaaaaabbbaabaaabbabaaaabbabbbaaabaabbbbaabbab\nbbaabaaaaabbbaaababaabaaabbabaab\nbbbbababababaabbbaaababa\nbaabaaaaabbababaaababaabaabbbabaabbabababbababbaabaaaabaabbbbaaaabaabbbbbaabbbbb\nbbababaaababababbababaaabbbabbbaaaaababa\nbbaabaaaabbbbbbbaaaabbbb\naabaabbaababbbbbbaaababb\nabbbaaaaaabbabbababaaabaabbabaabababaaaabababbbb\nabbbbbaaaaaabbabbbabaaabbaaaaaaabbbabbab\nbbabbabbbbabbabbaabbaabb\naabbabbababbaababbbabbba\nabababbabaababaababbbbaababbabab\nbbababbabbaabbbbbbbaaaaabababaabaaaaabba\nabaaaabbbaabbaabbaabaabb\nababbaababbabbbaabaababa\nabaaaabaaabbbabbbaabbaaaababaaaabbbabbbabbaaaaaa\naabbababbbabbbaaabaabbba\nabbabbbaaaaaabbbaabbabaabbaaabbbababbabbabaaabba\naabbbabaaaabbbabbabbbbbabbabaabbabaababa\nbabaabbaabaabaaababbabbaababababaabababa\nabbaaaaaaaabbbabbbaaabbbbaaaaaba\nbbaaabbbbbaaabbabababbab\naabbababbbbaabbbaababbba\nabaaabbaaabaabbbbaaaabab\nbabbaabaaabbbbabbaaabbaabbaaaabb\nbbabbabbababbbaabbaababa\nbabbbababbabbbbabbbaabbbbbaaaabaabbbababaabbabbabbabbaaababbbbaaaabaaaabbbaabaabaaabbabb\nbbabbabbbbbbbbabbabbbbbb\nbbbaaabbabaaabaaabbababbbabababbbbabaaabaaaababb\nbabaaababbaababbababbababbbabaabbbbbbabbabbaaababbabaabaaababbaa\naabbbbabbaaaabbaaabaabbabaabbabbabbbaaabaaaababa\nabbaaaaaabbababbbbbbbabb\nbaabbbaaabbaababbbbabbaa\nababbabababbbaabbbaabbbb\nabababbabaabbbabbaababaaababaabbbbbabbaabbaabbababbabbababbbbabbaabbbaaaaabbaababaabbaba\naabaababababbbaabbaabbab\nbabaabbabbbbaabbaababbaa\nbaabbaabbbbbbababaabbaaaabababaabaabbbabbbbbabaa\nabbabababbaabaabbbaababa\nbaababbbaabaaabaabaaabbbaabababa\nbbabaabbbbbbbaabbabaabbb\nbabaabbaabaabbbaaabaabbbbabbabaababbabbb\nbabaababbbaababbbbaabaaaabbbbabaabbabbbbaaaabbba\nababaabaababbbbaaaaabbba\naabbbabbaabbbbabaabbabbbabbbaababaaaaaaaabbabbbb\naaabaaaaaabaabbaaabaaaaa\nabbababbabbbaababbbaabba\nabababbababbbbabbaaaaaab\naaaabaabaaabbbabbbaabbab\nabbbbbbbbaababbbbabbabab\nababaabbbbbbbbababbbbaab\naaaaaaabaabbabababaaaaaaaaabababbabbbbaa\nbbaabaaaaabbbabbbaaabbba\nbaabbaaababbabaabbbbaaba\nbbbaabbbabbabbbabaaaaaab\naaaaababbbbabbaababbabababaabbab\naaabbbababbbabbaabaabbbb\nabababaaabababababbaabba\nababbbaaabbaabaaabbabbbb\nbbabaabbbaabbbbabaaabaaa\nababbaabaaaabaabbbbbbbab\nbaabaaabbbaabaaaaabaaaabbaabbbabbbbabbbbaabababb\nabbaabbbabaababaabaabaaaabbbaaaababbaabbbabaabaa\naababbabbababaaaababbbba\nbbabbabaabaaaaaaabaaaaaabbaababbaaaabbaababbbbaabbabbbbaaabbabaa\naaaaaaabbbaababbababbbaabbabbabaaababbaabbabbbbbaabababa\naaabaaaabaaabaababaabbab\nbaaaaaaabaabaaababaaaabaaabbaabb\nbbaabaabaabaaaabbbbbaaab\nabaabbbaaaabaaaaabbbababaaabaaaaaaaabaaaababbbabbbababbaaabbabbb\nabaaabbbabbbbbabbabaaaaa\nababbababbbabaababbbbabb\nbabaababaaaaaaaaaaabbbabaaaababa\naabaaabbaaaaabbbaaabbaba\nbaaabbaaaabaaababaababaaaabaaabaaaabaaaaabbbaaba\naaaaabbbbabbaabaaaabbaabbbbbbabb\naabbbbababbbaaaabbaaaaab\nbbbabaabaabaaaabbabaaaaa\nabbbbaaaabbbaabaabaabbbb\nabbaaaaababbaaaaabbbabbabaaaaaba\nabbbaabaabbbaababbababab\nbbbaaabbbaabaababaaabbab\naabaabababbbaaaabbbbaaba\nbaababbbbaababbbbabbbbabbbbababbabbbbaab\nbbbbababaababaabbbbbbaaabbaaaabaabbbbaaabbbabbba\nbaaabbaabaabbbabaaaaabaaaabbaabb\naabaaababbbabababbbabbbb\naabbaababaabbbbabaaaaaba\naaaabbababbaababbabbbabb\nababababaaaabbababaaabab\naaabaabababbbbababbabbbbaabbaaabaabaaabbbbbababbabbabbabaaabbbba\naabaaabbaabaaabbbbbaaabbbbbabaaa\nbbbaabbbbabaaababbbbbbabababbbbbaaabbabbabbabbaa\nabbaaaabbaabaababbbaaaab\nbaaaabaaabaaaabbbbabbbab\nbbabbababbbbbbbbbabaabbb\nbabaaabaaabbabbabbababab\nbbabbabaabbbababbbbabbba\nabaaaabababbbaaabbabbabaaabaaabb\naaaabbabaaaaaaabbabbbaba\nabaaaaaabaabbaaababbbbabaabbabbabbbaaaaaaaabbbba\nababbabaabbbbbaaaabaabaa\nabbbaababaaababbaabaaaaa\nbbbabaabbbaabbbbbaaabaaa\nbbabbabbbaaabbaabaaabbba\nbabbabaabbabbaababaabbba\nabbababaababababaabbbbaa\nbaabbbabaaaaabbbbabbbbbb\naabbabaaaabbabbaabbbaaab\nabbbbbaaaabaaaabbbbabbbb\nbbbaabbbbbbbabaaababaaaa\nababbaabbbaababbbbaaababbaaabaabbbaababbbbbbbbaa\nbbbabbababbbbbaaaabbbabbbbbaabbabbaaaaabbaabbaaaabbbbabaaababaaa\naababaaababbbaababaabbbaaababbbabbbbbbaa\nbabbabbbaaaabbabaaabaaab\naabbbaaaaaabaabaababaaab\nbabaaabaaabbbaaaabaabbba\naabaaaababbbabbaabaababa\nbbbbbbaaabbabbaaabaabaabaaabbabaaaababbbabbbabbb\naababaababbaaaabbabbaabb\nabbbaaaabaaabbaabbabababbaabaabb\naaaaaabbabbaaaaababababa\nbbbbabaabbbaaabaaababbbb\nbabaabababbbabbabbbabaaa\nbbbaaabbbaabbbbaaaabbbaa\nabbabbbababbbaaabaabbabbababbabbababbbbaaaabbabababbbbabaabbaaba\nabababbabbbaaababaabbaba\naabbababaaabbbbbbbaaaabbbbbbbbababbbabaabbabbbbb\nabaabaaabbababbbbaaaabababaabbaaaaaabbbbbbbbaaaabbbbbbaabbaababa\naabbabbaababbbbbbbbbaaaa\naaaaaabbaabbababbbaaaaaa\nbbbaaababbbbbbabaaabbaabbbbaabba\nbbabbabbabbbabbabbabbbab\nbbaabaaabbaabbbbabbbaabb\nbabbbaaaaababaabbbbbbabb\nabaaabaaabaaaabaaabbbbbb\nbbababaaabbbabbaabbbabbbbabbbbbaababaaba\nabababaabbabaabbbbaaabbabaabbbababbaabbb\nbabbaabaabbbabbaabaabbbb\nbaabbbbabbababbabaababba\nbbaaabbbaabbaaaabaaababbbabbabaabaabbbbb\naaaabbabbbbbbbbbaaaabbabbaaaabbb\nbbbbabaaabbaababbbaabbab\nbaaaabbaabaaaaaababbabaabaaababa\naabaabbabbaaaababababbaababbabab\nabaaaaaabaaababbabbaaabb\nabbbabbabbbbabaabbbbaaba\nbabababbbbabbbaaaabbbabbaaaaaabbbabbabbbaabaaaabababaaaa\naaaabaababbbbbbaabaabbaa\nababbbaaababababababbaaa\nababbbaabababaaabbbbbabb\nabbababbaabaaabbbbbaabab\nbabaababbababbbabbbbabbb\nabbbbabbabbbaabbabaaaaabbaaabbbbbabbaaababaababa\nbaabbbbaaaabbabbbbbababb\naaaaabaaabbabbbababbbbaabaaabbaabbbabbba\nbaabaaabaabbbaaaabaaabba\naabaabbabbbbbababaababbb\naabbbabaabaaaaaaabaabbaa\nabaabababaabaababbbbbbaabbabaabbaabaabbb\naabaaabbbbabbabaabaaaababbaababaaabbbaab\nabaaaaaabababbbaabbbaabb\nbbabaabbaaabaaaababbbabaabbaabba\nbbbbabababbbabababaababb\nbabbaaabababbabaabbabababaaababbbbabbbbbbbabbabbbaaaabaaabbbbbba\nabbbbbbbbbbbabababbabbaaabbaaaababbbbabaaabbaaaaaababbbbbbaababbbbaabaabababaabbababaabbbbbbbbba\nbbbaaababaaaabbabaaababbababbaabbbbbbbba\nbabbabbaaaabbbabababbabb\nababaabbabbabbbabbabbbba\naaabbaabababbbaaababaaab\nababbbabaababbaaababbaaa\nbaaaabaaaabbaaaaabaababa\nbaaababbababababbbabbaaa\nababbabababaabababaabaabaaaabbbbbbaaaaababaabbaabbaaaabb\nabbbbbaaaaaaabbbabbabaab\naaaaaaabbbaaababbbbaaababaababaaababbaaa\naaabbbabbabaabaaaabbbaab\nabbbabbabbababaaaaabbbbb\nabbbbabaaaaabbbaabbabaab\nbbabaabbaabbbaaabaabbbbb\nababbaababbabbbabbabbaabbbaaaaabbbbbbbba\naabaaabababbbbaabaabaabb\naabbbaaabaabaaabbbbabbaa\nbabbbaaababbaabaabbbabbbababbaabababaaba\naababaabbabbabbababbbbabaabbbbabbbbbaaaaaabaabaa\naabaaaabbbaabbbabaabaaababaaabababbbabbbabbaaababbaabaababbabbbbabbabaaa\nabbbabbbbabbbbaaaabbbabbaabaaabaabaababbbbbabaaa\nbabababbaababbababbabaaa\naaaaabbbabbbabbabbbaabba\nbbaabaaaabaabbabababaaab\nbabbabaaaaaaaababaaababbbaabbbaaabaabaab\nabbbbbbbabbaabaabbbbbbaa\naabaaaaabaaaaaabaaaaabbaaabababa\nabababbabbabbabbaabaabbb\naabbbaaaabababbaabbaaaabbbababab\nbaababaababbabaaaabaaabaaabbbababbbbabbabbabbaaababbbbba\nbbababaabaaaabbaababbababbabaaaaabbabbab\nabbbbbbbabbbbbaaaaaabbba\nbababbbabbbaaabaaabbbabbabaaabaaaabbabbbababbbbbababbbab\nabababaaaaaaaababbbaabaa\nbabbabbbaabbabbbaababaaa\nabbaabaababaaaabbbbbabbaaaabbabbbbbababaabbbbbabbaaaaabbbbaaaabaaabbaaab\naaababababbaaaabbaaaabbb\naaaaaabaaaaabaabaaaabbaa\nbbaaabbbabbbbbbaaabbaaaaababbabbbaaabbba\nbbbaabbbbbabbbaaabbbbbab\naabbaabaabbbababbaaabbbb\nbbabbbabbbaabbaaabbbbbbababaaabaabbababbaabbaabbbaabaaaabaababbb\naaaabaaaabbbabaababbbbaabaaaaaba\nabbbabbaabaaabbbabbababaaaaabbabbaabbaaaababbbab\nbaaabaabaabbaaaabbababbbabbaaaababbbbbab\nbbbbbbababaaabaabbaaaaaa\nbaaabbaaaabaaabaaaabaaab\nbbbaaabaaabbabbaabbabaab\nbabaabababbbbbbaaaaabbba\naaabbbabaaaaaaaabababbab\nbbbbababaabbabbababbbbbb\naaaaabaaaaaaaababaaaaabb\naaaaaaaababbbbababbbabbaabababbb\nabbbbbbaaababaababbbbaab\naaaaaabababaababaaaaabba\naabbaaaabababbabaabaababbbaabbbbabbbaaaaaabbabaaabaabbbb\nababbbbaabbabbbabbbbbaaababababbaababaaabaaaaaab\nbbabbabbbabaaabaaabbbbaa\nbaaaabbaaabbbabaabaabaaabbabbababbbbbbbbaaabaaaababbbbbabaaabbabbabbbbbaaaababaa\nabbababaaaabababbbabbaaa\nbabaabbabbbaabbbaaaabbaa\nabbbbbaaaabaabbaaabbabbaabbabaaaabbabaaa\nabababbababaaabaabbababaaaaabbababaaaaaaabababbaabaabbbabbaaaabb\nbbbaabbbababaabbabaaaaab\naabaabaaabbabaabbbaaabaa\nabababaabaabbaababbabbbb\nbabaabbaaaaaaaabaaaaabba\nbbaabbbaababaaaaaaaababa\nbbabaaaaabaaaaaaaaabaaaabbbabababaabbbababaaabba\nabaaabaaabaaaabbbaaaabab\naabbabaaaaaaabbbababbbba\nabababaabbbbaabbaabbaaabbbbbaaaabababababababaaaabbbbaaaaaaaabbbbabbbaaa\nabbbabbabababbaaabaabbaa\naaabaaaaaabbaaaabbaabbba\naabaabbababbabbaaabbabbbababbaab\nbbbbbaabaaabaaabaabbaabbbbaababa\n"
  },
  {
    "path": "advent-of-code/2020/inputs/2",
    "content": "1-4 m: mrfmmbjxr\n5-16 b: bbbbhbbbbpbxbbbcb\n7-8 x: qxrxmxccxxx\n9-11 k: kkkkkkktmkhk\n8-12 g: sgwvdxzhkvndv\n6-9 v: zvmvvmvvvd\n8-19 f: ffffsplmfflffhtfrfj\n5-16 p: pppppppppspppjpcp\n2-3 w: wwmw\n7-19 j: jjjjjjjjjjjjjjjjjjvj\n5-9 q: wqzqqqqqq\n14-15 g: gggggggggglggfgg\n4-6 p: tppzkppdt\n11-14 p: vppgpktpppppptpppqp\n5-9 f: bfflffrfgf\n7-9 p: ppppptbzn\n1-3 l: lllvn\n2-4 g: qvcdg\n1-3 m: wsmdv\n1-5 v: vvvvvvvv\n10-14 l: lckqlgjllltlwbl\n3-4 t: bsttftltjhbqbgtm\n15-17 j: jjzjjjjjhjjjjjjpzjj\n2-3 t: thtt\n6-17 f: ffwkwzjtjktvsfmfhvsf\n3-5 b: rqxbb\n4-7 m: nbcmcwmmxrxqvtjfmm\n1-2 v: gzvvvv\n1-3 w: hkwhv\n7-8 p: pppppppp\n3-4 h: hhnwh\n2-4 t: ttrtjtththkr\n3-4 w: wwww\n4-6 s: xsntgrftmpx\n4-7 s: ssskssmsbs\n10-15 m: bmmrbmmmmlmmmmmm\n12-13 w: wqpwdmwllnjwx\n5-14 n: nnnnlnnnnnnnnmnn\n5-6 k: kktkfczk\n5-7 r: nrdrtrvr\n4-6 c: ccqchcc\n2-9 l: fnldtfnbxjlvnlsnjhml\n1-13 d: dlchvkccnwrcc\n5-7 j: jjjjjjj\n3-5 z: zzzzz\n6-12 f: ffffflvmfhfx\n8-10 w: wwwwwwwwww\n3-4 r: rrbtr\n3-11 b: bbbrbbvphbxbqk\n16-17 n: nqhknnnnsnnnnnnnnnb\n18-20 k: kkkkkkkkkkkkkkkkkhtj\n3-15 r: ktvzqbmbrvczprfcw\n9-11 q: qnqqdqqqgrrqsqq\n3-5 p: pvppp\n7-11 m: mfcdmmxmmmp\n7-8 t: ttttktnt\n5-6 b: bbpbbbv\n14-16 z: zzzzzzzzzrzzblzw\n11-12 j: jkjjjkjjjjjjgj\n7-9 q: qqqqqqqqqq\n10-11 f: cfffffffffff\n4-6 c: nccccc\n7-8 r: gmdlqfpwmrr\n6-8 v: nvvpdnjx\n8-12 x: xxlxxbbxxxxx\n8-10 s: ssxssssssss\n5-12 z: zhzdfzgdzzhzlz\n11-12 k: qbkhvqjpqzfq\n2-11 w: wwmlttwjflwdjcpclww\n2-16 w: twkkmcrxmvjtwxlwsksf\n6-8 s: sssfxbskvs\n5-6 s: ssnsxsbs\n10-19 l: ndzmdxqlnllxsbbwvsl\n2-4 g: gggg\n5-10 x: zxxxsxxxxxxxsxx\n7-15 f: ffbrbdtzvdffktxfm\n7-8 m: xmkmmmmmtmm\n9-13 s: hksrdhzlsdmps\n15-17 b: bbbbbbbrbbbbbbbrbb\n3-5 x: xxxxxxx\n2-6 t: wtltztnct\n3-15 v: vvwvvvvvhvvvbwwvmdvr\n12-14 p: ppphsppppppbphp\n8-9 t: ttttvttttttt\n2-3 c: cchvj\n8-9 z: vzzzzzzgl\n11-12 q: qqmqqqqqqqsnqqqqqqq\n12-13 d: dddddddddddmd\n8-9 t: wttttttqt\n7-8 p: ppppvvcw\n4-5 g: gncgj\n12-13 s: sssssssssssmw\n7-9 f: pswpnjftf\n11-16 p: ppppnpkpkzppcpzbppp\n1-12 q: ksqrqpqnqmqxqb\n2-10 l: lllllllllll\n17-18 z: zzzzzzzzzzzxzzzzzz\n11-12 g: qggbjgggggssgggrk\n3-4 s: bpss\n6-8 v: vwvvvrvvv\n3-4 t: tglktt\n4-12 l: kvrnzqslwrdkfll\n12-16 b: fbbbbbnbbvbbbbbcbbb\n5-6 t: ttttzz\n5-8 w: sqwhwwxw\n8-9 z: zzzvztzrzzzz\n3-6 l: llvdlt\n7-8 r: mrcvnrrr\n10-11 k: kkkkkkkkkmc\n1-3 n: nnnmn\n4-16 c: dqlcbclcrxkkszvcv\n9-10 g: fxssmlmgbh\n5-6 p: nwpfpp\n3-7 w: cwhgrfshdwhwwll\n14-16 l: llllllllllllllpll\n3-4 f: ffff\n4-9 d: dcdddxzvmrd\n4-11 w: jwwnwwwwwvx\n3-4 t: ttvc\n4-17 r: rrsrrrrrrrrrbtrrrr\n8-9 x: wqxxxcfdx\n6-8 d: qgddwddtdddlc\n12-13 v: vvjvvvvvzvvtvv\n3-4 g: sghxg\n3-4 b: ckbbmprfbbmzgqtkbw\n5-6 x: xxxxxv\n10-13 f: zpfffbfchxfffffjff\n5-6 f: ffffwf\n12-19 l: mlllllplllldllnsllql\n4-5 v: vvvvp\n5-8 w: vjwvghggwww\n1-3 n: lnnn\n16-18 p: ppppppvpppppwppppppp\n15-18 z: zzzzzzzzzzzzzzjzzg\n4-6 b: bbmbbb\n5-7 z: wzlwzmzzzzzzzzzzzwz\n8-12 p: gppmpppvppkzpcnpb\n16-19 h: hhbhhhhhhhhhhhlnhhw\n2-3 n: nnnn\n3-10 m: mmntfkdjftmtmmbm\n3-5 j: jjjjw\n4-6 z: zjnzzzdzz\n1-7 s: zsvsssf\n6-7 v: vtvvvcg\n3-12 f: qsrtmnxkvlcmt\n5-11 q: mqgqqqqqrpch\n5-9 g: msxkggnggg\n3-8 v: vvvvhvjvdvxtr\n4-6 k: jcklxdhkwhsqhq\n6-7 x: vppxbhcjzxdqx\n2-3 n: ntrg\n7-8 g: gggwgjdhg\n1-3 d: dddd\n14-18 l: llllllllwlllxllllllz\n8-19 g: ggggghggkhgrtzcgrrk\n7-14 q: phzxvmbxxfsfwr\n8-14 r: hbjmdrhnpxnwgz\n15-17 d: dddddpddddldddtdgddd\n6-7 k: kkkkkgkkq\n2-12 w: wwzwwwwwwwwww\n5-8 q: qqqqqqqzqqwqqzqcq\n5-6 z: czzzrz\n14-15 b: bbbrzhbbbbnxbgbb\n12-13 d: dgddddddddtvddddvbz\n3-5 v: vvvvv\n13-16 q: qqqqqvzwqqqqqqqq\n2-3 n: jpznnwfpchs\n7-10 w: jwwpwkwwwpw\n6-7 b: bbcnbcjxbbb\n14-17 w: wqtwwwwwnwcwwbsww\n3-14 w: gwwwwwwwhwwnxwwwww\n4-9 w: mwllcfjfwwwjp\n9-12 n: nnnnnnnhnwjnn\n2-4 j: jjjjj\n3-6 t: mrmttccttqt\n16-17 p: ppmjpgptzgbppphfbp\n12-17 v: vvvvvvvvvvvvvfvvvv\n13-15 x: xxxxxxxxxxxxxxgx\n2-4 d: dddddddd\n2-5 t: ttmvt\n13-14 j: jjjjjjjjjjjjtj\n3-5 r: ggmrdf\n7-8 f: ffdfflszfsfffqff\n10-11 t: ttpttttttrgtt\n8-12 j: jjjjqdhzjhjdj\n19-20 z: zbzzzzzzzzzzzzzzzzrq\n7-11 b: bbbbbhbbbxbbb\n4-9 p: gzmkkbtpkzpgthklpq\n2-5 b: bbbbxgb\n4-13 k: kkkkkkzktckkkwkjkk\n10-12 q: vrxznfqqnqgq\n15-16 m: mmmmkmmmmmmmmmmmm\n15-18 h: hlhhvhchthhhhtphhh\n2-3 m: mftzmc\n6-11 s: ksssssssssszs\n5-6 q: qqqpqkq\n7-8 n: nnfnnnnpn\n6-8 c: chfcllrvxcnnjhtc\n6-8 k: kkkkkxlk\n2-4 s: tsspb\n9-12 q: qqqqqqqqqqqqqq\n17-20 h: hhhhhhhhhhhhhhhhhhhh\n6-13 r: rrrrrgrrrrrrn\n4-8 f: fffrfffz\n13-14 n: nbnnnngnnnnnnpz\n8-11 f: fvffsfqftcffff\n3-5 w: vwhxz\n8-10 x: nmxxknlptx\n3-4 p: pppt\n17-18 v: vvvvvvhkvvvvvnvvjlvv\n10-15 z: twnsdkmgpvzfmzg\n3-5 n: njnjnkghp\n10-12 q: qvqqqqqqqqqq\n6-7 r: rrrrrrrr\n3-4 t: qltt\n2-16 f: gffflcvtpfkfcjfrjvfs\n3-5 s: swssp\n11-13 l: lrpllllllvtslwllllld\n1-3 n: nnnn\n3-5 g: jjggnvg\n4-5 b: bvbbb\n13-15 l: llvllllllllllnll\n5-6 j: hjjjjfsj\n3-4 b: bkfbnb\n5-8 z: zdzzzzzzzrzzz\n3-4 r: rrrx\n2-12 c: mczhvchkmjdrjh\n12-16 x: sjxbcgdqtpfxflsxx\n2-4 c: tcxf\n4-5 w: kwjww\n1-2 r: rrrwzc\n4-7 d: ddddddkdd\n5-6 q: qqqqqp\n13-16 l: flljlllvnzlllllclldl\n3-6 j: jjjpjj\n3-4 g: gxgg\n10-11 n: nnnnnnnnnnn\n2-5 j: ztchj\n4-6 j: pjzzrmjvhcxn\n4-11 c: jchcccgccckc\n11-12 d: dddddddddddd\n6-7 n: nznnnnnntnnnnzpjfjnn\n8-9 k: kbkkkkkkk\n13-18 x: xbxxmxqxxxmxkxsxxxx\n7-16 r: rrrrrrzrrrrrrrjmrrr\n3-5 h: hhqhd\n1-2 b: bbmb\n2-3 n: rlnntn\n2-8 q: qnfqnqhx\n2-5 b: bjbbh\n5-11 t: twtjnpttqtvtttptt\n16-17 w: wtmwwhxtgwrrswwfblll\n8-16 g: ggggghshggdggggcpwg\n1-3 l: lsllzl\n11-13 n: nnnvncnnmvnqnnnnn\n6-7 s: ssqssss\n10-18 t: tttnmjxttjttttttdzt\n4-10 n: nkvncgtdpz\n16-18 p: cphtrgffcpphfspxppgp\n2-6 k: kkhgkskkm\n6-20 r: fhrwtrzwrddfrndnrlgr\n2-8 w: lkwnccgw\n6-10 x: lxxxxxxgxwxxxrxqxx\n4-9 q: tqtpgqjzdmqfq\n9-12 k: kkkkkqbkkckkkjkql\n5-9 r: rrrrrrrhcr\n17-20 h: hhshshhhhhhhshhhbhhq\n7-9 s: dngddfsss\n12-13 q: qqqqqqqqqqqcq\n2-6 v: vqtvvvv\n8-10 c: cccfcncccccc\n14-15 m: mmmmmmmmmmmmmmdm\n7-14 s: ssslssfdssflvvsj\n2-5 z: wcllj\n2-11 n: cvnrlftcjct\n8-16 k: krzkfbkkqkhnsjkjgkk\n2-7 q: mvhvqnzdjw\n5-8 l: lgbnlnclkllll\n4-12 l: llllmllrlgllrklnlrbt\n7-10 j: jjjjjjnjjcjsj\n1-2 k: dgwmgsn\n2-5 z: zjmxc\n6-7 c: ccccccccc\n14-17 k: bkkkkkkkkkkkndkkkk\n2-4 x: xxjxtxbq\n7-9 w: drjcfwzwwwfwwfzxww\n4-5 p: pppwc\n4-5 r: rrrvm\n1-8 r: qrrrmrrrrr\n16-18 l: llllllllldllltlklk\n1-11 p: pwcpppbppppppp\n5-19 w: wwwwwwwwwwwwwwwcwww\n17-18 k: kkkkkwkkkkkkkkkkkxk\n12-15 f: fsffffffflfqgfx\n6-13 d: zddpdvddrvrdxq\n1-10 f: ffffffrfkb\n13-14 x: xxxxxxxxxxxxxxx\n16-20 j: jjjjjjjdwjjfjjjjjjdj\n8-11 r: rrrrrrrrrrrr\n15-16 x: dxjxxxdxxxxxxxxxwxx\n3-9 m: mjhqdgkmzmsmtdmhfn\n2-7 k: kkkhwgtxlkmkqkk\n11-15 m: mmgmmmmnsjmmlmmm\n1-2 v: wvvk\n8-14 s: zssssssssssssts\n3-4 z: ztbzzr\n4-10 x: xxkmqxxxxx\n3-5 p: pkppppppppzpp\n3-15 q: qpqmkqfqqlqqdfqtkqq\n16-17 d: ddddddzbxcdddcddq\n4-5 s: nqssf\n4-5 s: sssbks\n4-5 s: tsjlhsbsmt\n1-5 z: zzzbztzf\n1-4 l: pvsgtvt\n3-6 b: bbbjbb\n2-4 d: wkdvd\n16-18 w: wwwwwwwrwwwwwwwzwkw\n15-17 t: tqttjttttttttvtttt\n5-9 q: qcqqqqdtqq\n8-11 s: sssssssfssssssssssss\n5-6 x: xxxvcpbxr\n13-15 d: ddwdtctnjdcdpch\n5-6 z: zzzwzzzq\n3-7 v: bsphcnvwvtvphdp\n3-4 q: vhcprqqgdmlfpwqqw\n11-18 b: bfbbbfbbbbvhwbbbzlb\n12-15 c: cccccccccccccqfcc\n4-10 j: jjjjjjjjjjjw\n8-14 s: ssssssspmssssssssms\n6-15 b: jxnbdvxbbbcbrsbxrs\n10-12 s: ssssjsssssfs\n8-12 f: ffffdfkqflfpf\n8-9 w: wwwwwwwwz\n7-10 z: fzzlzzbtmthzzzz\n2-3 k: kqzzb\n11-12 s: ssssssssssls\n16-17 r: rrrrhrrrrrrrrrrnr\n3-11 b: czpbpbzswgcddm\n4-8 z: cnzztzgzqz\n18-19 m: mjmmmmmmmmmmmmmmmpk\n10-13 q: gqqqqqqsxqqqqdtqkq\n10-11 x: nxmbxxxrgpmxxxfnxxxz\n2-5 x: xbxzrxd\n9-14 l: llllpljlllfllwv\n1-2 m: mmmmmm\n1-3 b: fblbbfbbbbbtbbgbbb\n3-4 g: gnnccg\n8-9 f: fffffffkffff\n5-6 r: rrrrhf\n7-8 l: lwlwllllllctl\n5-7 j: jrjjwgjvkkncnjbqc\n3-4 b: bbsbb\n4-13 c: jmcczvkbxccdf\n4-5 g: wgrgg\n7-8 d: dgddddzh\n3-8 h: hhbhhhhhhhh\n15-16 l: llldllllllldlllllll\n11-15 r: rrgrrrrrrrnrrgxr\n10-11 l: lllllllllll\n4-5 x: xfdbjsmbbcxdphvlfkxr\n9-12 m: rqmnmrmhcmmms\n3-8 b: tzsnnndnbwgbskbb\n4-10 v: vvkvvdrvwvc\n9-11 j: jjjdjjjjjsj\n6-11 b: hbbmbbbbbbjbtrbbbz\n13-16 v: vvpvvvbvcvvvvvvvv\n11-14 j: jjjjjjljjjtjjmj\n7-11 v: cvdglnvjxkvvgptxvp\n1-6 t: ttjqtttzt\n7-10 f: ffwpzfxjfgffzf\n4-7 d: dddgddp\n4-19 n: mjbdzqxhtfbnbfxrpgnh\n6-13 d: ddddddddddddd\n2-4 t: rhkd\n5-9 c: ccrcxzjdzccx\n3-4 j: fwjj\n15-19 q: qqqtxqqqqqqqqqqqqqqq\n1-11 c: gcccccmccctcc\n3-5 d: dxhhdr\n8-12 k: pkvrkkkvkkmbkcxjwktk\n9-11 p: ppnpppppxppp\n11-12 p: dppcsppppppqppp\n7-8 b: bbbbbbmbqp\n7-8 c: cbccccccc\n8-9 b: bbbbbbbcrbb\n2-6 z: gzlnpzpkhjwwqtswcrz\n5-6 d: dddsdkd\n1-5 w: dxwkgwwwwwwmwwwww\n4-7 q: qqqnwqlqrqdcqpq\n6-9 m: lmmmdmmvmmmm\n7-8 h: hhhghhxh\n2-3 j: jjjj\n1-4 r: rrrw\n4-7 m: mmjmmrm\n4-5 j: vljjrj\n19-20 j: jjjjjtjjjjjjjjjjjjgx\n2-6 h: xhltfh\n5-11 s: ssssjsssssss\n3-4 b: bbbb\n1-5 g: chgmtgnn\n6-7 j: jjjjjjz\n3-8 c: cccccrccccc\n3-17 s: sslstssssssssspsgs\n17-18 x: bxxxxxxxqxxxxxxxkwxx\n9-10 q: qfqqzqqqsddqqqqqqq\n6-10 k: kmkkkxvqkrk\n5-9 f: kffffffffcdfffffplf\n5-6 r: rrrrrz\n2-5 d: hdgzt\n7-10 k: zkrllwkkkjrkqfkkk\n9-11 b: bbrkbbbbcbqqb\n8-12 g: gfgkgggggggggggggg\n12-14 s: sssjsspstlvlsrsssss\n4-8 g: pqgzcgvgflgntlp\n13-14 j: jjjjjjjjjjjjjx\n4-6 k: kkkmqpk\n3-5 j: sjjbjlvjjvjr\n2-9 c: ckccjxzcrcctbfn\n10-12 n: hvnnnnxnntnlnn\n11-15 m: mmrmmmdmmmlmmmjqm\n6-8 p: qpzrrpcpbxg\n5-8 w: xwdzcgclxwsvfwtwbxnw\n3-8 q: qzqzhlzc\n2-3 v: hvvvvltft\n5-12 s: tgvsswttkwfssnsqjsxk\n5-17 b: bbbbbbbbbbbrbcbbbhb\n3-6 p: ppjpzw\n3-5 k: kkxvkswk\n4-8 v: vbvrvxvgrvvwwvvm\n3-12 v: njvvgvdcjvvtvvcnvg\n4-5 n: bnnnrn\n8-9 l: jlvxdlpll\n12-14 w: fkwwwwwwcwwjwmwc\n1-4 q: wmqrzpqhj\n4-7 t: tctsttlt\n13-14 h: hhhhhhhhhhhhhf\n2-3 j: jmjjjjj\n5-6 v: vvvvlv\n5-13 v: fnxvvvvvnvqvvvvvws\n16-17 l: gllllllllllgwqlll\n1-2 s: pnpfsqw\n6-13 g: ntzqggvbnwxrgskg\n5-12 k: krxmbxqbkhxlnvdxdkkq\n14-18 d: ddddddddjdddbdddddd\n4-7 z: zzzzxzzs\n15-18 d: dddddddddbddddpddh\n8-11 x: slxxxxxjkxxxrsdx\n4-6 n: nnnfzzn\n1-4 h: gslcmnhhfhvz\n1-4 d: tddqds\n2-3 c: fccp\n2-5 k: mkqrknj\n9-16 g: gpggdggwgwgwglggg\n2-5 h: hhjds\n4-5 b: zbnvld\n6-14 m: mfqmnmqtdmmzmm\n7-8 j: thvcsgjn\n1-5 x: xwjdxdqjtc\n4-17 r: fqbrqrnpslndrmjdhpjp\n4-5 c: ccccw\n5-6 v: vvvvdm\n5-12 n: nnqzjntfnnnd\n3-4 c: nccqlccq\n1-10 p: nrvvzpppqpn\n9-16 v: jvvrpvvvvvzvhhvvgz\n12-13 s: sjsslsssfxxkrssstkss\n1-3 t: vtwbh\n5-16 q: sxxfrqhqtvzbzqwg\n5-9 z: dnzlhzzzsdzz\n15-16 d: pdddddjddpkdddtdddd\n3-4 p: pplqppp\n7-9 s: scsslshsqssw\n2-3 v: vxvxv\n8-9 w: wqwwwwwgshww\n8-9 k: kkkkkkkkc\n9-10 v: vhfvvnvvtvvb\n1-12 z: zzzbzzzzzzzdzzzz\n6-7 b: bbbbbwhb\n12-13 z: zzzsvtlzzzzzz\n1-3 s: pssssssxw\n8-9 w: xwwwwwwdzw\n1-4 x: xxkxxx\n10-12 f: fffffffpffvffff\n18-19 w: wwspwwzwwqcrwwhwwww\n6-8 s: ssssstsks\n5-6 j: jjcjgm\n2-5 p: wprwpxbdkrfpmppqpd\n8-18 n: nnnnnnnnnnnnnnnnnn\n4-11 c: txncpqclrlc\n2-10 f: ffcffftfffxrxf\n1-4 t: ttttttt\n4-9 f: zdpjffffbfbl\n6-7 f: kfsffffffm\n1-4 b: bbdn\n6-12 k: kkhkkkkdqkbkjkkkl\n3-4 n: kmnn\n4-11 l: kllcllldllclll\n7-19 w: pfwdwdnkblwzgkfnfmh\n3-9 z: zzphzdnhqwlzzwzz\n15-16 h: hhhhhhhnhhhhhhhd\n1-4 l: vllll\n2-13 l: hdhvgdrlltlmjptzq\n1-3 p: njvpltppbkxpfpppp\n1-2 j: kkjv\n10-11 c: ccccccmcccjcc\n5-8 v: tqvmvtwvzfczvvvvw\n6-9 x: xxmxxxfxxxxx\n1-10 z: zgzzztmdtkzzpxztbgpp\n10-12 g: ggwzjgdsgbnggl\n5-6 j: jvxjvjj\n4-7 x: xnxxmgxxtjxxkj\n13-14 d: ddddmddddddddd\n12-15 c: cccccccccccnccc\n16-17 n: nnnnnnnntnnnnngnmn\n1-12 m: bzckgvmmbdcxtgtmb\n4-7 l: ljllllljl\n5-11 w: wzvzwwrkmtwh\n11-13 l: lmtpwxlllhlgllwvqnp\n6-10 f: fvgkffqvcfffdbfff\n3-5 j: kbfjjj\n1-2 h: hhztdpbttnc\n8-10 b: bbbbjbbqkbbbd\n1-13 c: hccvcxtcclpckzd\n6-10 w: wwwwwtwwzrwwf\n2-3 j: fjnnj\n2-4 j: njtjjjxrjv\n4-5 w: fwwzw\n7-9 k: qbnkghdbqlz\n2-9 s: dsdftlzsszlf\n4-5 v: vvvvd\n1-2 w: fbfwwb\n4-7 t: tttttmt\n3-10 h: hhhhnhhhskhh\n3-8 w: qwswwswfl\n1-3 p: pmpgpp\n2-7 n: nmmgnssmtn\n2-3 j: djvjgjp\n6-13 x: jxxbxxgnxvbxx\n6-10 v: vrvvvvvvdz\n2-3 b: bbbbjrkwnc\n1-2 h: fshnf\n1-5 n: htsknrzqnntknfnjx\n5-9 d: kkgtwrdjmxkzc\n12-13 x: xxxxxxxxxxxxx\n2-10 m: wmmmmmdpmmmmh\n2-12 n: xttqcmfkvnlkzskjhmzn\n6-9 m: mmmmmxmkp\n10-16 m: gmmdqmjmflmmmmmcmmm\n13-14 p: pprprppppspxfgnptppp\n1-16 b: gcnbbnbbmsjxnbppcb\n10-11 d: dkdddddfjmpvdddd\n1-9 f: zlfwstnzp\n14-15 n: nnnnnndnnnnnrnnvcndn\n2-6 l: lvvldlzdzgdf\n6-10 z: zzzzztzzzhzz\n13-14 n: nnnnnnnnnnnngln\n8-9 z: zjqztzztqzzbxzz\n2-3 v: dwcv\n4-6 m: kmmmkmm\n5-9 g: wtgfgdmxkx\n3-5 b: vbzbf\n10-11 w: wwwwwwwvwwz\n2-8 s: sztstsnssq\n2-6 l: lldzcslxdwghmn\n1-2 n: vmznndnnnbrhknjwzkzx\n3-4 k: kknp\n1-5 h: hhhhhhh\n12-13 z: zzzzzlszzzzzxz\n1-12 m: mtbspfpdgpznrsmvgq\n11-13 q: qqqqkqnqhqrqrq\n14-18 d: dtdrdddddddddxfddddd\n1-6 q: bqqqqqgqqqq\n1-7 c: dlmvcsztzpx\n4-6 g: gmgggg\n5-6 s: ssswsssgdghv\n8-9 k: kkkkkkkgn\n1-17 s: ssssssssssksssssss\n4-5 b: qqtlsh\n5-6 g: gggggg\n2-11 r: drkpvrrlrtrvrjhpd\n3-7 k: fkkhmddh\n6-7 h: hhhwhnfph\n3-4 p: ptppmwpnps\n3-6 w: hwcshlrm\n7-8 d: dtddqddzn\n1-6 s: sslsbssbsg\n12-15 n: tbnnjknnkwnnnnsnnnz\n8-9 z: zzzzzzzzz\n2-5 w: kjnwn\n4-7 m: mmmtdjmmmmtl\n4-7 h: dqfhzrqhfhntzhkhhdvb\n3-5 g: zvflgg\n5-12 s: lvsvqnvssgcx\n11-19 p: pcppvppplpwppppjlps\n5-19 p: gkpmfxlmppczdnhbqcw\n5-17 b: mdzljsdvxdmbbbbddvrw\n1-5 s: shpdss\n2-5 t: btggtltvw\n1-6 b: sbbbbbb\n3-6 w: wwpsfkwnrrr\n13-18 f: ffffwfffsfffwffffn\n4-5 m: mpmmmxmmggvnb\n5-6 z: pwsqhcztlf\n8-11 d: ddddddddddlf\n1-2 t: xttt\n6-8 m: mmmpmvmmm\n16-17 h: hhhhhhhhhhhhhhhrw\n1-5 g: gpgpgg\n3-7 p: gplrpzp\n11-18 t: ftqnxttzttxtgttntrtt\n10-11 z: zzzzzzdzzlgzzz\n3-10 z: lzfzzzzszbzzztj\n2-10 l: khdbddnxltnk\n4-8 b: tbbcjsnbrbhfb\n3-6 x: xgsxmn\n9-13 t: ttttttttmtttt\n7-11 l: fllllllzllmdshrll\n18-19 g: hffqfwssgqpcnmddkcw\n3-4 m: mmhvmc\n1-3 w: vwnw\n5-6 r: rrrrrb\n2-4 j: rjqj\n5-7 b: kgblcbbdrb\n3-5 g: jgggggg\n1-11 v: vvrvvhxvrvvnrvvv\n3-14 w: ncwphcwvjwhdpwqkg\n6-7 x: xxxfqmkvxx\n13-14 v: vvvvvvvvvvvvkt\n2-12 x: xzcvvxhhwwxxc\n6-14 m: mdtnmjmhmnmmmmm\n15-16 z: zzzzzzzzzznzzzzzzz\n4-6 s: mcssdssjshscvcl\n11-12 b: bnbbbmbjsbxbbbbbj\n7-13 c: cccfhccczccwcccsc\n3-4 m: cgtmmm\n5-10 l: hxhbggrllmtgn\n6-8 d: sdfdddlv\n4-9 x: xxxxxvxxcx\n11-12 c: rcmqkzjccccrdccmc\n1-3 g: jgng\n4-5 l: lvlll\n9-16 n: rnnnqjnvqnnnlnnwdnnn\n4-10 x: crdxgxrfjhr\n1-5 f: tgdffffffqf\n15-16 q: qqqqqqqqvqbfqknqqqqq\n9-11 s: sssnffssksq\n3-4 v: vqvvv\n5-19 z: jthjzpgmwjbftzvmnpzk\n3-10 w: mpxhrrnqdvncwssqwlxz\n14-15 b: bzbbbbbsbbbbbbbbbbb\n3-5 j: jpjvjjrjtmjj\n3-6 w: wwmwwzw\n1-6 c: ccccvzcccm\n10-11 m: mmvwgmjmmmrqjmmmglm\n2-3 f: fffw\n6-12 m: bmbzmmrshmmz\n5-6 n: nnnnnn\n4-5 k: kmsgkwvkk\n6-8 t: tttttbttt\n4-5 j: vtmvsqjl\n5-6 q: qshzdqqk\n1-3 w: dwgw\n8-9 q: qbqqqqqwq\n5-10 m: lmmmkgmmwb\n6-9 n: nnnlnnnnn\n4-5 t: tntct\n6-8 g: hgngghgw\n6-9 t: gttwtgvpgtlt\n6-7 l: lllllll\n4-5 j: jhjkjjm\n13-15 h: hhhhhhhhhhhhxnh\n1-4 m: mmmmm\n4-6 q: cqrtqsdqqzrknf\n9-13 f: fffffffffzfvff\n2-16 p: prxdxjpkppgpxsjwpppp\n3-4 r: rrzh\n1-2 g: cglblsnkg\n1-3 f: xqnfwjmmwqffd\n13-14 q: qqqqqqqqqqqqvjqq\n18-19 g: dggggggggggggggggvgg\n5-6 s: dsssssss\n4-6 z: szdzzb\n9-12 t: xtltpgftttmtt\n10-16 m: mqmmmmmmmcmmmmqx\n3-7 c: cpccngcvccm\n2-16 s: jsdfsjsjtswhkvmsskj\n2-3 c: kccc\n4-16 k: qhndnqmrvjcczfkpds\n4-6 n: nnnrkxl\n9-10 s: ssssssssds\n2-3 z: hfzcz\n2-3 s: sssz\n8-10 b: qbbbjbbbbw\n7-16 k: gcvskkjkkkkwkzkz\n7-9 n: nnnnnnhnnnn\n1-10 q: qjxqmqxcgg\n9-11 l: jdhjbbcnlzll\n7-14 l: llrlxlllllltlnl\n3-6 f: wfdqfbrf\n3-8 t: ttzttmtvttzpl\n10-12 v: vfvvvvvvvsvv\n5-6 v: vvvvvm\n11-13 t: ttttxtttttptttctttt\n3-4 k: kkdm\n4-6 n: nnnlnt\n13-15 m: mmmmmbmmmbmmmmmm\n5-6 l: klllnl\n2-3 f: flzff\n3-4 r: frrs\n1-5 d: cqwkvsdqdvb\n9-15 l: jvtfqczlnlwdpclxwp\n12-14 t: ttttttlqtpttnt\n11-12 m: mmmmmmmmmmmm\n4-5 j: jjjkbjjjjj\n9-12 w: wwwwwwwwkwxkwcb\n6-12 q: tcqrqqqqxjqqqqmqhq\n5-6 m: mmmsmmmm\n2-5 t: mttbttprttddtv\n10-13 t: tttttttttttztt\n10-11 f: kmqfxttfkfd\n5-7 v: vrlzpvjtvv\n6-7 l: nlllllj\n1-5 q: szdbqqkqqtkmssq\n3-4 q: kcmlwqzczwms\n13-16 b: bsbbbbbbbbrbsbbpzbb\n9-11 d: dddsdbddkdkdd\n2-15 j: xkjnntffvvxfnntcv\n4-6 v: hvvvcvqvrwv\n9-12 j: qjjjjdjgqhrjjfjrdj\n8-10 v: vvvvvvvnvnvv\n4-9 t: ttttthttt\n8-16 g: ggggklggcggggxgg\n1-3 z: wpqz\n4-5 g: wgdnmxccgj\n8-11 r: rrrrrrrxrrmd\n1-9 f: ffffsfgdbsqfffzf\n7-8 q: qzqqqqrrq\n12-13 n: nnnnnnnnnnnnnn\n8-12 j: jpjjjmjjjjjzj\n1-4 j: nvjw\n7-13 z: zzzzsnzxzznzrzgzzzz\n14-16 z: zzzzzzzzzzzzzzzm\n1-4 x: xxxxnxh\n8-15 k: gnrkktkpcmklkksnkk\n2-4 h: klph\n11-16 c: ccckzdccgckpcccsc\n15-16 l: dlllllllllllllll\n2-3 s: dsxss\n1-4 v: jvvv\n2-8 t: ktkdtxkt\n1-3 t: ftftttttt\n4-5 k: kkkbkk\n4-6 g: llqcggg\n4-14 r: fmdvrrwlstlbjr\n2-16 p: rpdfhpbqfwxlxhhc\n6-8 j: jjjjjjjjj\n1-7 f: fnnffblbqffkrff\n1-3 k: rfqwlnnkzdq\n15-16 s: ssssswssssssskssss\n11-13 z: zzzzngfzzzzzz\n5-7 h: hhbhhcnhfghhhv\n2-7 j: zjrmjgmjdkp\n5-8 z: bzzzpzzrzzzz\n12-16 j: jtjnjjjjgjjjjjjsj\n5-9 s: ssssssssms\n2-3 s: ssss\n13-14 d: ddddddddddddkt\n12-13 r: wfdtrknrhvrrc\n6-8 p: vpxphxngzhnkppppfp\n2-3 j: jtjx\n3-6 k: tkkvjkb\n2-6 t: tvftftvbfx\n5-7 z: zzzqzzz\n14-15 h: whdhxhhhhhhhfxzhhh\n3-4 g: ngjgg\n9-10 z: zzzzztzztq\n2-7 f: fffffqfszchff\n4-6 f: lfqjnzccffjslsdf\n5-6 z: lpzzzzsz\n11-13 t: tttttwtttttttttttt\n2-6 z: zzzzzz\n9-10 m: mmmmmmmmjm\n5-6 w: xwggfcwvwlx\n1-4 j: jjjjjljjjjjjj\n8-10 t: ttttttwttt\n5-12 x: zxxxxxxpxxxn\n3-4 v: vvlrv\n3-6 h: hhhwhlxhlrhl\n2-5 p: cptsjktp\n4-11 j: bmjjjjjjnwwdk\n15-17 p: ppppppppppfpppvpp\n7-11 m: wnnmmwmtmmxmm\n9-19 k: kkkkkjkkhwkcvkkkmknw\n11-15 s: sspssbshssscssssss\n1-8 s: sssssmssssssssssss\n4-8 x: xxxxdxxx\n9-10 n: nnnrnlnnnnnnnnnnnnnn\n10-11 d: ddddddddddn\n5-9 z: tzzzqzbmzzzqzjkzlr\n9-20 f: fffffnfffffffsfnffff\n5-6 g: gvggggg\n13-14 x: xxxxxxxxxxxxxxx\n6-7 v: vvvzvvvv\n5-10 l: kbcvlfvlszndtlldjlh\n4-9 s: vkcsdvszthkwmmmxs\n3-4 b: jbmb\n2-4 w: nmwm\n5-10 z: tztzzfzgdzzszq\n2-8 k: kzkkkkzwf\n16-17 d: vxvzdgzwssqdcgbdb\n4-5 b: bbbbb\n7-9 w: wwfwwwjwln\n5-12 k: ljkkkqfvqtkkxsd\n5-7 q: qqqqhqqq\n8-9 n: vnnnnnnpstnn\n5-10 m: mmgzmmmmmm\n3-14 q: qgbvqjxqnqqqqqqq\n2-4 c: cccc\n3-7 b: szbbkbdbmbbzbqs\n1-5 m: mhmmc\n3-6 n: nnlvnnvnq\n2-3 c: mccc\n11-12 m: ddmmmmxmmmmwfmmm\n8-10 n: nnnnnrnnnn\n1-12 g: sgbggglnggddgggsngrx\n7-9 p: phppppppp\n4-5 q: qxqqqq\n3-7 v: vwsvvrvxvvvvvvwvvdlv\n8-18 j: jmjcjjltjmjwjzrllgcj\n2-14 r: rdrrrrrrrrrrrp\n2-4 r: cxcbkmr\n6-9 r: vtlnnvbcndqhrxkkjp\n2-3 s: hxssnsswzc\n10-16 r: csrsrxrrrrrrfrfdrr\n7-9 w: wwbwmvrwdxww\n12-14 p: pppbpppppppgpt\n2-7 n: nnnnnnnn\n3-12 f: mhjxfxgbbvffpclfffg\n10-14 l: lllskllljllllll\n11-16 l: lwlklllglzllllllll\n13-14 h: hhhhhhhhhhhhhdhhhh\n1-2 t: tttb\n1-6 z: zzzrrzzbf\n1-6 v: jrvzvvrs\n3-6 g: jggbnl\n17-18 x: xxxxxxxxxxxxxxxxrx\n8-17 f: xnmffffbwfdcfrdfw\n3-9 k: jmkdvkdnk\n7-9 m: mmmmmmdml\n9-11 c: cdmshccckqmcccccckp\n16-17 g: gggggngggggggggggdg\n7-8 n: nnknnnnnnn\n3-13 n: fjhgrspsnkmnf\n14-17 z: zzzzzzzzzzzzzqzzzzzt\n13-14 r: rrrtrrfsvrzngw\n7-8 k: kvkvkpvc\n1-2 b: bbpbb\n1-7 n: tchnrtbtldnmnnvvnn\n3-4 s: sssssjv\n1-9 l: cllllztmlllrzfl\n9-10 x: qjxxxxxxdhxxxxxh\n6-7 p: ppppfppv\n3-8 q: mkqzqqbqzjrqbq\n6-8 x: xxxxxxxx\n1-7 f: ffffffff\n5-16 b: jbbbbbqcbbbbbbfb\n9-11 c: ccccccccccq\n1-2 x: fqkx\n4-12 z: znzzzzzzzzzzzzz\n3-4 l: lglll\n9-11 m: mmmmmmmmmms\n14-17 x: xrxpxgkxxzdrxxxxckxv\n3-5 t: gxjbbfcpmkbkxbtwbt\n5-6 j: jmjjjj\n14-15 g: ggggggggggggggx\n6-7 l: lllllbl\n2-14 q: qqtsqkqvqqqpxzqqcqq\n2-4 w: fwhw\n4-5 m: mzmtkm\n2-4 g: ghghgp\n5-6 r: rrrrnl\n1-4 h: chghhw\n7-12 r: rrrzglvrrrrsrr\n1-7 x: xxcxdwxjmx\n5-12 r: rrgrrffwtrrnrrqrrjnr\n2-5 r: srdqrlxrkrrdkr\n3-4 t: ttdg\n11-12 s: bfjrkqqgdtlwrskmfrp\n3-5 n: nnrnfzsnm\n10-15 z: zzzzhzzqqczxwzqztv\n2-7 f: ffgdfgff\n7-10 d: ddtbdddddjtdqfdddfq\n2-9 k: gkrkkkkkkkkhkqkx\n13-14 n: nngnlnnnhnnnnnnnn\n6-9 r: qrxrxzrff\n7-9 m: mmmmmtmqqmml\n11-12 p: pppppppppppp\n10-13 j: jjjjjjjjjznvbjj\n1-2 c: ccvc\n7-8 m: mmmmtdmckkpmcbkjmm\n5-8 j: sjptjjbjjjjj\n6-8 d: jchdwrhd\n5-6 z: lqzzzzkrzzvzwbbzktp\n6-8 l: ztbltlll\n2-3 z: zkrxzp\n7-18 g: phgpgggqgzgnmwlpkwd\n8-9 f: hffffffqf\n17-19 p: pppppphpppppppppzpp\n2-3 z: zzzfg\n1-2 v: bfvj\n4-8 b: bcbbbbbb\n15-16 s: ppsnsssssssnssss\n2-3 m: mnsm\n2-4 h: hwfshh\n9-15 h: hhwhhhhxhhhhhhh\n17-18 n: nnnnnnnnnnnnnnnnnn\n7-11 n: nnnnnqpnlbgqnqnshn\n15-16 j: cdjmbcwdppvvjqvv\n6-11 p: ppplppppxpt\n4-5 r: rrrrrr\n10-11 w: wwwwwwwwwww\n3-7 p: pzppzspppmkxbldwpnwf\n2-12 w: zwdljlzwgxfwvtdm\n2-10 f: mzfjqfspgfrfhst\n14-15 m: mzmmmvhwmdmmdpz\n1-12 r: vrxrrtrxgvrd\n4-5 n: nnnnnnpn\n6-12 x: xkbwfsxxxxxkxxxxk\n4-6 n: mncnxn\n9-10 f: ffffpfqftbf\n3-5 b: bzwbk\n4-7 c: ncdcccc\n11-12 t: dgdkrjgsgtlf\n8-11 z: rqzdjqznrpkzmblbt\n1-3 z: zfzx\n2-4 z: kzgzkp\n6-10 v: jvvvvvvvvs\n2-9 v: vrvvvvvvvc\n5-6 q: qqqqqqc\n6-10 p: ppdknlgpqkp\n10-13 z: zzzzzzzzzzzzvz\n19-20 g: dtckblrmggknmxwnrjgg\n4-18 p: ppcjpqfpcxtphlppmhcx\n6-7 n: nnsnnknthn\n10-11 f: fffffffffff\n2-4 f: ffccltsfgk\n6-11 d: dsqddtddddjcnssrcd\n7-13 x: xxxxxqlxxxxfw\n12-13 r: rrrdrrrrrmrrrr\n15-17 p: pqppppppppppvppppppp\n7-8 j: jjjjjrdp\n4-6 v: vvvvvt\n1-4 t: tltftjtjhz\n9-15 j: jjjjjjhjjjjjjjkjj\n6-7 c: ccccccccz\n8-9 x: xxjxxxxxsx\n4-5 h: hhrhh\n2-3 g: cgnm\n8-10 l: llqlgllzlvrllg\n12-13 c: cvnbccpzzxcccfh\n3-8 z: zbzrwzzzwrzbqnr\n6-7 n: nnnnnnn\n8-11 j: tjqjrjggjxxjggjj\n7-12 l: bsvxdhljlcsj\n3-6 j: jjfjjjjb\n2-3 z: dzztwhmzqdx\n9-12 v: vvvvvvmvzvvcv\n13-14 v: vvvzvvvvvvvvvk\n6-7 g: fgggghgng\n13-14 h: wcghlwdbjhpdphkcv\n1-2 t: nncsg\n6-7 w: kwjwwxlwz\n4-5 z: zzztvz\n3-4 n: nvbvngnw\n15-17 z: zzzzzzzzzzzzzzzzzzp\n8-10 r: rrrstrgxrhrr\n8-10 g: cggggggvgcg\n1-4 m: mmvbz\n3-14 j: bdbhbjnjnrldhwlbrkrj\n1-4 r: rrkrnnd\n2-3 f: fvwc\n4-13 c: ccccvcgwbhwrcqf\n3-9 c: jcghltcfkjchxmccccbs\n3-5 h: hhhshm\n5-9 h: hhhsjhhhhgthfgldw\n4-12 h: mcwvwwphwwbc\n6-11 g: gqgggvggggh\n9-15 x: xxxxxxxxxxxxxxsx\n16-18 t: rmqqtbtvttsdtjvbttl\n9-20 f: cllnvlfkfrwzpqxwqgnn\n9-18 v: vvvvvvvvzvvvvvvzvxvv\n4-5 f: fzffbfvfff\n1-5 p: pppppp\n1-7 z: zjvchwzqjrtxzgz\n4-9 v: vvvvvvvvvv\n5-8 w: cwwwzwwb\n7-8 r: rrrrxrrr\n8-9 f: sgdcqfhfcfsflb\n3-7 g: gdgtnfggq\n"
  },
  {
    "path": "advent-of-code/2020/inputs/20",
    "content": "Tile 2011:\n.##...#..#\n.#.#.#...#\n.......###\n.....##.#.\n#...#.....\n##...#...#\n#.#.#....#\n##..##....\n.....#.#..\n##.#......\n\nTile 3407:\n#..#..#.#.\n#..##....#\n..#.......\n......#...\n......##.#\n..#.#..#..\n.#.#....##\n##...#...#\n#.#.##....\n#.##..#...\n\nTile 3733:\n##..###.#.\n##.#.#..#.\n.....###..\n......#...\n.##...##..\n..##......\n#.#.#.#..#\n.#..##...#\n....######\n.#...#.#.#\n\nTile 2267:\n..##.#..##\n..#....#..\n#..#...#..\n.....##..#\n##..##.###\n#.#.....##\n#.#...##..\n#.......##\n..#.....##\n###.###.##\n\nTile 3853:\n.####..#.#\n.........#\n......#..#\n..#...#...\n...#.....#\n..........\n....####.#\n#........#\n#....###..\n.#..##...#\n\nTile 1531:\n#.#..#....\n.#..#.##..\n.....#..#.\n#....##...\n#.#...#...\n.#...###..\n##.....#..\n..##..#.#.\n##....##..\n###..###.#\n\nTile 3907:\n#..##.##.#\n##.##.##..\n........#.\n......##.#\n#.##..#..#\n#....#..#.\n.##.##....\n#.#.##....\n.#..#.....\n#.###...##\n\nTile 3329:\n#.##..####\n##....#..#\n...#..#.#.\n#..#..#..#\n###..#...#\n##.#.##..#\n.#.##.....\n##.#..####\n.....#.#.#\n#..#..#.##\n\nTile 3449:\n...#.#..##\n......#.##\n#......##.\n..##..#..#\n...##.....\n##.....##.\n##..#.....\n#...##...#\n#.##...#.#\n..#.#...##\n\nTile 1187:\n#.#.......\n...#.##.##\n#.#.##...#\n##..#....#\n#..#..#..#\n#.#.##...#\n.....####.\n..#...#...\n.....#....\n#.##...##.\n\nTile 1543:\n.##.####.#\n.##..#..#.\n#..#.....#\n###..#.#.#\n.#.##.#.##\n#...##.#..\n#..#.#####\n#...#.#..#\n#..##...#.\n..#..##..#\n\nTile 3631:\n#..###...#\n.#.##....#\n#......###\n#......#..\n#.#......#\n##..##...#\n###.#..##.\n...#..#..#\n...#......\n####.##..#\n\nTile 3917:\n##.#######\n.....##..#\n..#..#...#\n#......#..\n##.#..###.\n#....#.#..\n.......##.\n#....#..#.\n.##....#..\n#########.\n\nTile 1373:\n####....#.\n#......##.\n.....#....\n.##......#\n#........#\n#..##..#..\n##..#.....\n#......#..\n.#..#.#..#\n##...####.\n\nTile 2663:\n..#.##....\n.#..##..#.\n.......#.#\n##..#..#.#\n..##.##.#.\n....#.#..#\n##.#.....#\n#..#....##\n###.#..###\n...#.#....\n\nTile 3529:\n...#.####.\n.#.##....#\n...#.##.##\n#..#...#.#\n#.#..#.#..\n........#.\n##........\n....##...#\n#..#....##\n.###....##\n\nTile 2297:\n...##....#\n#...##...#\n#......#..\n##.......#\n.#...#..##\n.#....#.#.\n#....##..#\n#....###.#\n##.......#\n###..#..#.\n\nTile 2789:\n..#.##.##.\n#.#..#....\n#......#.#\n#......#.#\n..#..#....\n#...#.....\n...#....#.\n#......#.#\n.....#...#\n...#....#.\n\nTile 3461:\n..###.####\n##....####\n#.###.#...\n##......##\n#.#......#\n##......##\n#..#...#..\n.........#\n......#.#.\n#.#..#.###\n\nTile 2939:\n##.####...\n.......#.#\n###.##..#.\n.####....#\n#.#....###\n#.....#..#\n##.....#..\n..#....##.\n#.#.......\n.......#..\n\nTile 2903:\n##.#.#.#.#\n##.##..#..\n.........#\n#......##.\n....#..###\n###.#.#...\n...#.....#\n#.....#..#\n##..#.....\n....#.#.#.\n\nTile 1993:\n.##..#####\n....#....#\n.#..#...##\n...#......\n...#..#...\n#...#.##.#\n#....#...#\n#..#....#.\n..#..#..#.\n.###.#####\n\nTile 1669:\n.##.##...#\n###.###..#\n###...##.#\n##.#...###\n#.#.#.####\n.##....###\n.####.#.#.\n#.#.##...#\n#.#..###..\n....#.##.#\n\nTile 3823:\n##.......#\n###...##..\n##.....##.\n...##.##.#\n..#......#\n.##...#.##\n.##.#..#..\n###.#.....\n......#...\n.##.#....#\n\nTile 3929:\n#....###.#\n..........\n.........#\n#.###....#\n...#.##...\n.#.#.###..\n#...##....\n#..#.#..##\n#......###\n..####.#..\n\nTile 2521:\n....##..#.\n...###.#.#\n.#....###.\n#.#...#.#.\n##....#...\n#....##...\n#...##.#.#\n....##....\n#.....####\n#.#.##....\n\nTile 3361:\n....##..#.\n#.##.#...#\n..##..#.##\n#..#.#....\n...##...#.\n..#...###.\n.#####...#\n#.#####...\n#.#..#..##\n#.#####.##\n\nTile 1259:\n..##....##\n..#...#...\n#.#.#..#.#\n#........#\n.##......#\n##..##...#\n###..###..\n##....#..#\n..###.#.#.\n....#....#\n\nTile 2729:\n.##..####.\n#.##.#....\n.....#.#.#\n..#......#\n#.#....#.#\n..#..#..#.\n##...####.\n#...##....\n.#.......#\n..#..##.##\n\nTile 3511:\n#...##.###\n#...#.##.#\n......##.#\n#.........\n#.##..#.#.\n....#....#\n...#.##...\n##.##.###.\n..#......#\n#...##.#.#\n\nTile 3119:\n.....##.##\n#.....####\n..#..#.#..\n.#..##.#.#\n.##.....#.\n...#...#.#\n..#.#.#..#\n#.........\n#.......#.\n########.#\n\nTile 1427:\n###..#.#..\n#.#.....#.\n.####...##\n.#..#.....\n..#.......\n.#...#.#..\n..#..##...\n..##......\n###..#.#..\n...##.....\n\nTile 3307:\n...#...#..\n.###....#.\n..#.#..#..\n#......#.#\n##.####...\n#.##.#.##.\n.##..###.#\n...#......\n....#.#.##\n.#.####.##\n\nTile 2081:\n.....####.\n...#....##\n#.#..#..##\n#...#...#.\n.#..##.###\n...#.##.#.\n#.......#.\n##...#....\n....#..#..\n#.#...#.#.\n\nTile 1741:\n##.##....#\n#..##.##.#\n.#..#..##.\n.#.#..##.#\n.###......\n#.####....\n..#..#.##.\n####.#....\n##....#...\n#.#..#.#..\n\nTile 1481:\n#.#...#...\n#.#.##.###\n#.......#.\n#.#.#.....\n.####...##\n####....#.\n#.#..#....\n...#.#...#\n........#.\n#....####.\n\nTile 3719:\n.###..#...\n..#..##...\n#..#...#.#\n.##.#.#.##\n..####.#..\n#...###.##\n.#..###...\n...#.....#\n#..#..#.##\n.##.#.#.##\n\nTile 2797:\n..##.#.#..\n....#....#\n..###...##\n..........\n.......#.#\n.........#\n#.#.......\n####.####.\n#.#..##.#.\n.#.#...#.#\n\nTile 1319:\n..####.###\n.#.##.#.#.\n##.##.#.##\n#.##..##..\n#..##..##.\n.##.#..#..\n#.#..#...#\n..#.#...##\n#..#..###.\n#.###..###\n\nTile 2053:\n.##....###\n##..#.....\n#.#...#.#.\n.........#\n.#.#..##..\n..#..##.##\n#.##.#.#..\n......#..#\n#.#.###..#\n#...###.##\n\nTile 1867:\n.#.###..#.\n#...#..#..\n#.....##..\n#....#..#.\n#.......##\n#...#....#\n.#..####.#\n###......#\n.##.##.##.\n.##.##....\n\nTile 2131:\n##.##..#.#\n##..####.#\n...####...\n#....##..#\n..##....##\n##....#...\n..#..##..#\n.###..##..\n..#..#...#\n....#..###\n\nTile 1777:\n###..##...\n#.#.#...##\n#..##....#\n.........#\n#..#..#..#\n#...#.#..#\n#..#......\n.#..#.#..#\n##....#..#\n....##.#.#\n\nTile 3037:\n##..#..#..\n##......#.\n...###...#\n.####....#\n#..#......\n#...#.#...\n..#####.#.\n#..##.....\n......#...\n..##.#.###\n\nTile 2749:\n..###.##..\n####.....#\n#..####.#.\n#...#....#\n#.........\n#.......##\n.####..##.\n..##..###.\n#.##....#.\n#.#...#...\n\nTile 3919:\n#.#....##.\n.#....#.##\n......##..\n.#....##..\n#.......#.\n#..#...#..\n#.#..###..\n##...##..#\n..#..##.#.\n.####.#...\n\nTile 1231:\n.#.#.#####\n........#.\n##...#..##\n....#....#\n.......#.#\n.#.......#\n...#..#.#.\n.........#\n...##.#.#.\n####.#.###\n\nTile 2441:\n##.......#\n##.....##.\n.#......##\n#.###...##\n#.......#.\n....#...#.\n#.#...##..\n##.....#..\n.#.#.#.###\n#########.\n\nTile 3659:\n....#.#...\n##.#####.#\n...#....##\n.#.##..#.#\n#.##.....#\n#.#...#...\n#.....#...\n......#...\n#.......#.\n###...####\n\nTile 2411:\n.##...#.#.\n#..#.##..#\n#....##...\n#...#.....\n#......#.#\n#........#\n.#.##.....\n#...#..#..\n...#.##.#.\n##.#...#.#\n\nTile 1999:\n...###....\n.##.......\n.#...##.#.\n..#......#\n#.......##\n###...####\n.#......##\n.###....##\n..##..##..\n##..#.#.##\n\nTile 3623:\n###....#..\n....##.#..\n..#...#...\n.#......##\n#..#..#...\n#.#####...\n....##...#\n.#..#.....\n#..#.#.#.#\n#....#...#\n\nTile 2851:\n#.##.##.##\n##..###...\n...#.##.#.\n.....#....\n##....#..#\n#.##....##\n##.#.####.\n#..#..#...\n...##....#\n...##..#.#\n\nTile 3673:\n.#####.#..\n#.....#.##\n.#........\n..#..#....\n.##..#....\n#.........\n#.##..##..\n......#..#\n#.......#.\n###..##..#\n\nTile 2399:\n##..#....#\n#.######..\n.#.#.#####\n##.#..#...\n.#....#..#\n###..###.#\n#..#..#.##\n#..##....#\n.##....#..\n#.#....##.\n\nTile 3727:\n#..##.#...\n###....#.#\n.##..##.##\n.#...#..#.\n..#.....#.\n.#.#.....#\n####.....#\n..#..#....\n..##..#..#\n###.###..#\n\nTile 2311:\n#..#...#..\n..#.....##\n....#.#..#\n..#....##.\n.....#.#.#\n#........#\n..#...##.#\n#.#.#...##\n##.#.#..#.\n..#...#...\n\nTile 1009:\n.#.###.##.\n....#...#.\n#....#....\n#.##...##.\n#....#.#.#\n#.###.....\n.##..#.##.\n.#..#.##.#\n##..#....#\n.###.##.##\n\nTile 3313:\n##.#..####\n.#...#..##\n..#....#..\n...#...#.#\n######....\n...#......\n..........\n.#...#.##.\n...#.#....\n###.#.#.##\n\nTile 1733:\n.#.#.###..\n.##...##.#\n###..#.#.#\n#.#...##..\n#.....##.#\n##........\n##.##.#..#\n.#....#.#.\n####.#.##.\n####....#.\n\nTile 3947:\n.####...##\n.....#....\n#.#.......\n.....#...#\n..#....#..\n#...#..#..\n...#......\n##.#....#.\n..##..#...\n..#.#.#.##\n\nTile 1583:\n#..###....\n....#.#..#\n...##.#..#\n.##....##.\n.......###\n#.......##\n...#.##..#\n##.....#.#\n###..#..#.\n#...##....\n\nTile 3911:\n.###...###\n.#.......#\n###.#....#\n.###......\n..#.#.#...\n....#.#...\n#..#...#..\n#...#..#.#\n.#.#..#..#\n.#.#....#.\n\nTile 2833:\n.#####...#\n..##....##\n#####.....\n.#..##..##\n#.#..#.#..\n#..###.#..\n#.#.##...#\n...#..#..#\n...#..##..\n#.#.......\n\nTile 1117:\n...#####.#\n.##...#...\n.........#\n##......#.\n....#..#.#\n.###..#.##\n###..##...\n..##.#...#\n#..#.##..#\n.#..###...\n\nTile 2693:\n...#.#...#\n##..#...##\n.#.....##.\n...#.#....\n.###.....#\n...#......\n##.......#\n#........#\n....#.....\n..#..###..\n\nTile 3527:\n..##.##...\n.#.#......\n##..#...##\n#..##.#...\n#...#...#.\n#.#.#....#\n#..##..##.\n........#.\n......##.#\n.#####...#\n\nTile 2417:\n.###.#...#\n....#....#\n###....###\n..........\n.#...###..\n.#####.##.\n#.#.....##\n.....#...#\n..#..#.#.#\n###.##.#.#\n\nTile 1723:\n..#####.##\n#..##..#..\n#..##...#.\n..#.....##\n..#...#...\n....#...##\n....#.....\n#...#....#\n...#..###.\n.##.##....\n\nTile 2251:\n.....#####\n..#......#\n#....#..#.\n.#.##.#..#\n.....#..##\n........##\n..........\n.#...#...#\n.#..#..#..\n#.#..##.#.\n\nTile 3761:\n#.#.#...#.\n#.#.#.#.#.\n#..#....#.\n#.........\n##.##..#.#\n...#......\n##..#.....\n#...###.#.\n..###....#\n..##.##...\n\nTile 1697:\n.#...#....\n..##..#...\n#........#\n##..#...##\n......##.#\n...##...#.\n..##...#..\n.####....#\n..#......#\n##.#.#.#.#\n\nTile 1879:\n..#...#.#.\n#.#.....##\n..#..#..##\n.......#.#\n#...#...#.\n........##\n##.#.....#\n..###...#.\n.....#.#..\n#....#..##\n\nTile 1901:\n##.#.#.###\n.....#....\n##.#.....#\n#.#.#.#...\n.#........\n####.#...#\n#.#...##.#\n.##.##.##.\n..##...##.\n#.#...##..\n\nTile 1063:\n..#######.\n.....#.##.\n...#......\n#........#\n#........#\n#.#..##...\n...#...#.#\n###...#..#\n#.#.....#.\n.###..#.##\n\nTile 2389:\n.###.###.#\n...#...#..\n..#.....#.\n...#..#...\n.#...#....\n#...##..#.\n#...##.#..\n#.#.#.....\n##...#..#.\n##.#.#..#.\n\nTile 2393:\n..#..#.#..\n..#..##...\n....#.#...\n#..#.....#\n##........\n#.##...#..\n....##...#\n...##....#\n...##.#.##\n#.#.#.####\n\nTile 3067:\n.....##..#\n.#........\n#..##..#..\n#.#...#.##\n#..###.#.#\n#...#...##\n#.##.#..##\n...##...#.\n.##...#.##\n#.....#...\n\nTile 1747:\n.#######.#\n#...##....\n....###..#\n##...#.#..\n#..#.#..#.\n#..#.#.#.#\n..###.##..\n#.#.##..##\n..........\n###.#####.\n\nTile 3797:\n..#######.\n#.#.#.....\n..........\n#..##.##..\n##..##.#..\n#.#.#...#.\n.###.#..#.\n##...##.#.\n#..##.##.#\n.##.#.##.#\n\nTile 1811:\n##..###...\n.......##.\n......#..#\n..##....#.\n##..######\n#...#...#.\n####......\n#..#.##...\n#..##....#\n###.#...##\n\nTile 1087:\n.##.##..#.\n.#.##...##\n.#......##\n.#.....##.\n...#.#.##.\n###.#..###\n###.#...##\n####..#...\n##...#...#\n...#.#...#\n\nTile 1181:\n...##...##\n....#..##.\n.#...#..##\n##.#...#.#\n..#.#.#.##\n##.......#\n#...#.###.\n#.#.....#.\n.#......##\n..#.#.#..#\n\nTile 3821:\n.#...#.#..\n..#....###\n..##.#..#.\n#...#.#..#\n#.###...#.\n..##..##..\n#.#.#..#.#\n....####.#\n#.........\n..#.#.....\n\nTile 3457:\n#..#....##\n#........#\n#.#..#.#.#\n##.....#..\n.....###.#\n.#.##....#\n#.....#..#\n##...#...#\n.#.....#.#\n##.##...##\n\nTile 1657:\n###..#.###\n....#..###\n..#...#..#\n...###..#.\n.....####.\n#......#..\n.##...#.#.\n.#.#.#.##.\n....#...#.\n...#.##.#.\n\nTile 2503:\n.#....##..\n#.#...#...\n##..####..\n.#.#.....#\n#.#..##...\n...###...#\n...##....#\n.....#...#\n.....##...\n..#...####\n\nTile 2843:\n....#####.\n#.......##\n#...#.##..\n.#.#.#...#\n..#.##...#\n..#..#.###\n.......#..\n....#..###\n......#.#.\n#.####.##.\n\nTile 2273:\n#....##..#\n##.#....#.\n#.###...#.\n#.........\n...#......\n####......\n#.##.....#\n#..##..#..\n#.......##\n.#..#..###\n\nTile 2953:\n.#.#.###..\n#...##.#..\n.#........\n....#....#\n...##..##.\n#.....#...\n#.....#...\n#...#.##..\n.#......#.\n###..#..##\n\nTile 1021:\n##.#.###.#\n##....##..\n#......#..\n...#...#.#\n#.##.....#\n......#...\n#..#......\n.##...#...\n#...#...##\n.##...#..#\n\nTile 3643:\n#...#.....\n...#...#..\n......#.##\n.....###..\n.....#.###\n.....#.#..\n.......##.\n##..#.#...\n#......#..\n..#.####..\n\nTile 1609:\n##.#.#..##\n..........\n#.#..#.#..\n####...###\n.#...#..#.\n##....##..\n#.#.##..##\n#...##....\n##....#.#.\n###..#.#..\n\nTile 1949:\n#.#.#.##..\n#.#.......\n#.#......#\n###.#....#\n...#.##...\n#...#.....\n.#...#....\n...##.#...\n.#..#....#\n.##..###.#\n\nTile 1153:\n.##.##..#.\n..#......#\n#.#.....#.\n##.##..##.\n#.#......#\n....#....#\n.#.##....#\n#.#..#...#\n..#...#.##\n#.#.##..##\n\nTile 1367:\n.###.#####\n.........#\n#.##....##\n....##..##\n.#.#.....#\n####..##..\n..#.###..#\n.#..##.#.#\n..#.....##\n#...##.###\n\nTile 1061:\n..####....\n.......#.#\n#.....#...\n#..#.##..#\n#.##....#.\n.#...#.#.#\n###.....##\n..#...#...\n...#.##.##\n.#....#...\n\nTile 1193:\n...#....##\n...###..##\n#..##....#\n#....#....\n#...#..#.#\n..##.##..#\n.#.###...#\n##....#..#\n#...#..##.\n####.#....\n\nTile 3617:\n#..#.#..#.\n#.#.#.##..\n#.##.#..##\n#.#.#.....\n###......#\n##....#..#\n.....##.#.\n#......###\n...###..##\n.##.#..#.#\n\nTile 1093:\n#..##...#.\n.#.#.#...#\n#........#\n.#...##..#\n....#.#.##\n#.....#.##\n#........#\n...#..#...\n#.##..##..\n.#...#..##\n\nTile 1549:\n##..#.###.\n..#......#\n#.#..#..#.\n........##\n....#..#.#\n#.#.#.#...\n...##..#..\n######...#\n#....##..#\n.####..#.#\n\nTile 2281:\n###.######\n.#.#......\n#.#..##...\n.#.#...###\n..#...#..#\n..##.....#\n.......#..\n#....##..#\n....#..#..\n..####..##\n\nTile 3049:\n.....##...\n#..#......\n#....##...\n#...#.#...\n###...##.#\n##....#...\n##...##..#\n#...#.....\n.#.#.##...\n######...#\n\nTile 1523:\n##..###.#.\n.......#..\n##..####..\n.#...#...#\n.....#..#.\n.##.#.#..#\n##.#.....#\n###..#..#.\n...##.....\n##.##.....\n\nTile 3671:\n.#.#.###.#\n.........#\n...#..#...\n...#.#....\n.#...#.###\n###.#.#.##\n..#......#\n..........\n#..##.###.\n#.##.####.\n\nTile 3221:\n...##.##.#\n#....#...#\n##..###...\n#...##.#..\n##........\n##.....#..\n###.......\n.......#.#\n#.#..###.#\n#..#.#...#\n\nTile 1861:\n.....##..#\n##...#.#.#\n#...#....#\n....##...#\n#..##..#.#\n...#.#...#\n##........\n#.#.#.#...\n#.........\n##......#.\n\nTile 2111:\n#....##.##\n..#....#.#\n......##.#\n#..#..#...\n..#..##.#.\n##..###.#.\n.#..#.#..#\n.#.#...#..\n#.##.#...#\n#.#..##..#\n\nTile 1049:\n..#.######\n.#......#.\n.........#\n....##..#.\n.#....#..#\n....##..##\n..#......#\n#..#.#...#\n##........\n.#.##..##.\n\nTile 1871:\n.##.##.#.#\n#...#.....\n#..#.#..##\n.###..#.##\n.....#....\n#....#.#.#\n#..##....#\n.#.##....#\n.#...##.##\n.##.#.####\n\nTile 3389:\n...###..#.\n.#...#..#.\n###.......\n.#...#.#.#\n.#.#.#.#.#\n#..##.###.\n..###..##.\n#...#.....\n#.#...#...\n##.##.#.##\n\nTile 2699:\n.#..#.####\n#...#.#.#.\n##.....#.#\n#....#...#\n..#...#...\n...###..##\n#.#.##..#.\n...###.##.\n#....##.#.\n#..#..#.#.\n\nTile 3181:\n#.##.#..##\n#......##.\n........#.\n##.###....\n##.......#\n#.........\n##...#...#\n#.#.#....#\n...#.....#\n#..###....\n\nTile 3469:\n..##...#.#\n...##..#.#\n##.##.#.##\n.#####.###\n..#......#\n.#......##\n..#..####.\n##.#.#..#.\n.#......##\n#..##.#...\n\nTile 1249:\n##.###...#\n.#........\n....#..#.#\n#.....#..#\n#.###..#..\n.#.......#\n.....#.#..\n##....#...\n.#...##..#\n.#..###.##\n\nTile 1907:\n.####.####\n#....###.#\n...#.#..#.\n..#..#..##\n#..##...##\n#.#.......\n#...##...#\n#..#...#..\n.#...###..\n...###.##.\n\nTile 2539:\n...#.##.#.\n##.....#.#\n#..##.....\n#####.....\n#..#.#..#.\n###..#....\n....#..#.#\n.......#.#\n#.#.....#.\n#..#####.#\n\nTile 1217:\n.#.###.###\n.........#\n#.....#...\n##..#.#...\n..#.#.....\n......##.#\n.#.......#\n#.#.#.#...\n...###.#..\n..####...#\n\nTile 2377:\n.#...##..#\n..#...#..#\n........##\n.........#\n.#....#...\n.###.....#\n#....#....\n.#...###.#\n...#..#..#\n###.#..###\n\nTile 2767:\n.####..#..\n##....#..#\n#..#....#.\n#..#.#####\n###....#..\n..#..#.###\n#...#.....\n#.#......#\n.#...#..#.\n#.#.#.####\n\nTile 2879:\n#.....#..#\n.#..#..#.#\n##....##..\n..........\n#...#...#.\n##.......#\n#.###.#..#\n.......##.\n....####..\n..##...##.\n\nTile 2683:\n.##..##...\n.#........\n#..#.##..#\n.#.#..##.#\n........##\n#.#......#\n....#.##.#\n#.##.#..#.\n#.#.#...#.\n#...##.#.#\n\nTile 2003:\n.#.#.###.#\n#..##.#...\n##...##...\n.#...##..#\n.#..##.##.\n#...##...#\n#...#.#...\n.#...#.##.\n..........\n######....\n\nTile 1511:\n#..#.#..##\n......#...\n#.#.#..#.#\n##..#....#\n##......#.\n#.........\n.....#.#..\n..##......\n...##...##\n..##...###\n\nTile 3967:\n.##..###.#\n....#....#\n#.##...#.#\n#......#.#\n#.....####\n..##....#.\n#.#.#....#\n....#.....\n##.#.....#\n#.###.###.\n\nTile 3343:\n##.#.#....\n.......#.#\n..#......#\n..##.#..#.\n##....##.#\n.#.#......\n...#..#.##\n#..#.##..#\n.#.#.#.#..\n..##..#..#\n\nTile 2269:\n##........\n#........#\n.........#\n...##..###\n.###.##.##\n#....##..#\n.#..#.##.#\n##.#...#..\n##....#.##\n..#.#....#\n\nTile 2063:\n#...#.##.#\n##.......#\n.#..#.....\n.##...###.\n.#.....#..\n..#.....#.\n..#####.#.\n#####...##\n##.#...##.\n.#.....##.\n\nTile 2857:\n...##.####\n##......##\n#.#.#.#...\n.#.###....\n......#...\n.........#\n.#......##\n.#.#.....#\n#.#.#.....\n..##.#.#..\n\nTile 3167:\n.....#....\n...###....\n...##.....\n.....#..##\n..#.###..#\n#..#....#.\n..####....\n.......#..\n#...##..##\n#...###...\n\nTile 2551:\n.#.###....\n#.##..#.#.\n..###.#.#.\n#..####.##\n.......##.\n..##.#....\n.#..#....#\n####....#.\n#.##..###.\n#....#.###\n\nTile 2707:\n..###..#.#\n.....#.###\n#....#...#\n##....##.#\n...#..#.##\n.##.#..##.\n#...#.#.#.\n#.....#..#\n..##.##.#.\n######.#.#\n\nTile 3607:\n...#..#.#.\n#.#..#..##\n..##...#.#\n##.#.....#\n##...##...\n#.#..#....\n#........#\n.#..##..##\n####...###\n##.#..####\n\nTile 2113:\n....#.....\n.....#...#\n...#..#..#\n##..#.#...\n...##.....\n#.##..#..#\n.....#..##\n#..#.#....\n#.#.###...\n.#.####..#\n\nTile 2371:\n##.##...##\n#.#......#\n##.#......\n#......#.#\n....#....#\n##...#.#.#\n#...#...##\n#....#...#\n..#..#...#\n......#..#\n\nTile 2741:\n###..#####\n#..#..##.#\n##...##...\n##........\n...##...#.\n.##.....#.\n.#..#.#.#.\n#.#......#\n..##....##\n.###......\n\nTile 3779:\n..#.....#.\n##.......#\n..#.#.##.#\n.###.#.##.\n.#..####..\n#####.#..#\n...#.....#\n#...#.....\n.........#\n.##...#.#.\n\nTile 1483:\n##.#..##..\n#.#....#.#\n..........\n....#.#..#\n#...#....#\n#....#...#\n..##.#..#.\n#..###.###\n..##.#....\n..#.##....\n\nTile 2927:\n####.#####\n.###......\n#..##..#.#\n##...#....\n##.#..#...\n.##.#.....\n.#........\n..........\n#........#\n.##....#..\n\nTile 2153:\n#.#..#####\n#..#...#..\n#.......##\n##..#.####\n....##.#.#\n#.#.##....\n.#..##.#..\n..#.##..#.\n#.#####..#\n...#.##.##\n\nTile 1453:\n.....###..\n...#......\n.#.#..#..#\n.#..#...##\n.####..#..\n...#..##..\n....#.#.##\n.##....##.\n##......#.\n.##.#...##\n\nTile 2423:\n#..##.###.\n##...##..#\n#.........\n.#...#..##\n#.........\n.....##...\n#...#.....\n.......#..\n#....#....\n..##...###\n\nTile 1933:\n#.##.###.#\n##....#...\n#..##...#.\n.......#..\n##....#..#\n....#..##.\n#..#......\n.#........\n..#.#.....\n##....###.\n\nTile 3191:\n.#####.#.#\n##.#.....#\n....#...#.\n##.#......\n...#...##.\n..#..#...#\n#..#..#...\n#..#......\n..#.######\n.###..#..#\n\n"
  },
  {
    "path": "advent-of-code/2020/inputs/21",
    "content": "vzkbf lxrsn mnj bjqfl brqg kcddk nkjc bgblpf xxhp cfb pzqgtb cggl cjhv vplz dlhfnjb jtfmtpd ccmvjbn jgrrd dvjxl tdrxvd vlqz pfbz txvctk kqvhbt qcmgxlj kgf znvmcx ldkt lshjmc nrlf rjf mcvc tzkfgq fpgmtjg srvfk nhhbtd mdtrqk hqxp bgxpfm ncx sckjj vqn npxrdnd xvsxb bcvlvk tflkk sjdmzj zmkx jpvvt vvlbp fqpt lmcqt khmm gfgbq plgvrz klnrvd xmcdn hrrt (contains dairy)\ndvjxl sjpkc xdqx cfb jnmsr jzvjxf czcfdv zmvpzp srvfk tsch qqq qdhk pxf ttlvf jtfmtpd ndqk mrqgvd fqpt ctbvdq bgxpfm znvmcx sgczbl jpvvt zkjh kskbk mjzpgzs jxvc qvkdgn tdrxvd fzdltb csxkh mnj vbvbbh ldkt bcxxjq fpgmtjg nvxk hcrgt mqvf kqvhbt hnpd tmckpp lmcqt pzqgtb npxrdnd fdhfpn nbhhmfx dntsjl zbfqrn cmtvkq xmcdn xjsgl hrhzg zfrkt bxgzl zkfsg xzn zmmrgdf fkpjn dhz (contains shellfish, fish, nuts)\nrxjq qdhk hlzkpt tsch xl tcff vmhhjm xjsgl pfbz xhxkf ftqpg ctnb zhvhng zmvpzp djmbx dptsqvq fkpjn pzqgtb lg kcddk ngrcb tflkk fsbll svvjknm khmm mjzpgzs jpvvt lkvdg mcvc gmsnc lmcqt npxrdnd xtnsbgc xkzsk vlqz cfgc dvzz qtpvndc qlrrrgb zkfsg mzlzxcc ltrhm mk zmmrgdf pfhsdp hqtzllj ldkt dqntj mqvf vtrchx slkjz hrhzg tmckpp lbdlb mdqdgf pnpg dscxjl sgczbl gscxfbd nfkzd mnj cjhv zmkx rrtkdz njjvq rjf xxhp bcxxjq lfvdf sqg dvjxl fqpt vjpnd gkkcjs flrjj bnfhd mmlq tsrqc nbhhmfx bgblpf ctbvdq xbrtdm srvfk cfb (contains nuts, peanuts)\nkskbk qdhk cxbkg xpmx xskgz dvzz xdqx tsdcm pgcxql fkpjn rxjq bcxxjq mdh ngrcb sqg zmkx mdtrqk nfqkt tzkfgq dntsjl jzvjxf dmtcj dscxjl plgvrz npxrdnd jgrrd ftqpg hrrt zkjh dgbndg lmcqt fqpt kqvhbt hrhzg cfb qvkdgn flrjj tsch mcvc xvsxb blnsd pxf zhvhng ldkt jtfmtpd sckjj zmmrgdf xkgpch vzkbf cmtvkq mzlzxcc sfmbms mk (contains soy, shellfish)\nxvsbr cbdl lmcqt kqvhbt pxf ldkt kskbk zhvhng jzvjxf nfkzd mk fsjcf srvfk bqrsxn lkvdg cshq npxrdnd zfrkt vmhhjm znvmcx zpzzt slkjz ndqk fqpt qvkdgn ftqpg jnmsr cfb tsch lshjmc mnj xlqp hrrt mqqzg sqg kcddk mqvf xzn hqxp cmtvkq (contains peanuts, nuts)\nlkvdg xhxkf fpgmtjg szfxqq lshjmc cggl jxvc xmcdn tdrxvd jgrrd vvlbp hrhzg lxrsn xtnsbgc mzlzxcc ftqpg kcddk jmvt dgbndg cvd tsch pgcxql fqpt plgvrz tmckpp mmlq jpvvt xxhp dntsjl bxgzl mmhmx cfb svvjknm fsjcf rzc jtfmtpd xzn pzqgtb vjpnd hndcnf xskgz qdhk mdqdgf npxrdnd flrjj zkfsg mqvf lmcqt ctbvdq znvmcx khmm nhhbtd zpzzt hrrt tzkfgq slkjz xl mk pgct mrqgvd njjvq zhvhng kskbk blnsd gxmk vtrchx hjkqqr qtpvndc klnrvd xqbtls bgxpfm (contains fish, dairy)\nlmcqt vrl hmnln rjf ttlvf cfb cggl rxjq qpdd plgvrz mdh pfhsdp xpmx zhvhng dscxjl mrqgvd bxgzl mk lxrsn nrlf vvlbp fpgmtjg tsrqc dhz ccmvjbn npxrdnd ltrhm xvsxb sjpkc hcrgt cshq hlzkpt jpvvt xdqx xjsgl pzqgtb xhxkf tdrxvd hjkqqr fqpt tfnsz bcxxjq hclf ctbvdq mzlzxcc kgf gfgbq sckjj tflkk bgxpfm zkfsg vmhhjm qlrrrgb jnmsr qcmgxlj bcvlvk srvfk hrhzg jtfmtpd ngrcb jbmxr flrjj szfxqq csqrvk bggz ldkt mdtrqk sqg zfrkt slkjz tsch (contains sesame, soy)\ncxbkg fsjcf vqn xzn sjdmzj qcmgxlj cfb mrqgvd bcvlvk bggz hrrt npxrdnd dntsjl lfvdf tsch cmtvkq xjsgl pxf kcddk vdqtgt dgbndg ldkt xhxkf dptsqvq gscxfbd tmckpp bxgzl znvmcx mmlq flrjj xpmx kgf mmhmx tdrxvd dvjxl fqpt plgvrz zmvpzp zmkx xskgz ltrhm lmcqt csxkh (contains eggs, soy)\nsrvfk tsch szfxqq lmcqt xjsgl mqvf mrqgvd dhz kcddk mmhmx fqpt vvlbp gscxfbd jfl cjhv zbfqrn cfb vplz pgct jxvc mdtrqk sgczbl pbkr nfkzd lxrsn gmsnc blnsd fpgmtjg mjzpgzs fsbll rzc xvsxb mnj lkvdg kqvhbt hjkqqr njjvq klnrvd bgxpfm kskbk nsdk tsdcm bnfhd lfvdf hndcnf fkpjn jzvjxf bqrsxn txvctk xmcdn ldkt tsrqc zkjh slkjz dptsqvq lbdlb jtfmtpd jnmsr bjqfl zpqh csqrvk dscxjl cbdl dqntj sqg rbkr mzlzxcc bvzs nvxk hrrt vlqz fdhfpn pfbz mxfgnv pzqgtb hqtzllj (contains shellfish, sesame, dairy)\nxl hjkqqr fsbll mmhmx kcddk xkzsk kqvhbt jtfmtpd xlqp bgxpfm zmkx fpgmtjg fdhfpn zhvhng gxmk mjzpgzs tcff szfxqq mxfgnv rzc zmvpzp svvjknm sqg bcvlvk dqntj lfvdf jbmxr lmcqt pgt xjsgl tsdcm hnpd mnj vbvbbh plgvrz rxjq mdh mdtrqk tsch ldkt fqpt qpdd mqqzg vdqtgt jvxqc ccmvjbn hclf cfb ttlvf cxbkg vjpnd dmtcj vtrchx qqq nbh jmvt xskgz (contains sesame, peanuts)\nfqpt pfhsdp fkpjn tsch dscxjl tdrxvd klnrvd mnj czcfdv kqvhbt mzlzxcc mxfgnv dvjxl rrtkdz cggl nfkzd pgct bnfhd bxgzl djmbx lkvdg bjqfl xlqp xhxkf nkjc csxkh sjpkc lmcqt vbvbbh cshq npxrdnd mk plgvrz ldkt rzc qqq dlhfnjb hrrt xqbtls mjzpgzs cfb bqrsxn jvxqc fpgmtjg dptsqvq rbkr mcvc lshjmc cxbkg bcxxjq nrlf pnpg zpqh vzkbf zkfsg mmlq ndqk nbhhmfx zkjh kcddk vmhhjm fzdltb ccmvjbn bvzs (contains dairy)\nzmmrgdf zpzzt cmtvkq sgczbl jtfmtpd xskgz znvmcx hjkqqr vqn jpvvt mmlq hclf svvjknm pnpg lxrsn dmtcj vtrchx tmckpp lmcqt hmnln xdqx nhhbtd xqbtls gmsnc npxrdnd fqpt zkfsg brqg cxbkg mjzpgzs rbkr pfbz dptsqvq mnj vdqtgt kgf ldkt jxvc ftqpg zkjh hrhzg ttlvf kcddk jmvt cfb vbvbbh khmm xmcdn tcff mdtrqk fdhfpn srvfk (contains sesame)\nqpdd vrl sgczbl qdhk cfb cxbkg bgblpf kcddk tsch hnpd bxgzl jzvjxf svvjknm rbkr xzn lshjmc zkjh xjsgl ftqpg fdhfpn hqtzllj sjdmzj ldkt cggl xskgz jxvc bcxxjq tflkk vqn jvxqc blnsd xdqx lg tsdcm ngrcb vzkbf jmvt jtfmtpd gfgbq xl fqpt csqrvk zmkx nsdk xlqp rjf mnj mzlzxcc plgvrz cvd jbmxr sqg cfgc bqrsxn mqqzg cjhv zpzzt vdqtgt jfl mmlq vlqz pgt xtnsbgc vjpnd gxmk dscxjl lmcqt lxrsn (contains dairy)\npnpg lmcqt nbh zpzzt dptsqvq tdrxvd mdqdgf ncx gmsnc sckjj klnrvd dscxjl znvmcx dvjxl bgxpfm vdqtgt hmnln jvxqc gxmk tsch ngrcb csxkh slkjz jmvt xkzsk prnjsm hqtzllj jtfmtpd fdhfpn cshq xjsgl jzvjxf kcddk jbmxr xdqx jpvvt cmtvkq fqpt cfb npxrdnd (contains nuts, sesame, soy)\nflrjj zhvhng tsdcm xkzsk jtfmtpd mqqzg dntsjl npxrdnd tdrxvd znvmcx mzlzxcc vbvbbh gfgbq lbdlb mxfgnv khmm bcvlvk bjqfl zkfsg jzvjxf xvsbr hrhzg xkgpch czcfdv tsch pxf nhhbtd lmcqt rxjq njjvq kqvhbt cfb bgblpf tfnsz bggz csxkh kcddk fsbll gxmk zfrkt xxhp slkjz mmlq vtrchx ldkt dlhfnjb ftqpg (contains peanuts, fish, nuts)\ntsrqc lmcqt czcfdv pfhsdp xl zpqh qdhk jtfmtpd vtrchx csqrvk xmcdn nfkzd tfnsz blnsd fsjcf bgxpfm klnrvd srvfk mnj jbmxr sckjj xjsgl mqvf mxfgnv mdtrqk nbh gkkcjs bjqfl mjzpgzs zfrkt svvjknm lg pnpg pzqgtb kcddk mdh gscxfbd xvsxb nhhbtd qcmgxlj tsch mzlzxcc cjhv xqbtls spkl cmtvkq qpdd xkgpch rzc xpmx bgblpf vvlbp gfgbq dscxjl tmckpp fqpt vplz vlqz cfb vmhhjm npxrdnd fpgmtjg vbvbbh gmsnc zkjh cxbkg cfgc ctnb znvmcx mcvc pgt txvctk (contains nuts, shellfish)\nmrqgvd xvsbr cggl zmvpzp xxhp xbrtdm qqq bgxpfm cfb cfgc tsrqc kcddk mdqdgf bqrsxn bcvlvk bxgzl ldkt pgt lfvdf qlrrrgb jtfmtpd nvxk fqpt jxvc mmlq sjdmzj ngrcb zmmrgdf jbmxr pgct lg hnpd dscxjl npxrdnd jpvvt ndqk gkkcjs zfrkt bggz ncx bnfhd xskgz mnj dptsqvq hcrgt zkfsg sjpkc bjqfl pxf tflkk dvzz srvfk xmcdn fdhfpn mmhmx dlhfnjb ctnb vplz rzc nsdk xqbtls cvd jgrrd cbdl mdtrqk czcfdv mcvc bgblpf vqn pbkr lmcqt xhxkf (contains fish)\nvzkbf dvjxl nrlf cbdl xskgz sfmbms mdqdgf cjhv szfxqq ldkt mmhmx mzlzxcc qvkdgn fqpt gmsnc mmlq kskbk tzkfgq djmbx pgcxql kgf sjdmzj xkzsk vjpnd slkjz pgct kcddk pnpg nfqkt sckjj xlqp xvsxb qlrrrgb vtrchx bjqfl tsch cmtvkq dgbndg spkl cfb vvlbp lmcqt bgxpfm dntsjl jpvvt ctbvdq nbhhmfx mxfgnv xqbtls xjsgl bqrsxn prnjsm cxbkg fsjcf jtfmtpd ccmvjbn xtnsbgc (contains sesame)\nkhmm xxhp prnjsm vvlbp tdrxvd mdh jvxqc jgrrd jnmsr bnfhd bqrsxn ldkt xpmx cfb jbmxr vlqz zpzzt npxrdnd mnj pgct tfnsz dqntj hjkqqr hrrt nsdk gfgbq dlhfnjb qlrrrgb jpvvt tsch mrqgvd kskbk rrtkdz qdhk fzdltb nfqkt hndcnf dptsqvq xvsbr fqpt xl lfvdf lmcqt jtfmtpd (contains shellfish, soy, dairy)\nqpdd ldkt jfl vtrchx pbkr srvfk hmnln gkkcjs jtfmtpd djmbx fqpt cfb dhz vdqtgt hlzkpt zmvpzp tsch lg blnsd pgct qtpvndc ctbvdq mqvf flrjj vqn jzvjxf gxmk ccmvjbn jnmsr mdqdgf hclf cbdl vlqz hndcnf mxfgnv fsbll csxkh mmlq sqg dvjxl fzdltb gscxfbd npxrdnd lshjmc sckjj klnrvd nfqkt mqqzg dptsqvq nkjc xskgz tsdcm nvxk mjzpgzs lmcqt pxf dlhfnjb qvkdgn vplz szfxqq cshq kgf jbmxr mzlzxcc tmckpp zpqh (contains soy)\nzhvhng xmcdn gscxfbd xxhp jnmsr svvjknm ctbvdq dptsqvq ldkt hcrgt rzc cggl hnpd djmbx lmcqt xl nfkzd jpvvt kcddk dntsjl xlqp fqpt mzlzxcc qcmgxlj pzqgtb sgczbl vmhhjm nvxk tsdcm dmtcj vqn zkjh srvfk xtnsbgc jgrrd pxf vjpnd tsch sckjj ncx fkpjn cfgc lfvdf plgvrz kskbk cfb pfbz cshq ndqk bcvlvk khmm brqg sjpkc ccmvjbn cbdl lbdlb vplz nhhbtd jtfmtpd sqg (contains soy)\nhrhzg xvsbr rjf pfhsdp dvzz fsjcf klnrvd slkjz mxfgnv tsch rrtkdz rzc cfb srvfk pxf vvlbp pnpg mdqdgf lbdlb tcff hqtzllj jtfmtpd brqg mmhmx fqpt sfmbms xkzsk dptsqvq nrlf ldkt pgcxql vzkbf vjpnd znvmcx pbkr npxrdnd nkjc ltrhm cxbkg vplz lmcqt jvxqc prnjsm tmckpp pzqgtb jnmsr bgblpf vtrchx mqqzg pgct zfrkt svvjknm nvxk cbdl dgbndg ctbvdq rxjq mdtrqk nsdk hclf szfxqq nbh xlqp fkpjn dhz gxmk hjkqqr hndcnf tfnsz xkgpch mnj zmvpzp sqg zhvhng (contains soy)\nfkpjn ttlvf vlqz dscxjl dvzz vjpnd sqg srvfk qdhk gscxfbd xzn njjvq ldkt vmhhjm xskgz svvjknm xkgpch brqg hjkqqr mdtrqk sgczbl gfgbq pfbz nbh qqq xvsxb hclf lmcqt kqvhbt npxrdnd zbfqrn fqpt dqntj qcmgxlj pgct zmkx fdhfpn szfxqq ltrhm lg hqtzllj vdqtgt jvxqc hcrgt sckjj jtfmtpd zpqh kcddk fsbll zpzzt djmbx vplz cfb pnpg (contains nuts)\nhqxp lshjmc rrtkdz nvxk pfhsdp tcff jmvt mqqzg qdhk vdqtgt bqrsxn bxgzl mqvf kskbk qcmgxlj jvxqc nfqkt gmsnc hjkqqr qpdd ttlvf mdtrqk mmhmx ctbvdq vvlbp bggz hmnln xpmx lmcqt npxrdnd cggl prnjsm fqpt nkjc pgcxql qvkdgn xhxkf ftqpg gkkcjs mmlq sqg rjf cxbkg dqntj cvd zmvpzp slkjz pxf dscxjl tsch xtnsbgc jtfmtpd cbdl kqvhbt zfrkt fzdltb klnrvd bvzs sjpkc kcddk ldkt hcrgt zpqh sjdmzj nbh qlrrrgb dvzz vmhhjm txvctk tdrxvd vbvbbh vzkbf zhvhng zpzzt vqn fsjcf svvjknm xvsbr qtpvndc xl lkvdg nfkzd bgxpfm bcxxjq znvmcx (contains sesame)\njtfmtpd blnsd mmlq fkpjn pgt ldkt xzn tsch mcvc jzvjxf jfl cxbkg tzkfgq vqn klnrvd nhhbtd xdqx fqpt jvxqc sckjj vrl bggz xvsbr hlzkpt vlqz jbmxr bgblpf bcvlvk rbkr jgrrd bjqfl jnmsr ctnb nvxk vvlbp lmcqt cfb djmbx lkvdg zmkx sqg qcmgxlj mqvf svvjknm xqbtls hmnln nrlf lxrsn dhz zhvhng pfbz rrtkdz npxrdnd znvmcx qpdd txvctk jmvt gfgbq tsrqc bgxpfm bqrsxn ftqpg ccmvjbn gscxfbd dptsqvq xkgpch pbkr cvd xtnsbgc xlqp (contains shellfish, soy, peanuts)\nmcvc dgbndg vzkbf dptsqvq gscxfbd jzvjxf vtrchx lfvdf vplz ltrhm pbkr jtfmtpd sgczbl spkl khmm dntsjl mxfgnv njjvq lkvdg cshq qcmgxlj ldkt vjpnd qlrrrgb jmvt dscxjl bnfhd tsch sjdmzj csxkh hndcnf nbh ccmvjbn kcddk djmbx nfqkt bgxpfm mqvf cfb mjzpgzs txvctk dlhfnjb mdtrqk cxbkg lmcqt mk bggz hqtzllj fqpt dqntj qvkdgn nfkzd cmtvkq hjkqqr mmlq rxjq (contains sesame, peanuts)\nlg pxf jpvvt ndqk pzqgtb mmlq zmmrgdf sqg xlqp xvsbr lbdlb qcmgxlj gmsnc xpmx mqvf jtfmtpd pgt dvzz vvlbp sgczbl spkl lshjmc hrrt zkfsg szfxqq hclf qdhk bvzs npxrdnd dqntj bjqfl fqpt tcff ttlvf lmcqt hqtzllj xdqx nsdk ldkt ccmvjbn tsch ftqpg tzkfgq kcddk hrhzg rbkr (contains soy, eggs, dairy)\ntfnsz bcvlvk mjzpgzs prnjsm tsch xkzsk vzkbf lmcqt mqvf dvzz cxbkg zhvhng npxrdnd vqn fsbll ttlvf hclf vmhhjm bcxxjq fpgmtjg tcff mmlq plgvrz hrrt qcmgxlj kcddk vplz ctnb pgct mk mxfgnv pxf qpdd nrlf jnmsr rbkr dptsqvq rrtkdz jtfmtpd ldkt srvfk xpmx lfvdf bxgzl ctbvdq xjsgl gfgbq slkjz xskgz mqqzg cmtvkq nhhbtd nsdk mdtrqk cfb sfmbms hjkqqr jzvjxf pgt qlrrrgb xlqp ftqpg tdrxvd hqtzllj (contains dairy, shellfish)\nmrqgvd rxjq cmtvkq xzn fqpt mjzpgzs mqqzg xdqx kqvhbt pfbz tdrxvd lmcqt mcvc ftqpg mdh szfxqq tsch nrlf npxrdnd ndqk slkjz jtfmtpd cfb hlzkpt prnjsm cjhv vtrchx lbdlb sckjj sjdmzj gxmk nbhhmfx dgbndg gkkcjs lxrsn dscxjl dntsjl bnfhd zpqh ldkt pgt cbdl (contains fish)\njvxqc nbhhmfx jbmxr hclf nfqkt ctbvdq gxmk ctnb brqg fzdltb bnfhd dscxjl blnsd jtfmtpd flrjj bcxxjq bgblpf csxkh gfgbq fpgmtjg fdhfpn mcvc rjf zpzzt nbh vjpnd ldkt fqpt rbkr mnj pbkr vvlbp tmckpp xzn zkfsg cfb tsrqc lmcqt kcddk xvsbr ndqk sckjj djmbx vlqz lfvdf lxrsn tsch (contains dairy, soy)\njfl qvkdgn nkjc mcvc ltrhm nhhbtd cjhv nfqkt znvmcx zmvpzp fdhfpn dlhfnjb hndcnf dvjxl pxf bnfhd vbvbbh mjzpgzs xbrtdm cfb lbdlb plgvrz hclf lfvdf pgt hrhzg hjkqqr dscxjl jxvc tcff lmcqt mzlzxcc slkjz rxjq dntsjl bggz fzdltb svvjknm xtnsbgc vqn szfxqq pzqgtb rjf zmkx xlqp khmm tsch ngrcb nbhhmfx zkjh mmhmx blnsd lxrsn jtfmtpd kcddk zkfsg tzkfgq sfmbms mdqdgf ldkt czcfdv kqvhbt nvxk fsbll pnpg hqxp fqpt rbkr vlqz (contains nuts, dairy)\ntfnsz mjzpgzs zbfqrn mxfgnv nrlf ncx ccmvjbn qqq rbkr prnjsm xskgz jtfmtpd kqvhbt fqpt zhvhng zpqh pgct lmcqt ltrhm hrrt pgcxql hcrgt nfkzd qdhk ndqk mrqgvd xvsbr xjsgl ldkt tmckpp fkpjn npxrdnd xxhp cggl jzvjxf qvkdgn cvd vjpnd qtpvndc xdqx mdtrqk kcddk dptsqvq fsjcf cfb gxmk xbrtdm flrjj dntsjl (contains fish, shellfish, nuts)\nsfmbms mjzpgzs mcvc hcrgt xxhp kcddk zmkx ldkt mdh npxrdnd cfb tdrxvd tzkfgq nbhhmfx vvlbp vtrchx jfl xzn rrtkdz zkjh dntsjl hmnln fsjcf rbkr tmckpp qlrrrgb xjsgl mdqdgf lfvdf jgrrd mmhmx hrhzg gkkcjs jxvc pzqgtb vjpnd lg dlhfnjb fkpjn pgcxql mrqgvd tsch vbvbbh bcvlvk tsrqc vmhhjm lmcqt jtfmtpd flrjj sckjj kgf zfrkt nhhbtd kqvhbt (contains eggs)\nzhvhng xskgz vlqz qcmgxlj npxrdnd cxbkg xvsbr bcvlvk xkzsk jmvt ftqpg jfl nrlf fkpjn sqg cshq lxrsn dptsqvq rrtkdz lg bjqfl mnj dqntj xzn jtfmtpd bvzs gmsnc cvd svvjknm fdhfpn cbdl bggz ndqk lshjmc dntsjl nhhbtd sjdmzj pfhsdp tsch xmcdn zmkx cfb xkgpch mrqgvd szfxqq lmcqt fqpt kgf qdhk kcddk jpvvt pnpg jgrrd dscxjl jvxqc nkjc vtrchx pzqgtb fzdltb jzvjxf (contains soy, dairy, sesame)\nbjqfl jmvt vrl blnsd jxvc bgxpfm sjpkc tflkk mjzpgzs fsbll vjpnd czcfdv lfvdf ncx mmhmx ctbvdq vdqtgt jpvvt hjkqqr txvctk lg ccmvjbn rzc mk dvzz xbrtdm tzkfgq vvlbp flrjj nfqkt ldkt jnmsr kcddk zpzzt lkvdg xl mqvf hrhzg vtrchx cfgc pgt xlqp xskgz dvjxl nkjc mxfgnv mcvc hqxp xpmx tmckpp pxf nfkzd cggl kqvhbt kgf fdhfpn plgvrz zhvhng jbmxr qcmgxlj fqpt bcxxjq jtfmtpd lmcqt csqrvk fsjcf tsch brqg mdqdgf fkpjn nbh srvfk hndcnf cfb mnj lbdlb mzlzxcc xmcdn qpdd hnpd hclf xzn svvjknm dptsqvq (contains soy, nuts, peanuts)\nnrlf zfrkt pfbz dhz bcxxjq bxgzl dgbndg vplz jtfmtpd cggl spkl ftqpg ncx cjhv npxrdnd hrrt khmm sqg djmbx sjdmzj cshq lmcqt lshjmc fzdltb hjkqqr njjvq lbdlb nbhhmfx ttlvf zpqh tfnsz fqpt qqq kcddk gxmk qlrrrgb prnjsm xmcdn tzkfgq dmtcj txvctk mdh rzc pgct ldkt ctbvdq kskbk hnpd zbfqrn vlqz tdrxvd cfb (contains peanuts, eggs)\nsjdmzj dgbndg cfb tdrxvd hnpd dntsjl xskgz pfbz fpgmtjg mmhmx tzkfgq lmcqt ngrcb xvsxb npxrdnd khmm mdtrqk sgczbl hcrgt tsrqc sfmbms fdhfpn xjsgl kcddk nbhhmfx ccmvjbn hjkqqr xmcdn pbkr szfxqq mnj hqxp rzc zpqh hrrt xqbtls jtfmtpd gscxfbd fkpjn mzlzxcc dqntj ldkt mk fqpt pzqgtb gfgbq xkgpch qvkdgn rjf nfqkt bvzs hclf dhz dptsqvq (contains eggs, fish, peanuts)\nxmcdn kcddk lg zbfqrn tzkfgq pxf qtpvndc ldkt rxjq fqpt flrjj jfl sjdmzj rzc nvxk lxrsn vvlbp zmvpzp tsch zhvhng ngrcb cfb blnsd bqrsxn djmbx jnmsr cfgc hqxp mmhmx mk mxfgnv njjvq jxvc xkgpch ncx tsdcm fsjcf fpgmtjg cvd klnrvd jpvvt nkjc xvsxb tmckpp pfbz dvjxl ctnb nhhbtd rrtkdz mdtrqk prnjsm zmkx nbh tcff czcfdv tdrxvd xxhp lmcqt vtrchx cxbkg zfrkt slkjz xl mjzpgzs dvzz cmtvkq jtfmtpd xpmx xdqx vzkbf (contains shellfish, soy, nuts)\nhrrt dlhfnjb dntsjl xjsgl hclf rzc rxjq djmbx mzlzxcc jnmsr mjzpgzs xvsbr xvsxb ttlvf zbfqrn mmhmx fdhfpn lmcqt tflkk rbkr npxrdnd jgrrd fpgmtjg mdtrqk vplz sfmbms hmnln bgblpf qvkdgn lbdlb bqrsxn cfb lfvdf cxbkg hcrgt hnpd ngrcb cggl ndqk kcddk xkgpch jbmxr dgbndg fkpjn nbhhmfx tmckpp bcvlvk hndcnf qdhk cjhv slkjz tsch zhvhng qtpvndc blnsd ccmvjbn xskgz nrlf hlzkpt dqntj fqpt ldkt bnfhd vrl sjpkc pbkr (contains sesame, peanuts, dairy)\n"
  },
  {
    "path": "advent-of-code/2020/inputs/22",
    "content": "Player 1:\n6\n25\n8\n24\n30\n46\n42\n32\n27\n48\n5\n2\n14\n28\n37\n17\n9\n22\n40\n33\n3\n50\n47\n19\n41\n\nPlayer 2:\n1\n18\n31\n39\n16\n10\n35\n29\n26\n44\n21\n7\n45\n4\n20\n38\n15\n11\n34\n36\n49\n13\n23\n43\n12\n"
  },
  {
    "path": "advent-of-code/2020/inputs/24",
    "content": "neswsewswseswseenwseneswseswswswseswse\nnwnenwwnwnwneswnenweswnwnwnwnenwswnese\nwnewwwwwwwwswwwsewnwwswnee\nwseeeeeeesesenesenweseseeseesw\nnenenenwneenwnenenwnwswnenwseswsenwenw\nsesenwsesesenweseeseseesesesesenwsesesw\nsesesewseswsewesenwneseswswwsesesesenese\newnenenenenewwneeneneneneseneenew\neswswswwseswswsesese\newnwnwnwnwnwnwwswwwnwnwew\nswswswswswesewswswsweeswswswneswwsww\nnwwwesesewnwwwnewwwwwwenwsew\nwnesenwneeneneswnesenewnenwnesenwnenw\nswseswweseswswswswswseewse\nnenewnwsenwnwnenwnwnwnwnwnwnwnw\nneneneswnwnwnenenwwsenenenenenenenwsenenw\neeseeeeneneseenwseeweseeeeswe\nseneswesesesesewsw\nswswwsweswseneswswswseswnweswsesenwwswsw\nswnwnwsenwwnwnwnwwenwnwwnwwwnwnenw\nsesewseseseseseesesenwse\nneneneneenenenwneswneenene\nswswswewswnwsewswswseswseswswseswswswne\nnenwnwnewneeenenwswneneneseneswneesw\nneswwseswnwswswsesewesenwnwswsenewe\nneeneneenesenwneswnenenwnwwnwnenesenesw\nseseswswswneswswswswnwswneswsewseseesw\nwnwwseswnwenewenwnweewswswswsenw\neswwenweseewesenw\nswsewneenewnwseseweeswneeseneew\neeeeeseenweeee\neseswenwwseseseese\nsesesesenesesesesewseesewseneeweesese\nwwnwnwnwnwesenwnwwnwwsw\neeswnwnweesweeenwsewswswenewnesw\nswswswswswswnweswswswsweswnwswswswneswsw\nwwnwwnwnwwnwnwenwsenwsewwnwswnwnenw\nseseeseseseseswneswsenwsenwsesesesesw\nenwnwwnwnwsweneseswsenwwenwnwnwenw\nseeenenwewweseseseswseewenesesee\nweswswwswwswwswwswwnwswseneswwwnw\neeeeneseeneeeswneenweneneeewnesw\nnwwswswnweswswwwesewswswswwsw\nseeseneswneswswnwenwenwnwwneseswneee\nneneneseneneswneenenenenwnenene\nenenenewneswenesenwneneseneenenewne\nsenwseseseesweseesenwnesesesesesenesesew\nseesesesewsewnweseeeeneeseseeese\nwneseswenwswnenwnwwswseseswneesenew\nnesenwswwnwwseewnewwwsewwnwwsw\nseseeswswneswneesewnwnwenesewse\nwswnwswswwwweswswswwsw\neeeeweeseeneee\nswnwswnwseeeswenwnweswnwswswsewswswswne\nnenesenwnweenwneeneswneneeneeneeswnesw\nsenenenwwnweneswnwnwwnwnwnwenwnwnenenwne\nswewseeneswneweneeneeeswnwneneeee\nnenwwwswwnesweewwseswswswswewwew\nsesesewnwseneseswsenesesesenesewesesesese\nnwnenenwwnwwswsewswewswnwseeeew\nnwwweeseneeesweeeeeewew\nwwnwwwewwwwnwsewwwsew\nneewnwnwnwswswnwnwnwswnwnwnwnwnwnenwnw\neeeeenweeseeswseeeseesweneew\nwwwseswswswnewwwswwseneswswswsww\nnenesweneweeswswwnewnwnenweenee\nnwwwswwwwsenwwwnwwwwwenwsenww\nnwnwnwewnwnwwseenwnwseneenwwnwnwnwse\nwnwnwsewnwnwsenenw\nwwesewnwswenwswseenwneswswseswnwwww\nnwnwsewwwwwswwenwnwwnewsewwewnw\nwnewsenwsewseneseseeseseseseseneesee\nneneneneneeneswneswswnenenenenenenenwnw\nenwnwnwsenewnenenwnwnwnwewnwnwwnenw\nwwwseneseswseeneesenesenewseswenwsw\nnewneeneneneswnenwneneeseneneenenee\nneeswnwswswnewwnwewwswnwseewseswe\nseseesesewsesenwweweswesese\nwsewnwswswswswswswswnwseswswseeneneswwsw\nsenewneseswseseswswenesenwswswswswswswsesw\nwswneswwwswswwwwswswneswseewwe\nnewwwwswwwwwwnwsewewwww\nsesewsenewseneswwnewswswswseswnenene\nnwneneneewnwswnenwnenwneseneenwneneswsenw\neweeesweseseneneseeeeeenwsee\nwswenwenwswswseswsw\nsweenweeseneenweeeene\nnenwseneeeeseswnweeeeeswwneenee\nwewnweswwwwswwsewswnewwwswwswsw\nswseneeswwswwswwwswswswseswswswswne\nwneneneneneswnwwneeenwneneneenwnenw\nswnwnenwnwnwenwnenwnenwnwswnenwswnwenwnenw\nnenwnenwwnwnwweswneseneseneneneswnwnwsw\nweenwswnwnwwwnwnenwsenwnenw\nseseseeneeswseseeseesewswswsewsenwnwne\nnwwswwswwswwseswnewweseseswswwne\nnewwenwewnwnwnwswnwswwenwnwsewnwnw\nseswneswswswwswswswnwswswesweeswswswnwsw\nswswswseswswseneewsewwwneswwswneseswne\neenwseeeeneeeeeseewswseewe\nwwwwwwwwwnesww\nsenwewenwseseeeeseswseseseeesee\nneswnwnwnwwenwnwwwsewnenwnesesewswne\newesweseneneeeseesewsewewsenwnenw\nnewwswwweswsweswwwswwwwwwwe\nnweeenesweseneweenesewene\nenenweseseneneswwneswewseswseeew\nseneswsenwnenwseseswsenwseseseswsesesew\nseswnenwwnwswnweeeweseswnwnweesw\nwwnwwwwenwenwwnwwewnwnwnwnwnwsw\nswswnwswnewswswswswwwswsweeswswnwswswsw\nnenenenenenewenenenenenenesene\nswseeseswneseswneswswseswswswwswnwneswsw\nsewseneseseeeeseneew\nnwenenwsweeswwnwnweenwswswswenwnww\neeeseseswsenwwweeswnesenwswswneww\nnwnenenenenenenenenwneseneneswneneenwsene\nseneseesweeeesee\neneswseeeseseswseeeewnweesewenee\nwwsewswswswneswswswnew\nneseeswneneswneneneenwnenwnew\neseseewsewewneseeenwenwesesese\nnenenenenenewneneeneneenee\nsewewsesenwwwseeneneswnenesesesenw\nnenenwneswneswwneseswneenwnwneeswnwnwe\nseeeenwseeseeseeeswneeneweewsee\nnwenwswnwnwenwswnenwnwnwswnenwnewneenw\neswwnwneswswsenwwenenwseswseseesene\neesewswseseeenwwnweseewwnese\nneneseneneswneneenewnwneneneswnwneneene\nesesenwswesesewwnesenwewswswsenwswse\nsesewnwnwwnenewnwwwswsewne\nwnenwnwnwneenwnweswwnwswsenweswsesene\nwnwneneseeesewsesenwnesw\nesesenwnwswsewswnwseneeseseseesesenwse\nswnwnweseeeeeeeeesenwsewnwsese\nnwswnwswsweswseseseseswswswswswwneseeswsw\nwneenwseewsenwsesesewneswsesweesee\nwnewswwsenenwnwsewnwnwnwnenwnwsww\nswewswnewwneswwnweeenweenenesene\nsewneswseneseseswswswseseseseswneseswse\neeeenweeeneeseseewneeesweese\nwnwneswswnwnwnenwsenenwsenwnenwnwnenesw\nweneswnweneeneeesesweeneenenww\nseswneseseseswsesesesese\nneeeneneswneneweenenwnenwswneesene\nswswswsewnwnwseseeswswswnwswswsweswnene\nseseswseswwnenesese\nnwneswwseneneneeewwseneneenwesww\nwnwnenenenwsenwnwe\nnwwenenwenwswsenwwwsewswwnenwnwesw\nnwnesenwnwswsenwnwwnwwnenwwnewnwww\nsweeenweeeeenwsweeeeeeswneee\neeseseswnwnweeeeneeseeesewnwee\nseswsesewweneswseswnweswneswsewneswsw\nwwwwsenewnwwwwwnesewswwneww\nswwnwnwseseswewsenwswswewnw\nwenwwnenwsweswnewsewswwsewnwweesw\nseeseeneeeeswwenwseeeswseeeee\nnenwneswnewseswnenenwsenewnenenenwsene\nneneneneswenenenwwneeswneenenenenenene\nenwnwnwnenwwsenenewnwnene\nnenenwneswnwseeswnenwneseeneneeswnene\nnenenesenwnewnwnwnesenwnenwnwnwwnwnene\nwwwseseeneswseswnwsewswswseneeene\nwwwseesesenwwwwwnwwnewwswsw\nwwswswwnwnwesewseswwnweswnwseeww\nneswnwswnwswenesewnew\nwewsewnwnwnwnwnwnenwnwwnwnwnw\nswsesweswneswnwneneeswswwwswswswsesenw\nwwweswwwswwwswswwswnw\nseseswseswsweswnwseswswsweseswseseswnw\neswwneswswswneeswseswwwswswewene\nswsewnwneswnwswswseeswsewnwseswnwseese\nneweswswswswswsweseswnwnwnesenwswneswsew\nnenenenenewneneneneneeneswnwwnenenee\nnewnwwsesenwseeseseseeeesweneseee\neneeeeeseeeeeswee\nwswweneneseseswswseseneswswseswswwsw\newnenwneeseneeneneneseeneneweneee\nswwwswwenwnewswseneswswswswwwwsw\neeneesweenweeeeeneweeeesew\nnwwsenwnwnenweseeweewsewsenewswnesw\nnwwnwnwnwnwnwnwwenwnwnwnwnwnewswsenw\nnwnenwnenwnenenweswnwnenwnwne\nsesenenwenwnenweseneneeneneseenenew\nseseeeeseeswenwse\nseseseeenwseseeeewsweseesenwee\nseseseseeseswnwsesweneseswsenwsesesesese\nswwseswswseswswwwneswswwwswnesw\nnwnwswwneeswnwnwwnwnwwsewnwwnwew\nnewneswseswwwswwwwnewwsenwwswswswse\nnwwnwnwswenwnwwwnwnweswnwwewnwswnw\nwwsewwwwwneewwwwswswnwweww\nnwnwnwswnwnwnwnwnenwnwnwnwnwnw\nnwnwnwnwwnwswswwewwnewwne\nswwneeswwnwnenenenenenenenenenenenwnese\neeneeneeeweeeewnesenweeeesw\neseewwswwwnewwwnewwsewwwew\neswwsenenwsenewesesesewesesesenenwse\nswswswswswswwwnwswseswsw\neeseenewswwnesewweneeeenweseese\nwneseswswneswnwnewnewsenewnesewwsww\nswsenwseneswneswswswswnwswseswwwswswwsw\nnwnwnwsenwnwnwnwnwnwnwnwnwnwnwseswswnene\nnwsweseeseseswsenwenwseenwsw\nseswseneseswseswnwnwsewswe\nswsweeenwnweneswe\nenwwnwwnenwnwwewnwwwswsewnwnww\nnwewwsweewswsweswnwewneswnw\nwnenenwnenwnwwseneneneeneswnenesenene\nenwwswesewesene\nnenenwneneswnewenwnenenwswseenwwnwwsesw\nsenwnwseswswswswswseseswswsenwwswswswseee\neeeseeseeeewee\nneeswnweenweeswnwswwenenwneswneeene\nneseenenwseeeenwesweswwwswenenene\nnwnwwnwnwswseneneswwnenwsenwnwnwewnwswne\nsesesenwseseseseesenwseseswsesenwsesese\nnwesewseswsesesese\nwwswseswnwswwswnwsenesewsenwwwnene\nswnwwnenenwnwnwnenwnwnenwnwsenwnwne\nnenesenesenenenwneenenenwsesenwnesewnw\nsenwwwswwnwwnwwnwwnwwnewsewsew\neswnwswswwswswswwswsww\nwneneseneewnenene\nsewesweeeeeeseneweseseseneese\neeeseenwesweweewseenweee\nsesesenesenwsesewseswsesweseswsenenwsw\neenwnwwswswneewswnwnwswwswenewne\nsenwnwenenewwnwnwwwesenwnwnwnwnwew\nseewwseneswenweeeseseseseeeseenw\nswwswswsenwswswwswneswwswwenwswnesesw\nesenenwseeneenenenwenenewneeewnene\nwwswseswsenwwwswnwswenewnewswsw\nneeeeeeswenwseeneeneseeeenew\nnwswswnwnwswsesewswswswneswnweseseseese\nswseseewseseneeseseseeseneswsesenwe\nswwswwnwneseneeswswseswswwnwswnenwew\nseswsewseneneseseswwsesewseswseesenesw\nswseswswseswswnweswswswesewwswswenw\nwswnwnwsweneswenwnwsenewsenwwswnew\nswewwwnwnwwwwwnwww\nseeseseenesewseeeeeenesewneswesw\nsewseseswseswswseswsesesesweswwne\nnwnwwnwesewseswneswnwnwswnewwwneww\nnenenewneenenenenenenewenenene\neeeesewswneeeseeeeeswwenwnene\nesweenweeeeenee\nswesesewswsenewsesese\nseseswseswseswswseswswwnenweswseswswsw\nswswswseswwswswneswswnweswswewwwww\nsweeeeswneeeeeenweee\nswnenwnwenwnenwnwneswnwswnwneneenenwe\nsweseswswnwswseswwswswswswswswswswnww\nwwswswwswwneneswwwwwwnewseww\nseseesenweseswnwseseseswswseenwesese\nnenenenenenenwnewneseenenenenenene\nneeswnenwnwnewnwsweneeswnwnenwnwnenwnw\neewneeeeeeeneeenenwneneeswswne\nwseswswesesesenwsenewseseeseswswsesese\nnwewnwwwseswnwnenewswneseseneenwswsww\nnewwwnwnwwnenwwwwwsenenwwnwsesese\nnewwwwenwnwnwwwwwwewwwwsw\nwneseneswenwswneswneswwnesewswswswew\nesenwswsewsesesewsenesewseeneesese\nnwswwnwnwwnwewnwwwwnwwewwse\neeswnwnwnwnenwneneseswseswewsewseseswsw\neseenenwseeswswseseweneswswnewenene\nnenewsenwnenenenwneneswnweeeseneneswsw\nnweswswnwesewnewsewwwwwnwwnenwnww\nneeseenweneneneneeneesenewswwnee\nswesenwseneeesesesesesewsewsenwese\nwnwnewwwneewwwwwwwswwwwse\nnwwnwnwnwnwswnwnwnwnwenwnwnwseesewnwnw\neneswswenwneneseswwseneeenwewnenw\nneswnenwneneenenwnenenenwswneswnesesew\nsesesesesesenwswnwseseswsewseseswsesene\nwseswnwswseseenwnwswe\nwsenwsenwnwnwneewwwswenewnwwnwsw\nnwnwneswnenewnweswnwsenewneenwnwsene\nnewneewewnewneswwseeenewnwsesesew\neeseeswneseseswnwseswesenwswwenenwne\nesenwswswsweswswseneseseswsewsenwsese\neswneneneswnenenenwswnesweeeneenenw\nsweseseenwsewswseseseeseenesenwseesee\newnwwwwwwswsewwwswswnewwnesw\nneeweenwnesweeswneeswneneenenee\nwsewwnwswwnwwseesewwswnenewwwe\nsweswenwswnwwnenwnwnwneswnwenwnw\nswnenewenwswsesewswnwwswwswwwww\nsenenwewsesesenwsesewnewnesw\nwnenwseneswwnenenwswnwnenenesesenewneene\nswnenwewswswswwwswseswneswswswwswswsw\nwneeswnewwsewnwwwnwsenwwwwsenwnw\nseseneenewwnenwenwnwsewwswsenewsene\neeeswseseseewneseesenwewswsenenesw\nnesenenenewnwnwnenwnenw\nneswewnwsewwewswsewwwwnwwwwne\nnwnenenenenenesewneneneneneswne\nswseswsesenwnenewnwwwwswswwwnenesesesw\nswseseesesewsenwswseswsenwesenewwnew\nseseneenweenwseeneenweneeeewnene\nwneenwseseeenewnweneneesewsenewee\neewesenweeewneeeeeseeeeee\nseswneseenwsesesenwsesesesesesesewswswse\nseswnweswnwseswswswseswswseeenwswswswsese\neneswenenenewnenenenenwneneswneneswnwse\nwsenewwwsewnwwwwwswneseswwww\nnenenwswenwsenwswneweweswnewsenewe\nesweeneeeswneneenenwneseneenwe\nneseseswesewswsenwswseneswseswswswseswsesw\nnwnenwseneneeneseenee\nnenewneeeneeswewswwsenenenweenesw\nnwnwseswnenwnwenwwseeneswwwnwnwwswse\nseswswswseseseswnenwsesesesesenwswsweswsw\newneswwwswnwwnwnwswwwesewenww\nnwsenwnwnwnwwnenenenenenwnwne\nwnwsenwnwwnwenwsesenenewnewwnwwnw\nwsenwnwswsenwnwsewsenwnwwnenwenwsenw\nesewsewenweswenesesenweseeseseswese\nnwenwseenenwneneneewneneswnwnewnwwne\nneenenwswneswneenenenenwnenwswwnenenenw\nesenesweneesweswwenwneswnweswnene\newwwwewswwnewwwwnwwwsw\nesenesenwnewneseneneneenenenenwweene\nswneeswseswwsewwwwewenenwswwnwe\nsesesenweeseenwseswsesesewene\nwswsenwseseswseeseseswnwwswsesenesesese\nenweeeeeeeeeewsweenweswe\nswswseswswneswnewswswswswneswswseswsesw\neseswenweneeseswswnwwweneeeee\nsweswswswwswneswswswswswnesewswwswsw\nswnenwnwnwnenwneenenenwnwnweswnenwnwnesw\neseweneneenenwnewswnwnenwswswswenw\nnewnenesenwneenenenew\newswswswneenwnenenenenwnwnenenenenwsw\nneneneswswenwenenenenenesenewnenesenenene\nwnwwwsenwwwwwwwwnesewnwwsewnw\nneeneeenwewneenweeswswesenene\nseseneswswsenesesesenwswseswsesesesesewse\nnwnenwswseeeswnenwnwnwnwwnwnwnesenwne\nseswswswsweneswseswswswswswseswnwsw\nswwnwnwwnwnwnwnwnwnwsesenwnwnwnwenwnww\nenwnwnwneswnenwnwnwswnwnwnwenenwnwnwnwsesw\nnwswswswswswseswneswswswswseswswswswsenw\nwnweswneeeneeswswneeneewseneenee\nseneesenwnwnesewnwwnwnwnenw\nnwenwnenenwnwswnwnwnwnenenwswsenwnwenw\nnenwnwnwnenwnwnesweseneneswnenenwnwswswne\nwnwwwwnwwnwsenwnese\nnwwswwwnwwwnwwswenenwwwsenwww\neswswnenenenwswenewneeesweeenenene\nsweseneesesewsewweneeeeseewsew\neeneeeneeeeeeweseeeneeswsw\nsenwnwswnwenwnwwnwswnwenwnwnwnwnwnwwnw\neeswnenenweswneswwnwenwneeenwswsw\neeswswweeenweeeenweeneeee\nnenwnwnwnwnwnwnwneswnenenenenw\nseeseeenenweseeewsweewesesee\nsweseswseseswneswswswnwsenwnwswsweswesese\nnwwesewwwwwnwwnwwwwnenwswwnw\nwseswwswwwwneswswwweewwswswwe\nsewnwnwweseswnwswewswwswwnewsww\nswwwwswwswnwswswwwswe\nnwewneneswnwswswneswsewseeseewswse\nswswnwswswseswswswsenwnwsweneneneseswwsw\neenenenwseeewseneenwseneneneenee\nswswswseswswwneswnwswwswsweswswswswnew\nsewnesweewnenewneneneseswneweneese\nsenwsewnwsenwnenwenwsenwnwnwnwnwwnwnwnw\nsenwneswnenwnwnwwnwnwsewnwnwsewwnwnw\nswneneeneenwneeneeee\nswwswwswnwswswswswwswswswsesw\nnenwswnwnenwnwnwnenwenwnesweeswnenenene\nsweeenwnewenwsenwneeeneswneneeseee\nswenwenwsweswnweeeee\nnwwnwnwnwwenwnwnwnwnwnwseswnwnwnwwneenw\nnwnewnenwnwnwnwnwnwnwsenenwsenwnwnwnwnwse\nswseweswswswesewnwwwnwwwseewnew\nsenwswnewnwnesenwwsewesesewnwseneswnw\neneeneeneneeenwneesweenwesewsee\nsweenwswwwwwwwswswswswnw\neeseeseneweesewseseeneseswnwnew\nwswnwseewnwwsenwwnewwwwsweseswne\nnenwnwswnwnwneneneneenenenewnwnwsenene\nwwswseswseswseswsewneswseseeswneswseswse\nnwnwswwnwenwnwsweenwewswnwswnwnwne\nsenenenwwnenenenenenwsenewneneneswenwne\neeeseeneweneweenweneeeeesee\nswneswswseswswwswswswswsenewswswswswwne\nswneswswnwnwnwnenwenesweesewneenwswnenw\nwwnenwnewsenwsesesenwwnwneswwewne\nnewenwwnwsewseneewseneeeneeneesw\nenesewwnwnwnwswneenwnwswnwwwwnwwe\nsenwwwwwswwnewsweswww\nnwswswwnewwswwwwwswwwsesew\nnesweneewenwsweneseeneeenwnesww\nseseswwseseswseseseswsesewneseswswnese\nwseswnenwnewnwswneewnwwseenwenwene\nnwnwwwwweseswwwnwwwwsenwnwneew\nnwnwswnwnwnwswenenwnenwnenwnwnwne\nseeeeeswwsewewnwwwenwwsenwne\nneswnenwnwwwnenwenwnwnwneseneenwnenwnene\nswseswseseswenwneenwswswswsewewswsw\nnenwnwnenenwswnwnwnwnwnenwnw\nseneneseswseswsesesesesesesenwwseseswsese\nswwewewsewwswnwwneswswwwswwwsw\nneeewseseeswesesenwnweewnwseswsesesw\newsweneesenwnesewneseeneeneenee\nnwnwnwnwnenwnwnenewnwenenwnw\n"
  },
  {
    "path": "advent-of-code/2020/inputs/3",
    "content": ".#..........#...#...#..#.......\n.###...#.#.##..###..#...#...#..\n#.....#................#...#.#.\n#.....#..###.............#....#\n......#.....#....#...##.....###\n....#........#.#......##....#.#\n..#.......##..#.#.#............\n#.............#..#...#.#...#...\n.#...........#.#....#..##......\n......#..##..#....#....#...##..\n....#.##.#####..#.##..........#\n..#.#......#.#.#....#.....#....\n...###.##......#..#.#...#...#..\n...#..#.#..#..#.......#........\n...#....#..#...........#.#.....\n....#.........###.#....#...#...\n....#..##.....#.##....##.#.....\n........#.#.#.....#........#...\n..#..#.....#.#...#.#...#.#.....\n....#..........#....#....#...##\n.##...#..#...##....#..#.#....#.\n.#....##..#...#................\n..#.###.........#.###.....#....\n....#..#.......###.#...........\n#...#...#.#...........#.#......\n.#..#.......##.....##...#......\n....####.#..#.#.#...........#..\n.##...#..#..#.#....##.....#..##\n...#......##....#...#.#.###....\n##.#...........#.........#...#.\n...........#...#...........##..\n.....#....#...........#........\n...#..#.........#...#....#.##..\n.....##.........#...#........##\n....#....#..#.#...#...##.#.....\n...#.#..#...#...........#..#...\n.....#.#.....#....#...#....#...\n.#.............#..##..........#\n..........#......#..##.....###.\n..#....#........#.#.....##...#.\n#..#......#.#.##......#.#.##...\n.....#..#.........#...#.#.#.#.#\n#.#...#.......#.#..##.##.....##\n.....#......##......#.......#..\n#.....#...##.#.#........#......\n#..........#.#...#.......#.....\n..#..#........#........#.......\n...#....#....#..####.#....#...#\n#.............#.....##....#..#.\n##....#.....###..##....#......#\n#.....#...#.#.............#....\n.#.#..##..##.#..#....#.#.#...#.\n.#...#..#.....#..#.#.#..#...##.\n..#.#.#.#.#.#....##...#........\n.......##.....#..........#...#.\n...#..#...#...........#....#...\n.....#..#....#..#.##...#.......\n..##..#.......#.#..#....#......\n...#...............#.#..#......\n....#........#...#....#...#.#..\n...#...#..........##....##.#...\n..###.#.##.............#..#.#.#\n##.......##.#..#.#.#.....#.#.#.\n..#####...#......##...#........\n...#.##...#................#..#\n..#......#...#....#.#..##..#...\n#.#.........#............#.....\n##.............#.#.....#......#\n....#.......#..#..##....#.#....\n...#...##....#.........#..#....\n...####.....#...........#....#.\n#.#........##....#..#..#...#...\n....#.#.###..........#........#\n#.#......#.....#.##....#.#...#.\n#....##.#..##..#.#.............\n.#.....##..#..................#\n...#.#........#...#.#........#.\n..#....#......#.....##........#\n....#...#....#...#.....#.##....\n...#........#.......##.........\n.#.##......#......#....##......\n.#...#...###.#............#..#.\n.#...........#.#.#....#...#..#.\n.#.....#....#.....#...#........\n.#..#.....#............#.#.##.#\n...###.#.............#..##.....\n...#.#.##.#..#..........#..#...\n.#.#.#....#..#...............##\n.......#.#..#...#.#.#........#.\n....#.#...#..##....#........#.#\n..........#...#.......#..#....#\n...###.....#.#....#.....##.....\n#......#..#..#........#.#...#..\n#......#....#..#.#.............\n...#....#........#...#..#......\n...#..###........#.#.........##\n#......#.#..###..#........###..\n.#.#......#.#..#.#.#.#.....#..#\n#....#.....#..##.....#.........\n....#......#...#..#..#.#.##.#..\n........#.#...#...#..#...#.#..#\n.....##........#...#....#...#..\n....#...##..#........#....##.#.\n...............#.....#......##.\n..##.....#.....#.#.............\n.....#.#...........##.#.....#..\n.#..##..#.##.#...##.#....#....#\n.##.....#.##......#....#..#..#.\n.......#.##......#....#...#.#..\n.#........#......#...##.#....#.\n.........#..........#.......###\n#.#.........#..#..#....#...#...\n.......#.........#......#.#.#..\n.......#...........#....#....#.\n.###...##.#.#..........#...#..#\n....#.....#...#..#.............\n.......##........#..#.......#..\n....##..#.#....#....#..#...#..#\n..#.####.....#.........#.#....#\n..............#.#..#.....#...#.\n.....#.............#..........#\n..##.#...#.....#....#.#....##..\n.#...#.......#..####..#..#...#.\n#..........#................##.\n......##.....#.................\n..##...#.#..........##.#...#...\n....#.#.#.#...##...#...#...####\n.............##..#.###...#.....\n#.#....#.#..#..##........#..##.\n.....#.#...............#.......\n...#..##......#..##...........#\n#..#....#...........##..#......\n.##....#.#....###.......#..#...\n.....#..#.#....##...#......#...\n.#.........#####......#...#...#\n.......#.#.....#.....#.......#.\n#....#.......###.......#..#....\n#......##.###...#.......#......\n.......#...#......#....#..#....\n.#.####.......#...#.##.........\n................##.#......#....\n......##....#.#......#......#..\n....##...##....#.........#.....\n......#.#..............##.#...#\n....#.#......#.#.............#.\n.#.#..####...#................#\n....#.#.#.#......##...##......#\n.....#.#..#......#....#......#.\n..........#.#.....#.......#...#\n..##......##.#...##.#......#..#\n...#............#..#...###.....\n.#.#..###..#.......##...#.....#\n.#....#.#.......#.....##....#..\n#.............###...##.#.#...#.\n#........#.#........#.#...#.#.#\n##..#.................#....#...\n...#.#...#..#.#..##....#...#...\n#.....#.......#..............#.\n.......###...##..#.....#.......\n#.#.........#..#.#.........#...\n.#.#............#.....##.....#.\n........#....#....#.......#....\n...#.#....#..#.##....#.#......#\n.#.....#.#..#...........#.#.#..\n#......#..#......##.#.#.#.#..#.\n.......#.#..#......#.#.#..#.#.#\n..........#...#..........#.##..\n.#.#..####.......#..........#..\n......#.#.....#..#..#..#.....#.\n.....##..#.#.#..#..#...#.....##\n............#.#....#.#....#....\n..............#..#...#...#.....\n.....#......#.......#.....#....\n..##....#..#...........#..##...\n###...#.##..#.#...####....###..\n..#.#.....#.........#....#..###\n##...........##.............#..\n....##..............#.........#\n...#...##....#.#..#...##.....#.\n..#..##...#.......#..#..#.....#\n...#...#....####........##.#...\n....#........#..#.#.........#..\n.#..........#...#..#.#.#......#\n....#.#.....#.........#....#...\n...#....#...##.......#...#.....\n....#..#.......#.##.##.##...#..\n##....##........#........##....\n.#.#..#...........#.....#...#..\n...#.##...##..#...#...##.......\n.....#..###................#.#.\n...#........##.#....##.....#.##\n...#...#..##...#...#.#...#.....\n.#......#...#..#.##.......#...#\n.....#.......###.##...#........\n#.....#..#........##.##.#.##..#\n....#..............##.##...#...\n#..........#..................#\n..##.......#..........#..#..##.\n.#....###.#..#.........###....#\n.#....#.##..............#.##.##\n.#.##.#....#.......#.#......#..\n.#............#.#.....#........\n..#......#.......#.............\n#.#...#........##...#.#......#.\n....#.........#........##..#...\n..........##.....#.#......#....\n.##.#..#....#.......#...#...##.\n.#................#...#.##.....\n....###.......#..#..#.........#\n.#.....#..##...###......#.....#\n.#.##..........#..#..#........#\n.......#.##..............#...##\n#...#.#.#.......#..#......#.##.\n.#....#.#......#...#..........#\n.....#........##....#.##.....#.\n.#....................#..#.#.#.\n.....#.........#....#.......#.#\n.....#.#..##..#.....#..#.......\n...#..#..#...#.....#....#....#.\n#.....#.#.#..........#..#.#.#..\n.....##..##.....#.#..#.........\n#.#..##....##......##...#.##..#\n..##..#.....#..#..........##...\n......#.#...#..#.......##.....#\n..#.#.......#.#......#.........\n.....#........##..#.....####.#.\n.#.....#........#.......#..##..\n......#...#....#.##...#.......#\n..##..................#..#.....\n.....###.#..##...#.............\n...##...##...#......#....#....#\n#........#.#..........##..#....\n#........#....#..........#...#.\n...##.#.##..#...##......#......\n#........##....#.#..##.....#..#\n...####......#..#......#.#.....\n.#......#...#...#.#.....##....#\n.....###..##..#...#..........##\n##.##....#...#.................\n...##.#.......#.###......#..#..\n.....#.#.#.......#.......#..#.#\n#...#...#.##..#....###.......#.\n.#.#..##.....#....#...##.......\n.....#..........#....#...#.##..\n..........#....#...#...........\n.#....#..#...#...#.......#....#\n#..#..............#.....####.##\n.......#....###....#....#.#.#..\n###.#........##.#.......#......\n#..#...#..#......#.............\n#...###..#...#..#..##.#.###.#..\n..#..#...##......##............\n.#..#.......#..###..##...#.....\n....#..#..##.#.#.....##...#.#.#\n....#....#.....#..#....#.......\n..##..#....#.#...##..#.........\n.....#....#...........#.#......\n...#........#.#..#..#......#..#\n.#...##....#....#.#.##......#.#\n..#...........#..###.##.....#..\n.#.######.#..##.......#..#.....\n.....#..#......##.#.#...#......\n....#....#..#.....#.......#.#.#\n.....#........##.....#.....#.##\n........#....#...#...#.#.#...#.\n...#.#.....#...........#.....#.\n#.#.#...###......#.....#.....#.\n.#..........#.....#.......##...\n#................#.#.....#.####\n.#......#......#.#..##.#.##....\n..........#....#...........###.\n.##....#..####..#####..........\n##.......##............#.....#.\n...#.....#...#....#.......#....\n.#....##......#.#...#....#.....\n....#............##..........#.\n.#....#....#.....#.#...........\n.............##.#.##...#.#.#...\n..#............#.#..##.#....##.\n#.....#...##..........#.#.#...#\n......#............#..........#\n..##..#.....#........#.##..#..#\n#..#.#..##.#.....##.#..........\n#..#...#.#..#......##.......##.\n.##......#...........##.....#..\n...#.....#.....#..#....#.......\n.....#...............#........#\n.......#.....##..#..##..#.#.#..\n#.#.....#..#..........##...#...\n#..#......#.................#.#\n.##...#....#...#...#.......#...\n.#........##........#..........\n........#..........#.........#.\n.....#.##..#.......#........#..\n..##..#..#...##..#.#....#......\n......#........#.##.....#.#....\n.#...#.#.........#..#.#.#.#..#.\n.#..#.#...#............#.#..#..\n....#.................#...#..##\n.........##.....#.#.#......####\n...............#....##.#.#.....\n....##..#....#......#....#.....\n....##.#...#....#.#..#...#..#..\n..##......#.#..#........#.#.#..\n.........#.#................##.\n##.....#.....##..##.#........#.\n###....#..#..#..#..#.##..##.#..\n.....##..#...........##..#.#...\n....#..#..#..#....#...#.#....#.\n#....#............#..#....###..\n....#..#.............#....##.#.\n...#.................#...#.....\n.##...#....#..#..#........#....\n...#.#..#...#.#......#....#....\n...#.......##..........#...#.#.\n...##..#.......#........#...#..\n.....#.#.#....#..##......##...#\n....##......#........##....##..\n..#..........#.#.##.....#......\n..................#..#..#..###.\n.#..............#.#..#.#..#.###\n..#....#....#......#..##..#...#\n#.........#..#..#...........#..\n"
  },
  {
    "path": "advent-of-code/2020/inputs/3.sample",
    "content": "..##.......\n#...#...#..\n.#....#..#.\n..#.#...#.#\n.#...##..#.\n..#.##.....\n.#.#.#....#\n.#........#\n#.##...#...\n#...##....#\n.#..#...#.#\n\n"
  },
  {
    "path": "advent-of-code/2020/inputs/4",
    "content": "iyr:2015 cid:189 ecl:oth byr:1947 hcl:#6c4ab1 eyr:2026\nhgt:174cm\npid:526744288\n\npid:688706448 iyr:2017 hgt:162cm cid:174 ecl:grn byr:1943 hcl:#808e9e eyr:2025\n\necl:oth hcl:#733820 cid:124 pid:111220591\niyr:2019 eyr:2001\nbyr:1933 hgt:159in\n\npid:812929897 hgt:159cm hcl:#fffffd byr:1942 iyr:2026 cid:291\necl:oth\neyr:2024\n\ncid:83 pid:524032739 iyr:2013 ecl:amb byr:1974\nhgt:191cm hcl:#ceb3a1 eyr:2028\n\necl:gry hcl:eefed5 pid:88405792 hgt:183cm cid:221 byr:1963 eyr:2029\n\npid:777881168 ecl:grn\nhgt:181cm byr:1923 eyr:2021 iyr:2018 hcl:#18171d\n\nbyr:1941 eyr:2027 ecl:gry iyr:2016 pid:062495008 hcl:#a5e1b5 hgt:178cm\n\ncid:56\nbyr:1971\nhcl:#efcc98 pid:649868696 iyr:2011 eyr:2025 hgt:164cm\n\necl:blu\npid:117915262 eyr:2023 byr:1925 iyr:2020 hcl:#888785\nhgt:188cm\n\niyr:2012\ncid:174\neyr:2024\npid:143293382 ecl:brn byr:1946 hgt:193cm\n\neyr:2021 iyr:2011\nhgt:192cm pid:251564680\nbyr:1976\necl:blu hcl:#602927\n\nbyr:1973 ecl:blu hgt:164cm\neyr:2022 pid:695538656 iyr:2010 cid:244 hcl:#b6652a\n\niyr:2014\neyr:2027 pid:358398181 ecl:hzl hgt:74in byr:1949 cid:329\nhcl:#ceb3a1\n\ncid:211\nbyr:1954 eyr:2023 hgt:172cm ecl:blu iyr:2019 hcl:#623a2f pid:657051725\n\npid:562699115 eyr:2026 byr:2000\nhgt:162cm hcl:#602927 ecl:amb iyr:2018\n\necl:brn\niyr:2013\npid:835184859 byr:1981 hgt:157cm eyr:2027 hcl:#b6652a\n\npid:763432667 byr:1981 hcl:#cfa07d ecl:brn\niyr:2010 hgt:63in cid:107\neyr:2027\n\nbyr:2009\nhgt:177cm cid:314\nhcl:f55bf8 eyr:2025\npid:632519974\niyr:2015 ecl:amb\n\neyr:2024 pid:614239656 hgt:169cm iyr:2014 ecl:hzl byr:1992\nhcl:#602927\n\necl:blu\neyr:2026\nhcl:#efcc98\nbyr:1980 iyr:2013\nhgt:161cm\npid:065413599\n\nhgt:182cm\neyr:2025 iyr:2013 pid:939088351 hcl:#b6652a byr:1994 ecl:amb\n\nhgt:65in cid:220 ecl:amb hcl:#ceb3a1\niyr:2013 eyr:2025 pid:167894964 byr:1976\n\nhgt:185cm cid:88 ecl:blu iyr:2020\neyr:2020\nhcl:#888785 pid:582683387\nbyr:1981\n\nhcl:#866857 eyr:2020 byr:1948\npid:358943355\necl:amb hgt:164cm iyr:2019\n\npid:127467714\nhcl:#ceb3a1 byr:1991 hgt:163cm eyr:2020 iyr:2017 ecl:blu cid:229\n\ncid:156 byr:1942 eyr:2024 hcl:#cfa07d\necl:blu pid:843747591\niyr:2014 hgt:173cm\n\nhcl:#a97842 hgt:165cm\niyr:2013 ecl:#781088 byr:1952\npid:516882944\neyr:2026\n\nhgt:179cm\nbyr:1969 pid:408297435 iyr:2020 ecl:oth hcl:#cfa07d eyr:2020\n\necl:amb iyr:2013 hcl:#b6652a eyr:2023 cid:88\npid:324081998 hgt:66in byr:1945\n\niyr:2012\neyr:2024\nhcl:#18171d\npid:756726480 byr:1947 ecl:oth\nhgt:164cm\n\necl:blu\nhcl:#fffffd byr:1951 iyr:2019 pid:544645775\nhgt:153cm eyr:2027\n\npid:655906238 ecl:brn eyr:2028 byr:1959 hgt:63in cid:338\niyr:2020\n\neyr:2020\nhcl:#602927 hgt:72in iyr:2014\npid:305025767\ncid:297 byr:1957 ecl:gry\n\nhgt:155cm byr:1942 hcl:#a97842\niyr:2014 ecl:gry pid:593995708\neyr:2022\n\npid:219206471 byr:1955 eyr:2030\nhcl:#a97842 ecl:oth iyr:2015 cid:134 hgt:170cm\n\niyr:2013 cid:268\neyr:2020\nhcl:#a97842 ecl:grn pid:235279200 hgt:178cm\nbyr:1952\n\niyr:2013 pid:016384352 eyr:2027\nhcl:#866857 ecl:grn hgt:161cm byr:1943\n\necl:amb hgt:169cm pid:149540593\niyr:2012\neyr:2040 hcl:#a97842 byr:1954\n\nbyr:1938\necl:brn hcl:#b6652a eyr:2026 hgt:184cm iyr:2018 pid:832531235\n\nbyr:1945 iyr:2015 hgt:171cm eyr:2028 pid:998746896 ecl:hzl hcl:#866857\n\nhgt:73in ecl:hzl eyr:2023 cid:343 pid:458004221 iyr:2017 byr:1962 hcl:#efcc98\n\nbyr:1970 hgt:159cm pid:925022199 iyr:2013\neyr:2028 hcl:#888785\necl:hzl\n\neyr:2027 iyr:2016 ecl:gry\nhcl:#cfa07d\npid:006246552 byr:1939 cid:124 hgt:177cm\n\nbyr:1982\niyr:2016 hgt:159cm\ncid:102 hcl:#fffffd\neyr:2029\necl:grn pid:619798285\n\niyr:2018\nhgt:189cm hcl:#efcc98\nbyr:1937 eyr:2023 pid:727551553 ecl:oth\n\niyr:2014 byr:1976\neyr:2020 hcl:#7d3b0c pid:125102070 ecl:amb\nhgt:186cm\n\nhgt:187cm byr:1949\npid:027653233 eyr:2021 hcl:#341e13 ecl:hzl\niyr:2020\n\niyr:2016\nbyr:1954 pid:545631256\nhcl:#602927 eyr:2023\nhgt:191cm ecl:amb\n\npid:509762954\nhgt:190cm ecl:hzl byr:1991\neyr:2022 iyr:2019\ncid:187\n\nhcl:#c0946f eyr:2024 hgt:152cm cid:277 iyr:2015 pid:872373191 byr:1988\n\npid:544267207 cid:113\niyr:2015\nhgt:181cm\nhcl:#6b5442\necl:gry\nbyr:1971\n\necl:gry\nhgt:161cm iyr:2012 byr:1965\npid:574527322 hcl:#fffffd\n\niyr:2018 byr:1976 hcl:#b6652a\npid:024582079 hgt:169cm ecl:oth eyr:2021\n\npid:020478204\nbyr:1945 hcl:#7d3b0c\ncid:239 eyr:2025 hgt:188cm\necl:grn\niyr:2012\n\neyr:2026 pid:202653345\nbyr:1988\nhcl:#2cdc09\nhgt:185cm iyr:2010\necl:hzl\n\nhgt:183cm iyr:2017\nhcl:#18171d byr:1977 eyr:2029 pid:804559436 ecl:grn\n\nhcl:#602927 pid:812072269 hgt:170cm eyr:2026 byr:1955 iyr:2020 ecl:gry\n\neyr:2023 iyr:2010\nhcl:#cfa07d pid:592419048 byr:1943\necl:brn\nhgt:172cm\n\necl:brn iyr:2013 pid:558179058\nhcl:#fffffd eyr:2022\nbyr:1922\ncid:331 hgt:64in\n\necl:xry\nhcl:ade850 eyr:1995 pid:976028541\niyr:2030 hgt:179cm\nbyr:2030\n\necl:#2872b1 pid:158cm eyr:1927 hcl:ee8e92\niyr:2014 hgt:190cm\nbyr:2025\n\nhgt:155cm cid:283 eyr:2020 ecl:blu pid:755165290 byr:1936 hcl:#733820 iyr:2012\n\neyr:2030\nbyr:1943\ncid:323 pid:906418061 hgt:157cm ecl:amb iyr:2010\nhcl:#7d3b0c\n\nhcl:#fffffd\npid:873200829 hgt:192cm eyr:2022 ecl:blu iyr:2016 byr:1920 cid:200\n\neyr:2021\nbyr:1963\nhcl:#a97842 pid:585551405\niyr:2019 cid:91\necl:brn hgt:60cm\n\nbyr:1946\npid:520273609 hcl:#341e13 cid:66\niyr:2020 hgt:154cm eyr:2024\necl:brn\n\necl:brn hcl:#d64d7b eyr:2020\nbyr:1957 hgt:181cm iyr:2019 pid:378496967 cid:135\n\npid:002446580\neyr:2027 byr:1939 hcl:#888785\niyr:2011 cid:168\necl:oth hgt:160cm\n\niyr:2019 hgt:70in hcl:#7d3b0c byr:1983\neyr:2024 pid:369493064 cid:54 ecl:oth\n\niyr:1979 pid:170cm\nhgt:65cm eyr:1933 hcl:z\n\necl:zzz pid:193cm hcl:z eyr:2020 byr:2013 iyr:2016 hgt:177in\n\niyr:2010 hgt:187cm\nbyr:1932\nhcl:z ecl:oth pid:665967850 eyr:2030\n\neyr:2029\niyr:2013 hcl:#b6652a ecl:amb\nbyr:1936 pid:516025566\nhgt:181cm\n\nhcl:#c0946f pid:238825672 byr:2000\niyr:2013 eyr:2028 ecl:amb hgt:183cm\n\neyr:2021 hcl:#866857\ncid:77 iyr:2017 hgt:156cm pid:271118829 ecl:amb\n\niyr:2014\nhcl:#fffffd\ncid:321 hgt:159cm ecl:gry\npid:691381062 eyr:2022 byr:1991\n\npid:111506492 hcl:#c1d296 iyr:2011\nbyr:1934 hgt:176cm cid:263 eyr:2028 ecl:amb\n\niyr:2014 hgt:64in eyr:2024 cid:193 hcl:#b6652a byr:1967\necl:oth pid:138677174\n\nhgt:168cm iyr:2020 eyr:2030\nhcl:#6b5442 ecl:brn pid:975843892 byr:1927\n\nbyr:1957 ecl:amb iyr:2012 pid:177266671 eyr:2026\nhcl:#866857 hgt:162cm\n\neyr:2029\nhcl:#341e13\nhgt:175cm pid:465809700 ecl:amb byr:1974\niyr:2010\n\nhcl:#a97842 iyr:2010\nhgt:176cm eyr:2029 byr:1931 ecl:grt pid:161604244\n\neyr:2024 iyr:2018 hgt:170in byr:1959 ecl:gmt hcl:#888785\npid:94163132\n\niyr:2011\nhgt:186cm pid:998471478 byr:1956 ecl:amb\neyr:2029\nhcl:#efcc98\ncid:76\n\necl:brn\nbyr:2001 pid:378527883 iyr:2013 hcl:#83bdc5 eyr:2020 hgt:181cm\n\niyr:2017 ecl:grn hgt:172cm hcl:#888785 cid:100\neyr:2022 byr:2030\npid:311562177\n\npid:097558436\ncid:141 hgt:152cm iyr:2019\necl:brn eyr:2023\nbyr:1940\nhcl:#6b5442\n\niyr:2016 eyr:2023 byr:1992\nhgt:174cm ecl:amb\npid:691291640 cid:190 hcl:#fffffd\n\nhcl:#623a2f ecl:brn\neyr:2028 cid:227 iyr:2012 hgt:74in pid:964273950 byr:1965\n\nhcl:#ceb3a1 eyr:2028\niyr:2013 pid:175294029 hgt:150cm ecl:grn\nbyr:1936\ncid:143\n\nbyr:1935 hcl:#a97842 ecl:oth hgt:180cm iyr:2019\npid:857891916\neyr:2026\n\npid:084518249 ecl:hzl eyr:2027 hcl:#c0946f hgt:192cm cid:315 byr:1961\niyr:2010\n\nhgt:67cm pid:37925169 eyr:2022\nhcl:z iyr:2012 cid:315 byr:2028 ecl:dne\n\nhcl:#c0946f byr:1924\nhgt:176cm cid:87 pid:682212551 iyr:2011\neyr:2026\necl:gry\n\nhgt:181cm byr:1935\niyr:2018 pid:644964785\neyr:2026 ecl:amb\n\npid:789810179\necl:gry eyr:2021\ncid:159 hgt:185cm iyr:2020 hcl:#602927\nbyr:1965\n\npid:672386364\niyr:2013 eyr:2021 byr:1951 hcl:#341e13\necl:gry hgt:173cm\n\nhcl:#18171d eyr:2030 pid:957722245 iyr:2012 byr:1955\necl:grn\nhgt:154cm\n\nbyr:1955 ecl:oth\nhcl:#cfa07d\neyr:2030\niyr:2013 pid:361945273 hgt:154cm\n\niyr:2012 eyr:2027 ecl:grn hcl:#16d373\nhgt:192cm\n\npid:275525273\nbyr:1986\niyr:2017\neyr:2022\necl:grn\nhgt:75in\nhcl:#919cc0\n\neyr:2029\ncid:84 hcl:#cfa07d iyr:2013 hgt:78\necl:brn\nbyr:1925 pid:281331549\n\neyr:2027\ncid:219 iyr:2016 byr:1971 hcl:#7d3b0c hgt:179cm ecl:grn\npid:301296222\n\neyr:2030 iyr:2010 pid:995982765\nbyr:1926 ecl:amb hcl:#888785 hgt:186cm\n\nbyr:1955 iyr:2015 hgt:165cm cid:101\neyr:2027 ecl:amb hcl:#602927\npid:168654790\n\nhcl:#7d3b0c byr:1956 eyr:2029 hgt:155cm\necl:grn pid:816685992\niyr:2016\n\necl:grn hcl:#cfa07d cid:71\npid:914724136 iyr:2012 eyr:2024\nhgt:184cm byr:1938\n\necl:gry\neyr:2029 hcl:#602927 pid:255062643 iyr:2015 hgt:175cm\n\nhcl:#341e13 iyr:2017 eyr:2028\npid:459704815 byr:1922\ncid:312\necl:brn hgt:152cm\n\necl:dne eyr:1981\npid:8356519470 hgt:176 iyr:1941 byr:2006 hcl:z\n\necl:amb pid:753377589 hcl:#a97842 eyr:2022 hgt:187cm\ncid:130 iyr:2013 byr:1961\n\npid:952444443\nhcl:#bde835 byr:1963 iyr:2020 eyr:2025\necl:amb hgt:162cm\n\neyr:2027 iyr:2018 hcl:#ceb3a1 hgt:152cm pid:882429463 ecl:blu byr:1969\n\ncid:134 eyr:2021 hcl:#a97842 hgt:63in\necl:grn byr:1975 iyr:2019 pid:154078695\n\nbyr:1956 eyr:2027\npid:396230480 hcl:#b6652a\nhgt:175cm iyr:2020 ecl:oth\n\necl:grn\ncid:263 hcl:#506937 byr:1924\neyr:2030 pid:705511368 hgt:159cm\niyr:2011\n\neyr:2020 hgt:178cm ecl:grn\nbyr:1947 hcl:#888785\npid:177476829 iyr:2019\n\necl:hzl cid:211 iyr:2016 hgt:176cm pid:405182470\nbyr:1952\nhcl:#866857 eyr:2028\n\neyr:2032 cid:152 ecl:gmt hgt:150in\npid:75969209\nbyr:2019 hcl:z iyr:1940\n\nhcl:#fffffd hgt:193cm pid:607407479 cid:300 byr:1944 iyr:2017\necl:oth\neyr:2026\n\nhcl:z\ncid:125 eyr:2040 ecl:dne byr:2015 pid:733096171 hgt:63cm\niyr:1922\n\npid:575721428 hgt:152cm cid:275\nhcl:#cfa07d eyr:2028\nbyr:1935 ecl:hzl iyr:2016\n\niyr:2012\necl:grn eyr:2027 hcl:#623a2f pid:029106453 byr:1984 hgt:168cm\n\necl:blu cid:140 eyr:2028 iyr:2018 hcl:#c0946f\nhgt:163cm byr:1944\npid:709288293\n\nbyr:1936\nhgt:172cm eyr:1997 hcl:#8b8c88 cid:50\niyr:2016 pid:205477922 ecl:grn\n\nhgt:170cm pid:872750582 eyr:2027 byr:1985 iyr:2017 hcl:#d6976a ecl:blu\n\nhgt:163cm\npid:189634089 cid:116 byr:1975 eyr:2030\nhcl:#efcc98 ecl:brn iyr:2020\n\necl:amb byr:1953 hcl:#6b5442 pid:418787965\niyr:2018 hgt:193cm\neyr:2026\n\necl:#3ec898 cid:339 hcl:#866857 eyr:2025 hgt:179cm pid:591430028 iyr:1936 byr:1995\n\npid:285371937 hgt:159cm\nbyr:1922\niyr:2013 eyr:2023 hcl:#6b5442 ecl:amb\n\npid:545260883 ecl:oth\nhgt:163cm\niyr:2015 eyr:2021 byr:1975 hcl:#866857\n\necl:hzl hgt:182cm pid:053762098 eyr:2023 cid:174 hcl:#6daac4 iyr:2017 byr:1937\n\nhgt:178cm iyr:2015 byr:1956 pid:815359103\necl:blu hcl:#cfa07d eyr:2030\n\nhcl:#7d3b0c\npid:438108851 hgt:162cm byr:1930 iyr:2014 eyr:2024 ecl:amb\n\neyr:2027 iyr:2019 hcl:#90eb1c hgt:178cm\npid:314810594 cid:278 ecl:amb\nbyr:2001\n\nbyr:1949 iyr:1942 hcl:#888785 ecl:hzl hgt:184cm eyr:2027 pid:899137640\n\nhgt:153cm\neyr:2022 iyr:2011 byr:1975\nhcl:#602927\necl:amb pid:178cm\n\nhcl:#6b5442\necl:amb iyr:2018 eyr:2025 pid:418735327 byr:1922 hgt:74in\n\necl:gmt hcl:z iyr:2024\neyr:1988 hgt:75cm cid:125 pid:690872200 byr:1928\n\neyr:2024 hgt:184cm\npid:4634589837 ecl:zzz iyr:2022 byr:2000 hcl:89c187\n\niyr:2017 byr:1966 hcl:#efcc98 ecl:brn pid:473085232 eyr:2021 hgt:174cm\n\nhgt:67in eyr:2030 iyr:2014 byr:1943 hcl:#602927 cid:344\necl:oth\npid:210476779\n\nbyr:1955\necl:oth\nhgt:193cm iyr:2012 hcl:#623a2f pid:818289829 eyr:2021\n\nbyr:2018 ecl:#872a51 iyr:2024 hcl:97783d\npid:155cm hgt:174cm\neyr:1964\n\nhcl:#6b5442 hgt:157cm byr:1932 ecl:brn pid:4275535874\neyr:2024 iyr:2015\n\npid:959861097\nhgt:151cm cid:140 byr:1935\neyr:2029\niyr:2018 ecl:hzl\nhcl:#623a2f\n\nhgt:181cm pid:911791767 eyr:2027\niyr:2016 byr:1962\necl:grn hcl:#866857\n\neyr:2021\nbyr:1994\nhgt:162cm hcl:#866857 ecl:oth iyr:2014\npid:712345689\n\nhcl:#7d3b0c\nhgt:170cm pid:600132416 eyr:2025\niyr:2016 byr:1978 ecl:brn\n\nhcl:#0a9307\ncid:287 byr:1940 pid:786271493\neyr:2028 hgt:186cm\niyr:2019 ecl:oth\n\neyr:2025 hgt:190cm ecl:hzl cid:228 iyr:2019\nbyr:1932\nhcl:#623a2f pid:648307551\n\npid:304587325 iyr:2019 byr:1923 hcl:#7d3b0c\nhgt:190cm\necl:gry eyr:2030\n\nhgt:188cm eyr:2027 byr:1958 pid:572934921\nhcl:#888785 ecl:hzl iyr:2010\n\niyr:2019\nhgt:178cm ecl:grn hcl:#7d3b0c pid:007601227\nbyr:1975 eyr:2023\n\npid:808872803 byr:1929\necl:grn\neyr:2022 iyr:2019 hgt:74in hcl:#602927\n\niyr:2019\ncid:67 hcl:#602927 pid:292601338 ecl:hzl\nbyr:2001 eyr:2023 hgt:171cm\n\nbyr:1962 eyr:2022 hcl:#b6652a hgt:193cm\necl:oth\niyr:2010\n\nhgt:70in iyr:2014 hcl:#a97842\ncid:169 eyr:2020 ecl:amb\npid:329751670 byr:1959\n\nbyr:1920\necl:oth hgt:172cm cid:57 pid:515139276\neyr:2030\nhcl:#18171d\niyr:2013\n\niyr:2012\nhcl:#a97842 pid:946040810 hgt:65in\nbyr:1936 ecl:amb eyr:2020\n\nbyr:1948 hcl:#18171d\niyr:2019\necl:hzl cid:185\neyr:2023\npid:583625200 hgt:191cm\n\nhgt:154cm eyr:2022\npid:460137392 iyr:2010\necl:grn\nhcl:#ceb3a1\n\neyr:2024\niyr:2016 pid:890698391 hgt:172cm hcl:#a97842 cid:271 ecl:oth byr:1926\n\nhgt:162cm pid:340904964 hcl:#b6652a\nbyr:1966\niyr:2010\ncid:260 eyr:2028\necl:amb\n\nbyr:1933 eyr:2029 pid:642043350\niyr:2016 hcl:#b6652a ecl:grn\n\npid:602218620 eyr:2023 ecl:blu\nhcl:#623a2f\nbyr:1950 hgt:168cm iyr:2015\n\necl:gry pid:490792384\nbyr:1974\nhcl:#a97842 iyr:2016 hgt:170cm\n\niyr:2020 ecl:gry byr:2002\neyr:2029 hcl:#9f45c4\nhgt:155cm pid:604239618\n\nhgt:190cm pid:560653271 iyr:2020 cid:349\neyr:2024 ecl:blu hcl:#efcc98 byr:1936\n\neyr:2021 byr:1964 hcl:#efcc98 ecl:grn iyr:2018\nhgt:165cm pid:218376636\n\npid:186217101\niyr:2019 hgt:155cm\nbyr:2017 eyr:2022 ecl:grn cid:349 hcl:ece72e\n\niyr:2015\neyr:2026 pid:802832833\nhcl:#888785 hgt:190cm ecl:brn\nbyr:1952\ncid:202\n\ncid:151 iyr:2017 hgt:152cm hcl:#a97842 eyr:2020 ecl:hzl\npid:554959609 byr:1941\n\ncid:116\niyr:2019 hgt:159cm byr:1992 pid:662111811\nhcl:#18171d ecl:oth eyr:2024\n\necl:grn byr:1966\niyr:1950 pid:585351486\neyr:2038 hgt:178in hcl:a27d2b\n\niyr:2014 cid:238 hgt:187cm pid:523401750 ecl:amb hcl:#18171d eyr:2023 byr:1984\n\neyr:2021 byr:1957\npid:340752324\niyr:2015 hgt:157cm\nhcl:#602927 cid:70\necl:oth\n\npid:458479816 ecl:hzl\neyr:2022 hcl:z\nhgt:60cm\nbyr:2012 iyr:2005\n\ncid:57\nhgt:154cm pid:446142864\nhcl:#341e13 byr:1968 eyr:2030\niyr:2019\necl:brn\n\neyr:2028\npid:243811429 byr:1977\niyr:2011 hcl:#18171d hgt:185cm ecl:oth\n\ncid:205 byr:1976 eyr:2029 pid:649877471 hcl:#cfa07d hgt:152cm\necl:blu\niyr:2013\n\niyr:2009 pid:559014976 ecl:oth hgt:189cm byr:1936 eyr:2037\nhcl:#efcc98\n\npid:134378987 byr:1983 iyr:2013 hgt:173cm\necl:oth hcl:#ceb3a1\ncid:80\neyr:2020\n\nhgt:151cm byr:1964 ecl:grn iyr:2010 hcl:#b6652a pid:939492531\neyr:2028\n\nbyr:1961 iyr:2014 hcl:#733820 hgt:179cm\neyr:2026 ecl:gry pid:732892920\n\niyr:2018 byr:1996\npid:944007809 ecl:hzl\nhcl:#866857 eyr:2021\nhgt:155cm\n\npid:374875696 hcl:#7d3b0c\necl:oth\nhgt:193cm byr:1948 cid:238\niyr:2020\n\npid:305782299 hcl:#b6652a\necl:brn\nhgt:172cm\niyr:2018 byr:1927\n\npid:945869114 cid:95 byr:1989 hgt:173cm eyr:2025 hcl:#b6652a iyr:2012 ecl:amb\n\npid:55484149\neyr:1958\niyr:1956 ecl:grn\ncid:95 byr:2028\nhcl:c2af7e\n\nhgt:176cm ecl:amb\nhcl:#a97842 eyr:2029 pid:937928270\ncid:251\nbyr:1978\niyr:2018\n\nhgt:154cm\ncid:213 pid:767329807 ecl:hzl\niyr:2013\nhcl:#888785\neyr:2026 byr:1998\n\ncid:158 hcl:#b6652a hgt:155cm iyr:2010 eyr:2025\nbyr:1980 pid:338567803 ecl:amb\n\nhcl:#efcc98 byr:1940 hgt:62in ecl:oth pid:537307591\neyr:2030\niyr:2017\ncid:179\n\nbyr:1965 eyr:2027 pid:691913618 hgt:75in\nhcl:#6b5442 ecl:gry iyr:2012\n\nhgt:163cm byr:1964 eyr:2025\niyr:2010 hcl:#ceb3a1 ecl:oth\npid:936536544\n\npid:712946803\ncid:343\nhgt:187cm ecl:oth iyr:2020 byr:1983 eyr:2030\nhcl:#7873b3\n\necl:blu\niyr:2010\nhcl:#fffffd\neyr:2030\nhgt:175cm pid:047567505 byr:1963\n\necl:gry byr:1946 eyr:2026 hcl:#602927\nhgt:164cm\niyr:2010\n\npid:223378458\niyr:2014 cid:151 ecl:hzl hgt:171cm\neyr:2020\nhcl:#341e13 byr:1964\n\necl:brn byr:1948\nhcl:#866857\nhgt:193cm eyr:2024\niyr:2013 cid:277\n\nhcl:#623a2f byr:1943 iyr:2011 ecl:oth\nhgt:184cm\npid:371604584 eyr:2024 cid:176\n\nhcl:#efcc98\neyr:2025 pid:241834382\nhgt:178cm\nbyr:1985\niyr:2017\n\nhcl:#c0946f\nbyr:1996 pid:701366586 eyr:2026 hgt:163cm iyr:2015 ecl:oth\n\nhgt:65cm hcl:#18171d\neyr:2024 ecl:brn pid:172cm\niyr:2010\nbyr:1990\n\nhcl:#fffffd pid:68659204 hgt:161cm iyr:2025\necl:#94b8aa byr:2021 eyr:2032\n\necl:blu iyr:2018 byr:1993 cid:184\nhgt:177cm pid:289871693 hcl:#733820 eyr:2026\n\ncid:138\necl:gry hgt:174cm eyr:2024 byr:1988 iyr:2014 hcl:#341e13 pid:864852584\n\ncid:321 eyr:2028 pid:93285596 hgt:173cm\niyr:2013 ecl:gry hcl:#623a2f\nbyr:1927\n\npid:431242259 eyr:2022 ecl:hzl\nbyr:1960 hgt:151cm hcl:#efcc98 iyr:2020\n\nhcl:#866857 eyr:2029 iyr:2016 ecl:grn pid:526060780 byr:1929\ncid:310 hgt:162cm\n\necl:blu hgt:183cm cid:168\niyr:2015\neyr:2021 byr:1951 hcl:#6b5442\npid:594960553\n\nhcl:#ceb3a1\niyr:2020 byr:1951 hgt:186cm eyr:2022 ecl:amb pid:317661479\n\niyr:2016\nhgt:163in hcl:#accfa0\necl:brn\npid:307377995 byr:2000 eyr:2028\n\npid:933380459\nbyr:1938\ncid:291 hcl:#c0946f\necl:oth iyr:2018\neyr:2026 hgt:170cm\n\nbyr:1974\npid:262927116 eyr:2027 ecl:gry\nhcl:#341e13 iyr:2014 cid:232 hgt:161cm\n\nhcl:#602927\nbyr:2001 iyr:2011\nhgt:177cm eyr:2028 pid:165733929 ecl:amb\n\nbyr:1922 cid:144 pid:333716867 hgt:183cm iyr:2015\nhcl:#c25ea9 eyr:2022 ecl:blu\n\neyr:2021 cid:147 byr:1978\niyr:2020 pid:938828535\nhcl:#7d3b0c ecl:amb hgt:159cm\n\nhgt:153cm ecl:hzl\ncid:232 byr:1953 hcl:#a97842 iyr:2016 pid:356632792 eyr:2029\n\npid:745727684 ecl:gry iyr:2020\nhcl:#a97842\neyr:2025 cid:275\nhgt:65in\nbyr:1957\n\nhcl:#733820\necl:grn iyr:2019 byr:1943 eyr:2024 hgt:70in\npid:953607814\n\necl:gry eyr:2028 hcl:#cfa07d\nhgt:163cm\nbyr:1942 iyr:2019 pid:310104177\n\nhgt:190cm\neyr:2027 iyr:2010 byr:1978\necl:gry\nhcl:#964ba7\n\ncid:320\neyr:2022 hgt:169cm\necl:blu hcl:#a97842 iyr:2015 pid:669007078 byr:1986\n\niyr:2019 pid:901370677 hcl:7f2398 cid:305\necl:amb eyr:2011 hgt:190cm byr:1991\n\necl:brn\ncid:256 byr:1987 iyr:2017 eyr:2026 hcl:#623a2f pid:875646528\nhgt:160cm\n\nbyr:1955 pid:120131971 hcl:#18171d\nhgt:156cm\necl:blu\niyr:2011 eyr:2028\n\niyr:2020 ecl:brn cid:188\nhgt:157cm\neyr:2026\npid:504067323 hcl:#733820 byr:1982\n\ncid:102 hgt:177cm\nhcl:#733820 ecl:hzl byr:1984 pid:542750146 eyr:2028 iyr:2020\n\npid:419639528 iyr:2013 hgt:175cm ecl:blu\neyr:2026 byr:1999 hcl:#733820\n\nbyr:1963 eyr:2020\npid:683641152 ecl:gry cid:207 hgt:180cm\nhcl:#cfa07d\niyr:2020\n\nhgt:192cm pid:156436859 iyr:2020 hcl:#cfa07d\necl:blu byr:1963 eyr:2025 cid:147\n\neyr:2002\nhcl:z iyr:2011\npid:6830168962\nhgt:156in cid:288 byr:2029\n\neyr:2021\npid:277739802 byr:1992 ecl:hzl iyr:2020\nhcl:#7c5fe8 hgt:184cm\n\nbyr:1989 pid:066973099\niyr:2017\neyr:2022 ecl:hzl hcl:#888785 hgt:76in\n\nhcl:#866857\niyr:2016 cid:306\necl:hzl\npid:453816800 byr:1971 hgt:71in eyr:2030\n\npid:248573931 hcl:#cfa07d\niyr:2014 eyr:2024 hgt:186cm byr:1970 cid:128 ecl:blu\n\npid:172567579 ecl:brn iyr:2014 byr:1948 cid:309\nhgt:151cm hcl:#888785 eyr:2024\n\nhgt:153cm eyr:2026 byr:1929 ecl:hzl pid:684760742\nhcl:#c45e93 iyr:2018\n\npid:#d50a43\niyr:1940\necl:#7880a9 byr:2018 hcl:dc2fa7 hgt:185in eyr:1978\n\nhcl:#602927 cid:71 eyr:2020\npid:620634584 hgt:157cm byr:1991\niyr:2020 ecl:amb\n\neyr:2023\nbyr:1959 iyr:1947 hgt:152cm ecl:#503286 pid:63978523 hcl:57dd0d\n\nhgt:190cm\nbyr:1955 ecl:blu\npid:507892696\nhcl:#9bd1f0 eyr:2029\niyr:2010\n\npid:365539813\neyr:2022 hcl:#623a2f iyr:2020 hgt:184cm\necl:oth byr:1920 cid:213\n\ncid:50 ecl:oth pid:774859218 hgt:193cm\niyr:2017 byr:1925 hcl:#866857\neyr:2021\n\nhgt:189cm\niyr:2019 byr:1937\nhcl:#a97842\neyr:2025 ecl:oth\npid:787390180\n\niyr:2019 eyr:2027 hgt:183cm\necl:hzl pid:549757712\nbyr:1956\nhcl:#866857\n\npid:755580715\nhcl:#602927 hgt:187cm iyr:2017 byr:1925 eyr:2020 ecl:blu\n\niyr:2019 hgt:69in\necl:amb\nhcl:#602927 eyr:2026\npid:951019647 byr:1974\n\nbyr:1943 eyr:2034 hgt:150 pid:#36aedf ecl:oth\nhcl:z\n\neyr:2024\necl:hzl pid:824745692 iyr:2012 hcl:06ab6e\nbyr:1944\nhgt:159cm\ncid:183\n\nhgt:169cm ecl:blu\neyr:2030 iyr:2013 byr:1945 pid:791359040 hcl:#7d3b0c\n\niyr:2018\necl:hzl hgt:152cm\nhcl:#18171d eyr:2026 byr:1924 pid:534667048\n\neyr:2029 pid:933295825\niyr:2011\nhcl:#cfa07d byr:1981\nhgt:164cm ecl:grn\n\necl:amb byr:1964 iyr:2018\npid:014457573\ncid:152\neyr:2028 hgt:171cm hcl:#866857\n\nhgt:167cm\nbyr:1974 iyr:2012 ecl:amb pid:512315114\ncid:278\neyr:2028 hcl:#623a2f\n\nhgt:153cm ecl:oth iyr:2012\neyr:2027 hcl:#888785 byr:1999 pid:416990697\n\neyr:2025 ecl:blu byr:1991 hcl:#866857\nhgt:189cm pid:546461828\n\niyr:2016\nbyr:1988\nhgt:160cm eyr:2025 ecl:amb hcl:#602927\npid:562766105\n\necl:oth byr:1942\nhcl:#341e13 pid:564975864 cid:158\nhgt:159cm eyr:2028\niyr:2018\n\npid:406209763 hgt:170cm cid:331\niyr:2018 eyr:2026 byr:1981\nhcl:#733820 ecl:gry\n\npid:279164109 ecl:oth\ncid:197 hcl:#7d3b0c\neyr:2024\nhgt:185cm iyr:2020 byr:1925\n\nhcl:#efcc98 ecl:hzl\ncid:92 hgt:190cm pid:724466265 iyr:2020\neyr:2025 byr:1996\n\nbyr:1996\ncid:55 pid:906572505 ecl:grn eyr:2022 hcl:#602927 hgt:160cm iyr:2014\n\neyr:2028 hcl:#b6652a ecl:hzl hgt:186cm iyr:2016 pid:132872161 byr:1932\n\nhcl:#fffffd iyr:2019 eyr:2020 hgt:188cm\nbyr:1951 ecl:brn\npid:842126902\n\nhcl:#602927\nhgt:158cm\neyr:2023 iyr:2010\npid:681061896 byr:1977 ecl:gry\n\niyr:2018 hgt:192cm byr:1970 cid:200 ecl:grn eyr:2027\npid:164408694 hcl:#888785\n\neyr:2029\npid:447061655 iyr:2010 hcl:#341e13 ecl:oth\ncid:187 hgt:185cm byr:1943\n\nbyr:1925 iyr:2012 eyr:2025\nhgt:190cm hcl:#18171d pid:017534154 ecl:brn\n\nhgt:172cm byr:1923\neyr:2026 iyr:2015\npid:580812884 hcl:#c0946f ecl:hzl\n\nhcl:#888785 eyr:2028\nbyr:1952 ecl:brn pid:818889983\niyr:2010 hgt:180cm\n\neyr:2026 ecl:gry byr:1982 hgt:188cm hcl:#c0946f pid:610689703 iyr:2011\n\neyr:2028\niyr:2018\npid:921660781 ecl:amb\nhcl:#cfa07d hgt:178cm byr:1975\n\nbyr:1977 pid:667631009 iyr:2010\ncid:86 eyr:2022 hgt:189cm hcl:#7d3b0c ecl:oth\n\npid:214679440 hgt:190cm ecl:blu iyr:2017\neyr:2025 cid:292\n\necl:amb\niyr:2017 hcl:531ad3\nhgt:163 pid:689027667 byr:2006 eyr:2033\n\nhgt:68in byr:1928 iyr:2010 cid:227 eyr:2023\necl:hzl pid:#87bab9 hcl:#fffffd\n\necl:grn byr:1940 cid:294 hgt:152cm pid:310277488\niyr:2015 hcl:#18171d eyr:2030\n\nbyr:1965 pid:240720987\neyr:2030 ecl:oth hgt:192cm hcl:#733820\niyr:2016\n\npid:830487275\necl:blu byr:1930\nhcl:#b6652a iyr:2013 hgt:188cm eyr:2025\n\nhgt:177cm byr:1955 eyr:2030 ecl:amb pid:476675886 iyr:2016 hcl:#c0946f\n\npid:152702068 iyr:2016 hcl:#b6652a\ncid:82 ecl:blu eyr:2029 byr:1975 hgt:161cm\n\npid:136852264\neyr:2024 cid:339 ecl:oth byr:1949 iyr:2011\n\niyr:2020 pid:772739059\neyr:2025 hgt:157cm\nbyr:1945 ecl:brn\nhcl:#6b5442\n\nhcl:#18171d eyr:2022\niyr:2018 ecl:grn byr:1933 pid:053763751\n\npid:214212776 hcl:#18171d\neyr:2030\niyr:2020 byr:1988\ncid:122\nhgt:170cm ecl:oth\n\npid:883116919 iyr:2018 ecl:brn byr:1938 hgt:187cm eyr:2020\n\niyr:2020 hcl:#a97842\ncid:329 eyr:2025 byr:1946 pid:636649774\necl:grn hgt:158cm\n\neyr:2023\necl:blu hgt:161cm\nhcl:#341e13 byr:1951\niyr:2020 pid:461889565 cid:97\n\nhgt:168cm pid:492241189\neyr:2029\niyr:2013\ncid:150\nbyr:1980 hcl:#cfa07d ecl:hzl\n\nbyr:1998 ecl:gry hgt:150cm eyr:2024 pid:401735295 cid:153 hcl:#733820 iyr:2016\n\necl:hzl hgt:184cm iyr:2018\nbyr:2001\npid:453480077 eyr:2025 hcl:#a97842\n"
  },
  {
    "path": "advent-of-code/2020/inputs/4.sample",
    "content": "ecl:gry pid:860033327 eyr:2020 hcl:#fffffd\nbyr:1937 iyr:2017 cid:147 hgt:183cm\n\niyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884\nhcl:#cfa07d byr:1929\n\nhcl:#ae17e1 iyr:2013\neyr:2024\necl:brn pid:760753108 byr:1931\nhgt:179cm\n\nhcl:#cfa07d eyr:2025 pid:166559648\niyr:2011 ecl:brn hgt:59in"
  },
  {
    "path": "advent-of-code/2020/inputs/5",
    "content": "FBBFFBBLLL\nFFBFFFBRLL\nFFBBBBFRRL\nFBFBBBBRLL\nBFBBBBFLLR\nFFFBBBBLRR\nBFFFFFBLLL\nBBFFFBFRRL\nFFBFFFFLLR\nBFFFBBBRRL\nFBFBFFFLRL\nFFFBBFBLRR\nFBFBFBFLRR\nFBBBBFBRRL\nBFFBFFBRRR\nFBBBFBBRLL\nFBFFBFBRLR\nBBFBFFFLRL\nFFBFFFFRLR\nFFBBFBFRRR\nBFBBBFBLRR\nFFBBFFFLRL\nFBBBBFFRLR\nFBBBBBBRLR\nFFBFBFBLLL\nBBFBFBBLLL\nFFFFFBBRRL\nFBFFBFBRRR\nFFFBFFFRLL\nBFBFBFFLLL\nBFBFFBFLLL\nFFFFBFFRRL\nFBFFFFFRLR\nFBBFFBBLLR\nBFFFFFBLRL\nBFBFFFBLLR\nFBBBBBBLLL\nBBFBFBFLLL\nFFBFFBFLRR\nBBFFFBBRLL\nFFBFFFFLLL\nFBBFFBFLLL\nFFFBBBFRRR\nBFBBFBFRLL\nFBBFBFFRRL\nFBFBBFBLRR\nFFBBBBBRLR\nFFBFBFFLLL\nFBFFFBFRRL\nBFFBBFFRLL\nBFFBBFFLLR\nBBFFBFFRRL\nFBFBFBFLLR\nBBFFBFBLRL\nBFBFBFBLRR\nFFBBFBBRRL\nBFBBBFBRLR\nFBFFFFBLLR\nBFBFFBBLRR\nBBFBFBFRRR\nFFBFBBBRRL\nBFBFBBFRLR\nFBFBBBBRLR\nBFFFFBBRRR\nBBFFFBFLLR\nFBFFFFBRRL\nBBFFBFBLLL\nBFFFBBBLLL\nFFBFFFBLRR\nBFBFBBBRRR\nFBFFBFFRRR\nBFFBFFBLLL\nBFBBFFFLRL\nBBFBFFBRLR\nFBBFFFFLLL\nFBFFFFBLLL\nBBFFFFBRLR\nBBFBFFBRRL\nFBBFBFBRRR\nFBFFBFFLRR\nFFBBBFBLLR\nFFFFFBFRRR\nBFBBBBBLLR\nBBFBFFFRLL\nBFFBFBBLRR\nBFFBBFBRLL\nFBFFBFFRLR\nFBFBBFFLLR\nFFFFFBFRRL\nFFBFFBFRLR\nFBFBBBFLLL\nFFBFBBFLLR\nFBFFBBBRLR\nFFFBFBFLLR\nBFBBFBBLRL\nBFFFFBFLLL\nBFBFFBFLRL\nBBFFBFBLLR\nBFFFBFBRRL\nBBFBFFBLLR\nFFBBFFFRLL\nFFFFFBBRLR\nFFBFBFBRLL\nFBBBBFBLRR\nFFFBFFFRRL\nFFFFBFFLRL\nFFFFBFFRLR\nBFFFFFFRRR\nBBFFBFBRRL\nBBFBFFFLRR\nFFBBBFFLLR\nFBFBFBBRLR\nFBBFBBBLRR\nBFFBBBFRLL\nBFBBFBBLLL\nFBFFFBBLLR\nFBBBBFFRRL\nBFBBFFFLLR\nBFBBBFFLRL\nFFBFFBBRLL\nFBFBFFBRRR\nFBBFBBBLRL\nBFFFBFFLRL\nBFFBFFBLRR\nBFBFBBFLRL\nFBFBBFFRLL\nBFFFFBBRRL\nFFBBBBBLRL\nFBBFFBFRRL\nBBFFBFBRLL\nFBFFFFFLRL\nFFFBFBFRLR\nFFBBBBFLLR\nFFFBBBFRLR\nFFBBFFBRRR\nFFFBFFBLRL\nFBFBFBBLLL\nBFFFFBBLRR\nBBFFBBFLLR\nFFFFFFBRLL\nFBBBBBBLRR\nFFFFBFBLLR\nBBFFBBFRRL\nBFBBBBBLRR\nBFBBFBBLRR\nBBFFFFBRRR\nBFBBBFBLLR\nBBFFBBBRRR\nFBBFBFBRLL\nFFFFFBBLRR\nBBFBFBBLLR\nFBFFFBFRLR\nBBFFBFFLLR\nBBFBFFFRLR\nFFFFBFBLRL\nFFBBBBBLRR\nFBBBFFBLRR\nFBBFBBFRLL\nFBBFBFBRLR\nFFBFBBBLRL\nFBFFBBBLLL\nFFFBBBBRRR\nFFBFFBFLRL\nBFFFBBFRLL\nBFFFFBBLLR\nBFFFFFBRRL\nBFFBFBBRRL\nFFBFFFBRRL\nBFFBFFFLRL\nBFFBBBFLLL\nFFBBFFFLRR\nFBBBFFBRLL\nFFBBFFFRLR\nBFBFBFFRLL\nFFFFBBFRRR\nBFBFBBFRRL\nFBFBBBFLRL\nFFFBFBBRLL\nFFBBBFFLLL\nBBFFFBBLRL\nFBBBFFBRRR\nBFBFBFBLLL\nFFBFFBBRLR\nFFBFBBBRLR\nFFFFFFBRLR\nBFFBBFFLRL\nFFBFFBFRRR\nFFBFBFFRLL\nFBFBFFBLLR\nFBFBFBBRRR\nFFFBBFBRRR\nFBBBBFBLLR\nFFFFBFBRLR\nFFFBBBFRLL\nFBFFBFBLLL\nFBFBFFFLRR\nFFFBBFFLLL\nBFBFFFFLLL\nBBFFFBFLLL\nFFFFBFBRRL\nFFBBBFBRRL\nBFBFFBBRLR\nFFFBBFFLRL\nFFFBFBBLLR\nFFBBBFFRLR\nFBBBBFBLRL\nBFFFBBFLLL\nBFFBFBFLLR\nFBFFBBFLRR\nBFFBBBBLLR\nFBBBFFFRRR\nFBFFBFBLRL\nBFFFFFFRLR\nFBBBBFBRRR\nFFBBBBFLRL\nBBFBFFBLRL\nBFBFBBBLRR\nFFFFFBFLLR\nFBBFFBFLLR\nBFFFFBBRLL\nFFBFBBBLRR\nFFFFBFFLLR\nBBFFFFFRLR\nFBBBBFFRLL\nBFFFBFBLRR\nFBFBBBBLLR\nBFFBFFBRLL\nBFBFBFFLRR\nBFFFFBFLRR\nFBBFFBFLRR\nBFFBBFBLLR\nFBBFFFBLRL\nFBFBFBBRRL\nFBFFBFFRRL\nBFBBFBFLLR\nFFFFBFFLRR\nBFBFFFBLRL\nBFFBBBBRRR\nFFFFBBBLRR\nFFFBBFBLLL\nFFBBFBFLLR\nBFBBFBFLLL\nFBBFBFFLLR\nFFFBBFFRRR\nFFBBBBBRRR\nFFFBFFFRLR\nBFFBFBFLRR\nFBFFBFBRLL\nFFFFBFFLLL\nFFBBBFFRLL\nFBFBFFBLLL\nFBFBBBFLLR\nBFBBBFFRLL\nBFBBBBBRRL\nFFFFFFBRRL\nFBBFBBFLRL\nBFFBFBBRLL\nFFFFFBFLRL\nBFBFFFBLRR\nBBFFFBFLRR\nBFBFBBBLRL\nFBFFFFBRLR\nBFBFBBBLLL\nBFFFFFFRRL\nFBBFFFBRRR\nFBBFBFFLRL\nBBFFFFFLRL\nBFFFFBBLRL\nFBFBBFFRRR\nFBBFFFFLRR\nFFFBFFFLRR\nFBFBBFFRRL\nBFFBFFBRRL\nBFFBFBFRRL\nFFBBFBBLLR\nFBFFBFFRLL\nBFBFFBBLLL\nFFBBFFBLLL\nBBFFFBBRRL\nBFFFFFFLLL\nFFBBBBFRLL\nBFBBBBFRRR\nBFFBBBBRLR\nFBFFBBFRLL\nBBFBFFBLRR\nFBFFBBBLRR\nBBFBFFFRRL\nBFBFFFFLRR\nBFBFFBBRRR\nFBBFFFBLLL\nBFFBBBFRLR\nBFFFFBFRLL\nFBFBBBBRRL\nBBFFBBFLRL\nFBBBBFFLLR\nBFBBFFBRRR\nFBBFFBBLRR\nFBBBBBBRRL\nBBFFFBBLLR\nBFBBBBFLRL\nBFFBFFFRLR\nFFFFBFBRRR\nFFFFBFBRLL\nBFFFFFFRLL\nBFFFBBBRLL\nFFFFFBBLLL\nFBFFFBFLRR\nFBFBFBFLLL\nBFBBFFBRLL\nBFFFBBFRLR\nBFBBFFFRLL\nFFFBBFBLRL\nBBFFFFFLRR\nBBFFFBFRLR\nBFBBBBFLRR\nFBFFFBBLLL\nBBFFBFBRRR\nFBFBFBBLRR\nFBBFBFFRLR\nFBFBBBBLLL\nFFFBBFBLLR\nFFFFBBBRRL\nFFBBBBFRLR\nFFFBFFBRRL\nBFBBFBBLLR\nFFBFFFFLRL\nBFFBFBFRLR\nFFBBFBBLLL\nBFFBBBFLRL\nFFFFFBFRLL\nBFFBFFBRLR\nBFFFBFFRRL\nBFBFBBBRLL\nBFFFFFBLRR\nFBBFFBBRLL\nFFFFBBBLRL\nBBFFFFBLRR\nBFBFBBBLLR\nBFFFBFFRLR\nBFBBFBFRRR\nBFFBBBFLRR\nFFBFBBFRRR\nFBBBFBFRLR\nBFBFFBBRLL\nBBFFBFFRLL\nBFFFBFBLLR\nFBFBBFFLRL\nBFFFFBBLLL\nBFBBFBBRRL\nBFFFBFFLLL\nBFBBBFBLLL\nFFBBFBFLRR\nFFBBFBFRLR\nBFBBBFFRRR\nBBFBFFFLLL\nBFFFFFBRLL\nFBBFBBFRRR\nBFFFBBFLRR\nBFFBBBFRRL\nFFBFFFFRRL\nFBFFBFBLRR\nFFBFBFBRLR\nBBFFBFFLRR\nBFFBBFFLLL\nFFBBBFBRRR\nBBFFBFFRRR\nFBBFFFFRRR\nFBBBBFFLRR\nFBBFBBBRRR\nFFBFBFBLRL\nFBBFFFBLRR\nFBFFBFFLRL\nBFBBFFFRRR\nFBFBBBFRLR\nBFFFFFBRRR\nFBFBFFFRRR\nBBFFFBFLRL\nFFBFBFBLLR\nFBFFFBBRRL\nFBBBFFBLLL\nBFBFBFFRRR\nFBFFBBBRLL\nFFBFFBBLLR\nFFBBFBBRLL\nBFBFBBFRLL\nBFBBFFBLLL\nBFFBBBFRRR\nBFBFBFBRRL\nBFFFFFFLLR\nBFFFBBBRRR\nFBBBFBFRRR\nFFFBFFBRLL\nBFFFFBFLRL\nFBFBBFFRLR\nFBBBBBFLRL\nFFFBBBFRRL\nBFBFFFFLLR\nFBFFFBBLRR\nFBBFBBBRRL\nFFFBBBFLRR\nBFBFFBFRRL\nBFFFBBFRRL\nFBBBFFBLLR\nFFBBFBBLRL\nBBFBFBFRLR\nFFBFFBFLLL\nFFFFBFBLLL\nBBFFFFBRLL\nFBFFFBBRLR\nFFBBBFFRRR\nFFFBFFFRRR\nFFBFBBBLLR\nFFBFFFBRLR\nFFBBBFBLRR\nBFFBBBBLRL\nBFFFFBFRRR\nBBFBFBFRLL\nFBFBBBFLRR\nFFFFFBFLLL\nBFBBBFFLLR\nBFFBFBFRRR\nBFBBFFBLRR\nBBFFFBBRLR\nFBBBBBBLRL\nBFFBBBBRRL\nFFBFBFFRLR\nBFFFFFBLLR\nBBFFFFBRRL\nFFFBBFFLRR\nBFFFFBFRRL\nBBFFBFFLRL\nBBFBFBFLRR\nFBFBBBBLRR\nBFFBBFBRRR\nFFFBBBBRLL\nFBFBBBFRRL\nFFFFFFBRRR\nBFFFFFFLRL\nFFBBFFFLLR\nFBBFBFBLLL\nFBBFBBFRLR\nBFFBFFBLLR\nFBFBBFBRLL\nFBFBFBFLRL\nFFBFFFBLLR\nFBBFFBBLRL\nFFFBBBBLLR\nBFFBBBBLRR\nBFFBFBBLLR\nFFBBFFBRLR\nFBBBBFFLLL\nBFFFFFBRLR\nBFBBBBFRLL\nFFFBBFFRLR\nBFFFBFBLLL\nBBFFFFFRRL\nFBFFFFBRLL\nBFBFBFBLRL\nFBBFBBFLRR\nFFBFBBFLRR\nFFBFBFFLRR\nFFBFFFFRLL\nBFBFBFBRRR\nFBBBBFFLRL\nFFBFFFBLLL\nBFBBBFFRLR\nFBFBFFBRLL\nFBBBBBFRRL\nFBFFBFFLLL\nBBFFBBBLLR\nBFFFBFFRRR\nBBFFBBBRLL\nBBFFFBBLRR\nFBBFBBBRLR\nBFBFBBFRRR\nFBFFBBFLRL\nFFFFBBFLRR\nBFFFBFBRLL\nBBFFFFFRLL\nFFFBFBFRRR\nBFBBBBFLLL\nFFBBBFBRLR\nFFFFBBBRRR\nBFBFFBFRLR\nFBFFBBFLLL\nFFBFFBBLRR\nFBFBFFBLRR\nFFBFFBBRRL\nFFFBBBBRRL\nBFFBFBBLRL\nBBFFBBBLRR\nFFFBBFBRLL\nFFFBFBBLRL\nBFBFFFBRRL\nFBBFFFFLLR\nBBFBFFBLLL\nBFBFBBFLLR\nBFFBFBBRRR\nFBFFFFFLLR\nFFBBBFFLRL\nFBFFBBFRLR\nBFFFBFBLRL\nFBFBBBFRRR\nFFBFFBFRRL\nFBFBBFBRLR\nBFBFBFFRLR\nFBFFBBBRRR\nBBFBFFFLLR\nFBBFBBBLLL\nFFBBBFBLLL\nFFBFFFFRRR\nBFFBFBFLLL\nBFFBBBFLLR\nFBBBBBBRLL\nFBBFFBFRLL\nFFFBFFBLLR\nFFBBFFBLRL\nBFBBFBFLRR\nBFBFFFBLLL\nFBFFFBBRRR\nFFBFBFFLLR\nFBFFBBBRRL\nFBBBBFBLLL\nFFFFFBBLLR\nFBBFBFBLRL\nBFBBFBBRLL\nFFFFBFBLRR\nBBFFBBFLLL\nFBBBFBFRLL\nFBFBBFBLLL\nBBFBFBFLLR\nBFBFBFBRLR\nFFFFFBFRLR\nFFFFFBBRLL\nFBFBFBFRRR\nFBBBFBFLRL\nBBFFBBBLRL\nFFBBBBBRLL\nFBBBFBBRRR\nBFFFBBBLLR\nBFBBBBBRLL\nFFFFFBBLRL\nBBFFBFFRLR\nBFBFBFBRLL\nFFFFBBFLLL\nBFBFBFFRRL\nFFBBFFBLLR\nBFBBFFFLLL\nBFBBFFBRLR\nFBFBFFBRLR\nFBFFFBFRLL\nFBBFBFFLRR\nFBBFFBFRRR\nBFBFFFFRLL\nBFFFBBBLRL\nFBFBBBBRRR\nBBFFBBFLRR\nFBBBBFBRLL\nBBFFBBBRRL\nBFBBBFFLLL\nFBFFFFBLRL\nFBFFFFFRRL\nBFBBBFFLRR\nFBBFBFBLRR\nFBFBFBBLRL\nFFBFBFFRRL\nBFFBBFBRLR\nFFBFFBBLLL\nFBBBFBBLLL\nFBBBFBBRRL\nFBBBFBBLLR\nFBFFFBFLLL\nFBBBFFBRLR\nFBBFBBBRLL\nFBBFFFBLLR\nFFFBFBBRRR\nFBBFFFFLRL\nBFFFFBFRLR\nFBBBFFFLLL\nFFBBFBFLLL\nBBFFFFFRRR\nBBFFFBFRRR\nFFBFFBBLRL\nFBBBFFBLRL\nFFBBFBFRRL\nFBFFFBFLRL\nFBBBFFFLRL\nFFFFBBBRLR\nFFBBFBBRLR\nFBFBFFBRRL\nBFBFFBFRRR\nBFBFBFFLRL\nBFFBFFFLLL\nFBBFBFBRRL\nFFBBBFBLRL\nBFFFFBFLLR\nFBBBFBFLLL\nFBFFFBBLRL\nFBBFFFBRRL\nFBBBBBFLLR\nFBBBFBFRRL\nFFFBBFBRRL\nFBBBFFBRRL\nFBFBFBBRLL\nBFBBBBBLLL\nFBFBFFFLLR\nFFFBFFBRLR\nBBFFBFBLRR\nBFFFBFFLLR\nFBBFBBFRRL\nFFBBBBBLLL\nFBBFBFFRLL\nFFFBBBFLRL\nFFBBBBFLRR\nFBFFFFFRLL\nBBFFFFBLLR\nFFFFBBFRRL\nFFBBBBFRRR\nFBBBFBBLRL\nBFFBBFBLRL\nBFBBFFFRLR\nFFFBFBBRRL\nBBFBFBFRRL\nFFFBBBFLLR\nBFFFFBBRLR\nBFFBFFFLLR\nBBFBFFFRRR\nFFFFBBFRLR\nBFBBBFBRRR\nFBFBBBBLRL\nFFFFBBFLLR\nFBFBBBFRLL\nBFBBFBBRLR\nFFBBFFFRRR\nFFBBBFBRLL\nFBBFFBFLRL\nBFBFFFBRRR\nBFFFBBBRLR\nFFFFBFFRRR\nFFBBFFBLRR\nFBBFBFBLLR\nFFFBBBFLLL\nFBBBBBFLLL\nFFFFBBBLLL\nFFFBFFBLLL\nBFBBBBBRLR\nBFBFBBFLRR\nFBFBBFBRRR\nBFBBFFFLRR\nFFBBFFFLLL\nBFFFBBFLLR\nFFBBFBFRLL\nFBBBFFFRLL\nFFFBBFBRLR\nBFBFFBFLRR\nFBFBBFBLLR\nFBFFFFBRRR\nFFFBFBBLLL\nFBFBFFFRRL\nFFFBFBFLRR\nFFBBBBBRRL\nFFFBFFFLLR\nBFFFBFFRLL\nBFBBBBBLRL\nFBBBFBFLRR\nFFFFBBBLLR\nBFFFBFFLRR\nFBBBBBFLRR\nFBBBBBFRLR\nBFFBFFFRRR\nFFBFBBFLRL\nFFBFBBFRRL\nFFBFFBBRRR\nFFFFBBFRLL\nBBFBFBFLRL\nFBFBBFFLLL\nBBFFFFBLLL\nFBBBBFFRRR\nBFFBFBFRLL\nBFBBFBFRRL\nFFBFBBFLLL\nFBFFFBFRRR\nFFBFFBFLLR\nBFBBFFBRRL\nFBBFFBBRRR\nFFBFBBBRLL\nFBBBBBBLLR\nFBFBBFBRRL\nBFFBFFFRLL\nBBFFBBFRRR\nFBBBBBFRLL\nFBBFFFFRLR\nFBBFFBBRLR\nBFBFBFBLLR\nFBFFBFBRRL\nFFFBBFFRRL\nFFBFBBFRLR\nBFFBFBBRLR\nBFFFBFBRRR\nBFBBBFFRRL\nFBBBFBBLRR\nFFFBFBFRLL\nFFBBFFBRLL\nFFFBBBBRLR\nFBBBFBFLLR\nBFBFBBBRRL\nFBBBFFFRLR\nFBFFFFFLRR\nFFBFBFFRRR\nFFFBFBBLRR\nFBBFBFFLLL\nFFBFFBFRLL\nFFBBBFFLRR\nFFBFBFBRRR\nFFFBBBBLRL\nFFBFBFFLRL\nFBFBBFBLRL\nFFFBFBFLRL\nBFBFFBFLLR\nBBFFFBFRLL\nFFBBBBBLLR\nBBFFFBBLLL\nBBFBFFBRRR\nBFBFFFBRLL\nFFFBFBFRRL\nFFBFFFFLRR\nBBFFFFFLLL\nFBBBFFFLRR\nBFFFBBFRRR\nFBBFBBBLLR\nBFBFFFFRRL\nFFBBFFBRRL\nBFBFFBBLRL\nBBFFFBBRRR\nFFFBBFFRLL\nBFFBBFBRRL\nBFFFFFFLRR\nBFBBBBFRLR\nFBBFFBFRLR\nBFFBBFFRRL\nBFFBFFFRRL\nFFFFBBBRLL\nFBFBFFFRLR\nBBFFBBFRLR\nBBFFBBFRLL\nBFFFBBFLRL\nFBFFBFFLLR\nBFBBFBFLRL\nFBFBFBFRLL\nBFBFBBBRLR\nBFBFFBBLLR\nFBBBBFBRLR\nFBFFFFBLRR\nFBFFBBFRRR\nBBFFBFFLLL\nFFFBFBFLLL\nBFFBBFFRRR\nFBBFBFFRRR\nBBFFBBBRLR\nFFFBFFBLRR\nFBFBFBFRLR\nBFBBBBBRRR\nBFFBFBFLRL\nBBFFBBBLLL\nBBFFFFFLLR\nBFBFFBFRLL\nBFBBBBFRRL\nBFBBFFBLRL\nBFFBBFBLLL\nBFFBBBBLLL\nBFBFBBFLLL\nFBFBFFFRLL\nFBFBFBFRRL\nBFFBFBBLLL\nFFBBFBBRRR\nFFFBFFBRRR\nFBFFFBFLLR\nFBFFFFFRRR\nFBBFBBFLLL\nFFFBFBBRLR\nFBFFFFFLLL\nFBBFFFFRRL\nBFBBFFBLLR\nBBFBFBBLRL\nFBBFBBFLLR\nBFBFFFFLRL\nFFBBFBBLRR\nBFBBBFBLRL\nBFFBBFFRLR\nFFFFBFFRLL\nBFFBBFFLRR\nFBBBFBBRLR\nFBFBFFFLLL\nFFBBBFFRRL\nBFBBFBFRLR\nFBFFFBBRLL\nFFFBFFFLRL\nBFBBBFBRRL\nFBBFFFBRLR\nFFBBBBFLLL\nFBBBFFFLLR\nFBFFBBFLLR\nFFBFBBFRLL\nBBFFBFBRLR\nFBFFBBBLLR\nFFBFBFBRRL\nBFFBFFBLRL\nFBFFBFBLLR\nFFBFBFBLRR\nFFBBFBFLRL\nFFBBFFFRRL\nBFBFBFFLLR\nFBBBBBBRRR\nBFBFFFFRLR\nBFFBBBBRLL\nFFFFFBBRRR\nFFBFFFBRRR\nFFFBFFFLLL\nBFBFFFFRRR\nFBBBBBFRRR\nFBBBFFFRRL\nFBBFFFFRLL\nFFFFFBFLRR\nFFBFBBBLLL\nBFBFFBBRRL\nFFFFBBFLRL\nBFBBBFBRLL\nFFBFFFBLRL\nFBBFFFBRLL\nBFFBBFBLRR\nFFFBBFFLLR\nFBBFFBBRRL\nFFBFBBBRRR\nFBFBFFBLRL\nBFBBFBBRRR\nBBFFFFBLRL\nFBFBFBBLLR\nBFFFBBBLRR\nBFBFFFBRLR\nFFFBBBBLLL\nBFFBFFFLRR\nBFBBFFFRRL\nFBFFBBBLRL\nFBFBBFFLRR\nFBFFBBFRRL\nBBFBFFBRLL\n"
  },
  {
    "path": "advent-of-code/2020/inputs/6",
    "content": "bapocnysdr\nlpandcmb\nbplndca\n\nrgi\nci\ni\niv\n\nxdgwtsc\ngtcxswd\nsdcxtwg\n\ng\nj\nk\n\ndrcmwzh\naostudi\n\nqziunh\nhgkaslmyz\n\nfovlpdhurzqsway\nzvciokytxbaf\n\ny\ny\nyp\ny\ny\n\ngqouslwfihtxvke\nbapdmyncjzr\n\nywirnpmozqle\njhapfdzuvgc\n\nce\nevn\nyzsem\n\nphdcuxgtosjier\njfixnurtyopdh\n\nmxjs\nmxkjis\njxsm\nxvmbsj\nsxjcmh\n\nsgrbtmqxpwkacnzd\nbrncqxtskawgpzdm\nmxqjtcpzbswgrnka\n\nfxijprlkbhte\nherpxfbikmtlj\n\nltuyidqkcrevanw\nwhbqavirludxtye\nvfirqwmsaopyzld\n\nq\nq\nq\n\nfaxhswigtprou\nxhlusnijytkrwza\nxaqsburiftwh\nrtahxwcsiu\n\ncuplrimdtxke\nletpjuimzrvkcyx\ncpleiuxdktmar\nwrfgkubeoqxsihpntmc\n\nzpbjimulvrdwxsog\nhfmspnuokbxe\n\nctm\nctm\nmct\n\ntvkocqebls\nqcnbktsveo\nfnvkbscqyeot\nmbcsoevkthqj\n\ntyjgd\ntydjg\ntgdyj\ndtgyj\n\nxgiybeuhtkfdonq\ndiuqvfycrokhgxbt\nigfdbhpqklxuyntjo\nzxqkymfohstuiwdgb\nkgoutiyhfxqcbd\n\nwzfiaexksp\nfizxyskw\n\nazsqntcghjmio\nmgksdwpcitvxqjr\n\nctwzu\njwctuzes\n\nbpymqfisrvtuheljwadx\niejsubvxhdmwpqgfrltya\njbxmfshuvyegwqlpridta\nvpxbwlqumetdrijhfnays\n\nw\ni\ni\ni\ni\n\nfctbvjmnroypuxhlakzw\ncbpnmyzrtjuavfohkxlw\nznoptxwakjfucmhrlvy\nnkmlrhygxcazowtpquvjf\n\nibanduczjfmpt\ngqimbtadcuoszjfprl\nmtaizxcdjpbfu\nmjfaiubcdzpt\n\nkdxav\nmaxvudr\nadxv\nqxavdi\n\nuajvepgoxhwsqkym\nhwesxqvpuzgb\n\nlp\npl\npl\nlp\n\ntawk\nsuwtc\nstw\nixltp\nwto\n\nphrawmes\nbscrhki\n\nxhwurk\nhwea\nbhwe\n\ntuhvebm\nbemtuhv\n\nprziuqhcye\nqipyrhezcu\nueqzyprhci\nyurseihcqpz\n\nmnfotvpzdxbaglye\nnbjlomxzacfqgey\nglxhuwoskyrabi\n\ntohbrluismcagnypqdv\nduqbhylatcvosnprimg\nqtpbduycrlosngivhma\nnvgucpayidlhsomrbqt\n\ngrslqxjdytzficnuo\nklarqjpxfscgyouzi\n\nqozstka\npjnruvic\nfchup\n\nyjautz\najue\nvlufjx\nujy\n\ninythxv\nbhxvytin\nhtlnxviy\n\nmhcqvt\nsqtvchm\nhtqmvc\n\nvswymdnahrq\nhrnqvysawmd\nndsmqvwyrah\nmraywhsvndq\n\njtxayp\natjxp\njpraxgt\njatpx\nadbwpjltx\n\nvbni\nivgfn\navyqtmsikn\nnhwivrf\n\nfkygvtsbpazdjwxrmqoi\nbtyfwsvpdiarjqoxmg\nwvqyiaprsmftgxdojb\n\na\na\nan\n\npynvsfcbherzqiwumjaod\ndsivqjmurcfnzebyhopaw\nmqsvnueoihczyrfdwpbja\ngjqsaiwdczpvublmnokfryeh\n\ndrawsthnfvzylebo\njmkzqhbgicxsu\n\npg\nhdob\nnq\n\ngdbxpwmtvhoaely\nomvdgatwbxlpyeh\ngtbyxrvwmhladpeo\n\nugowlqebtcpdxz\nwzobutlqgdxep\ntulbvxwfadjpogqze\nqubdxgztpknolwe\nepztwlbxqgodu\n\nrsvebtycq\nbecltsrnvw\n\ntgsljhz\nzhltjs\nhsjltxz\n\ndaguc\nfbpudxyg\nglidjuo\ngoadus\nudjgaz\n\nqkpwetasjfbdvh\nglixc\n\npufekjh\nxegpq\npoewviyn\nenlbvp\ntpesm\n\nzqfiwx\nzqfriw\nwfzxil\nzwxu\ndznwktpb\n\nkcaomdbszyi\nildpzaqsbx\nxsdqirazb\n\nmqebolfk\npeqmgf\ndeqfmw\n\ngrcqpi\ndvpmqte\nohlwfujxkanbsyz\n\ntxnhgzuwaicrfl\nqtnwizslxuahocgr\nmcxhglnibardwtkuz\n\ncvjbyrewa\nwczb\nzbwc\nwcb\n\npsvotmiaqyuhdnrekw\naovnrqwsiyjmdutpehx\ngaephqunbrwdsmyiltov\nrmftshdpcznwiyuoaveq\npyatoimwhxeusnvrqd\n\nwsjvydieaurhqxofzlgpmbk\nkemhzfusnpajxirywlo\n\nypiz\nipz\njwiz\niz\n\npxoedfk\npxogkd\ntkjsdocpex\n\nlsoz\nzxc\nz\nwkz\nzpw\n\nfrmcndwyeix\nqritwfuymc\nmzrwyfixc\nmfczprywi\n\nygvtslukaeoinhwd\nvnepzqmcwyjlufrdobk\n\nbi\nitb\nbi\n\nwy\nqomwberkixc\ngw\nhswg\nlpw\n\nkrifxwcusnjmle\ncnijrwxkmspf\ncnrfiegmqswkxjh\nskiyrmwxcdzjnf\n\nifwqlzhrudsmn\nfzblomnwspjvk\n\nvnjsxdiobeuhcgfw\ndhwienfjsobgcvux\nwsinxchtegujbdvof\ncioehdxvnjgwbusf\ngdcsfeobjrunhxwviy\n\nlpzntyhsxruiqjckwv\nixyprghzqfvjsuotlw\nayltehsxubqpmwrdjivz\n\nr\nlmb\n\nn\nn\nn\nk\n\nlfsxwgkeioztnuydmqbc\nwkosmqcxtdnluebigyfz\nolekfdcyxgqtsbumzwin\nkwqzfedxblcitgmnuoys\nibdetugcmfzoknwlxsyq\n\nc\nc\nc\nc\n\nnmrohgpcwsjadkyqzl\nmgjhdwcpoknsqyazr\nchnajzmwopkgdyrqs\nbdcnhgamkjqysropfzw\n\nyqtid\nujgkz\nrmas\njk\nog\n\nf\ncrj\ncyo\nneqhmb\nf\n\nuwxc\nwpcu\n\nbkhpcqyeljvftxnz\nkpvxqcjin\n\neqjzkctynvo\nqyovecnjgkt\nxjckqenybvhpto\njnkmezvyctqo\n\nlon\nw\nvwh\nh\n\nzrosv\noblzfats\ncuozbmak\ndpyegwhnjz\noztiqx\n\nbvlwgjrixaskqpuzyonth\nhatusdrovjgwcyipeqkmzln\n\nvhneajldr\napnvjderl\nlynrjcae\n\nqodczyfijam\nfkdxpgrcnmio\n\noai\niao\noia\noai\nioa\n\nnhgewpbozmjascrk\nvsocxumhryfnbqwkaj\n\njxrls\nsycjpwr\nbdcrqenuhtsz\nsravkif\n\nbymwecxqrloj\nlhofkz\nvzldo\nklof\noulk\n\nlfxobdwcji\nodbpnilxjcw\n\npbcr\nrcpb\n\nmsp\nesm\nsm\npsm\ndcsm\n\nclkiabts\nhskec\nsckgf\nkfncs\nsekc\n\ndyckmholpqbtaunf\nlacdqknfhuymtopb\nkntfqadpjlbcyhumo\nqoflmbpdhauykctn\ndphmolaynqcfbtku\n\nwhkzitxfqem\nftixzqmrwek\nmitabqyxkzjwfpne\nqzwekxtmfi\niztmkfwxeqd\n\nwxktrn\ntxr\n\ntapvryqbecdklwsjzxug\nmwjgatucpvydsnqbklxr\n\ntw\nwt\nwt\n\nirsehx\nehsxri\nrhxise\n\nekwyuzsvpfjg\nlcspakbhnmiod\n\nqifdbzapc\nrwpvkbd\n\nf\nf\nf\nf\nf\n\nyskpcdmber\nbnpdelmcryksu\neqcbzdpkgyrmsixj\n\nibt\niez\ncz\nb\nxvls\n\nd\nd\nd\nd\ndq\n\nubfpqyrkhceo\nyfhqckubre\n\nzyhnmseuivlbxgfk\nnviufhobsyelxzkm\n\nagbdzfsqetclpw\nwctbfaqeszpgdl\ncsbtraldqepvgzfiw\n\ndmatzvowqcklbgirf\nldiczavboqgwmfktr\ngkaditvmclqrwfboz\ndvrfntlcijagmzobuqkw\niwzrtblvdoamqkfcg\n\nxhjydaekowcgsmruftbpqvln\nwzryxjmfdloqvskubanh\n\nskglcvahyx\nxyp\nyx\n\ntvsguaxobzkd\ntxoguzsmkbv\nsoegkitjbxyuzv\nkvobgsztux\ngtxvcspoukqfhznb\n\nosca\nosai\n\nsjv\nsjv\nvusofja\nvjs\nsjv\n\nipwxnmkbzhscarlejtdoufqyg\nujlxyqzkgtpfrdnihwaomscbe\ndyslimrkjqxnftcpbewzuohga\ngyphacbxnqdriweumloszjktf\nczbroamputiwjdnqhleyksgxf\n\ndygktjflepbcqm\nzfwsneviuo\n\nusz\nusez\nusz\nzscu\n\njkbies\nejikm\nejphkoi\nkmjseiz\njike\n\nqwjvbzmypcif\nhveligmbpatow\n\naumeftxligdy\ntylfgicdx\nwlditgfyx\ntcxdgrilfsy\n\nwi\niw\niw\niw\nwi\n\nzsd\ncbmoz\nouwbaq\nghexrpyf\nasmz\n\nax\nw\nwrd\nvqclmnjfob\n\nsy\naumz\nazs\nhvoecbdfgq\n\np\np\np\npo\np\n\nsydzgpwourlbqfcj\nmnzcjkeubaprofg\n\nkiatxsph\niphktsa\nwaplhikjt\nthapik\n\ncpv\npcve\nvpc\nlmtcv\n\neyghlrunfctbqzos\nnsryfzuqtmecol\n\nzayxpivkctudsmgrhqfl\nynfsuctxhakdpjglmovq\nfdvgeskyaublpmhctrwqx\n\negymspiuwoarnlj\npoidtzjyglwume\n\ntmlv\nmotv\nmvthn\n\nvh\nvh\nvh\nvh\nvh\n\nvthobzjux\nojutxvhbz\nvxhojbzut\nzhtvbxouj\n\nk\nk\ne\nk\n\nbkwvlpt\nxormzn\n\naforqletdymv\neyorqmflvdta\nytvaqoejmdlrf\n\nrqakhn\nkhrqusmaj\nrkhqa\n\nbmyztkxldgiosnw\ntsoyzwixdmlbnkg\nbtimzdlywknsgxo\n\nmqifeszchaoxjygvdrklubwn\nzjdhxnboagfrc\ncgarozjxdnbfph\nxbnrhcjzfgaod\nfzdhrxtancjobg\n\ngzdvh\ngztvmch\nzgdhv\nghzv\n\nyjldgioabsr\nmusahntecwl\n\nfujnlstvgcbwio\nclgkwmijsupqzbo\n\ncqi\niqga\nqza\nelgyxq\ndujqtkprvf\n\ndzrawsxvhgtflnjeikoubqypm\npryqevnbkiusghjlofadztxw\neawipgrutyohqvsbcknjzfxld\nbavdzsphqugykftnjeorilxw\n\nq\nvxoln\nfeq\n\ny\ns\ns\nl\n\ngfdp\npgd\naep\npdfsb\n\nwatcn\ntawn\n\nl\nnly\nloy\ngwsvl\nl\n\nehfqltbkvizcmpaxn\nvzqkecthbmnfxliap\n\nl\nlrx\nl\nel\n\nmznoqpxfvedutclhar\ngsibywkj\n\ngft\ndqs\nrm\nrbe\ndnsrh\n\ndgwncrbfo\nuboewdjnagxcr\nogrcdbnyw\nbwgrdnoc\norwbcgnd\n\nxlnyqidbvfuopwsmetkaz\naxsnipqkotbydfvuzle\nzsyaohudvqweikfpljxnbt\naezfhxqipvkdtbnoyuwsl\nqsneybxfzidcagokulptv\n\nphnrogdiuwlqtmfvjcb\nsdmufyklricxpg\nifdxpmkruealgzc\n\nxdiushclzbkvnfw\nbjmzunysickrfvxd\nxciutvyksbldfzn\nxfqpzabiuecnogsvkd\n\nolv\novl\nlov\novl\n\njirywmg\njnxmg\njfbgm\nmjhg\n\nsjfvbhimpyauqctgx\nxasifmnuqtyvgwojclp\njxyqabfuismptgcv\n\nspgmtcvwlxyfaq\ngpnqlctymxw\n\nxthqemkfpyls\npqhtsymrgzoef\nyskhmtfpqe\n\nxcsqaokhpt\nhcopsqtxak\npqoaxstchk\n\noqexlariumftkcg\nxceqoumklaiwnhtf\nxekitmlufoqcag\n\nzkjmutfxryowbnv\neuomntlvzxiqydrgwspa\nwhcyrmvozxktun\n\nhxqncgbjrsl\nbnlxcjrqhs\ncjqngsblxhr\nihpsnrblcxqj\n\nrjtlufdmxiqkn\nafmrkuindxljt\nuktrmjilxnfd\n\nypxqris\nhpgk\nbudwp\n\noqulm\nu\nu\niu\n\nkahocwxnueyri\nrzesvkxyltmbpqg\n\npkxjboidfvymngzrts\nrsizgmydxkpfvbtnjo\nbopgismxvrzntydfjk\novgfdztnspyxibkrmj\noecxdvmgrfkzbnypijts\n\nruvmcpojzsqtayw\nrqotdwzmpjcuys\nptnscirkowujyzqfm\nocszmjwrtyqpu\n\nnzxqdbwvpkioaj\nbqijkzpxwonadv\nkivqoujwxdzpntab\ninxabjvzpqdkow\n\nochlv\ncovl\ncovyl\n\nqsoypnvewrhjkdgtb\njpgwdknqeytbhsovr\nbdpwyrjuhoqgevtsnk\nrkoeypwbvgjnhsqdt\nqgtnyodrepsvkbwjh\n\nu\ni\no\no\nrx\n\necikgqxbyjhupozvdnrstawfm\ncnuiyopkzwmsbtadgeqrfxvj\nomkbnwrszvaetclqdpxfiygju\nwimrdtexbnjspgokuvzaqcyf\nveacgjpzmnioqksfwybxurdt\n\negfkhxi\ngkshf\n\nshiayxrwutmzf\nisyatmhuzf\n\ntfgmicrqnpxz\njeurkptlyh\nkvtphwr\n\ntyqrx\nhotsrdyqz\nyptqr\ntyqr\nryxtq\n\nlxtdzqwcakvm\nxdkqrlzv\n\nipujabzkmldhfrwg\nbjmpkavhlgqrwfdiz\nofhizbrtdcagljwmp\nbfgvdaesjpwrlzumhi\n\ns\ns\ns\ns\nhs\n\nnobqduvlcjtw\ndyrbtpzwng\n\niohlwxgfs\nzokfn\n\nuawlqejvnfkzhor\nrqhkanfvexlwzoju\navqekulojnfrzwh\nkljwrhonqfzauev\n\nln\nnl\nnl\nln\nln\n\nqyxi\nfmxbo\nqxo\npkvnutje\n\ntjsz\nzjr\ngydfxcjliq\n\nufa\ndohwy\nf\nkau\n\nezjqncv\njqvzenc\n\npnhlasjrztw\nrlswpatnjz\nhpntrjslazw\nzjnrwtlapcs\n\ni\ni\ni\ni\ni\n\naovitgfucj\nbowihz\niol\niweoz\niyo\n\nbdgmouhjvyxr\ninpshdz\nnhdfia\nhtdl\n\npnzawmosg\nzganost\n\nemrakn\nglveamkr\nrkgames\nakfqmper\nimudroeak\n\ntibgokrjpxmy\niydtpmjkx\ndkcjpxseiymt\n\nimfnqegj\nmcp\nnwgkhmbrpjac\nszovdtxl\n\nqnosfwmzpiubkxdhctg\nmsutibqnakhgczfopxw\nxtnowmgicfqsuzbhkp\npwbkcqiutxfshzngmo\n\njgaqubtpokrn\njpqgotluzna\n\nsiblotrefupcmyajdwxhvn\ntdxpnfrbuivjchlsawoeym\n\ngvbfkphuqwsrdoejlt\nixpkoqzldfncbahwt\n\nrdlfmyaejnswgopv\nysjfvmazeilonurbpwx\njayvlrwcmpefnos\nyowvefjknltqamscprh\n\nr\nd\nd\nd\nd\n\niry\ngi\nlri\n\nkzopchbqgf\nphcifmsbgz\ncanbyhlvdfpg\n\nljmtd\nstlxdvmkjqy\notcljbfehmd\n\nzgkiqsjrm\nrmqosfenz\nzqdmrsig\n\njaegcxl\ndelcpxa\nlktzbxcea\npdclajxe\n\ngdrfnb\ndngbqriyh\nojnbgrzd\nfdnrbg\n\nixnhlufgkqojyrcdwms\nuvfmspygeizlkhxcawrbdotq\n\ncfzy\nzfcy\nczfy\n\nkfbqdvgacxnluszhejiowmytr\ndurgtzlkjpwnechqibxfamvoys\n\nnjcgoslbyutihpqxwe\nwrbgpdquiykhnofvecztl\n\ncozxyqbvugrmkdwlh\nrxcdwuylztbvgmqhk\nurmhkcdlxvgyqzbw\n\nokzsvutdehimnc\nmednkuhxgqwvizots\n\nsogfalbukwvchqmjdtypzix\npyfazktchbmvsqguojwxild\nimsgakcotjpdhuwbfyzxlqv\n\nyzpafqijdchrvosxkt\ntqvsdrxzojhipfkyc\ntsfqokvphixzdcryj\npjfqzhtxocrdkvyis\n\nysmndq\nqdsnm\nrskilmn\n\nq\nq\nq\nq\n\nfygruq\nfxckylwohur\nfspaznjvbmdt\n\nztqa\na\nnma\na\na\n\nerml\nejrm\nrem\nemr\n\nqkmpeuatxdbrcghnjlo\nxnlmcohutkdbeaqvpfrj\nrboxcdpaujeqhknmtl\n\nbpmiwjrs\n\ntyr\nry\n\njkyolgr\ndv\nanwid\nidzv\n\nz\nxzpnb\nz\nz\nhz\n\nmwxibru\ndxrwzobi\nwixqvrb\nsbrxwi\nbaixrw\n\nyzcdlgujxrpmbs\niadjzpcnyrm\n\nnq\nqn\n\nsbwtamevgyicuhxrlfz\nuzxkpmitwvlfqhcgjn\n\nxvhbkanc\nbozyjftqrl\n\nvpcougdijwlxtsmznarqfy\nqyroagjdmsicwlftvxunpz\nnylpitxuqdwrszamfgjcvo\namogspxyvrdniztqfuwlcj\nfuoiwmpvtlxdszqncrjayg\n\nocmqey\nyqoce\n\nmvulfyk\nfxyuivlmk\nafvulokym\nxufvjmykl\n\nwjz\nowpfqnsrgt\newycah\nwebhjid\nbwi\n\nucxqaszovj\nxacvqjskizuo\n\nauxsjhkiq\nzcymv\n\nqyljukpbitdx\npxqjlduitkyb\nutbpqxjyklid\nyjkdqxptbluir\npuliqbtkdjxy\n\nljurghymqktvpenzsbofwdxc\nofyrjptgnczlwebdxvqmkuhs\nblopcvezhdsjnxgyktqfmrwu\ndwmqkuhtjsofnzgbrvelxcpy\n\nzn\nndz\ntzn\nnkdz\nnzvk\n\nvmyrlzxcwkjp\nmkqlvyrcp\n\nxduvzyfarpkewscjqlmh\nfzcyvxkmhwqreapds\n\nnt\ncs\nc\n\njxraviqybmgutesdwkfohlp\nhnkfweosqvbijpymuxdtalrg\n\nfcjz\nmnwvo\n\nmfqnkiaj\nnakqfimj\narikjubnmqf\nzfqikanjxm\n\npjetdfwsxohlz\nwpkzntbfsdcai\n\nzoifjgyxkluhbrtq\nyjolrgquihbnxktfz\nzoibyqghrjxtkufl\niuklgxbyrtmjfqhovz\n\nr\nr\nr\n\nytqzlvcwseb\nbcvqntlswyez\ncvqbtewyszl\n\nhfyj\njsbrzyhiwknfg\nvfyajhd\ndjfhlym\nfohyjux\n\ndzcjlgutfoipaexkmn\nkoetcadiuznpmljf\nctnilkamodfpzjue\ncofuezanjlpktdim\n\nnvtjmurwhfzex\nthxnrwmvuejaz\njexztumwrhnv\n\nr\nr\nr\na\n\nenoclavqmypruwkb\ntzspyhlawuimvrq\n\nyxcbvjpsgt\ncrxgvitlzjbop\ngukcdbjtwvexp\nbgjcmqspztoxv\n\nw\nw\nw\nw\nw\n\nqmocdhri\nqpwioderm\ndvmocjruiq\n\nnvghcjxd\nnbcvdp\nnvhcd\ndjcvn\n\nyfzukw\nkuywf\nkwsyu\n\nadjzmqebokxhtuspwgiynf\nfmshwkpoguljtyrziabqn\nanyofkgzsbvpuiqthwmj\nqfbhkytzgnwoicjsapmu\n\ntlmn\nnlti\ntyehjn\n\ns\nr\ns\ns\ns\n\nn\nu\nu\n\ntie\njet\net\n\nachjyurqb\njpcbrhutqy\nrbjyuhcqp\nybfucqjhrw\nqujrhbcy\n\no\no\ni\n\nmigypa\npyimag\npmgiya\nagypim\nyaimgp\n\nkdzafylcnst\naznrtshxgylcb\ncstzyaln\nanetplcsyzq\n\nhilubmsyznrtvqxpjo\nyqbirxnpzslojvtumh\ntyxlnibhzmsovrjqup\n\nzloiuyekfpx\naqtxzmig\nwsgxinqbzj\nbavthrdxsiz\n\nacwdny\nghrxysndq\novdncy\n\np\nglxy\n\nksnzbjyxgwtvm\nnbwzvtkjysgxemro\nbvnykztsxjwcmg\nqyzbmxjhtakgnwfdvs\nxzjmbsevgwytnklo\n\nuolyhfmwcpnk\nykuchfolpnwm\nlnckhofpyumw\nylnfuowmrcphk\n\noumqj\nulzybvfsp\num\nu\n\nzh\ngh\nzh\nhns\nhg\n\nxlvaqwncsizrbopukyegdmh\nlxmsgzqyothupikvrbn\n\nlhqdviu\nqafnemdvlzbrpk\nqlvyxdw\nsdluoqygv\n\nv\nv\nv\nv\nv\n\nblqcsyup\nclmpubs\n\nnoumlji\nnouji\n\nwkvj\nd\nghy\nx\nk\n\nohbjykuena\njbyahkpez\njyafhevbk\nyeajhkb\n\nauqjksywpcthxf\nzchkqmanpd\nkvaephqcn\n\nygrvwtleidhapqcoxjzkbm\nuvmtjkcxphybegzqrawiold\ndpckejybntqgvhzaomwixlr\n\nwuvknho\nwunhkv\nawhuixnkv\n\nxtsglwhpkozumein\ntiwzoklpxheumsgn\n\nkdicmfpsejygzlraqh\nrgpqkamdfecyiljzs\nfgjrczaedymqliksp\nadlgcpfieqrmsyjzk\nmfwincakdjelorbygqszp\n\njhtufzbolnrpgiv\nrymwi\n\nbcdfkrgujzqwheptivls\nwlzfyvtimksqcdujngorb\n\neruyigjwb\nwojeybiulrg\nygujbwvzei\n\nfizsg\njnue\n\nyalxikzg\niagxkz\nxizkga\nzikaxg\nikxzag\n\npjzlhqwixksnovbtygr\nljnvgzykoswbtrhm\nrjtnogykswczhlbv\nychwztvrgsonebaljk\n\nwcmyzldhtfrposgnj\nfcrmtyphngjlzs\ngpalbicyvfnmjxekrz\n\nysmpe\nyemps\nstype\n\nmeruv\nmbrse\nryvmsei\nlaremdjq\nbremck\n\njaeutopnmdhvfklscirqgx\nselpyhdginkxfouq\ndifgepshqlukonx\n\noyz\nyoz\nyoz\nyoz\n\nkohdfzpsj\nrjkphfdzog\njopfsukhbdz\n\ncpvr\ncvy\n\nxavdpsto\nbweoysidhp\nrndplvsukoca\nodgusp\n\nofzgbwqdnkjp\nvcbnlqwofisg\nenbrymdqpogjwf\n\nukrdtiphflv\nfvdlnuirtkh\n\ns\ns\ns\nms\ns\n\nsmodvglcpenzbtw\nvgwcmfdnlobi\ndobmzclwvng\nconvbglwdim\nwrcojghvdblnmx\n\neuy\niey\nhrkyowpesz\nqeuyn\nylfe\n\njd\nygd\nd\nd\n\nifxlcevjr\nmuqybvdntl\n\nhpjdqw\nwjcmqdp\npkojqud\ndjpqm\n\nfz\nz\nz\nauzlgh\nzf\n\noadfixtrspzymgkjvhc\nkureodwxjzvqcagmflt\n\numdbplaejicognthw\nmldwpqitgubajnecho\ngdrhabsmketcwpolunij\n\nutpjbioagl\npujgaobsti\n\nwzqkmfigsenp\nbtdpmnrhaix\n\ng\nh\nfmy\n\nqfdshywubmn\nasnjyumvhfepqwbd\n\ntko\nk\nki\nk\nkvj\n\najrftpclemziyx\ntyfcpmzxjrael\nrlymxejactzpf\nxpfzalrmjteyc\n\nlngatvoimxerfs\nxvsyefntoli\nixvdqstzlonbefk\n\ndytmarichvj\ntvhdurymj\nmefohydrtjpvx\nyajumrtvhd\nmjrvthdy\n\nmdizkcbhuqxfpew\nlciqkhpdzwumfxbe\ndmwbhzqpojuexikcf\n\nav\na\na\na\na\n\nbuwiq\nwbqi\nbqviw\nwbjifuq\n\nszyogteivkjmubnl\ngnmeioyhdjzkutvwqb\n\nvetwlrjnzuxfamsydoqbhpcigk\nlhagxseotdcqbyrwnpfkizmjvu\n\nikt\nsxuik\nrigbk\n\nixzofbapunser\numbfxasovni\noansfubxi\nxsoauibnfk\n\nebzhanm\nrsywcgfuaoqxjvz\n\ndygrvauxpemhosqkwtfji\npxafqktysdjvgriwuehom\nikurtagpdqswmfjvhyxeo\nmhqlyugsravkxoptdwzfjei\nwejrsutgikxqpfvydhaom\n\nynam\nny\nnys\n\nexwzkcjqnvp\nekpzvqxjwacn\nwqnjveazxpkc\nzjvbqkwcrnepx\necnvywqzjsxkp\n\nqmfe\nqmep\n\ndlwymbrsvgxefi\ngxeyfiqmr\n\nmjgkdnbqzcrtfvue\nujgvnrtedqkzfobmc\nnerkmbcuztivgfdpjqy\nbktnacmqvjredfuzg\njgdecrktqnbvmufz\n\ndesyfjcwkgpabomrxluq\nuecwxsrgybalkpqofjm\ngmlaojpwqxsebufrcyk\nsxfoakcyjlmrghqepwub\ngmwouepvzjsirxaylfqbkc\n\nlugbrcezj\nekzuhpxtl\n\nbzurvkdm\ngkzbdvmuwq\n\nvihtwalesoqmgzrfub\ndqogrhlvueimaszbtw\nlmbiwygzaenursotvhq\n\nfagwlnujrsv\nujhnvmcrpsqwl\n\ndsoq\nodzqs\noxehvgqunspa\nsmoqd\ndsroq\n\nlw\nqnlwbze\n\nzcs\ndpalw\noqevmritxf\n\nhw\nwh\nmhz\nh\n\nxwpkgiureobdvamtlcs\nsumvltgxoerdpwbacki\nfaozilpxetcbvwnsrkugdm\ndioulrkpawstcbxgevm\n\ncfziqrvtghejx\nzahecstbvjrqy\ngcqrzvjnteolfhd\n\njronwks\nkjwrso\n\nxtfp\naqwzv\n\ngjvrecbxaqns\nkoficxqpjsvnalzb\nvcjbqxtunsa\nbvjxnqcas\n\nn\nn\nk\nif\n\nhnzquyjxadotim\nctrmnlvfugjkoziqy\nubnfoyqctmzpij\ngyqzvjwimunot\nnzmoluqikjywt\n\nwykxduqrzl\ndrklx\n\nxdr\nxrd\n\nsdrbokn\nrsnbdkio\n\nqespuyziargjdlwnkbv\niaorexbukcmtnwhf\n\ngti\ndit\nitb\n\ntzmwbguraxjcieodnf\ngmitqzdsnekjoxaf\n\nkdeziwsnf\nlgzkiwen\n\nfbvikdpshltegu\nkpfvidlguehtsb\ngdysepktuihlvfb\n\njzegrfyducaospkltvwq\ncrzgkleptvuwsfyoqjda\nrogqtajuweylsdfkzcpv\nzwacrlsptgqfoveydukj\nufokdrzglqjcewtaypvs\n\nhsqnofzvt\nahvpn\n\numaznoshrwf\nhzosundfr\nushfnzor\n\nw\nie\n\nbyandqklvw\nwadvyxbqikn\n\nxspcwfvnkuoydagthjmzbq\nahnprtxeojdmgfqvwzuikscyb\n\ntxpwbvjacrzifgshyluo\nhgytapvojfsbrxwilcuz\nwpvxzshcrabfjtygliou\nbvourjgzfytpiwchlaxs\n\nufesbdavpn\nsiunvefpdab\nnspafhdvbue\nvednpusafb\nsufvpbande\n\nlnzxudorwykfqs\nvckufbqxhwjmtga\n\ntwz\ntwz\ntwz\ntzw\nzwt\n\nnuaeqphyvo\novaqetnphu\nwvhulnpsxroqi\nntvqephou\nhyvuqpon\n\nszky\nkz\nkz\nkz\nkz\n\nuekpcxjqrbzy\newiyrkobtl\n\nrghuyp\nntyzexi\nyjnq\nsy\neysao\n\nyohactxlqbvsfe\nyacfqtxlsvbeho\nqxtaesbfhlovyc\nybotxfqschvela\ntsxbqlcyvfohea\n\ncrvkbef\nefbvkc\nerfvbkc\nfvbikec\necvfkb\n\neziafud\nodfeiz\nfeizd\nrmeflzidc\nzeifdo\n\nuh\nu\nu\nu\n\nslzwuvhqnbpogia\nbhviznawou\nufazbvinhwo\nariwbuvzhon\nvawnobztduhif\n\nlyi\nsyi\nimy\n\nigx\nqfz\n\nyugfqtepvxwdocijlzmhka\nymdleizpjgxcvtfhoakuwq\nutenhymdcgjqzlorxfvakiwp\nzwlvymtgfxeqcopuahjkdi\nauzpqtcifejhomdklyvwgx\n\nxfvdiwqpktjlaborgez\nmlcubagjpwzynxekqfiotd\nfadoezjwqxtpgbkli\nosldxpzbqeifajtkgw\n\nmfxjtn\npqesvmxf\nxmbojhft\nxbmafc\nacbfxhm\n\nbsua\nuasb\n\ndtmpiwjkuahzryfvqgx\niavzqyhgmrxwtdukjp\nthzkaxwjpydqmviurg\n\nuabgmyoidlekzcqnfvxsrw\nkcybroagdmufqxiseznvl\neroscxuqvglanbikzyfdm\ngfmdeibnkvuaqryzloxcs\n\nwtmds\ncxm\nwqdrmz\nvoahgpkfml\n\nqmougypvzh\nyoqsgdpnmhuz\ngauxyzpkoqmjbwfl\nqguzoivyrdmpt\n\nuyerotgj\nwqszinpyv\n\nrosx\nors\nors\nosr\n\ndtcuiwlse\nbgaosqntxuwfpvrc\nuymskctjwz\n\ncshbnzoduxlpfrayj\nhcasypofnrxblduj\npjyuoxrfbsaldhnc\nuharfpoxcdysbnlj\n\nbsklgcdmpxio\nojbpdlcmtugskx\nexdkmpboclgy\naipogmwxdkrclb\ndilmqcpkxnwbgo\n\nxsajoug\npxujgatso\nguxojsa\nmbxuwzjosga\npxjsugoa\n\ntgfw\nxemdgvyfu\njfga\nlfg\n\nkhvg\nkghv\nvghk\nghkv\nvgkh\n\nxfogcwnvkey\nkvxwomyfeqc\nwoxycvafkbe\nyovafwxcke\nekvfyxnwco\n\nezpfkoxycuwgimqvabdtjnsrh\nnmpoxgwdyruecazsfjbhqktiv\nqtjzmaycsgnibdxeuwrfkhvop\nyfaqredhbxinsvucogwtkmpzjl\n\nmhlnsrfadjpekczwquvo\nvsdneluworhbqjfztamcp\nsmthfdwjznvqpclogaure\ncevkfuzqxjmwrlasphnod\nijrnwqpvudzalfoesmch\n\nicmdtnrpq\ntmdqnirp\nmdintrqp\nrtpmniqd\n\nclspvk\nxclpsw\n\nrmdoajtxvc\nvurmjotdsa\nmdrovatj\nnadvmrjlot\ndrjotavm\n\nkl\nhfjkblv\ncklr\nlrsk\nglk\n\nxpoawenkc\nyrkpnzjocxue\npskncodex\n\nb\nb\nbq\nbh\nb\n\nkngbuqcyijvxeh\nkbcmngjshaxiyve\nenybjkvqtucgixh\nzhrevfodplyxnwikjgbc\n\nvizojfmup\nmfzhjqpuoiv\nuvtmfzipjgol\n\nysobmzkthjdw\nqlncxwamrtujevfpzgbhkdo\n\ngz\ngd\nickxr\n\nbrenfplc\nrzpvwumik\nrjctp\n\nhfwcruyoa\nihyduxfw\n\nzlumthynfkjixo\nkgxnbhztfyojmli\nkifzxhtlymngoj\n\nrqpdbzgjsowakvt\ngdzoyhjetcfbqkl\nnbjgqftozkud\nzxbogjqktd\n\nwritbe\netri\ndtfkern\n\nctwyqdi\nj\nme\nnkgzau\nsxkare\n\nqlwakzuxsnfjc\nufzkhmwax\n\nnjuysxmhdzivfgqb\nuamlqxdhnyvgjibfz\n\neigl\nlige\nelig\ngeli\nlegi\n\nvrmhebiqupxoclfatdkg\nytaoiknwcgrsdzevxj\n\nrhac\ndcajbr\noxizsuykfvlwn\n\na\nna\na\nnka\nzdua\n\nzedtlhmj\nyqoxn\n\nwyqhegrp\nwypqhegdr\nunrypgwqhez\nhypqrgbwe\nyrgpeqhw\n\nmxjkhbqgwuniftedzvcl\njciqfnbeumlkhgtvzxwd\nnjwquxidvbhctzmklefg\nhqfwtcmkuxvbjdelgzni\n\nlsigyrmjndapwtehux\nmtwpirehgfxuasdjnoly\nhpdlgjnimeusbtyawxr\nagywjlsmktzihxuceprdn\nnjwhigapyexmdlutvrsb\n\nwiaejbsdzncytol\ncjelwafyindtbzos\nzalobneisywctdj\n\njbsipuwdcyth\nthbauysdcgpiw\n\nbw\nb\no\nlr\n\nojkmnthfzlvg\nvhpzmgtonw\nyjovmnfwthz\nfnzhtmoav\nzcosivnmhdetx\n\nhdkofir\nkanxoflugziyd\nkodfcrwi\n\nqxpmckuelwtarij\nspxmvqwjrileckuat\ntuiqrajpwlmekxc\ntaeupwljxricqmk\n\ndn\ndn\nnd\npnd\n\nfvyxadu\nfwxmny\n\nvsxgc\nvscxg\nscgvx\n\nwovudbian\ndyeosauvinbw\nauvdwinbyo\nuaxoqnwirbvzc\n\naosvcdn\nosna\nsano\n\nshqt\nsqth\n\nktlracvqpeju\ntukcwearql\ntrealcukq\n\nrsezcvdbal\nzebvamcdrp\ncbedrvafxzn\nvxnibedzrac\ndbirvczae\n\ngbpzy\nubglkzp\npbgz\n\njtxhnfge\nxgfhevjtwn\ntjhngfxe\n\npvodec\ngoedfvamlx\neyovd\nevdorpn\nvedot\n\nlsyqpjuviohbz\nluzjybidopvx\nyiplobzvj\nzobwtpjlvnyi\nbzoilvpjyu\n\ncevybwgdmuahsqzp\nucpnimw\nowunkcpm\npmwoucf\n\nuqchtxvoaze\nehocxtvza\ncetazvhxo\nztvxcaeoh\n\ncgsonqxtdfwhzymv\nqbkncfmuxapdwl\nmfxjztcwryqdne\n\nzbkyrc\nckrzb\ncrkzb\nzkbrc\n\nmca\ncam\nmca\ncafm\n\nz\nz\nz\nz\n\nzytoupbkxdhmgcsflweai\nsmpikvyzcxlawobhefudgjnt\ndolpihwzxqckmaufytgbse\n\nktsr\nktfs\nitsxvkb\n\nn\ni\naklsuty\n\nwkgtem\nmewgtk\ngkemwt\nemwgtokb\n\nmbuxkiycz\nfhronqjexplgwa\n\nhu\nemlw\n\nvkuwrqnj\nhys\nmzet\n\nfmclnjvsaexpkg\nzjwpxevkmacsglf\nxsamjlvkcenfgp\nvapjkcmglxefs\n\nlegmbjuqsdkihtv\ndlsqkegihbcjtvm\nhqgdmvljsrktebi\nehlbvgidqtjkms\nbtmshvdikljgqe\n\nk\nkr\nlfi\n\nobmup\nubm\n\nazqdrvjimbfnoyp\nzbejcqxfkotplndv\npbojdfsnzvuwq\ngjpounhvqdfsbrz\n\nminxopwrsbvqegyuajcdth\noahnukmgepbtdriscxwvyj\nxmbtcwgrasnozhdjiupeyv\n\njitgzlokacv\nvzkushynclojtxgep\n\nntj\nntj\ntjn\njtn\njnt\n\ngdzxykoialsqurtj\nkigupewoxqjaztcdy\nzugyaqksiojtxd\nhyjqxgzdauktio\nkygqutaszdbxjoi\n\norsfkumexiq\nrsbjepxmi\nsmrxqgeik\narnsetyiomxv\nmwighaxsdrce\n\nmcuzkqvsdpltxe\npklvsuexmgqwizd\nzdqxseckmtyvlwgrp\ndvslkezanoqxmpb\n\ntcbqprkjgnihzs\nivgmxyzaernhwcqdjlt\notqhfjgcunsrzpi\n\nomqbwvktlsxjcfzaphyeid\nzijtkyxhqvowpulmbgenrdca\n\nigrz\nirzg\nrzgi\n\nkefw\nkewa\nakew\nxtekw\newkf\n\nlvxahjydcer\nsobnzgkp\nmusqfg\n\norijnpvwm\nobqzv\nulvo\nozuvt\nzcbolkqv\n\nouzpgsxejbmqkat\nbtiuxyojspgzqalrek\nekbqupzaxfotjgvs\n\nt\ntb\nt\n\nksyegbpm\nslmpgdetzbk\ngbseumpyxk\nekvphnbcjgms\nwgqrmispobkefa\n\ngwexf\nwfxeg\nxwfeg\ngfewhxb\n\noephijmkngbxw\nkxobwjhiegpm\nwehixbgkjmop\n\nrmvtujdxhki\nlkunxhme\nmafxsbhuogkypw\n\nrpimb\nprbi\nipbr\nbrpi\nribp\n\nhvjdeyw\njhecqpbyvsdw\nwvhdjye\nwvjedhy\n\nuodmbcpvr\nwvhk\n\nj\nj\nj\nj\n\ncrzngwqm\nzqgrwnc\nrcgnwqz\n\nxstoyzgvaefqclbuhi\nywbmiguzthefkvqo\npcuezdviyoqfbjght\nubigqfztyohve\nzovpgfueibjtqsyh\n\nqatefihbypn\nxwvskd\n"
  },
  {
    "path": "advent-of-code/2020/inputs/7",
    "content": "dim silver bags contain 3 posh fuchsia bags.\nwavy olive bags contain 1 striped olive bag, 1 dull cyan bag.\ndull coral bags contain 1 dim olive bag, 5 muted violet bags, 2 dark gray bags.\nbright olive bags contain 3 light indigo bags, 3 dark coral bags.\nclear lavender bags contain 1 dark olive bag.\ndim lime bags contain 3 dotted red bags.\ndrab indigo bags contain 5 striped coral bags, 2 muted bronze bags.\nstriped orange bags contain 5 wavy fuchsia bags, 5 clear red bags, 3 plaid red bags.\ndotted indigo bags contain 2 plaid white bags, 1 wavy gold bag, 1 plaid silver bag.\nposh crimson bags contain 3 clear crimson bags, 5 dotted silver bags, 3 dull crimson bags, 5 wavy violet bags.\nmirrored tan bags contain 1 plaid white bag, 3 vibrant beige bags, 3 drab silver bags, 1 pale blue bag.\ndull turquoise bags contain 5 plaid magenta bags, 3 bright aqua bags, 1 dim purple bag, 1 wavy orange bag.\ndark tomato bags contain 1 plaid gray bag.\nshiny red bags contain 4 vibrant maroon bags, 5 faded bronze bags.\nclear tan bags contain 4 pale lime bags, 4 faded plum bags.\nmirrored plum bags contain 1 wavy silver bag, 4 dim purple bags, 3 dim coral bags.\ndotted orange bags contain 4 pale aqua bags, 3 dotted aqua bags, 4 clear beige bags.\nwavy lime bags contain 5 dim salmon bags, 4 dark violet bags, 4 clear turquoise bags.\nfaded gray bags contain 2 dotted lime bags, 5 plaid tomato bags.\npale orange bags contain 5 faded maroon bags.\nshiny lime bags contain 3 striped olive bags, 5 light fuchsia bags, 1 pale crimson bag, 1 pale salmon bag.\ndrab red bags contain 5 muted chartreuse bags, 4 clear purple bags, 4 drab silver bags, 3 posh green bags.\nplaid plum bags contain 2 dim blue bags, 1 dim coral bag.\nclear red bags contain 3 plaid teal bags, 4 vibrant orange bags, 1 pale red bag.\ndark yellow bags contain 5 mirrored lavender bags, 5 dull bronze bags, 4 pale salmon bags, 5 wavy crimson bags.\nclear violet bags contain 5 clear turquoise bags, 3 clear beige bags, 4 dim plum bags.\nplaid cyan bags contain no other bags.\nlight salmon bags contain 3 dull yellow bags, 2 vibrant violet bags, 2 dark orange bags, 1 light magenta bag.\ndim indigo bags contain 2 vibrant orange bags, 3 drab teal bags, 4 plaid indigo bags.\nshiny magenta bags contain 1 dark salmon bag, 4 shiny gray bags, 2 mirrored purple bags.\ndrab coral bags contain 5 pale crimson bags, 1 mirrored aqua bag, 4 light red bags.\nmuted blue bags contain 1 dark green bag, 5 muted salmon bags, 4 posh beige bags, 4 pale salmon bags.\nplaid salmon bags contain 5 striped white bags, 4 posh fuchsia bags, 5 faded turquoise bags.\nvibrant bronze bags contain 1 bright orange bag, 2 bright plum bags.\ndull salmon bags contain 2 pale crimson bags, 3 dark tan bags, 5 light plum bags.\nstriped magenta bags contain 4 wavy yellow bags, 3 bright chartreuse bags, 5 plaid cyan bags.\nlight olive bags contain 5 vibrant beige bags, 3 faded tomato bags, 1 dark indigo bag.\nfaded turquoise bags contain 2 shiny salmon bags, 3 wavy crimson bags, 5 dim yellow bags, 1 posh salmon bag.\npale fuchsia bags contain 2 posh blue bags, 4 mirrored blue bags, 3 wavy silver bags, 2 wavy crimson bags.\ndotted tomato bags contain 2 dotted lime bags, 1 wavy teal bag, 1 mirrored black bag, 3 dull gold bags.\nshiny maroon bags contain 5 striped salmon bags.\nvibrant gray bags contain 5 clear tan bags, 5 plaid crimson bags, 3 striped cyan bags, 1 dark gold bag.\nmuted tomato bags contain 1 dull salmon bag.\nstriped salmon bags contain 4 plaid white bags, 5 dim salmon bags, 4 vibrant lime bags.\nlight tan bags contain 2 posh lavender bags, 5 shiny aqua bags.\nwavy brown bags contain 2 posh lavender bags.\ndrab beige bags contain 5 plaid coral bags, 3 bright turquoise bags, 5 dark purple bags, 3 mirrored black bags.\nbright tomato bags contain 1 bright teal bag, 2 bright tan bags, 2 dotted salmon bags.\ndim tan bags contain 2 striped cyan bags, 5 wavy green bags, 3 drab beige bags.\nlight plum bags contain 4 clear silver bags, 1 vibrant chartreuse bag.\nlight black bags contain 1 muted tan bag, 2 dim yellow bags.\nclear orange bags contain 5 mirrored violet bags, 1 wavy salmon bag, 3 dim plum bags.\nbright gray bags contain 5 dim blue bags, 1 dotted red bag, 5 mirrored aqua bags.\nstriped cyan bags contain 4 striped teal bags, 1 dark tan bag, 1 dim green bag.\nshiny olive bags contain 1 dark aqua bag, 2 muted lime bags.\nclear brown bags contain 5 dark salmon bags.\ndotted tan bags contain 2 plaid brown bags.\nlight green bags contain 5 plaid silver bags, 5 posh aqua bags, 3 dull green bags, 5 faded red bags.\nposh coral bags contain 1 muted teal bag.\ndrab green bags contain 1 dotted blue bag.\ndark fuchsia bags contain 2 wavy tomato bags, 3 faded plum bags.\nvibrant purple bags contain 3 posh tomato bags, 4 dim purple bags, 5 plaid brown bags, 4 dotted red bags.\nvibrant tomato bags contain 5 wavy orange bags, 1 striped teal bag.\nfaded coral bags contain 5 dotted maroon bags, 2 light tan bags, 1 plaid black bag, 4 dark indigo bags.\nposh gold bags contain 4 mirrored plum bags.\nmuted beige bags contain 2 pale brown bags, 4 dull black bags, 4 vibrant blue bags.\ndull green bags contain 3 drab silver bags, 5 dotted red bags, 3 mirrored violet bags, 3 bright black bags.\ndark lime bags contain 5 light chartreuse bags, 3 pale magenta bags, 1 dull indigo bag.\ndark orange bags contain 1 dark crimson bag, 2 clear turquoise bags, 2 dotted silver bags.\nmuted yellow bags contain 2 pale salmon bags, 3 bright plum bags, 3 shiny aqua bags, 5 plaid cyan bags.\nvibrant white bags contain 5 dim coral bags, 5 dim bronze bags.\nposh white bags contain 2 wavy blue bags, 3 clear chartreuse bags, 1 wavy coral bag, 5 drab turquoise bags.\nfaded violet bags contain 4 dim bronze bags.\nbright yellow bags contain 5 pale violet bags, 2 striped fuchsia bags.\ndim blue bags contain 2 posh salmon bags, 4 posh red bags, 5 clear turquoise bags, 4 muted lavender bags.\nplaid olive bags contain no other bags.\nposh plum bags contain 2 drab turquoise bags, 4 bright fuchsia bags, 4 drab indigo bags.\nposh violet bags contain 3 plaid olive bags, 2 posh teal bags, 1 posh purple bag.\npale beige bags contain 4 wavy crimson bags, 5 shiny gold bags.\nshiny turquoise bags contain 5 dark gray bags, 4 clear brown bags.\nclear bronze bags contain 1 dull coral bag, 1 mirrored cyan bag, 2 dotted orange bags, 1 plaid magenta bag.\ndark magenta bags contain 3 vibrant orange bags, 1 dull lime bag, 1 dim plum bag.\nlight silver bags contain 2 posh coral bags.\ndrab gold bags contain 5 mirrored gold bags, 1 bright blue bag.\ndull fuchsia bags contain 3 pale blue bags.\nmuted brown bags contain 4 drab fuchsia bags, 4 plaid bronze bags.\nbright coral bags contain 2 dull crimson bags.\nclear black bags contain 5 striped brown bags.\nmirrored coral bags contain 2 striped brown bags, 4 clear coral bags.\ndull purple bags contain 1 plaid green bag, 5 shiny gold bags.\ndrab brown bags contain 4 striped coral bags, 1 muted magenta bag, 4 faded red bags.\nfaded plum bags contain 5 shiny orange bags.\nvibrant violet bags contain 1 drab gold bag, 1 light violet bag.\nclear salmon bags contain 5 posh orange bags, 1 wavy fuchsia bag, 5 mirrored yellow bags.\ndull yellow bags contain 5 light orange bags, 4 striped purple bags.\nstriped olive bags contain 1 plaid beige bag, 1 shiny turquoise bag, 2 drab gold bags, 1 pale lime bag.\nclear beige bags contain no other bags.\nmirrored fuchsia bags contain 1 clear olive bag, 3 pale aqua bags.\nposh turquoise bags contain 5 pale crimson bags, 3 dull cyan bags.\ndull lime bags contain 3 plaid chartreuse bags.\nwavy black bags contain 3 dull salmon bags, 5 plaid teal bags.\ndim lavender bags contain 1 dark gray bag, 2 muted indigo bags.\nwavy yellow bags contain 2 striped turquoise bags.\nstriped gray bags contain 3 drab white bags.\ndotted magenta bags contain 3 plaid white bags, 4 clear beige bags, 1 faded maroon bag, 3 muted lavender bags.\nvibrant coral bags contain 5 shiny olive bags, 2 pale brown bags.\ndim aqua bags contain 5 striped crimson bags, 3 bright lavender bags.\npale lavender bags contain 3 vibrant tan bags.\nbright fuchsia bags contain 2 dotted fuchsia bags.\ndark black bags contain 5 drab purple bags, 3 striped yellow bags, 2 posh tan bags.\ndark teal bags contain 3 plaid white bags, 5 bright cyan bags, 1 posh blue bag, 4 mirrored magenta bags.\nplaid brown bags contain 3 bright plum bags, 1 muted magenta bag, 4 clear gray bags, 2 clear crimson bags.\nmirrored magenta bags contain no other bags.\nlight brown bags contain 4 wavy red bags, 2 faded white bags.\ndotted purple bags contain 2 pale lime bags.\nclear teal bags contain 3 plaid red bags, 3 striped coral bags, 4 mirrored black bags, 2 posh red bags.\nstriped gold bags contain 3 bright plum bags, 2 mirrored gold bags.\ndotted black bags contain 2 clear crimson bags, 1 dark violet bag, 2 clear teal bags, 3 mirrored purple bags.\ndim gray bags contain 1 dotted salmon bag, 2 dim silver bags, 5 wavy black bags, 2 dotted green bags.\nshiny black bags contain 3 plaid bronze bags, 5 dim plum bags, 3 muted teal bags, 5 muted magenta bags.\nplaid orange bags contain 5 plaid crimson bags, 4 muted white bags, 4 dark lime bags, 5 plaid cyan bags.\nstriped fuchsia bags contain 1 dull bronze bag, 1 wavy aqua bag, 1 plaid salmon bag, 2 faded cyan bags.\nwavy white bags contain 4 posh beige bags.\ndull teal bags contain 1 vibrant blue bag, 1 light red bag, 3 striped brown bags.\nvibrant chartreuse bags contain 1 shiny aqua bag, 4 clear crimson bags, 1 faded red bag, 1 dull crimson bag.\nwavy cyan bags contain 5 striped red bags, 1 shiny magenta bag.\nvibrant olive bags contain 3 light fuchsia bags, 5 pale tan bags, 5 light tomato bags.\ndotted fuchsia bags contain 5 clear silver bags, 5 light aqua bags, 5 posh beige bags.\nwavy tomato bags contain 2 wavy tan bags, 3 muted lavender bags, 2 pale salmon bags.\nposh lime bags contain 4 drab lime bags, 4 dull lavender bags.\nshiny white bags contain 1 plaid olive bag, 2 faded white bags, 2 dull salmon bags.\nbright plum bags contain 1 dotted salmon bag, 4 plaid red bags, 1 mirrored purple bag, 3 shiny aqua bags.\ndotted lavender bags contain 1 light green bag, 3 light magenta bags.\nbright gold bags contain 4 dim blue bags, 5 dark salmon bags, 2 posh crimson bags.\nstriped violet bags contain 4 posh plum bags, 1 drab crimson bag, 2 faded orange bags, 3 dotted green bags.\ndull plum bags contain 1 dark maroon bag.\nstriped tomato bags contain 5 striped maroon bags, 1 plaid turquoise bag.\nmuted bronze bags contain 1 plaid red bag.\ndull lavender bags contain 2 plaid white bags.\ndark bronze bags contain 1 clear turquoise bag, 5 dim purple bags, 2 bright turquoise bags, 2 striped coral bags.\nmuted green bags contain 3 plaid white bags, 5 pale blue bags, 3 plaid tan bags, 2 clear turquoise bags.\nmirrored bronze bags contain 2 faded white bags, 3 bright teal bags, 2 clear red bags, 2 clear crimson bags.\nclear silver bags contain 5 dim yellow bags, 2 striped brown bags, 1 muted magenta bag.\ndark indigo bags contain 3 faded maroon bags, 3 mirrored purple bags.\nposh silver bags contain 3 dotted maroon bags, 1 striped indigo bag, 1 faded red bag.\nlight teal bags contain 1 vibrant beige bag, 1 striped plum bag, 4 dim salmon bags.\ndull orange bags contain 2 shiny teal bags, 5 muted teal bags, 1 dark fuchsia bag, 4 bright magenta bags.\nmuted red bags contain 2 mirrored magenta bags.\ndotted gray bags contain 3 dull maroon bags, 4 mirrored blue bags, 3 mirrored red bags.\nlight lime bags contain 5 plaid fuchsia bags, 4 posh plum bags.\npale coral bags contain 3 shiny gray bags, 2 plaid beige bags.\ndim brown bags contain 1 faded gray bag.\ndrab tan bags contain 5 dotted crimson bags.\nclear chartreuse bags contain 4 faded maroon bags, 5 plaid white bags.\nposh maroon bags contain 1 clear beige bag, 5 light black bags.\nmirrored blue bags contain 4 faded gray bags, 5 mirrored olive bags, 1 pale lime bag.\nclear coral bags contain 1 plaid fuchsia bag, 4 drab yellow bags, 4 light bronze bags.\nmirrored orange bags contain 4 mirrored lavender bags, 3 faded orange bags, 4 mirrored gold bags, 3 dim silver bags.\npale bronze bags contain 4 plaid orange bags, 3 wavy chartreuse bags, 2 clear red bags.\nfaded yellow bags contain 2 posh green bags.\nlight magenta bags contain 3 clear silver bags, 3 pale magenta bags.\nclear aqua bags contain 2 dark tan bags.\nclear yellow bags contain 5 dim violet bags, 5 drab bronze bags.\nplaid yellow bags contain 4 dotted salmon bags.\npale salmon bags contain 2 plaid olive bags, 5 clear beige bags.\nbright magenta bags contain 2 shiny maroon bags, 1 bright maroon bag, 5 shiny white bags.\ndull brown bags contain 4 posh fuchsia bags, 2 dotted tan bags.\nmuted magenta bags contain no other bags.\nmuted lavender bags contain 5 light aqua bags, 1 faded maroon bag, 4 plaid lavender bags.\ndotted violet bags contain 2 pale red bags, 3 mirrored magenta bags.\nwavy gray bags contain 5 dark indigo bags, 3 dim yellow bags, 3 posh lime bags, 1 wavy yellow bag.\nposh beige bags contain 4 mirrored magenta bags, 1 striped brown bag, 1 mirrored aqua bag, 5 dotted silver bags.\ndrab crimson bags contain 2 faded coral bags, 4 light indigo bags, 4 dark indigo bags.\nwavy magenta bags contain 5 clear gold bags, 4 dim purple bags, 3 pale green bags.\ndim fuchsia bags contain 2 drab teal bags, 4 plaid brown bags, 5 faded orange bags.\nfaded indigo bags contain 2 faded orange bags, 4 striped turquoise bags, 4 pale salmon bags, 4 bright cyan bags.\nposh yellow bags contain 2 pale gold bags, 3 posh coral bags, 1 dotted tan bag.\nmuted chartreuse bags contain 5 plaid brown bags, 3 dull green bags.\ndotted plum bags contain 4 mirrored purple bags, 1 drab tan bag, 3 striped white bags.\nclear plum bags contain 3 posh green bags.\nstriped red bags contain 1 striped tomato bag, 1 wavy fuchsia bag, 3 clear yellow bags.\nstriped aqua bags contain 4 posh teal bags, 2 bright beige bags.\ndim gold bags contain 5 dull salmon bags, 3 mirrored red bags, 1 mirrored black bag.\nmirrored brown bags contain 1 mirrored salmon bag.\nwavy plum bags contain 3 shiny yellow bags, 5 light crimson bags, 5 dotted silver bags.\nstriped coral bags contain no other bags.\ndark gray bags contain 4 dotted salmon bags, 2 clear brown bags, 2 posh crimson bags, 5 mirrored plum bags.\nposh chartreuse bags contain 2 wavy fuchsia bags, 4 mirrored beige bags.\ndotted gold bags contain 1 dark lavender bag, 1 striped black bag.\nposh green bags contain 3 dotted salmon bags, 4 pale salmon bags, 3 posh red bags, 4 dim green bags.\nplaid blue bags contain 2 posh green bags, 3 dim cyan bags, 5 dull bronze bags.\nlight lavender bags contain 5 muted green bags, 1 light violet bag, 5 muted plum bags.\npale plum bags contain 5 muted lavender bags, 5 light bronze bags, 4 plaid crimson bags.\nmirrored indigo bags contain 4 dark violet bags, 2 wavy purple bags, 5 plaid tan bags.\ndim violet bags contain 4 mirrored black bags, 4 dull lime bags, 3 posh crimson bags, 1 pale brown bag.\nshiny coral bags contain 1 light aqua bag, 5 plaid olive bags, 4 bright turquoise bags.\ndotted cyan bags contain 4 shiny olive bags, 4 light bronze bags, 2 dim plum bags.\nmirrored teal bags contain 5 dim violet bags.\nshiny purple bags contain 4 dim magenta bags, 2 clear white bags, 3 posh silver bags, 1 shiny turquoise bag.\nshiny gray bags contain 5 pale lavender bags, 3 vibrant turquoise bags, 1 faded maroon bag, 1 bright cyan bag.\nmirrored chartreuse bags contain 2 clear white bags.\nlight beige bags contain 5 mirrored turquoise bags, 5 plaid maroon bags, 3 light silver bags.\ndull tomato bags contain 1 shiny gold bag, 4 pale blue bags.\nplaid teal bags contain 1 dim purple bag, 3 striped turquoise bags, 3 light indigo bags, 2 faded red bags.\nvibrant aqua bags contain 3 mirrored turquoise bags, 1 light plum bag, 5 clear teal bags, 1 dull blue bag.\ndotted turquoise bags contain 5 bright fuchsia bags, 5 dim blue bags, 3 posh green bags, 3 wavy red bags.\ndark lavender bags contain 1 mirrored lime bag, 2 plaid red bags, 2 striped white bags, 1 plaid tomato bag.\nplaid tan bags contain 5 plaid white bags.\npale olive bags contain 1 clear salmon bag.\nwavy indigo bags contain 1 plaid black bag, 1 wavy teal bag, 3 mirrored salmon bags.\ndrab chartreuse bags contain 2 light lime bags, 3 drab yellow bags.\ndrab blue bags contain 3 vibrant brown bags.\nmuted purple bags contain 2 shiny yellow bags.\nmuted aqua bags contain 4 striped white bags.\nmirrored violet bags contain 3 wavy violet bags, 4 mirrored aqua bags.\nbright cyan bags contain 3 wavy fuchsia bags, 2 dark coral bags, 1 shiny orange bag.\nposh teal bags contain 5 bright gray bags, 4 faded gray bags, 2 plaid turquoise bags.\nmuted lime bags contain 2 striped coral bags, 1 dark tan bag, 4 plaid cyan bags.\nmirrored crimson bags contain 4 faded violet bags, 1 posh purple bag.\nlight blue bags contain 2 dotted blue bags, 2 dark gold bags, 5 bright cyan bags, 1 light crimson bag.\ndull beige bags contain 2 dark turquoise bags, 5 mirrored violet bags, 1 muted crimson bag.\ndark cyan bags contain 5 muted blue bags.\ndim turquoise bags contain 3 shiny silver bags, 1 pale yellow bag, 3 plaid chartreuse bags, 1 posh bronze bag.\nfaded brown bags contain 3 dim silver bags, 2 mirrored bronze bags.\nwavy bronze bags contain 3 shiny tomato bags, 3 dim salmon bags.\npale brown bags contain 3 pale tan bags, 2 plaid olive bags, 2 posh lavender bags, 1 shiny aqua bag.\ndull white bags contain 1 dull red bag, 5 dark gold bags, 3 striped magenta bags, 2 muted green bags.\nplaid crimson bags contain 5 drab bronze bags, 2 pale blue bags.\nbright lavender bags contain 1 dark bronze bag.\nplaid red bags contain 3 striped turquoise bags, 4 dull crimson bags, 1 striped brown bag, 2 clear crimson bags.\nmuted gold bags contain 5 dotted black bags, 1 striped salmon bag, 3 drab purple bags, 5 bright red bags.\nstriped silver bags contain 3 posh black bags.\nbright aqua bags contain 4 light orange bags, 3 wavy blue bags, 3 dull lime bags.\nplaid fuchsia bags contain 2 shiny orange bags.\nbright violet bags contain 1 drab turquoise bag, 1 dim cyan bag, 4 pale blue bags, 3 wavy blue bags.\ndim white bags contain 1 plaid black bag, 5 plaid violet bags, 2 light gray bags.\nbright tan bags contain 5 bright gold bags, 3 shiny salmon bags, 2 muted magenta bags, 1 dotted black bag.\nshiny bronze bags contain 3 light aqua bags, 4 clear crimson bags, 1 light beige bag, 4 clear blue bags.\nmuted silver bags contain 4 striped lavender bags.\ndull red bags contain 1 dim coral bag, 1 faded plum bag, 4 plaid red bags.\nwavy aqua bags contain 2 dotted fuchsia bags, 2 mirrored tomato bags.\ndark olive bags contain 4 muted yellow bags, 2 shiny gold bags, 2 posh crimson bags.\ndark crimson bags contain 3 shiny aqua bags, 1 wavy black bag.\ndark brown bags contain 2 drab lavender bags, 5 posh green bags, 4 pale turquoise bags.\npale blue bags contain 2 striped coral bags, 2 shiny gold bags.\nvibrant blue bags contain 1 mirrored lavender bag, 4 dark aqua bags, 5 wavy coral bags.\nposh cyan bags contain 1 dull lavender bag, 3 striped gray bags, 1 vibrant orange bag.\nfaded red bags contain 1 posh crimson bag, 1 wavy coral bag, 5 clear beige bags, 3 dotted silver bags.\nvibrant gold bags contain 3 drab lavender bags, 5 dim magenta bags, 2 bright tomato bags, 4 light magenta bags.\nshiny chartreuse bags contain 5 vibrant turquoise bags.\nclear gray bags contain 4 wavy coral bags, 2 dark salmon bags, 3 dark indigo bags.\npale maroon bags contain 4 posh tomato bags, 5 bright tan bags.\nlight turquoise bags contain 3 drab fuchsia bags, 4 bright silver bags, 5 light green bags.\nmuted crimson bags contain 1 dim yellow bag, 4 wavy fuchsia bags, 2 mirrored magenta bags, 2 clear beige bags.\ndull gray bags contain 2 posh green bags.\nlight fuchsia bags contain 5 dark gold bags, 3 plaid black bags, 2 bright lavender bags.\nstriped green bags contain 2 striped fuchsia bags, 5 dull tomato bags, 2 posh crimson bags.\nmirrored purple bags contain 2 posh crimson bags, 2 mirrored magenta bags, 3 wavy violet bags, 1 striped coral bag.\nvibrant black bags contain 3 clear magenta bags, 4 muted salmon bags, 5 posh blue bags.\nplaid beige bags contain 2 dark black bags, 5 plaid yellow bags, 2 bright violet bags.\npale teal bags contain 3 pale crimson bags.\nstriped turquoise bags contain no other bags.\ndim purple bags contain 2 dull crimson bags, 5 bright red bags.\nfaded cyan bags contain 5 posh aqua bags, 4 dull green bags, 3 dark olive bags.\nmirrored cyan bags contain 5 plaid salmon bags, 4 dim salmon bags, 4 posh tomato bags.\nstriped purple bags contain 2 faded salmon bags, 2 bright tan bags, 4 drab white bags.\nbright blue bags contain 3 light purple bags, 1 pale yellow bag.\nfaded bronze bags contain 1 light indigo bag, 3 plaid green bags, 5 posh orange bags.\nstriped white bags contain 4 drab indigo bags, 5 wavy tomato bags, 5 dotted fuchsia bags, 2 dim silver bags.\nclear lime bags contain 2 dotted magenta bags, 5 striped magenta bags, 3 bright coral bags, 3 mirrored silver bags.\nbright white bags contain 3 dim lavender bags.\ndim crimson bags contain 1 posh black bag, 1 mirrored silver bag.\nclear olive bags contain 4 vibrant purple bags, 3 drab lavender bags, 2 pale violet bags.\nlight coral bags contain 2 dotted green bags, 2 wavy aqua bags, 4 dark salmon bags, 3 light gold bags.\nmuted plum bags contain 5 plaid tan bags, 1 mirrored silver bag, 3 vibrant turquoise bags.\ndim plum bags contain 4 bright plum bags.\ndrab bronze bags contain 1 light indigo bag, 3 striped brown bags, 3 clear gold bags, 3 clear gray bags.\nplaid maroon bags contain 1 dotted orange bag, 5 light magenta bags, 4 faded salmon bags, 3 pale yellow bags.\nwavy violet bags contain 2 dotted silver bags, 3 dull crimson bags, 5 mirrored aqua bags, 4 striped brown bags.\npale crimson bags contain 3 bright chartreuse bags, 4 light turquoise bags, 1 bright gray bag, 1 muted bronze bag.\nmirrored aqua bags contain no other bags.\nclear crimson bags contain 2 pale salmon bags, 4 mirrored magenta bags, 1 striped coral bag, 5 plaid olive bags.\ndark tan bags contain 4 wavy silver bags, 4 dark aqua bags.\nwavy maroon bags contain 3 clear gray bags.\nlight crimson bags contain 3 clear silver bags.\nvibrant green bags contain 1 clear magenta bag, 1 dim white bag, 4 plaid black bags.\nbright bronze bags contain 2 light brown bags.\nlight maroon bags contain 5 bright red bags, 2 bright tan bags, 5 dim silver bags, 4 pale salmon bags.\ndark coral bags contain 2 light crimson bags.\npale silver bags contain 2 mirrored magenta bags, 3 posh red bags, 1 muted yellow bag, 5 dark salmon bags.\ndotted crimson bags contain 4 faded salmon bags, 4 vibrant beige bags, 5 dim beige bags.\ndull silver bags contain 1 striped brown bag, 2 shiny magenta bags.\nstriped beige bags contain 4 clear crimson bags.\nfaded orange bags contain 2 drab white bags, 3 striped salmon bags, 5 bright chartreuse bags.\ndrab olive bags contain 4 clear purple bags.\ndull maroon bags contain 3 dotted magenta bags.\nvibrant lavender bags contain 2 light tomato bags, 1 shiny teal bag.\ndotted chartreuse bags contain 4 faded white bags, 2 light brown bags.\ndrab cyan bags contain 2 pale coral bags, 3 light purple bags, 2 drab bronze bags, 1 dim beige bag.\nbright teal bags contain 2 vibrant plum bags, 2 dull tan bags, 1 dim tomato bag, 5 dark violet bags.\nwavy fuchsia bags contain 1 dim green bag, 2 wavy violet bags.\ndrab black bags contain 3 striped tomato bags, 4 light salmon bags, 4 dim yellow bags, 3 shiny black bags.\ndark green bags contain 5 dark tan bags.\nclear tomato bags contain 4 mirrored gold bags, 4 dark gold bags.\nplaid aqua bags contain 5 dotted coral bags, 1 muted white bag.\nplaid white bags contain 3 clear crimson bags, 3 wavy gold bags, 3 pale lime bags, 2 striped brown bags.\nmuted black bags contain 1 wavy tan bag, 4 mirrored turquoise bags.\nfaded aqua bags contain 5 dull turquoise bags, 1 vibrant tan bag.\nvibrant brown bags contain 5 pale silver bags, 3 drab orange bags, 1 clear olive bag.\npale cyan bags contain 2 faded cyan bags, 1 mirrored tan bag, 3 vibrant aqua bags, 3 light gold bags.\nshiny salmon bags contain 5 posh red bags, 5 light chartreuse bags, 2 striped brown bags.\nplaid lime bags contain 4 dim gold bags, 1 clear magenta bag.\ndrab tomato bags contain 5 clear orange bags.\nfaded beige bags contain 3 dark crimson bags, 2 mirrored tan bags.\nvibrant crimson bags contain 4 wavy blue bags, 5 clear gray bags.\ndotted maroon bags contain 5 dotted red bags, 4 wavy silver bags, 1 drab brown bag, 3 dark black bags.\nstriped indigo bags contain 3 striped orange bags.\ndim orange bags contain 1 wavy lavender bag, 5 drab brown bags, 1 dull salmon bag.\nposh olive bags contain 3 faded indigo bags, 1 plaid white bag.\nstriped lavender bags contain 1 bright red bag.\nmuted violet bags contain 3 bright tan bags, 5 striped coral bags, 1 drab bronze bag.\nwavy tan bags contain 1 striped brown bag, 3 dim salmon bags, 1 posh fuchsia bag, 4 mirrored violet bags.\ndull magenta bags contain 1 clear red bag, 4 dull green bags, 2 posh lime bags, 5 mirrored gold bags.\ndotted red bags contain 1 mirrored black bag, 3 dull bronze bags, 2 dim salmon bags.\ndrab turquoise bags contain 5 muted yellow bags, 1 light indigo bag, 5 dotted black bags.\nfaded purple bags contain 5 dim orange bags, 3 dark red bags.\nfaded teal bags contain 1 bright fuchsia bag.\nplaid gray bags contain 5 pale aqua bags.\nbright black bags contain 4 wavy violet bags.\ndim green bags contain 3 mirrored aqua bags, 1 light chartreuse bag, 1 light indigo bag.\ndark gold bags contain 2 mirrored red bags, 2 bright lavender bags, 3 pale crimson bags.\ndark plum bags contain 2 pale salmon bags.\nwavy orange bags contain 2 light tan bags, 1 pale yellow bag, 2 shiny aqua bags, 4 vibrant orange bags.\nbright chartreuse bags contain 5 dark salmon bags, 1 plaid olive bag.\nwavy purple bags contain 4 faded coral bags, 2 vibrant orange bags.\nshiny violet bags contain 3 plaid chartreuse bags, 2 plaid brown bags.\nposh indigo bags contain 1 posh salmon bag.\nclear indigo bags contain 3 light violet bags.\nplaid purple bags contain 1 clear blue bag, 2 muted gold bags, 1 dull brown bag.\nposh lavender bags contain 1 plaid black bag, 3 shiny orange bags, 3 posh red bags, 4 plaid cyan bags.\nwavy silver bags contain 3 plaid cyan bags, 1 plaid olive bag.\nposh salmon bags contain 3 clear gray bags, 5 dotted silver bags, 4 shiny aqua bags.\nfaded lavender bags contain 4 drab chartreuse bags, 4 plaid magenta bags, 1 vibrant tomato bag.\npale red bags contain 4 bright red bags, 4 pale lime bags, 3 striped turquoise bags.\nbright purple bags contain 3 muted lavender bags.\ndim magenta bags contain 1 plaid teal bag, 3 posh lavender bags.\nposh magenta bags contain 3 pale teal bags, 5 mirrored tomato bags, 2 striped gold bags, 2 bright tomato bags.\nbright brown bags contain 1 dark fuchsia bag, 4 pale yellow bags, 5 shiny crimson bags.\nlight red bags contain 1 wavy teal bag.\npale turquoise bags contain 3 mirrored yellow bags.\nvibrant magenta bags contain 4 dark gold bags.\ndotted salmon bags contain 3 wavy violet bags, 4 shiny aqua bags, 4 dull bronze bags.\nmirrored gray bags contain 3 dark plum bags, 3 striped gray bags, 4 plaid violet bags.\ndim yellow bags contain 3 striped turquoise bags, 2 pale salmon bags, 4 mirrored magenta bags, 5 striped brown bags.\ndrab lavender bags contain 2 faded maroon bags, 2 shiny orange bags.\nmuted maroon bags contain 1 wavy tomato bag, 2 drab red bags.\nclear gold bags contain 3 mirrored olive bags, 3 striped turquoise bags.\nlight bronze bags contain 1 muted lavender bag.\ndotted bronze bags contain 2 dotted turquoise bags.\npale tomato bags contain 3 shiny beige bags, 1 mirrored tomato bag, 2 dotted maroon bags, 2 wavy teal bags.\npale chartreuse bags contain 5 plaid silver bags.\ndrab magenta bags contain 5 wavy tomato bags, 1 drab brown bag, 2 posh maroon bags, 5 mirrored teal bags.\nposh blue bags contain 3 muted lime bags, 1 mirrored tomato bag, 5 shiny aqua bags.\nposh purple bags contain 5 dull maroon bags.\nposh bronze bags contain 2 mirrored orange bags, 2 pale violet bags, 2 plaid gray bags.\npale gold bags contain 4 striped brown bags, 2 muted green bags.\nfaded crimson bags contain 5 drab salmon bags, 2 posh crimson bags, 3 light purple bags, 5 clear red bags.\nvibrant fuchsia bags contain 2 posh beige bags, 4 dotted indigo bags, 5 pale silver bags, 4 clear black bags.\nfaded lime bags contain 3 posh plum bags, 3 shiny aqua bags, 4 dull chartreuse bags.\nshiny fuchsia bags contain 4 shiny salmon bags, 3 pale chartreuse bags.\nwavy lavender bags contain 2 dark blue bags, 5 muted salmon bags.\npale indigo bags contain 1 wavy gold bag, 1 clear silver bag, 3 dim blue bags.\ndrab violet bags contain 4 muted yellow bags.\nshiny plum bags contain 3 bright black bags, 5 pale teal bags, 5 light red bags, 2 plaid magenta bags.\nshiny gold bags contain 1 vibrant chartreuse bag.\nwavy gold bags contain 5 posh beige bags, 1 mirrored aqua bag.\ndark salmon bags contain 3 light aqua bags, 3 posh red bags, 2 mirrored black bags, 1 posh crimson bag.\npale tan bags contain 4 wavy coral bags.\ndull tan bags contain 4 bright cyan bags.\nclear maroon bags contain 4 dim magenta bags, 2 shiny lavender bags.\nlight white bags contain 3 dark brown bags, 4 bright fuchsia bags.\nwavy red bags contain 4 dim red bags.\ndotted aqua bags contain 4 striped teal bags.\nbright beige bags contain 5 shiny tomato bags.\nplaid indigo bags contain 1 muted bronze bag.\nlight yellow bags contain 2 striped black bags, 2 muted gold bags, 3 dotted tan bags, 5 dark coral bags.\nvibrant silver bags contain 2 dim blue bags.\nposh tomato bags contain 5 bright red bags, 3 posh red bags, 3 plaid olive bags, 4 clear crimson bags.\npale magenta bags contain 3 mirrored blue bags, 5 dull maroon bags, 5 dark violet bags.\nlight indigo bags contain 2 plaid olive bags, 1 plaid black bag, 3 dark indigo bags.\nshiny green bags contain 1 vibrant chartreuse bag, 4 bright lavender bags, 3 wavy crimson bags, 4 dull red bags.\nstriped maroon bags contain 2 posh coral bags, 2 striped gray bags, 3 clear plum bags.\nposh fuchsia bags contain 2 wavy gold bags, 2 posh beige bags.\ndim coral bags contain 4 wavy gold bags, 4 muted lavender bags.\nfaded maroon bags contain 5 dim purple bags, 4 bright red bags, 5 wavy violet bags, 1 mirrored aqua bag.\nstriped black bags contain 4 plaid fuchsia bags, 5 bright lavender bags, 4 dull black bags.\nmirrored gold bags contain 3 dotted silver bags.\nlight tomato bags contain 5 pale brown bags, 3 wavy coral bags.\ndark white bags contain 2 mirrored tomato bags, 1 striped orange bag, 1 dim olive bag, 2 dotted blue bags.\ndotted green bags contain 3 clear plum bags.\ndotted brown bags contain 1 clear magenta bag.\nmuted orange bags contain 3 muted olive bags, 2 faded yellow bags, 2 faded turquoise bags, 3 muted violet bags.\ndull olive bags contain 2 dotted teal bags.\nmirrored lime bags contain 4 dark violet bags, 4 muted yellow bags.\nwavy green bags contain 5 bright lime bags.\ndrab purple bags contain 2 striped turquoise bags, 4 clear silver bags, 1 muted lime bag.\nclear cyan bags contain 5 light lavender bags.\ndim black bags contain 3 dull black bags.\nposh gray bags contain 4 mirrored magenta bags.\ndotted yellow bags contain 4 light maroon bags, 1 clear blue bag, 5 dark maroon bags.\nmirrored olive bags contain 2 dark violet bags, 2 dull crimson bags, 5 dim salmon bags, 5 bright tan bags.\ndark blue bags contain 3 dull aqua bags, 1 dim teal bag.\ndull bronze bags contain 4 striped coral bags.\ndrab maroon bags contain 2 dark bronze bags, 1 wavy blue bag.\nmirrored lavender bags contain 4 clear black bags.\ndim beige bags contain 3 shiny silver bags, 2 dark purple bags, 3 dull green bags.\nlight violet bags contain 1 muted gray bag, 5 wavy tomato bags.\nstriped chartreuse bags contain 3 dull tan bags, 1 dim salmon bag.\nposh red bags contain 2 clear crimson bags, 2 striped coral bags, 2 bright red bags.\nwavy beige bags contain 5 muted silver bags, 5 pale teal bags.\nlight gray bags contain 5 drab indigo bags, 3 posh crimson bags, 1 dark tan bag, 2 pale red bags.\nmuted white bags contain 3 wavy fuchsia bags.\npale violet bags contain 4 wavy tan bags, 2 plaid yellow bags.\ndrab fuchsia bags contain 1 plaid lavender bag, 2 pale lime bags.\nclear green bags contain 4 light indigo bags.\nvibrant turquoise bags contain 2 vibrant tan bags, 3 clear silver bags.\nfaded green bags contain 5 striped orange bags, 4 bright fuchsia bags.\nstriped tan bags contain 4 wavy silver bags.\nclear white bags contain 3 vibrant fuchsia bags, 2 pale silver bags, 1 vibrant indigo bag, 3 shiny silver bags.\ndim cyan bags contain 2 mirrored black bags, 2 plaid chartreuse bags, 4 bright gold bags.\nmuted gray bags contain 3 mirrored violet bags, 4 dim yellow bags.\nmirrored maroon bags contain 5 clear crimson bags, 2 clear gray bags, 1 dotted salmon bag.\ndim bronze bags contain 2 striped plum bags, 2 bright orange bags.\nshiny tomato bags contain 4 dim yellow bags, 2 faded bronze bags, 1 drab maroon bag, 3 dim gold bags.\nmuted olive bags contain 2 mirrored yellow bags, 4 bright olive bags.\nshiny brown bags contain 3 bright coral bags.\nclear blue bags contain 2 pale green bags, 2 light violet bags, 4 plaid crimson bags.\nfaded tan bags contain 4 dim crimson bags, 3 mirrored turquoise bags, 3 drab gold bags.\nmuted cyan bags contain 2 drab silver bags.\nmirrored red bags contain 1 bright gold bag.\nfaded salmon bags contain 5 posh red bags, 4 dull crimson bags, 3 dotted salmon bags, 5 shiny olive bags.\ndark purple bags contain 5 dim magenta bags.\ndotted lime bags contain 4 posh fuchsia bags, 3 wavy tan bags, 2 mirrored aqua bags, 1 shiny aqua bag.\nposh tan bags contain 3 plaid tan bags, 2 drab fuchsia bags.\ndotted teal bags contain 4 dull crimson bags, 2 bright lavender bags, 2 wavy tan bags, 4 muted crimson bags.\nclear purple bags contain 4 shiny aqua bags, 1 dim cyan bag, 3 dotted black bags, 4 dull gray bags.\nlight gold bags contain 2 dotted magenta bags, 5 dark olive bags, 3 dim cyan bags, 2 dark indigo bags.\nmirrored silver bags contain 2 plaid black bags, 3 vibrant beige bags, 3 mirrored purple bags, 3 dotted lime bags.\nposh black bags contain 4 wavy violet bags, 3 plaid teal bags.\nfaded silver bags contain 2 vibrant purple bags, 5 shiny olive bags.\ndrab teal bags contain 2 dotted salmon bags, 4 posh beige bags, 4 mirrored tan bags, 1 muted green bag.\ndark maroon bags contain 2 dark tan bags, 5 mirrored gold bags, 2 dim plum bags.\nstriped plum bags contain 3 striped coral bags, 5 clear brown bags, 1 striped brown bag.\nstriped bronze bags contain 4 drab yellow bags, 4 striped chartreuse bags, 5 posh plum bags, 3 clear blue bags.\ndrab plum bags contain 1 shiny gold bag, 5 vibrant tan bags, 3 light gold bags.\nclear fuchsia bags contain 1 vibrant red bag.\ndark silver bags contain 5 clear salmon bags, 1 faded yellow bag, 1 shiny lavender bag, 3 wavy fuchsia bags.\nstriped lime bags contain 2 dim tomato bags, 3 light fuchsia bags, 1 light lime bag.\nwavy salmon bags contain 1 shiny tomato bag, 1 light tomato bag.\ndim maroon bags contain 4 faded beige bags, 2 bright turquoise bags, 4 dull purple bags, 4 vibrant olive bags.\nfaded chartreuse bags contain 4 mirrored blue bags, 5 posh white bags, 2 wavy magenta bags.\nclear magenta bags contain 2 muted bronze bags, 5 dim yellow bags, 2 dotted lime bags.\nbright silver bags contain 2 bright gold bags, 4 wavy yellow bags.\ndull violet bags contain 3 faded beige bags, 1 mirrored orange bag, 1 mirrored aqua bag.\nvibrant cyan bags contain 2 clear aqua bags, 2 dark maroon bags, 5 pale tan bags.\nlight chartreuse bags contain 1 wavy gold bag, 2 posh tomato bags, 2 clear silver bags.\ndotted olive bags contain 5 wavy crimson bags, 1 drab tomato bag.\nposh aqua bags contain 3 striped brown bags.\nposh orange bags contain 2 wavy coral bags.\ndull cyan bags contain 1 dark tan bag, 5 dull gray bags, 3 drab turquoise bags, 4 shiny aqua bags.\nmuted teal bags contain 4 dull blue bags.\nbright turquoise bags contain 5 dull bronze bags, 1 plaid lavender bag.\nplaid tomato bags contain 2 muted lime bags, 1 light indigo bag, 5 posh tomato bags.\ndim salmon bags contain 1 dark indigo bag, 5 plaid brown bags, 3 clear crimson bags, 4 clear silver bags.\nposh brown bags contain 3 clear silver bags, 5 faded cyan bags, 4 posh crimson bags.\ndark turquoise bags contain 1 drab crimson bag, 5 striped coral bags.\ndull crimson bags contain no other bags.\nstriped teal bags contain 5 plaid lavender bags, 4 faded red bags.\ndotted blue bags contain 5 muted beige bags.\nvibrant plum bags contain 1 pale lime bag, 1 posh red bag, 1 dull bronze bag, 3 drab silver bags.\nwavy coral bags contain 4 mirrored magenta bags, 5 dim yellow bags, 4 bright red bags, 2 posh crimson bags.\ndark chartreuse bags contain 5 dotted fuchsia bags, 3 mirrored silver bags, 5 mirrored aqua bags, 4 dim cyan bags.\nvibrant teal bags contain 3 vibrant silver bags.\nshiny beige bags contain 5 posh teal bags.\ndim olive bags contain 3 clear gray bags, 4 wavy gold bags.\ndrab yellow bags contain 4 light chartreuse bags, 3 striped crimson bags, 2 faded gray bags.\ndull chartreuse bags contain 1 light lavender bag.\ndotted silver bags contain no other bags.\nshiny blue bags contain 5 dull brown bags, 2 dark coral bags, 4 shiny crimson bags.\nmirrored black bags contain 5 mirrored magenta bags, 1 striped turquoise bag, 2 plaid cyan bags.\ndull black bags contain 4 dim purple bags, 4 dark salmon bags, 2 mirrored gold bags.\nmirrored beige bags contain 4 striped fuchsia bags, 4 plaid black bags, 5 dim red bags, 5 light green bags.\ndim chartreuse bags contain 4 shiny yellow bags.\nshiny teal bags contain 1 vibrant maroon bag.\ndim tomato bags contain 5 plaid tomato bags, 5 mirrored violet bags, 2 mirrored orange bags.\nvibrant beige bags contain 1 plaid black bag, 3 dotted salmon bags, 2 posh fuchsia bags.\ndull aqua bags contain 5 wavy tan bags, 3 bright olive bags.\npale lime bags contain 5 bright turquoise bags, 5 dim yellow bags, 3 shiny orange bags.\nbright orange bags contain 4 muted gold bags, 1 clear white bag.\ndrab salmon bags contain 2 dark fuchsia bags, 2 dull gray bags.\nmirrored salmon bags contain 3 posh plum bags, 1 dotted silver bag, 1 clear plum bag, 5 dull black bags.\nshiny silver bags contain 4 drab lavender bags, 2 dim violet bags, 5 dark aqua bags, 2 vibrant chartreuse bags.\nplaid coral bags contain 4 dim blue bags, 1 vibrant lime bag.\nmirrored white bags contain 2 pale gold bags, 3 shiny green bags, 5 striped white bags.\npale gray bags contain 5 mirrored gold bags, 1 wavy silver bag, 5 posh green bags, 1 mirrored red bag.\npale white bags contain 4 shiny turquoise bags, 4 bright plum bags, 5 dotted bronze bags.\nmuted fuchsia bags contain 5 plaid turquoise bags, 2 dark aqua bags, 4 pale brown bags, 4 striped plum bags.\nstriped yellow bags contain 5 posh red bags, 1 plaid black bag.\nplaid silver bags contain 2 dark indigo bags, 3 clear teal bags, 3 dotted black bags.\nplaid black bags contain 3 dull crimson bags.\nvibrant lime bags contain 1 dotted fuchsia bag, 4 dull bronze bags, 4 dark aqua bags, 1 dark salmon bag.\ndotted white bags contain 5 dim red bags.\nlight aqua bags contain 5 mirrored aqua bags, 2 striped brown bags, 4 posh crimson bags.\nstriped brown bags contain 1 dotted silver bag, 5 clear beige bags.\nvibrant red bags contain 3 bright olive bags, 3 plaid chartreuse bags, 3 light olive bags, 4 dim violet bags.\ndim teal bags contain 3 clear violet bags.\nbright lime bags contain 2 dull lavender bags, 4 pale turquoise bags.\nstriped crimson bags contain 5 bright gray bags, 4 dark green bags, 4 posh plum bags, 5 shiny coral bags.\nmirrored tomato bags contain 1 wavy tan bag.\ndull blue bags contain 5 bright turquoise bags, 2 striped brown bags.\nmirrored yellow bags contain 4 vibrant purple bags, 4 faded bronze bags, 2 dull lavender bags, 3 light plum bags.\nplaid gold bags contain 5 striped olive bags, 5 dotted chartreuse bags.\ndotted coral bags contain 2 bright teal bags.\nwavy crimson bags contain 5 dotted salmon bags, 1 dull crimson bag.\ndark aqua bags contain 3 dull crimson bags, 5 light aqua bags, 3 mirrored purple bags, 1 striped brown bag.\nvibrant yellow bags contain 1 faded beige bag, 3 dark brown bags, 1 wavy bronze bag.\nwavy teal bags contain 5 dotted magenta bags.\ndrab white bags contain 3 pale blue bags.\nmuted salmon bags contain 4 posh salmon bags, 1 bright chartreuse bag.\nlight purple bags contain 5 dark maroon bags.\nfaded black bags contain 4 dull gold bags.\nmuted turquoise bags contain 1 wavy silver bag, 4 clear purple bags.\nplaid chartreuse bags contain 1 posh crimson bag, 5 striped brown bags.\nvibrant tan bags contain 2 dull blue bags, 1 posh black bag, 1 faded red bag, 5 plaid magenta bags.\nshiny orange bags contain 5 vibrant chartreuse bags, 3 shiny gold bags.\nshiny lavender bags contain 2 posh teal bags.\npale black bags contain 5 dark brown bags.\nshiny cyan bags contain 5 wavy tomato bags, 3 bright bronze bags, 3 faded crimson bags.\nfaded olive bags contain 3 clear aqua bags.\ndark violet bags contain 4 faded red bags.\nlight orange bags contain 1 posh aqua bag, 2 light crimson bags, 2 dark maroon bags.\ndrab silver bags contain 1 pale blue bag.\nplaid bronze bags contain 5 mirrored orange bags, 4 plaid cyan bags, 1 dotted black bag.\nplaid violet bags contain 1 plaid fuchsia bag, 5 clear teal bags.\nclear turquoise bags contain 4 dim yellow bags, 5 plaid teal bags, 3 plaid red bags, 1 dotted salmon bag.\nplaid lavender bags contain 3 clear silver bags, 4 dull bronze bags.\nmirrored green bags contain 3 striped lavender bags.\nfaded white bags contain 2 light chartreuse bags.\nbright crimson bags contain 2 mirrored purple bags.\ndotted beige bags contain 1 pale salmon bag, 5 dotted teal bags, 5 light lavender bags, 3 wavy violet bags.\npale green bags contain 2 dark gold bags, 4 clear gray bags.\ndull indigo bags contain 2 striped brown bags, 3 plaid plum bags.\nshiny yellow bags contain 3 striped silver bags, 2 mirrored plum bags, 1 muted red bag, 5 clear gold bags.\nbright maroon bags contain 2 muted crimson bags, 2 plaid chartreuse bags, 1 dim violet bag, 1 plaid blue bag.\nvibrant orange bags contain 5 posh plum bags, 4 shiny gold bags.\nfaded fuchsia bags contain 2 dotted aqua bags.\nbright indigo bags contain 3 shiny coral bags, 1 muted salmon bag, 2 clear white bags, 1 vibrant maroon bag.\nshiny indigo bags contain 4 dark red bags, 2 pale lime bags.\nlight cyan bags contain 2 clear black bags, 2 mirrored aqua bags, 1 faded beige bag, 2 faded salmon bags.\nfaded gold bags contain 5 muted lime bags, 3 plaid fuchsia bags.\nmuted coral bags contain 2 faded indigo bags, 1 dim beige bag, 5 dotted orange bags, 4 posh black bags.\ndrab gray bags contain 5 clear magenta bags, 5 bright tomato bags, 1 dull gold bag.\nvibrant salmon bags contain 4 bright gold bags.\ndark red bags contain 5 posh black bags, 4 faded teal bags.\nwavy blue bags contain 3 dim green bags, 4 dull green bags, 2 posh aqua bags.\nmirrored turquoise bags contain 5 dull lime bags, 4 dark gray bags, 1 striped cyan bag, 4 muted gold bags.\nwavy chartreuse bags contain 1 pale brown bag, 4 shiny chartreuse bags, 4 wavy fuchsia bags.\ndim red bags contain 1 bright blue bag, 3 clear purple bags, 2 wavy crimson bags, 5 shiny black bags.\ndull gold bags contain 4 wavy blue bags.\nfaded blue bags contain 1 plaid turquoise bag, 2 vibrant indigo bags.\nshiny aqua bags contain 4 plaid cyan bags, 4 posh crimson bags.\nbright salmon bags contain 1 posh red bag, 1 shiny orange bag, 1 vibrant crimson bag.\npale yellow bags contain 4 plaid cyan bags.\nplaid magenta bags contain 3 plaid brown bags, 5 pale yellow bags, 5 drab fuchsia bags, 1 clear black bag.\nvibrant maroon bags contain 4 dull tomato bags, 1 dotted indigo bag, 2 plaid teal bags, 2 shiny gold bags.\ndrab orange bags contain 3 wavy coral bags.\npale aqua bags contain 5 wavy lime bags, 5 drab turquoise bags.\nshiny crimson bags contain 3 posh black bags, 5 drab fuchsia bags, 1 plaid fuchsia bag, 4 posh plum bags.\npale purple bags contain 2 clear green bags, 2 striped crimson bags, 4 drab indigo bags.\nfaded magenta bags contain 5 light red bags.\nshiny tan bags contain 5 plaid silver bags, 3 light lavender bags, 4 wavy purple bags.\nvibrant indigo bags contain 5 plaid beige bags.\nwavy turquoise bags contain 4 dark teal bags, 2 dark cyan bags, 4 mirrored olive bags, 5 bright red bags.\nstriped blue bags contain 1 vibrant lime bag, 3 vibrant indigo bags, 1 pale maroon bag, 2 dark white bags.\nfaded tomato bags contain 3 plaid tan bags, 4 pale tan bags, 5 wavy violet bags, 3 pale lime bags.\nbright green bags contain 1 bright purple bag, 5 posh magenta bags.\ndark beige bags contain 4 light green bags, 4 light magenta bags, 5 dotted lime bags, 4 plaid salmon bags.\nplaid green bags contain 2 pale salmon bags.\nbright red bags contain 2 dotted silver bags.\ndrab lime bags contain 3 dotted bronze bags.\nmuted indigo bags contain 4 posh gray bags, 2 dark lavender bags, 2 plaid chartreuse bags, 2 pale red bags.\nmuted tan bags contain 2 muted brown bags, 3 dull maroon bags.\nplaid turquoise bags contain 3 clear teal bags, 2 dull tomato bags, 5 dotted purple bags, 1 posh salmon bag.\ndrab aqua bags contain 3 bright lime bags, 5 posh red bags.\n"
  },
  {
    "path": "advent-of-code/2020/inputs/8",
    "content": "acc +13\njmp +412\nnop +137\nnop +144\nacc +33\nacc -11\njmp +445\nnop +327\nacc -10\njmp +1\njmp +578\njmp +1\njmp +415\nacc +25\nacc +21\njmp +58\njmp +180\njmp +96\nnop +190\nacc +20\njmp +167\njmp +194\nacc +24\nacc +9\nacc +14\njmp +1\njmp +443\njmp +1\nacc +18\njmp +465\njmp +245\njmp +219\nnop +280\nacc +13\nacc +23\njmp +133\njmp +300\nacc +35\nacc +50\nacc +24\nacc +32\njmp +458\nacc +36\nacc +14\njmp +103\nnop +262\njmp +233\nacc +14\nnop +313\njmp +30\nacc +7\njmp +324\nacc +12\njmp +1\nacc +12\njmp +326\nacc +14\nnop +151\nacc +2\njmp -14\njmp +1\nnop +18\njmp +288\nacc +24\nacc +7\nacc +0\njmp +268\njmp +267\nacc +3\nacc +4\nacc +35\njmp +25\njmp -16\nacc +14\nacc +38\nacc +41\njmp +3\nacc -16\njmp +546\nacc +42\nacc -6\nacc +38\nacc +18\njmp +391\nacc +45\njmp +464\njmp +144\nacc +33\nacc -18\nacc +36\njmp +313\njmp +286\nacc +34\nnop -72\nacc -17\njmp +430\nacc +35\nacc -18\nacc -1\njmp +75\nacc +48\nacc -2\njmp -76\nacc -13\nnop +453\nacc +0\nnop +48\njmp +40\nacc +40\nacc -5\nacc +14\nacc +1\njmp +323\nacc +16\nacc +17\nnop +408\nacc +22\njmp +126\nacc +2\njmp +404\nacc +22\nnop +373\nacc -15\njmp +134\nnop +242\njmp +1\nacc +19\njmp +372\nacc +18\nacc +33\nacc +31\nacc -12\njmp +417\nacc +27\nacc -4\njmp +84\nnop -86\njmp -87\njmp +174\nacc -19\nacc +17\nnop +353\njmp +301\nacc +14\nacc -16\nacc +2\njmp -109\nacc +24\njmp +366\nacc -8\nacc -14\nacc +20\nacc +38\njmp -62\nacc +4\njmp +1\nnop +423\njmp +33\nacc -19\nacc +50\njmp -128\nacc +10\nacc +2\njmp +371\nacc +31\nacc +12\nacc +12\njmp +337\nacc +42\nacc -19\njmp +64\njmp +1\nnop -52\njmp -19\nacc +34\njmp +287\nacc -6\njmp +130\nacc +22\nacc +22\nacc +46\nacc -18\njmp +190\nacc +13\nacc -18\nacc +26\njmp +283\nacc +15\njmp +193\njmp -168\nnop +165\nacc -3\nacc +26\njmp -54\nacc -4\njmp -174\njmp +96\nacc +44\nacc -18\nacc +8\nacc +23\njmp -164\nacc -11\nacc -13\nacc +30\njmp +114\nacc -9\njmp +386\nacc -15\njmp +98\nnop -74\nacc +31\nacc -4\nacc +15\njmp +113\nacc -3\nacc +36\njmp +362\njmp +225\njmp +131\nacc +14\nacc +48\nacc -16\nnop +302\njmp +383\nacc -14\njmp +97\nacc +5\nacc -6\njmp -4\nacc +27\njmp +165\nacc +49\njmp +36\nnop -213\nacc +30\nacc +18\njmp +1\njmp +54\nnop +73\nnop +185\nacc -4\njmp -156\nacc +17\njmp +1\nacc +30\njmp +357\nnop +60\njmp +1\njmp -186\nacc -17\nacc +26\nacc +45\njmp +74\nacc +27\nacc +1\njmp -109\nacc +49\nacc +4\njmp +298\nacc +12\njmp -42\nacc -16\njmp -195\nacc +19\nacc -13\nacc +31\nacc +31\njmp +201\njmp +274\njmp +1\nacc +27\nacc +41\nacc +35\njmp +9\nnop +32\njmp -190\nacc +2\njmp +1\njmp +172\nacc +10\nacc -13\njmp -95\nacc -10\nacc -12\nacc -4\njmp +290\nnop -91\nnop +288\nacc +45\nacc +40\njmp +322\nacc +9\njmp +314\nacc -10\nacc +3\nnop -62\nacc +46\njmp +186\nacc +14\nacc +40\nacc +49\nacc +29\njmp -175\nacc +37\nacc -8\njmp +254\njmp +48\nacc +30\nacc +40\njmp +1\njmp -172\nacc -9\nacc +42\nnop -269\njmp -154\nnop +109\nacc +0\njmp -68\nacc +40\njmp +310\nacc +4\njmp +266\njmp +80\nacc +15\nacc -14\njmp -206\nacc +17\njmp +156\nacc -19\nacc +25\nnop +82\nacc +13\njmp +243\njmp +259\njmp +258\nacc +29\nacc +9\njmp -76\nacc +5\nacc +41\nacc +49\nacc +17\njmp +161\nacc +29\nnop +215\njmp +179\nacc +45\nacc +23\njmp +208\nacc +3\nacc +30\njmp +38\nnop +204\njmp -62\njmp +1\nacc +10\njmp +78\nacc +32\nacc +29\njmp -269\nacc +20\nacc +24\njmp +1\njmp -114\njmp +160\nacc -19\njmp +137\nnop -312\nacc +8\nacc +3\njmp -181\njmp +122\nacc +9\njmp -166\njmp -106\njmp +98\njmp -152\nacc -7\nacc +19\njmp +180\njmp +195\nacc -17\nacc +19\nacc +8\nacc +21\njmp +193\njmp +226\nacc +5\njmp +14\njmp +228\nacc +44\nnop +112\nacc +0\nacc +12\njmp +223\nacc +21\nnop +87\nacc +32\nacc +42\njmp -264\nacc +31\njmp +49\nacc -3\nacc +16\nnop -277\nacc +45\njmp +50\nacc +0\nacc +7\nnop -223\nacc +11\njmp +113\nacc +32\nacc +20\njmp +108\nacc -7\nacc +30\njmp +66\nacc -12\nacc +34\nacc -9\nacc +39\njmp +126\njmp -351\njmp -89\njmp -45\nacc +4\nacc +7\nacc -1\nacc +41\njmp -229\nacc -9\nacc +29\njmp -115\nacc +27\nacc -11\njmp +187\nacc -10\nacc +11\nacc +29\nacc +46\njmp -115\nnop -116\nacc +31\njmp -202\nacc +12\njmp +1\nacc +16\nacc +15\njmp -25\nacc -7\njmp -439\nacc +10\nacc +26\nacc +13\njmp -75\nnop -214\nacc +2\nnop -202\njmp +105\njmp -65\nacc -15\nacc +6\njmp +1\njmp -182\nacc +13\nacc -19\njmp +26\nacc +20\nacc -16\nacc +14\njmp -59\njmp -204\nacc +27\nacc +44\nnop -33\nacc +36\njmp -300\nacc +48\nacc +28\nacc +29\nacc +39\njmp -249\nacc +33\nacc +31\njmp +1\nacc +33\njmp -269\nacc +8\nacc +31\nacc +10\nacc +5\njmp -194\njmp -477\nnop -196\nacc +50\nacc -13\njmp -47\nnop +77\nacc +45\njmp -293\nacc +39\njmp -19\nnop -391\nacc +28\nacc +50\nacc +16\njmp -209\nacc -1\nacc +39\nacc -17\nnop -233\njmp -283\nacc +19\nacc +0\nacc +22\nacc +22\njmp -488\nacc +39\nnop -286\nacc +33\njmp -23\njmp -173\njmp -274\nacc +5\nacc +45\nacc +0\nacc -14\njmp -342\nacc +16\nacc +28\nnop -155\njmp -488\nacc +12\nacc +28\nnop -181\nacc +17\njmp -447\nacc +40\nacc +40\nacc +13\njmp -38\nacc -12\nnop -494\nacc +43\njmp -533\nacc +30\njmp -518\nacc +39\nacc +4\nnop -179\njmp -127\nacc +31\nacc +42\nacc +17\njmp -82\nnop -520\njmp -521\njmp -193\nacc -8\njmp -142\njmp +1\nacc +39\njmp -532\nacc +30\nacc +3\nacc +22\nnop -84\njmp +2\njmp -402\njmp -468\nacc +0\nacc -4\nacc -19\njmp -379\njmp -357\nacc +0\njmp -159\nacc +13\nacc +24\nacc -3\nacc +0\njmp -387\nacc +31\nacc +20\nacc +27\njmp -308\njmp -161\nacc -6\nnop -163\nacc -3\njmp -585\nnop -586\nnop -6\nacc +10\nacc +42\njmp -590\nacc +0\nacc +34\nacc +16\nacc +9\njmp -175\nacc +29\njmp -217\nacc +0\njmp -234\njmp -47\nacc +28\nacc +0\nacc +25\nacc -5\njmp -556\nnop -144\njmp +1\nacc +27\njmp -117\njmp -10\nacc +24\nacc -17\nacc +9\nacc +18\njmp -310\njmp -455\nnop -437\njmp -593\nacc +15\nacc +50\nacc -3\njmp -50\nacc -13\nacc +14\nacc +34\nacc -16\njmp +1\n"
  },
  {
    "path": "advent-of-code/2020/inputs/9",
    "content": "30\n20\n2\n19\n18\n15\n49\n50\n23\n39\n16\n31\n41\n36\n22\n35\n40\n38\n33\n8\n13\n43\n48\n24\n42\n69\n44\n10\n29\n60\n21\n54\n18\n26\n28\n34\n37\n39\n23\n30\n31\n32\n83\n36\n79\n33\n38\n40\n59\n41\n42\n43\n44\n46\n53\n85\n56\n48\n49\n63\n81\n55\n54\n74\n84\n64\n65\n80\n76\n78\n71\n79\n82\n90\n87\n92\n89\n93\n147\n119\n97\n102\n136\n103\n118\n109\n120\n206\n129\n143\n175\n141\n150\n180\n212\n160\n161\n169\n176\n325\n182\n186\n190\n205\n199\n200\n249\n221\n223\n227\n259\n270\n272\n311\n399\n329\n531\n336\n373\n343\n584\n448\n345\n358\n368\n376\n411\n459\n581\n811\n472\n444\n680\n450\n486\n643\n542\n583\n640\n960\n701\n679\n779\n688\n824\n703\n713\n721\n744\n1153\n945\n992\n1255\n1165\n894\n1362\n1265\n1364\n1286\n1028\n1331\n2520\n1693\n1319\n1367\n1503\n1382\n1391\n1401\n1434\n1416\n1457\n1465\n1909\n1839\n1886\n1922\n2392\n2059\n2314\n3793\n2293\n2347\n2359\n2395\n3343\n2686\n3615\n2701\n2749\n2773\n2798\n2792\n2817\n3351\n2873\n2922\n5317\n4610\n4198\n5085\n5215\n4352\n5081\n4607\n6152\n6969\n6044\n4754\n5387\n8950\n7405\n5518\n5450\n5522\n8952\n5590\n5609\n5690\n5795\n7071\n9361\n8962\n9413\n9106\n9567\n9688\n10272\n9994\n14374\n10141\n10204\n10549\n11040\n10837\n16139\n10968\n10972\n19960\n11212\n30164\n11280\n11299\n15936\n15999\n18519\n18068\n18956\n18673\n25105\n21034\n26133\n20135\n20690\n20345\n30486\n21041\n26976\n21809\n21805\n36970\n21940\n41944\n22579\n22492\n41041\n27216\n27235\n36071\n36587\n36741\n37024\n37629\n58392\n40480\n40825\n42924\n54211\n41035\n61380\n42846\n64786\n43614\n58550\n58910\n62972\n44432\n45071\n59166\n86538\n73700\n77504\n63306\n81515\n74216\n144821\n74653\n152157\n81305\n140749\n81860\n83881\n86106\n84649\n87278\n86460\n107404\n88046\n89503\n103342\n119085\n103598\n108377\n271242\n137959\n189264\n137522\n171927\n148869\n155958\n248153\n190237\n211002\n163165\n205191\n237818\n169987\n171109\n172695\n173738\n177549\n222683\n191388\n192845\n206940\n409201\n341914\n245899\n275481\n397022\n328910\n293480\n304827\n312034\n501605\n333152\n336903\n334274\n335860\n343725\n341096\n508012\n363954\n346433\n351287\n368937\n384233\n580173\n486325\n557933\n521380\n598307\n539379\n568961\n605514\n616861\n655759\n676877\n646308\n854445\n905613\n670134\n675370\n1163771\n715370\n697720\n872667\n710387\n867813\n720224\n753170\n923612\n1007705\n1025704\n1060759\n1266681\n1358684\n1544690\n1174475\n1222375\n2226497\n1366532\n1316442\n1578200\n1367854\n1345504\n1385504\n1390740\n1463557\n1473394\n1408107\n1430611\n3572001\n1620983\n1780983\n2069612\n2342146\n2033409\n2086463\n2235234\n3611609\n3452995\n2396850\n2541007\n2538817\n2661946\n2682974\n3051594\n2713358\n2731008\n2736244\n2776244\n2798847\n4608429\n4186752\n3690595\n5444366\n4321990\n3401966\n5724004\n4103021\n4430259\n4119872\n4321697\n4632084\n4935667\n4937857\n5133094\n5449602\n5200763\n7793616\n5396332\n7977007\n7384673\n5467252\n8266099\n6178210\n7092561\n7504987\n8643687\n8012585\n10136430\n7521838\n7723663\n9499353\n9257364\n8441569\n11311304\n8953781\n9567751\n12293324\n15745961\n10333857\n14190795\n10597095\n11574542\n14040019\n12559813\n17021191\n11645462\n13270771\n20087031\n14597548\n17838844\n15245501\n15534423\n22838522\n16475619\n19287638\n25462760\n17395350\n20879055\n19901608\n20164846\n36682988\n25564095\n32640851\n20930952\n22171637\n22242557\n42959445\n24205275\n33870969\n24916233\n49116470\n27868319\n29843049\n33373267\n34314463\n30779924\n42144165\n35763257\n38647256\n37296958\n37560196\n38326302\n58227910\n40066454\n56113526\n43102589\n43173509\n44414194\n45136227\n46376912\n52085606\n49121508\n52073594\n52784552\n58289500\n70970908\n57711368\n60622973\n64153191\n74380917\n69106226\n73060215\n95259115\n77626650\n74857154\n75886498\n78392756\n108898078\n83169043\n86276098\n89550421\n104870158\n90791106\n91513139\n95498420\n104159200\n147332709\n104858146\n113407525\n116000868\n137213406\n118334341\n146732876\n133259417\n185107094\n164604646\n147917369\n150743652\n152483804\n179727312\n154279254\n161561799\n172719464\n180341527\n175826519\n181063560\n308294675\n285222760\n187011559\n199657620\n284546115\n246666942\n223192487\n229408393\n461049279\n251593758\n265067217\n347574989\n465564287\n298661021\n327644681\n300401173\n303227456\n342625359\n484880380\n315841053\n348545983\n353060991\n356168046\n368075119\n476075335\n386669179\n410204046\n579238439\n451251378\n785281553\n808646832\n545249446\n481002151\n852955499\n516660975\n592711898\n616242226\n599062194\n601888477\n659395502\n837920557\n619068509\n658466412\n926865021\n664387036\n701606974\n989442485\n724243165\n754744298\n796873225\n1330530999\n861455424\n967912353\n1053139855\n997663126\n1026251597\n1061910421\n1215304420\n1109372873\n1115723169\n1191774092\n2392441420\n1200950671\n1220956986\n1653829521\n1277534921\n1322853448\n1656129538\n1713685650\n1365994010\n1425850139\n1478987463\n2162867235\n2225096042\n1658328649\n1923365845\n1398413738\n3650946181\n2023914723\n2059573547\n2088162018\n2253684513\n2301146965\n3581694494\n2307497261\n2392724763\n2421907657\n3630350709\n3591090052\n3402353308\n2600388369\n4768347318\n2764407748\n2791844149\n2824263877\n4646409276\n3871712226\n3056742387\n3321779583\n3947280568\n4224512810\n3422328461\n4331411984\n5641268041\n4147735565\n4341846531\n4554831478\n5882841459\n6194197457\n4814632420\n7379095355\n5022296026\n5364796117\n5392232518\n6226617185\n5424652246\n5616108026\n5556251897\n13020363396\n5881006264\n10071061522\n6378521970\n8236960881\n6744108044\n9038436487\n7753740445\n15435857639\n8479147549\n10933353448\n10905137485\n8896678009\n9369463898\n9836928446\n10179428537\n11558740464\n10387092143\n10414528544\n10757028635\n19971789935\n11497114290\n16792176932\n21320445591\n17311875418\n12259528234\n12625114308\n19236176184\n13122630014\n14497848489\n15223255593\n16232887994\n17375825558\n17848611447\n18266141907\n18733606455\n19311206553\n27730002284\n26647416538\n20251456990\n21171557179\n32763990396\n20801620687\n21911642834\n22254142925\n28872939848\n29345725737\n36028353116\n47606546303\n30498455572\n31388771921\n27620478503\n50517282916\n28345885607\n29721104082\n31456143587\n33608713552\n45469089950\n36114753354\n37577348460\n38985063445\n39562663543\n41053077677\n41423014169\n41973177866\n42713263521\n63735231857\n64107169124\n44165785759\n61954599159\n55966364110\n56966204240\n57341582585\n86632036270\n62844915508\n58066989689\n59076622090\n59802029194\n92566019590\n61177247669\n65064857139\n69723466906\n73692101814\n75677416897\n76562411905\n78547726988\n80615741220\n82476091846\n83396192035\n84686441387\n114033353799\n100132149869\n118878651284\n138442455956\n137739659574\n173181760810\n114307786825\n116418204675\n117869018883\n124866886333\n117143611779\n120253869759\n120979276863\n126242104808\n136854664566\n134788324045\n158153508743\n152239828802\n154225143885\n155110138893\n159163468208\n163091833066\n165872283881\n168082633422\n184818591256\n318201971959\n214439936694\n255042193804\n230725991500\n231451398604\n232176805708\n280960851949\n242735905216\n235012630662\n320097427766\n237397481538\n241233146622\n247221381671\n495400788643\n322255301274\n292941832788\n478630628160\n306464972687\n401446525556\n314273607101\n400396614830\n380312220575\n333954917303\n352901224678\n399258527950\n445165928194\n557494909304\n462177390104\n466464029266\n482234012333\n467189436370\n472410112200\n476245777284\n484618863209\n530339314326\n488454528293\n773654409057\n626896750091\n599406805475\n1400551159148\n607215439889\n620738579788\n640419889990\n686856141981\n667174831779\n714267137878\n820090661048\n733213445253\n837520087887\n1327276031971\n1099306862291\n949423448703\n928641419370\n948655889484\n939599548570\n1419497466523\n957028975409\n1128874418283\n1643885117390\n1018793842619\n1313752892072\n1206622245364\n1528048224845\n1220145385263\n1227954019677\n1606774380349\n1261158469778\n1307594721769\n1420069587234\n1447480583131\n1534357798926\n2264623697178\n1570733533140\n1777119636457\n1868240967940\n2813396625713\n1877297308854\n2456689644215\n1888255438054\n1896628523979\n3096194987617\n2533898277335\n2147668260902\n2426767630627\n2948117812079\n2489112489455\n3149413907832\n2448099404940\n2708639052909\n3297366896088\n2568753191547\n2681228057012\n2727664309003\n2867550170365\n3018214116271\n3745538276794\n4430526801314\n3347853169597\n3924787897359\n5184353953218\n4336354842994\n6763122473621\n4624292832982\n3784883962033\n4044296784881\n4681566538237\n4595767665842\n4574435891529\n4874867035567\n4937211894395\n5249981248559\n9256002429766\n5129327461952\n5277392244456\n6075517478600\n9851828135985\n5408892366015\n8427104815031\n7132737131630\n6366067285868\n7093391446391\n8261142740353\n8969237915251\n10313681415170\n8380651627875\n7829180746914\n8359319853562\n8409176795015\n13013534700132\n8618732676410\n9170203557371\n17587970591661\n9449302927096\n9812078929962\n13636712098018\n10379308710511\n13670035106368\n10406719706408\n11352909723056\n14984799962278\n13789543993890\n13818069161030\n13459458732259\n14961917878544\n26650246798150\n14922572193305\n16090323487267\n16188500600476\n16447913423324\n16209832374789\n28940880314717\n16768496648577\n17027909471425\n22078191408669\n17788936233781\n23267372088126\n38229289966670\n19261381857058\n25368637584952\n20786028416919\n34575572410809\n49917618886276\n21759629429464\n24812368455315\n27249002726149\n27607613154920\n31607005394811\n28382030925564\n36876351904186\n31111072793781\n33216410071901\n32278824087743\n47299573394257\n44276912197574\n37554525065496\n39106100880094\n68665597859277\n49008632155613\n69340362760451\n37050318090839\n40047410273977\n41021011286522\n42545657846383\n46571997884779\n45598396872234\n50141660355028\n54038453517207\n70153271001303\n74954028810343\n95059464803729\n78850821972522\n61598440997465\n70266728162740\n83358070426929\n63389896881524\n117452844395560\n69329142178582\n74604843156335\n76156418970933\n77097728364816\n94085863791184\n88144054718617\n153624798589669\n78071329377361\n205596899114177\n81068421560499\n100610451401986\n"
  },
  {
    "path": "advent-of-code/2021/.gitignore",
    "content": "Cargo.lock\ntarget/\n"
  },
  {
    "path": "advent-of-code/2021/day01/Cargo.toml",
    "content": "[package]\nname = \"day01\"\nversion = \"0.1.0\"\nauthors = [\"Stefan Kanev <stefan.kanev@gmail.com>\"]\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day01/src/main.rs",
    "content": "use std::fs;\n\nfn main() {\n    println!(\"first = {:?}\", first());\n    println!(\"second = {:?}\", second());\n}\n\nfn numbers() -> Vec<i64> {\n    fs::read_to_string(\"../inputs/01\")\n        .unwrap()\n        .lines()\n        .map(|line| line.parse::<i64>().unwrap())\n        .collect::<Vec<i64>>()\n}\n\nfn first() -> usize {\n    numbers().windows(2).filter(|a| a[1] > a[0]).count()\n}\n\nfn second() -> usize {\n    numbers()\n        .windows(3)\n        .map(|a| a[0] + a[1] + a[2])\n        .collect::<Vec<_>>()\n        .windows(2)\n        .filter(|a| a[1] > a[0])\n        .count()\n}\n"
  },
  {
    "path": "advent-of-code/2021/day02/Cargo.toml",
    "content": "[package]\nname = \"day02\"\nversion = \"0.1.0\"\nauthors = [\"Stefan Kanev <stefan.kanev@gmail.com>\"]\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day02/src/main.rs",
    "content": "use std::fs;\n\nenum Direction {\n    Forward(i64),\n    Up(i64),\n    Down(i64),\n}\n\nuse Direction::*;\n\nfn main() {\n    println!(\"first = {:?}\", first());\n    println!(\"second = {:?}\", second());\n}\n\nfn directions() -> Vec<Direction> {\n    fs::read_to_string(\"../inputs/02\")\n        .unwrap()\n        .lines()\n        .map(|line| {\n            let words = line.split(\" \").collect::<Vec<_>>();\n            let amount = words[1].parse::<i64>().unwrap();\n            match words[0] {\n                \"forward\" => Forward(amount),\n                \"up\" => Up(amount),\n                \"down\" => Down(amount),\n                _ => panic!(),\n            }\n        })\n        .collect()\n}\n\nfn first() -> i64 {\n    let mut x = 0;\n    let mut y = 0;\n\n    for direction in directions() {\n        match direction {\n            Forward(delta) => x += delta,\n            Up(delta) => y -= delta,\n            Down(delta) => y += delta,\n        }\n    }\n\n    x * y\n}\n\nfn second() -> i64 {\n    let mut x = 0;\n    let mut y = 0;\n    let mut aim = 0;\n\n    for direction in directions() {\n        match direction {\n            Forward(delta) => {\n                x += delta;\n                y += aim * delta\n            }\n            Up(delta) => aim -= delta,\n            Down(delta) => aim += delta,\n        }\n    }\n\n    x * y\n}\n"
  },
  {
    "path": "advent-of-code/2021/day03/Cargo.toml",
    "content": "[package]\nname = \"day03\"\nversion = \"0.1.0\"\nauthors = [\"Stefan Kanev <stefan.kanev@gmail.com>\"]\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day03/src/main.rs",
    "content": "use std::fs;\n\nfn main() {\n    println!(\"first = {:?}\", first());\n    println!(\"second = {:?}\", second());\n}\n\nfn input() -> Vec<String> {\n    fs::read_to_string(\"../inputs/03\")\n        .unwrap()\n        .lines()\n        .map(|line| line.to_string())\n        .collect()\n}\n\nfn ones(numbers: &Vec<String>) -> Vec<usize> {\n    let length = numbers[0].len();\n    let mut counts: Vec<usize> = vec![0; length];\n\n    for number in numbers {\n        for (i, _) in number.chars().enumerate().filter(|(_, b)| *b == '1') {\n            counts[i] += 1\n        }\n    }\n\n    counts\n}\n\nfn decimal(digits: &Vec<usize>) -> usize {\n    digits\n        .iter()\n        .rev()\n        .enumerate()\n        .fold(0, |a, (i, &b)| a + (b << i))\n}\n\nfn first() -> usize {\n    let numbers = input();\n    let n = numbers.len();\n    let counts = ones(&numbers);\n    let most_common_bits = counts\n        .iter()\n        .map(|&count| if count > n / 2 { 1 } else { 0 })\n        .collect::<Vec<_>>();\n    let least_common_bits = most_common_bits.iter().map(|&b| 1 - b).collect::<Vec<_>>();\n\n    decimal(&most_common_bits) * decimal(&least_common_bits)\n}\n\nfn filter<F>(numbers: Vec<String>, position: usize, f: F) -> Vec<String>\nwhere\n    F: Fn(usize, usize) -> bool,\n{\n    let count = ones(&numbers)[position];\n    let target = if f(count, numbers.len()) { b'1' } else { b'0' };\n\n    numbers\n        .into_iter()\n        .filter(|number| number.as_bytes()[position] == target)\n        .collect()\n}\n\nfn iterate<F>(numbers: &Vec<String>, f: F) -> usize\nwhere\n    F: Fn(usize, usize) -> bool,\n{\n    let mut numbers = numbers.clone();\n    let w = numbers[0].len();\n\n    for i in (0..w).cycle() {\n        if numbers.len() == 1 {\n            return usize::from_str_radix(&numbers[0], 2).unwrap();\n        } else {\n            numbers = filter(numbers, i, &f);\n        }\n    }\n\n    panic!()\n}\n\nfn second() -> usize {\n    let numbers = input();\n\n    iterate(&numbers, |count, total| count * 2 >= total)\n        * iterate(&numbers, |count, total| count * 2 < total)\n}\n"
  },
  {
    "path": "advent-of-code/2021/day04/Cargo.toml",
    "content": "[package]\nname = \"day04\"\nversion = \"0.1.0\"\nauthors = [\"Stefan Kanev <stefan.kanev@gmail.com>\"]\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day04/src/main.rs",
    "content": "use std::fs;\n\nstruct Cell {\n    number: i64,\n    marked: bool,\n}\n\nstruct Board {\n    rows: Vec<Vec<Cell>>,\n    score: Option<i64>,\n}\n\nimpl Board {\n    fn iter(&self) -> impl Iterator<Item=&Cell> {\n        self.rows.iter().flat_map(|row| row.iter())\n    }\n\n    fn iter_mut(&mut self) -> impl Iterator<Item=&mut Cell> {\n        self.rows.iter_mut().flat_map(|row| row.iter_mut())\n    }\n\n    fn mark(&mut self, number: i64) {\n        for cell in self.iter_mut().filter(|c| c.number == number) {\n            cell.marked = true\n        }\n    }\n\n    fn is_winning(&self) -> bool {\n        self.rows.iter().any(|row| row.iter().all(|c| c.marked))\n            || (0..4).any(|col| self.rows.iter().all(|row| row[col].marked))\n    }\n\n    fn unmarked_sum(&self) -> i64 {\n        self.iter().map(|c| c.number).sum()\n    }\n}\n\nfn parse_input() -> (Vec<i64>, Vec<Board>) {\n    let lines = fs::read_to_string(\"../inputs/04\")\n        .unwrap()\n        .lines()\n        .map(|x| x.to_string())\n        .collect::<Vec<String>>();\n\n    let numbers = lines[0]\n        .split(\",\")\n        .map(|n| n.parse::<i64>().unwrap())\n        .collect();\n\n    let boards = lines[2..]\n        .chunks(6)\n        .map(|rows| Board {\n            score: None,\n            rows: rows\n                .iter()\n                .take(5)\n                .map(|line| {\n                    line.split_ascii_whitespace()\n                        .map(|x| Cell {\n                            number: x.parse().unwrap(),\n                            marked: false,\n                        })\n                        .collect()\n                })\n                .collect(),\n        })\n        .collect();\n\n    (numbers, boards)\n}\n\nfn main() {\n    let (numbers, mut boards) = parse_input();\n\n    let mut scores: Vec<i64> = vec![];\n\n    for number in numbers {\n        for board in boards.iter_mut().filter(|b| b.score == None) {\n            board.mark(number);\n\n            if board.is_winning() {\n                let score = board.unmarked_sum() * number;\n                board.score = Some(score);\n                scores.push(score)\n            }\n        }\n    }\n\n    println!(\"first = {}\", scores.first().unwrap());\n    println!(\"second = {}\", scores.last().unwrap());\n}\n"
  },
  {
    "path": "advent-of-code/2021/day05/Cargo.toml",
    "content": "[package]\nname = \"day05\"\nversion = \"0.1.0\"\nauthors = [\"Stefan Kanev <stefan.kanev@gmail.com>\"]\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day05/src/main.rs",
    "content": "use std::collections::HashMap;\nuse std::fs;\n\n#[derive(Debug, PartialEq, Eq, Hash)]\nstruct Point {\n    x: i64,\n    y: i64,\n}\n\n#[derive(Debug, Hash)]\nstruct Line {\n    from: Point,\n    to: Point,\n}\n\nfn parse_input() -> Vec<Line> {\n    fs::read_to_string(\"../inputs/05\")\n        .unwrap()\n        .lines()\n        .map(|line| {\n            let parts: Vec<Vec<i64>> = line\n                .split(\" -> \")\n                .map(|part| part.split(\",\").map(|d| d.parse::<i64>().unwrap()).collect())\n                .collect();\n\n            Line {\n                from: Point {\n                    x: parts[0][0],\n                    y: parts[0][1],\n                },\n                to: Point {\n                    x: parts[1][0],\n                    y: parts[1][1],\n                },\n            }\n        })\n        .collect()\n}\n\nfn range(a: i64, b: i64) -> Box<dyn Iterator<Item = i64>> {\n    if a > b {\n        Box::new((b..=a).rev())\n    } else {\n        Box::new((a..=b).into_iter())\n    }\n}\n\nimpl Line {\n    fn is_diagonal(&self) -> bool {\n        self.from.x != self.to.x && self.from.y != self.to.y\n    }\n\n    fn points(&self) -> Vec<Point> {\n        if self.from.x == self.to.x {\n            range(self.from.y, self.to.y)\n                .map(|y| Point { x: self.from.x, y })\n                .collect()\n        } else if self.from.y == self.to.y {\n            range(self.from.x, self.to.x)\n                .map(|x| Point { x, y: self.from.y })\n                .collect()\n        } else {\n            range(self.from.x, self.to.x)\n                .zip(range(self.from.y, self.to.y))\n                .map(|(x, y)| Point { x, y })\n                .collect()\n        }\n    }\n}\n\nfn intersections<'a>(lines: impl Iterator<Item = &'a Line>) -> usize {\n    let mut counts: HashMap<Point, usize> = HashMap::new();\n\n    for point in lines.flat_map(|line| line.points()) {\n        let count = counts.entry(point).or_insert(0);\n        *count += 1;\n    }\n\n    counts.values().filter(|c| **c > 1).count()\n}\n\nfn main() {\n    let lines = parse_input();\n\n    println!(\n        \"first  = {}\",\n        intersections(lines.iter().filter(|line| !line.is_diagonal()))\n    );\n    println!(\"second = {}\", intersections(lines.iter()));\n}\n"
  },
  {
    "path": "advent-of-code/2021/day06/Cargo.toml",
    "content": "[package]\nname = \"day06\"\nversion = \"0.1.0\"\nauthors = [\"Stefan Kanev <stefan.kanev@gmail.com>\"]\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day06/src/main.rs",
    "content": "use std::fs::read_to_string;\n\nfn parse_input() -> Vec<usize> {\n    let input = read_to_string(\"../inputs/06\").unwrap();\n    input[0..input.len()-1].split(\",\").map(|chunk| chunk.parse().unwrap()).collect()\n}\n\nfn iterate(numbers: &[usize; 9], iterations: usize) -> usize {\n    let mut counts = numbers.clone();\n\n    for _ in 0..iterations {\n        let born = counts[0];\n        for i in 1..=8 {\n            counts[i - 1] = counts[i]\n        }\n        counts[8] = born;\n        counts[6] += born;\n    }\n\n    counts.iter().sum()\n}\n\nfn main() {\n    let numbers = parse_input();\n    let mut counts: [usize; 9] = [0; 9];\n\n    for number in numbers {\n        counts[number] += 1\n    }\n\n    println!(\"first  = {}\", iterate(&counts, 80));\n    println!(\"second = {}\", iterate(&counts, 256));\n}\n"
  },
  {
    "path": "advent-of-code/2021/day07/Cargo.toml",
    "content": "[package]\nname = \"day07\"\nversion = \"0.1.0\"\nauthors = [\"Stefan Kanev <stefan.kanev@gmail.com>\"]\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day07/src/main.rs",
    "content": "use std::fs::read_to_string;\n\nfn parse_input() -> Vec<i64> {\n    let input = read_to_string(\"../inputs/07\").unwrap();\n    input[0..input.len() - 1]\n        .split(\",\")\n        .map(|chunk| chunk.parse().unwrap())\n        .collect()\n}\n\nfn main() {\n    let numbers = parse_input();\n    let max = *numbers.iter().max().unwrap();\n    let first: i64 = (0..=max)\n        .map(|i| numbers.iter().map(|n| (n - i).abs()).sum())\n        .min()\n        .unwrap();\n\n    let second: i64 = (0..=max)\n        .map(|i| {\n            numbers\n                .iter()\n                .map(|n| (n - i).abs())\n                .map(|n| n * (n + 1) / 2)\n                .sum()\n        })\n        .min()\n        .unwrap();\n\n    println!(\"first  = {}\", first);\n    println!(\"second = {}\", second);\n}\n"
  },
  {
    "path": "advent-of-code/2021/day08/Cargo.toml",
    "content": "[package]\nname = \"day08\"\nversion = \"0.1.0\"\nauthors = [\"Stefan Kanev <stefan.kanev@gmail.com>\"]\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day08/src/main.rs",
    "content": "use std::fs::read_to_string;\n\n#[derive(Debug)]\nstruct InputLine {\n    patterns: Vec<String>,\n    output: Vec<String>,\n}\n\nfn parse_input() -> Vec<InputLine> {\n    read_to_string(\"../inputs/08\")\n        .unwrap()\n        .lines()\n        .map(|line| {\n            let parts = line.split(\" | \").collect::<Vec<_>>();\n\n            let patterns = parts[0].split(\" \").map(|s| s.to_string()).collect();\n            let output = parts[1].split(\" \").map(|s| s.to_string()).collect();\n\n            InputLine { patterns, output }\n        })\n        .collect()\n}\n\nfn bits(n: u8) -> u32 {\n    n.count_ones()\n}\n\nfn bitset<'a>(number: &'a str) -> u8 {\n    number\n        .as_bytes()\n        .iter()\n        .map(|c| 1 << (c - b'a'))\n        .fold(0, |a, b| a | b)\n}\n\nfn consume<F>(patterns: &mut Vec<u8>, f: F) -> u8\nwhere\n    F: Fn(u8) -> bool,\n{\n    patterns.swap_remove(patterns.iter().position(|n| f(*n)).unwrap())\n}\n\nfn decrypt(line: &InputLine) -> usize {\n    let mut left: Vec<u8> = line.patterns.iter().map(|str| bitset(str)).collect();\n    let mut m = [0_u8; 10];\n\n    m[1] = consume(&mut left, |p| bits(p) == 2);\n    m[4] = consume(&mut left, |p| bits(p) == 4);\n    m[7] = consume(&mut left, |p| bits(p) == 3);\n    m[8] = consume(&mut left, |p| bits(p) == 7);\n    m[3] = consume(&mut left, |p| bits(p) == 5 && m[7] & p == m[7]);\n    m[6] = consume(&mut left, |p| bits(p) == 6 && m[1] & p != m[1]);\n    m[2] = consume(&mut left, |p| bits(p) == 5 && m[8] & !m[6] & p != 0);\n    m[5] = consume(&mut left, |p| bits(p) == 5);\n    m[9] = consume(&mut left, |p| m[8] & !p & m[4] == 0);\n    m[0] = consume(&mut left, |_| true);\n\n    line.output\n        .iter()\n        .map(|number| bitset(number))\n        .map(|target| m.iter().position(|pattern| *pattern == target).unwrap())\n        .fold(0, |accumulator, digit| accumulator * 10 + digit)\n}\n\nfn main() {\n    let first: usize = parse_input()\n        .iter()\n        .flat_map(|line| &line.output)\n        .map(|seq| seq.len())\n        .filter(|&n| n != 5 && n != 6)\n        .count();\n\n    let second: usize = parse_input().iter().map(|line| decrypt(line)).sum();\n\n    println!(\"first  = {}\", first);\n    println!(\"second = {}\", second);\n}\n"
  },
  {
    "path": "advent-of-code/2021/day09/Cargo.toml",
    "content": "[package]\nname = \"day09\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day09/src/main.rs",
    "content": "use std::{collections::VecDeque, fs};\n\nfn parse_input() -> Vec<Vec<u8>> {\n    let text = fs::read_to_string(\"../inputs/09\").unwrap();\n    let height = text.lines().count();\n    let width = text.lines().next().unwrap().len();\n\n    let mut result = vec![vec![9; width + 2]; height + 2];\n\n    for (i, line) in text.lines().enumerate() {\n        for (j, byte) in line.bytes().enumerate() {\n            result[i + 1][j + 1] = byte - b'0';\n        }\n    }\n\n    result\n}\n\nfn low_points(map: &Vec<Vec<u8>>) -> Vec<(usize, usize)> {\n    let height = map.len();\n    let width = map[0].len();\n\n    let mut result = vec![];\n\n    for i in 1..(height - 2) {\n        for j in 1..(width - 2) {\n            if map[i][j] < map[i - 1][j]\n                && map[i][j] < map[i + 1][j]\n                && map[i][j] < map[i][j - 1]\n                && map[i][j] < map[i][j + 1]\n            {\n                result.push((i, j));\n            }\n        }\n    }\n\n    result\n}\n\nfn fill(map: &mut Vec<Vec<u8>>, point: (usize, usize)) -> usize {\n    let mut left: VecDeque<(usize, usize)> = VecDeque::new();\n    let mut count = 0;\n\n    left.push_back(point);\n\n    while left.len() > 0 {\n        let point = left.pop_front().unwrap();\n\n        if map[point.0][point.1] == 9 {\n            continue;\n        }\n\n        map[point.0][point.1] = 9;\n        count += 1;\n\n        left.push_back((point.0 - 1, point.1));\n        left.push_back((point.0 + 1, point.1));\n        left.push_back((point.0, point.1 - 1));\n        left.push_back((point.0, point.1 + 1));\n    }\n\n    count\n}\n\nfn main() {\n    let mut map = parse_input();\n    let lows = low_points(&map);\n\n    let first: usize = lows.iter().map(|&(x, y)| (map[x][y] as usize) + 1).sum();\n\n    let mut basins: Vec<usize> = vec![];\n\n    for point in lows {\n        basins.push(fill(&mut map, point));\n    }\n    basins.sort();\n\n    let second: usize = basins[basins.len() - 3..].iter().product();\n\n    println!(\"first  = {}\", first);\n    println!(\"second = {}\", second);\n}\n"
  },
  {
    "path": "advent-of-code/2021/day10/Cargo.toml",
    "content": "[package]\nname = \"day10\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day10/src/main.rs",
    "content": "use std::fs;\n\nfn score(input: &str) -> (usize, usize) {\n    let mut stack: Vec<char> = vec![];\n\n    for char in input.chars() {\n        match char {\n            '(' | '{' | '[' | '<' => stack.push(char),\n            next => match (stack.last().unwrap_or(&' '), next) {\n                ('(', ')') | ('{', '}') | ('[', ']') | ('<', '>') => {\n                    stack.pop();\n                }\n                (_, ')') => return (3, 0),\n                (_, ']') => return (57, 0),\n                (_, '}') => return (1197, 0),\n                (_, '>') => return (25137, 0),\n                _ => panic!(),\n            },\n        }\n    }\n\n    let score = stack.iter().rev().fold(0, |score, char| {\n        5 * score + \" ([{<\".chars().position(|c| c == *char).unwrap()\n    });\n\n    (0, score)\n}\n\nfn main() {\n    let results: Vec<(usize, usize)> = fs::read_to_string(\"../inputs/10\")\n        .unwrap()\n        .lines()\n        .map(|line| score(line))\n        .collect();\n\n    let first: usize = results.iter().map(|s| s.0).sum();\n\n    let mut scores: Vec<usize> = results.iter().map(|s| s.1).filter(|&c| c != 0).collect();\n    scores.sort();\n\n    let second = scores[scores.len() / 2];\n\n    println!(\"first  = {}\", first);\n    println!(\"second = {}\", second);\n}\n"
  },
  {
    "path": "advent-of-code/2021/day11/Cargo.toml",
    "content": "[package]\nname = \"day11\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day11/src/main.rs",
    "content": "use std::fs;\n\ntype Board = Vec<Vec<usize>>;\n\nfn advance(board: &mut Board, h: usize, w: usize) -> usize {\n    fn increment(board: &mut Board, i: usize, j: usize, h: usize, w: usize) {\n        board[i][j] += 1;\n\n        if board[i][j] != 10 {\n            return;\n        }\n\n        for x in i.saturating_sub(1)..(i + 2).min(h) {\n            for y in j.saturating_sub(1)..(j + 2).min(w) {\n                increment(board, x, y, w, h);\n            }\n        }\n    }\n\n    for i in 0..h {\n        for j in 0..w {\n            increment(board, i, j, h, w)\n        }\n    }\n\n    let mut flashes = 0;\n\n    for cell in board\n        .iter_mut()\n        .flat_map(|line| line.iter_mut())\n        .filter(|c| **c >= 10)\n    {\n        *cell = 0;\n        flashes += 1;\n    }\n\n    flashes\n}\n\nfn first(board: &Board, h: usize, w: usize) -> usize {\n    let mut board: Board = board.clone();\n    let mut flashes = 0;\n\n    for _ in 0..100 {\n        flashes += advance(&mut board, h, w);\n    }\n\n    flashes\n}\n\nfn second(board: &Board, h: usize, w: usize) -> usize {\n    let mut step = 0;\n    let mut board = board.clone();\n\n    loop {\n        step += 1;\n\n        if advance(&mut board, h, w) == h * w {\n            break;\n        }\n    }\n\n    step\n}\n\nfn main() {\n    let board: Board = fs::read_to_string(\"../inputs/11\")\n        .unwrap()\n        .lines()\n        .map(|line| line.bytes().map(|b| (b - b'0') as usize).collect())\n        .collect();\n\n    let h = board.len();\n    let w = board[0].len();\n\n    println!(\"first  = {}\", first(&board, h, w));\n    println!(\"second = {}\", second(&board, h, w));\n}\n"
  },
  {
    "path": "advent-of-code/2021/day12/Cargo.toml",
    "content": "[package]\nname = \"day12\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day12/src/main.rs",
    "content": "use std::{collections::HashMap, fs};\n\ntype Graph<'a> = HashMap<&'a str, Vec<&'a str>>;\n\nfn is_small(cave: &str) -> bool {\n    cave.chars().all(|c| c.is_ascii_lowercase())\n}\n\nfn parse_input(text: &str) -> Graph {\n    let mut graph: Graph = HashMap::new();\n\n    for line in text.lines() {\n        let mut parts = line.split(\"-\");\n        let from = parts.next().unwrap();\n        let to = parts.next().unwrap();\n\n        graph.entry(from).or_insert(vec![]).push(to);\n        graph.entry(to).or_insert(vec![]).push(from);\n    }\n\n    graph\n}\n\nfn paths(graph: &Graph) -> (usize, usize) {\n    let mut first: usize = 0;\n    let mut second: usize = 0;\n    let mut sofar: Vec<&str> = vec![\"start\"];\n\n    fn visit<'a>(\n        graph: &Graph<'a>,\n        sofar: &mut Vec<&'a str>,\n        twiced: bool,\n        first: &mut usize,\n        second: &mut usize,\n    ) {\n        for cave in &graph[sofar.last().unwrap()] {\n            let seen = is_small(cave) && sofar.contains(cave);\n\n            if *cave == \"start\" || seen && twiced {\n                continue;\n            } else if *cave == \"end\" {\n                if !twiced {\n                    *first += 1;\n                }\n                *second += 1;\n            } else {\n                sofar.push(cave);\n                visit(graph, sofar, twiced || seen, first, second);\n                sofar.pop();\n            }\n        }\n    }\n\n    visit(graph, &mut sofar, false, &mut first, &mut second);\n\n    (first, second)\n}\n\nfn main() {\n    let text = fs::read_to_string(\"../inputs/12\").unwrap();\n    let input = parse_input(&text);\n    let (first, second) = paths(&input);\n\n    println!(\"first  = {}\", first);\n    println!(\"second = {}\", second);\n}\n"
  },
  {
    "path": "advent-of-code/2021/day13/Cargo.toml",
    "content": "[package]\nname = \"day13\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day13/src/main.rs",
    "content": "use std::{collections::HashSet, fs};\n\ntype Point = (usize, usize);\ntype Fold = (char, usize);\n\nfn parse_input() -> (HashSet<Point>, Vec<Fold>) {\n    let text = fs::read_to_string(\"../inputs/13\").unwrap();\n    let mut input = text.split(\"\\n\\n\");\n\n    let points = input\n        .next()\n        .unwrap()\n        .lines()\n        .map(|line| {\n            let mut parts = line.split(\",\");\n            let x = parts.next().unwrap().parse().unwrap();\n            let y = parts.next().unwrap().parse().unwrap();\n            (x, y)\n        })\n        .collect();\n\n    let folds = input\n        .next()\n        .unwrap()\n        .lines()\n        .map(|line| {\n            let mut parts = line.split(\"=\");\n            let axis = parts.next().unwrap().chars().last().unwrap();\n            let coordinate = parts.next().unwrap().parse().unwrap();\n\n            (axis, coordinate)\n        })\n        .collect();\n\n    (points, folds)\n}\n\nfn fold(points: HashSet<Point>, fold: Fold) -> HashSet<Point> {\n    let (axis, point) = fold;\n\n    points\n        .iter()\n        .map(|&(x, y)| {\n            (\n                if axis == 'x' && x > point { 2 * point - x } else { x },\n                if axis == 'y' && y > point { 2 * point - y } else { y },\n            )\n        })\n        .collect()\n}\n\nfn draw(points: &HashSet<Point>) {\n    let h = points.iter().map(|(_, b)| *b).max().unwrap();\n    let w = points.iter().map(|(a, _)| *a).max().unwrap();\n\n    for x in 0..=h {\n        for y in 0..=w {\n            if points.contains(&(y, x)) {\n                print!(\"#\")\n            } else {\n                print!(\" \")\n            }\n        }\n        println!(\"\")\n    }\n}\n\nfn main() {\n    let (points, folds) = parse_input();\n\n    let first = fold(points.clone(), folds[0]).len();\n    println!(\"first = {}\", first);\n\n    let folded = folds.iter().fold(points, |p, &f| fold(p, f));\n    draw(&folded);\n}\n"
  },
  {
    "path": "advent-of-code/2021/day14/Cargo.toml",
    "content": "[package]\nname = \"day14\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day14/src/main.rs",
    "content": "use std::{collections::HashMap, fs};\n\ntype Pair = (u8, u8);\ntype RuleSet = HashMap<Pair, u8>;\ntype Histogram = HashMap<Pair, usize>;\n\nfn expand(pairs: Histogram, rules: &RuleSet) -> Histogram {\n    let mut result: HashMap<Pair, usize> = HashMap::new();\n\n    for (pair, count) in pairs {\n        let middle = rules.get(&pair).unwrap();\n\n        let first = result.entry((pair.0, *middle)).or_insert(0);\n        *first += count;\n\n        let second = result.entry((*middle, pair.1)).or_insert(0);\n        *second += count;\n    }\n\n    result\n}\n\nfn parse_input() -> (String, RuleSet) {\n    let text = fs::read_to_string(\"../inputs/14\").unwrap();\n    let mut parts = text.split(\"\\n\\n\");\n    let polymer = parts.next().unwrap().to_string();\n    let rules = parts\n        .next()\n        .unwrap()\n        .lines()\n        .map(|line| {\n            let chunks: Vec<&str> = line.split(\" -> \").collect();\n            let a = chunks[0].as_bytes()[0];\n            let b = chunks[0].as_bytes()[1];\n            let c = chunks[1].as_bytes()[0];\n            ((a, b), c)\n        })\n        .collect();\n\n    (polymer, rules)\n}\n\nfn histogram(polymer: &str) -> Histogram {\n    let mut histogram = HashMap::new();\n\n    for window in polymer.as_bytes().windows(2) {\n        let pair = (window[0], window[1]);\n        let count = histogram.entry(pair).or_insert(0);\n        *count += 1;\n    }\n\n    histogram\n}\n\nfn solve(polymer: &str, rules: &RuleSet, iterations: usize) -> usize {\n    let mut pairs = histogram(&polymer);\n\n    for _ in 0..iterations {\n        pairs = expand(pairs, &rules);\n    }\n\n    let mut counts: HashMap<u8, usize> = HashMap::new();\n\n    for (pair, count) in pairs {\n        let sofar = counts.entry(pair.0).or_insert(0);\n        *sofar += count;\n    }\n\n    let last = counts.entry(polymer.bytes().last().unwrap()).or_insert(0);\n    *last += 1;\n\n    let min = counts.values().min().map(|s| s.to_owned()).unwrap_or(0);\n    let max = counts.values().max().map(|s| s.to_owned()).unwrap_or(0);\n\n    max - min\n}\n\nfn main() {\n    let (polymer, rules) = parse_input();\n\n    println!(\"first  = {}\", solve(&polymer, &rules, 10));\n    println!(\"second = {}\", solve(&polymer, &rules, 40));\n}\n"
  },
  {
    "path": "advent-of-code/2021/day15/Cargo.toml",
    "content": "[package]\nname = \"day15\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day15/src/main.rs",
    "content": "use std::{\n    cmp::Reverse,\n    collections::BinaryHeap,\n    fs,\n};\n\nfn parse_input() -> Vec<Vec<i64>> {\n    fs::read_to_string(\"../inputs/15\")\n        .unwrap()\n        .lines()\n        .map(|line| {\n            line.as_bytes()\n                .iter()\n                .map(|b| (b - b'0') as i64)\n                .collect()\n        })\n        .collect()\n}\n\nfn adjancent(x: usize, y: usize, h: usize, w: usize) -> Vec<(usize, usize)> {\n    let mut result = vec![];\n\n    if x > 0 {\n        result.push((x - 1, y))\n    }\n    if x < h - 1 {\n        result.push((x + 1, y))\n    }\n    if y > 0 {\n        result.push((x, y - 1))\n    }\n    if y < w - 1 {\n        result.push((x, y + 1))\n    }\n\n    result\n}\n\nfn five_expand(grid: &Vec<Vec<i64>>) -> Vec<Vec<i64>> {\n    let h = grid.len();\n    let w = grid[0].len();\n    let mut result = vec![vec![i64::MAX; w * 5]; h * 5];\n\n    for i in 0..(h * 5) {\n        for j in 0..(w * 5) {\n            let increment = i / h + j / w;\n            let extra = grid[i % w][j % w] + increment as i64;\n            result[i][j] = extra % 10 + extra / 10;\n        }\n    }\n\n    result\n}\n\nfn lowest_risk(grid: &Vec<Vec<i64>>) -> i64 {\n    let h = grid.len();\n    let w = grid[0].len();\n\n    let mut total: Vec<Vec<i64>> = vec![vec![i64::MAX; w]; h];\n    let mut left: BinaryHeap<Reverse<(i64, usize, usize)>> = BinaryHeap::new();\n\n    left.push(Reverse((grid[h - 1][w - 1], h - 1, w - 1)));\n    total[h - 1][w - 1] = grid[h - 1][w - 1];\n\n    while let Some(Reverse((d, x, y))) = left.pop() {\n        for (i, j) in adjancent(x, y, h, w) {\n            if i == 0 && j == 0 {\n                return d\n            }\n            let risk = total[x][y] + grid[i][j];\n            if risk < total[i][j] {\n                total[i][j] = risk;\n                left.push(Reverse((risk, i, j)));\n            }\n        }\n    }\n\n    i64::MAX\n}\n\nfn main() {\n    let first = parse_input();\n    let second = five_expand(&first);\n\n    println!(\"first  = {}\", lowest_risk(&first));\n    println!(\"second = {}\", lowest_risk(&second));\n}\n"
  },
  {
    "path": "advent-of-code/2021/day16/Cargo.toml",
    "content": "[package]\nname = \"day16\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day16/src/main.rs",
    "content": "// This is significantly more complicated than it needs to be, but I wanted to play a bit with Rust\n// and do the following:\n//\n// * Parse the input while streaming it, instead of loading it all, converting it to packets and\n//   evaluating it afterwards.\n// * Evaluate each packet as early as possible (e.g. before the parent subpacket has finished\n//   parsing).\n// * Have a single abstraction that can both add up the version numbers and evaluate the packets\n// * Convert the file to a stream of bits by massively abusing iterators and without creating a\n//   custom struct that implements Iterator (hence the Boxing and the dyns).\n// * Alias all the numeric types I use so they can easily be changed (e.g. bits, versions, type\n//   ids, literal values).\n// * Have a parse_number() function that is generic on its return type.\n//\n// This is very unnecessary and in places uncrustacean, but I did learn a bunch of stuff while\n// doing it.\nuse std::fs::File;\nuse std::io::Read;\nuse std::ops::{Add, Shl};\n\ntype Bit = u8;\ntype LiteralValue = u64;\ntype Version = u8;\ntype TypeId = u8;\ntype Result = i64;\n\n#[derive(Debug)]\nenum Packet<T> {\n    Literal(Version, LiteralValue),\n    Operator(Version, TypeId, Vec<T>),\n}\n\nfn bits(char: u8) -> [Bit; 4] {\n    let num = match char {\n        (b'0'..=b'9') => char - b'0',\n        (b'A'..=b'F') => char - b'A' + 10,\n        _ => panic!(),\n    };\n    let mut result = [0; 4];\n\n    for i in 0..4 {\n        if num & (1 << i) != 0 {\n            result[3 - i] = 1\n        }\n    }\n\n    result\n}\n\nfn read_number<N, I>(stream: &mut I, size: usize) -> N\nwhere\n    N: Shl<usize, Output = N> + Add<Output = N> + From<Bit> + Default,\n    I: Iterator<Item = Bit>,\n{\n    stream\n        .take(size)\n        .fold(N::default(), |a, b| (a << 1) + N::from(b))\n}\n\nfn read_literal<I>(stream: &mut I) -> LiteralValue\nwhere\n    I: Iterator<Item = Bit>,\n{\n    let mut number = 0;\n\n    loop {\n        let chunk: LiteralValue = read_number(stream, 5);\n        number <<= 4;\n\n        if chunk < 16 {\n            number += chunk;\n            break;\n        } else {\n            number += chunk - 16;\n        }\n    }\n\n    number\n}\n\nfn read_packet<T>(mut stream: &mut dyn Iterator<Item = Bit>, eval: fn(Packet<T>) -> T) -> T {\n    let version = read_number(&mut stream, 3);\n    let type_id = read_number(&mut stream, 3);\n\n    if type_id == 4 {\n        eval(Packet::Literal(version, read_literal(&mut stream)))\n    } else {\n        let length_type_id: u8 = read_number(&mut stream, 1);\n        let mut subpackets = vec![];\n\n        if length_type_id == 0 {\n            let length = read_number(&mut stream, 15);\n            let mut substream = stream.take(length).peekable();\n\n            while substream.peek() != None {\n                subpackets.push(read_packet(&mut substream, eval));\n            }\n\n            eval(Packet::Operator(version, type_id, subpackets))\n        } else {\n            for _ in 0..read_number(&mut stream, 11) {\n                subpackets.push(read_packet(&mut stream, eval));\n            }\n            eval(Packet::Operator(version, type_id, subpackets))\n        }\n    }\n}\n\nfn eval(packet: Packet<Result>) -> Result {\n    match packet {\n        Packet::Literal(_, val) => val as Result,\n        Packet::Operator(_, code, vals) => match code {\n            0 => vals.iter().sum(),\n            1 => vals.iter().product(),\n            2 => vals.iter().min().unwrap().clone(),\n            3 => vals.iter().max().unwrap().clone(),\n            5 => (vals[0] > vals[1]) as Result,\n            6 => (vals[0] < vals[1]) as Result,\n            7 => (vals[0] == vals[1]) as Result,\n            _ => panic!(),\n        },\n    }\n}\n\nfn stream_input() -> impl Iterator<Item = Bit> {\n    File::open(\"../inputs/16\")\n        .unwrap()\n        .bytes()\n        .map(|b| b.unwrap())\n        .take_while(|&b| b != b'\\n')\n        .flat_map(|b| bits(b))\n}\n\nfn main() {\n    let first: u64 = read_packet(&mut stream_input(), |packet| match packet {\n        Packet::Literal(version, _) => version as u64,\n        Packet::Operator(version, _, subpackets) => version as u64 + subpackets.iter().sum::<u64>(),\n    });\n\n    let second = read_packet(&mut stream_input(), eval);\n\n    println!(\"first  = {}\", first);\n    println!(\"second = {}\", second);\n}\n"
  },
  {
    "path": "advent-of-code/2021/day17/Cargo.toml",
    "content": "[package]\nname = \"day17\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day17/src/main.rs",
    "content": "use std::fs;\n\nfn parse_input() -> (i64, i64, i64, i64) {\n    let line = fs::read_to_string(\"../inputs/17\").unwrap();\n    let mut chunks = line[15..line.len() - 1].split(\", y=\");\n    let mut xs = chunks.next().unwrap().split(\"..\");\n    let mut ys = chunks.next().unwrap().split(\"..\");\n\n    let left = xs.next().unwrap().parse().unwrap();\n    let right = xs.next().unwrap().parse().unwrap();\n    let bottom = ys.next().unwrap().parse().unwrap();\n    let top = ys.next().unwrap().parse().unwrap();\n\n    (left, right, bottom, top)\n}\n\nfn main() {\n    let (left, right, bottom, top) = parse_input();\n\n    let mut max_height = i64::MIN;\n    let mut hits = 0;\n\n    let from = (((left as f64) * 8.0 + 1.0).sqrt() / 2.0 - 0.5).floor() as i64;\n\n    for dx in from..=right {\n        for mut dy in bottom..=-bottom {\n            let mut dx = dx;\n            let mut x = 0;\n            let mut y = 0;\n\n            let peak = dy * (dy + 1) / 2;\n\n            while y >= bottom && x <= right && (dx > 0 || left <= x) {\n                if left <= x && x <= right && bottom <= y && y <= top {\n                    max_height = max_height.max(peak);\n                    hits += 1;\n                    break;\n                }\n\n                x += dx;\n                y += dy;\n\n                dx -= dx.signum();\n                dy -= 1;\n            }\n        }\n    }\n\n    println!(\"first  = {}\", max_height);\n    println!(\"second = {}\", hits);\n}\n"
  },
  {
    "path": "advent-of-code/2021/day18/Cargo.toml",
    "content": "[package]\nname = \"day18\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day18/src/main.rs",
    "content": "use std::fs;\n\n#[derive(Debug, PartialEq, Clone, Copy)]\nenum Part {\n    Open,\n    Close,\n    Comma,\n    Number(u8),\n}\n\nuse Part::*;\n\ntype Snailfish = Vec<Part>;\n\nfn parse_number(text: &str) -> Snailfish {\n    text.bytes()\n        .map(|char| match char {\n            b'[' => Open,\n            b']' => Close,\n            b',' => Comma,\n            b'0'..=b'9' => Number(char - b'0'),\n            _ => unreachable!(),\n        })\n        .collect()\n}\n\nfn explode(snailfish: Snailfish) -> Snailfish {\n    let mut result = vec![];\n    let mut depth = 0;\n\n    let mut remaining = snailfish.into_iter();\n\n    while let Some(part) = remaining.next() {\n        match part {\n            Open => depth += 1,\n            Close => depth -= 1,\n            Number(first) if depth > 4 => {\n                assert_eq!(remaining.next(), Some(Comma));\n\n                let second: u8;\n                match remaining.next() {\n                    Some(Number(n)) => second = n,\n                    _ => unreachable!(),\n                }\n\n                assert_eq!(remaining.next(), Some(Close));\n\n                for previous in result.iter_mut().rev() {\n                    match previous {\n                        Number(val) => {\n                            *val += first;\n                            break;\n                        }\n                        _ => {}\n                    }\n                }\n\n                assert_eq!(result.pop(), Some(Open));\n\n                result.push(Number(0));\n\n                while let Some(part) = remaining.next() {\n                    if let Number(n) = part {\n                        result.push(Number(n + second));\n                        break;\n                    } else {\n                        result.push(part);\n                    }\n                }\n\n                while let Some(part) = remaining.next() {\n                    result.push(part)\n                }\n\n                break;\n            }\n            _ => (),\n        }\n\n        result.push(part.clone())\n    }\n\n    result\n}\n\nfn split(snailfish: Snailfish) -> Snailfish {\n    let mut result = vec![];\n    let mut done = false;\n\n    for part in snailfish {\n        match part {\n            Number(n) if n >= 10 && !done => {\n                let a = n / 2;\n                let b = n - a;\n\n                result.push(Open);\n                result.push(Number(a));\n                result.push(Comma);\n                result.push(Number(b));\n                result.push(Close);\n                done = true;\n            }\n            _ => result.push(part),\n        }\n    }\n\n    result\n}\n\nfn reduce(snailfish: Snailfish) -> Snailfish {\n    let mut previous;\n    let mut result = snailfish;\n    loop {\n        previous = result.len();\n        result = explode(result);\n\n        while result.len() != previous {\n            previous = result.len();\n            result = explode(result);\n        }\n\n        result = split(result);\n\n        if previous == result.len() {\n            return result;\n        }\n    }\n}\n\nfn add(mut first: Snailfish, mut second: Snailfish) -> Snailfish {\n    let mut result = vec![];\n    result.push(Open);\n    result.append(&mut first);\n    result.push(Comma);\n    result.append(&mut second);\n    result.push(Close);\n\n    reduce(result)\n}\n\nfn magnitude(snailfish: &Snailfish) -> u64 {\n    let mut stack: Vec<u64> = vec![];\n\n    for part in snailfish {\n        match part {\n            Open => stack.push(3),\n            Close => {\n                let a = stack.pop().unwrap();\n                let b = stack.pop().unwrap();\n                let c = stack.pop().unwrap();\n                stack.push(a * b + c);\n            }\n            Comma => {\n                let a = stack.pop().unwrap();\n                let b = stack.pop().unwrap();\n                stack.push(a * b);\n                stack.push(2);\n            }\n            Number(n) => stack.push(*n as u64),\n        }\n    }\n\n    stack.pop().unwrap()\n}\n\nfn parse_input() -> Vec<Snailfish> {\n    fs::read_to_string(\"../inputs/18\")\n        .unwrap()\n        .lines()\n        .map(|s| parse_number(s))\n        .collect()\n}\n\nfn main() {\n    let first = parse_input().into_iter().reduce(|a, b| add(a, b)).unwrap();\n\n    let first = magnitude(&first);\n\n    let mut second = 0;\n    let numbers = parse_input();\n\n    for a in numbers.iter() {\n        for b in numbers.iter() {\n            if a == b {\n                continue;\n            }\n\n            let sum = add(a.clone(), b.clone());\n            second = second.max(magnitude(&sum));\n        }\n    }\n\n    println!(\"first  = {}\", first);\n    println!(\"second = {}\", second);\n}\n"
  },
  {
    "path": "advent-of-code/2021/day19/Cargo.toml",
    "content": "[package]\nname = \"day19\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day19/src/main.rs",
    "content": "use std::{\n    collections::{HashSet, VecDeque},\n    fs,\n    ops::{Mul, Sub},\n};\n\ntype Number = i16;\n\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]\n#[repr(transparent)]\nstruct Matrix([[Number; 4]; 4]);\n\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]\n#[repr(transparent)]\nstruct Point([Number; 4]);\n\nstruct Variation {\n    rotation: Matrix,\n    beacons: Vec<Point>,\n}\n\nstruct Scanner {\n    position: Option<Matrix>,\n    beacons: Vec<Point>,\n    variations: Vec<Variation>,\n}\n\ntype Beacons = Vec<Point>;\n\nimpl Sub<&Point> for &Point {\n    type Output = Point;\n\n    fn sub(self, rhs: &Point) -> Self::Output {\n        Point([\n            self.0[0] - rhs.0[0],\n            self.0[1] - rhs.0[1],\n            self.0[2] - rhs.0[2],\n            1,\n        ])\n    }\n}\n\nimpl Mul<&Matrix> for &Matrix {\n    type Output = Matrix;\n\n    fn mul(self, rhs: &Matrix) -> Self::Output {\n        let mut result = Matrix([[0; 4]; 4]);\n\n        for i in 0..4 {\n            for j in 0..4 {\n                for k in 0..4 {\n                    result.0[i][j] += self.0[i][k] * rhs.0[k][j];\n                }\n            }\n        }\n\n        result\n    }\n}\n\nimpl Mul<&Point> for &Matrix {\n    type Output = Point;\n\n    fn mul(self, rhs: &Point) -> Self::Output {\n        Point([\n            self.0[0][0] * rhs.0[0]\n                + self.0[0][1] * rhs.0[1]\n                + self.0[0][2] * rhs.0[2]\n                + self.0[0][3],\n            self.0[1][0] * rhs.0[0]\n                + self.0[1][1] * rhs.0[1]\n                + self.0[1][2] * rhs.0[2]\n                + self.0[1][3],\n            self.0[2][0] * rhs.0[0]\n                + self.0[2][1] * rhs.0[1]\n                + self.0[2][2] * rhs.0[2]\n                + self.0[2][3],\n            1,\n        ])\n    }\n}\n\nstatic ROTATE_X: Matrix = Matrix([[1, 0, 0, 0], [0, 0, -1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]);\nstatic ROTATE_Y: Matrix = Matrix([[0, 0, 1, 0], [0, 1, 0, 0], [-1, 0, 0, 0], [0, 0, 0, 1]]);\nstatic ROTATE_Z: Matrix = Matrix([[0, -1, 0, 0], [1, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);\nstatic IDENTITY: Matrix = Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);\nstatic ORIGIN: Point = Point([0, 0, 0, 1]);\n\nimpl Matrix {\n    fn translate(point: Point) -> Matrix {\n        Matrix([\n            [1, 0, 0, point.0[0]],\n            [0, 1, 0, point.0[1]],\n            [0, 0, 1, point.0[2]],\n            [0, 0, 0, 1],\n        ])\n    }\n\n    fn rotations() -> Vec<Matrix> {\n        let mut result = vec![];\n        let mut matrix = IDENTITY;\n\n        for i in 0..6 {\n            if i % 2 == 0 {\n                matrix = &matrix * &ROTATE_X;\n            } else {\n                matrix = &matrix * &ROTATE_Y;\n            }\n\n            for _ in 0..4 {\n                matrix = &matrix * &ROTATE_Z;\n                result.push(matrix.clone());\n            }\n        }\n\n        result\n    }\n}\n\nimpl Point {\n    fn new(x: Number, y: Number, z: Number) -> Point {\n        Point([x, y, z, 1])\n    }\n\n    fn manhattan(&self, other: &Point) -> Number {\n        (self - other).0.iter().map(|n| n.abs()).sum::<Number>() - 1\n    }\n}\n\nfn parse_input() -> Vec<Beacons> {\n    fs::read_to_string(\"../inputs/19\")\n        .unwrap()\n        .split(\"\\n\\n\")\n        .map(|scanner| {\n            scanner\n                .lines()\n                .into_iter()\n                .skip(1)\n                .map(|line| {\n                    let parts: Vec<Number> = line.split(\",\").map(|p| p.parse().unwrap()).collect();\n                    Point::new(parts[0], parts[1], parts[2])\n                })\n                .collect()\n        })\n        .collect()\n}\n\nfn overlap_transformation(first: &Scanner, second: &Scanner) -> Option<Matrix> {\n    for origin in first.beacons.iter().skip(11) {\n        for variation in second.variations.iter() {\n            for other in variation.beacons.iter() {\n                let translation = Matrix::translate(origin - other);\n                let overlapping = variation\n                    .beacons\n                    .iter()\n                    .map(|p| &translation * p)\n                    .filter(|x| first.beacons.contains(x))\n                    .count();\n\n                if overlapping >= 12 {\n                    return Some(&first.position.unwrap() * &(&translation * &variation.rotation));\n                }\n            }\n        }\n    }\n\n    None\n}\n\nfn prepare_scanners() -> Vec<Scanner> {\n    let mut scanners: Vec<Scanner> = parse_input()\n        .into_iter()\n        .map(|beacons| Scanner {\n            position: None,\n            beacons,\n            variations: vec![],\n        })\n        .collect();\n\n    let rotations = Matrix::rotations();\n\n    for scanner in scanners.iter_mut() {\n        for rotation in rotations.iter() {\n            let beacons = scanner\n                .beacons\n                .iter()\n                .map(|beacon| rotation * beacon)\n                .collect();\n\n            scanner.variations.push(Variation {\n                beacons,\n                rotation: rotation.clone(),\n            });\n        }\n    }\n\n    scanners\n}\n\nfn merge(scanners: &mut Vec<Scanner>) {\n    scanners[0].position = Some(IDENTITY.clone());\n\n    let mut known: VecDeque<usize> = VecDeque::new();\n    known.push_back(0);\n\n    while let Some(i) = known.pop_front() {\n        let scanner = &scanners[i];\n        let mut found: Vec<(usize, Matrix)> = vec![];\n\n        for (i, unknown) in scanners.iter().enumerate().filter(|s| s.1.position == None) {\n            if let Some(matrix) = overlap_transformation(scanner, unknown) {\n                found.push((i, matrix));\n            }\n        }\n\n        for (i, position) in found {\n            known.push_back(i);\n            scanners[i].position = Some(position)\n        }\n    }\n\n    assert!(scanners.iter().all(|s| s.position != None))\n}\n\nfn main() {\n    let mut scanners = prepare_scanners();\n\n    merge(&mut scanners);\n\n    let beacons: HashSet<Point> = scanners\n        .iter()\n        .flat_map(|scanner| {\n            scanner\n                .beacons\n                .iter()\n                .map(|beacon| &scanner.position.unwrap() * beacon)\n        })\n        .collect();\n    let beacon_count = beacons.len();\n\n    let scanner_positions: Vec<Point> = scanners\n        .iter()\n        .map(|s| &s.position.unwrap() * &ORIGIN)\n        .collect();\n\n    let mut max_distance = 0;\n    for x in scanner_positions.iter() {\n        for y in scanner_positions.iter() {\n            max_distance = max_distance.max(x.manhattan(y));\n        }\n    }\n\n    println!(\"first  = {}\", beacon_count);\n    println!(\"second = {}\", max_distance);\n}\n"
  },
  {
    "path": "advent-of-code/2021/day20/Cargo.toml",
    "content": "[package]\nname = \"day20\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day20/src/main.rs",
    "content": "use std::{collections::HashSet, fs};\n\ntype Number = i32;\ntype Point = (Number, Number);\n\nfn parse_input() -> (String, HashSet<Point>) {\n    let input = fs::read_to_string(\"../inputs/20\").unwrap();\n    let mut data = input.split(\"\\n\\n\");\n    let decoder = data.next().unwrap().to_string();\n    let points: HashSet<Point> = data\n        .next()\n        .unwrap()\n        .lines()\n        .enumerate()\n        .flat_map(|(x, line)| {\n            line.bytes()\n                .enumerate()\n                .filter(|(_, c)| *c == b'#')\n                .map(move |(y, _)| (x as Number, y as Number))\n        })\n        .collect();\n\n    (decoder, points)\n}\n\nfn iterate(points: &HashSet<Point>, decoder: &String, mode: bool) -> HashSet<Point> {\n    let mut result = HashSet::new();\n\n    let deltas = [\n        (-1, -1),\n        (-1, 0),\n        (-1, 1),\n        (0, -1),\n        (0, 0),\n        (0, 1),\n        (1, -1),\n        (1, 0),\n        (1, 1),\n    ];\n\n    let min_x = points.iter().map(|p| p.0).min().unwrap_or(0);\n    let max_x = points.iter().map(|p| p.0).max().unwrap_or(0);\n    let min_y = points.iter().map(|p| p.1).min().unwrap_or(0);\n    let max_y = points.iter().map(|p| p.1).max().unwrap_or(0);\n\n    for x in (min_x - 5)..=(max_x + 5) {\n        for y in (min_y - 5)..=(max_y + 5) {\n            let index = deltas\n                .iter()\n                .map(|(dx, dy)| {\n                    if points.contains(&(x + dx, y + dy)) == mode {\n                        1usize\n                    } else {\n                        0usize\n                    }\n                })\n                .fold(0, |a, b| (a << 1) + b);\n\n            if (decoder.as_bytes()[index] == b'#') != mode {\n                result.insert((x, y));\n            }\n        }\n    }\n\n    result\n}\n\nfn main() {\n    let (decoder, points) = parse_input();\n    let mut points = points;\n\n    points = iterate(&points, &decoder, true);\n    points = iterate(&points, &decoder, false);\n\n    let first = points.len();\n\n    for i in 0..48 {\n      points = iterate(&points, &decoder, i % 2 == 0);\n    }\n\n    let second = points.len();\n\n    println!(\"first  = {}\", first);\n    println!(\"second = {}\", second);\n}\n"
  },
  {
    "path": "advent-of-code/2021/day21/Cargo.toml",
    "content": "[package]\nname = \"day21\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day21/src/main.rs",
    "content": "use std::{collections::HashMap, fs};\n\n#[derive(Copy, Clone, PartialEq, Eq, Hash)]\nstruct Game {\n    positions: [u16; 2],\n    scores: [u16; 2],\n    turn: usize,\n}\n\nimpl Game {\n    fn from(positions: (u16, u16)) -> Game {\n        Game {\n            positions: [positions.0, positions.1],\n            scores: [0, 0],\n            turn: 0,\n        }\n    }\n    fn is_finished(&self, winning_score: u16) -> bool {\n        self.scores.iter().any(|score| *score >= winning_score)\n    }\n\n    fn leader(&self) -> usize {\n        if self.scores[0] > self.scores[1] {\n            0\n        } else {\n            1\n        }\n    }\n\n    fn play(&self, roll: u16) -> Game {\n        let new = increment_position(self.positions[self.turn], roll);\n        let mut scores = self.scores.clone();\n        let mut positions = self.positions.clone();\n        positions[self.turn] = new;\n        scores[self.turn] += new;\n        Game {\n            positions,\n            scores,\n            turn: 1 - self.turn,\n        }\n    }\n}\n\nfn parse_input() -> (u16, u16) {\n    let numbers: Vec<u16> = fs::read_to_string(\"../inputs/21\")\n        .unwrap()\n        .lines()\n        .map(|line| line.split(\": \").nth(1).unwrap().parse().unwrap())\n        .collect();\n    (numbers[0], numbers[1])\n}\n\nfn increment_position(position: u16, count: u16) -> u16 {\n    (position + count - 1) % 10 + 1\n}\n\nfn first(positions: (u16, u16)) -> u64 {\n    let mut game = Game::from(positions);\n\n    let mut die = (1..=100).cycle().enumerate();\n\n    while !game.is_finished(1000) {\n        let mut roll = 0;\n        roll += die.next().unwrap().1;\n        roll += die.next().unwrap().1;\n        roll += die.next().unwrap().1;\n        game = game.play(roll);\n    }\n\n    let winner = game.leader();\n    let rolls = die.next().unwrap().0 as u64;\n\n    (game.scores[1 - winner] as u64) * rolls\n}\n\nfn second(positions: (u16, u16)) -> u64 {\n    let mut unfinished: HashMap<Game, u64> = HashMap::new();\n    let mut finished: HashMap<Game, u64> = HashMap::new();\n\n    let dirac = [(3, 1), (4, 3), (5, 6), (6, 7), (7, 6), (8, 3), (9, 1)];\n\n    unfinished.insert(Game::from(positions), 1);\n\n    while unfinished.len() != 0 {\n        let mut next = HashMap::new();\n\n        for (game, count) in unfinished {\n            for (roll, times) in dirac {\n                let result = game.play(roll);\n\n                if result.is_finished(21) {\n                    *finished.entry(result).or_insert(0) += times * count;\n                } else {\n                    *next.entry(result).or_insert(0) += times * count;\n                }\n            }\n        }\n\n        unfinished = next;\n    }\n\n    let mut wins: [u64; 2] = [0, 0];\n\n    for (game, count) in finished {\n        wins[game.leader()] += count;\n    }\n\n    wins.into_iter().max().unwrap()\n}\n\nfn main() {\n    let input = parse_input();\n\n    println!(\"first  = {}\", first(input));\n    println!(\"second = {}\", second(input));\n}\n"
  },
  {
    "path": "advent-of-code/2021/day22/Cargo.toml",
    "content": "[package]\nname = \"day22\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day22/src/main.rs",
    "content": "use std::fs;\n\ntype Num = i64;\n\n#[derive(Copy, Clone)]\nstruct Interval {\n    from: Num,\n    to: Num,\n}\n\nimpl Interval {\n    fn new(from: Num, to: Num) -> Interval {\n        Interval {\n            from,\n            to: from.max(to),\n        }\n    }\n\n    fn truncate(&self, other: &Interval) -> Interval {\n        Interval::new(self.from.max(other.from), self.to.min(other.to))\n    }\n\n    fn overlaps(&self, other: &Interval) -> bool {\n        self.from < other.to && other.from < self.to\n    }\n\n    fn len(&self) -> Num {\n        self.to - self.from\n    }\n\n    fn split(a: &Interval, b: &Interval) -> [Interval; 3] {\n        let mut points = vec![a.from, a.to, b.from, b.to];\n        points.sort();\n        [\n            Interval::new(points[0], points[1]),\n            Interval::new(points[1], points[2]),\n            Interval::new(points[2], points[3]),\n        ]\n    }\n}\n\n#[derive(Copy, Clone)]\nstruct Cuboid {\n    x: Interval,\n    y: Interval,\n    z: Interval,\n}\n\nimpl Cuboid {\n    fn truncate(&self, interval: Interval) -> Cuboid {\n        Cuboid {\n            x: self.x.truncate(&interval),\n            y: self.y.truncate(&interval),\n            z: self.z.truncate(&interval),\n        }\n    }\n\n    fn overlaps(&self, other: &Cuboid) -> bool {\n        self.x.overlaps(&other.x) && self.y.overlaps(&other.y) && self.z.overlaps(&other.z)\n    }\n\n    fn subtract(&self, other: &Cuboid) -> Vec<Cuboid> {\n        if !self.overlaps(other) {\n            return vec![self.clone()];\n        }\n\n        let mut result = vec![];\n\n        for x in Interval::split(&self.x, &other.x) {\n            for y in Interval::split(&self.y, &other.y) {\n                for z in Interval::split(&self.z, &other.z) {\n                    let cuboid = Cuboid { x, y, z };\n\n                    if self.overlaps(&cuboid) && !other.overlaps(&cuboid) {\n                        result.push(cuboid)\n                    }\n                }\n            }\n        }\n\n        result\n    }\n\n    fn volume(&self) -> Num {\n        self.x.len() * self.y.len() * self.z.len()\n    }\n}\n\nfn parse_input() -> Vec<(Cuboid, bool)> {\n    fs::read_to_string(\"../inputs/22\")\n        .unwrap()\n        .lines()\n        .map(|line| {\n            let chunks: Vec<&str> = line.split(\" \").collect();\n            let on = chunks[0] == \"on\";\n\n            let intervals: Vec<Interval> = chunks[1]\n                .split(\",\")\n                .map(|part| part.split(\"=\").nth(1).unwrap())\n                .map(|range| {\n                    let numbers: Vec<Num> = range.split(\"..\").map(|n| n.parse().unwrap()).collect();\n                    Interval {\n                        from: numbers[0],\n                        to: numbers[1] + 1,\n                    }\n                })\n                .collect();\n\n            let cuboid = Cuboid {\n                x: intervals[0],\n                y: intervals[1],\n                z: intervals[2],\n            };\n\n            (cuboid, on)\n        })\n        .collect()\n}\n\nfn solve(input: Vec<(Cuboid, bool)>) -> Num {\n    let mut cuboids: Vec<Cuboid> = vec![];\n\n    for (cuboid, on) in input {\n        cuboids = cuboids\n            .into_iter()\n            .flat_map(|c| c.subtract(&cuboid))\n            .collect();\n\n        if on {\n            cuboids.push(cuboid)\n        }\n    }\n\n    cuboids.into_iter().map(|c| c.volume()).sum::<Num>()\n}\n\nfn main() {\n    let input = parse_input();\n\n    let first_input = input\n        .iter()\n        .map(|(cuboid, on)| (cuboid.truncate(Interval::new(-50, 50)), *on))\n        .collect::<Vec<_>>();\n\n    println!(\"first  = {}\", solve(first_input));\n    println!(\"second = {}\", solve(input));\n}\n"
  },
  {
    "path": "advent-of-code/2021/day23/Cargo.toml",
    "content": "[package]\nname = \"day23\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day23/src/main.rs",
    "content": "use std::cmp::Reverse;\nuse std::collections::{BinaryHeap, HashMap};\nuse std::fs;\n\ntype Cost = i32;\ntype Point = (usize, usize);\n\n#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]\nstruct Game {\n    maze: Vec<Vec<u8>>,\n}\n\nfn is_amphipod(char: u8) -> bool {\n    b'A' <= char && char <= b'D'\n}\n\nfn is_empty(char: u8) -> bool {\n    char == b'.'\n}\n\nfn is_room(point: Point) -> bool {\n    point.0 > 1\n}\n\nfn is_hallway(point: Point) -> bool {\n    point.0 == 1\n}\n\nfn cost(from: Point, to: Point, char: u8) -> Cost {\n    ((from.0 as Cost - to.0 as Cost).abs() + (from.1 as Cost - to.1 as Cost).abs()) * weight(char)\n}\n\nfn weight(char: u8) -> Cost {\n    match char {\n        b'A' => 1,\n        b'B' => 10,\n        b'C' => 100,\n        b'D' => 1000,\n        _ => unreachable!(),\n    }\n}\n\nfn dedicated_room(char: u8) -> usize {\n    match char {\n        b'A' => 3,\n        b'B' => 5,\n        b'C' => 7,\n        b'D' => 9,\n        _ => unreachable!(),\n    }\n}\n\nfn is_entrance(y: usize) -> bool {\n    y == 3 || y == 5 || y == 7 || y == 9\n}\n\nimpl Game {\n    fn all_moves(&self) -> Vec<(Game, Cost)> {\n        let mut result = vec![];\n\n        for (x, line) in self.maze.iter().enumerate() {\n            for (y, &char) in line.iter().enumerate() {\n                let from = (x, y);\n\n                if !is_amphipod(char) {\n                    continue;\n                }\n\n                for to in self.possible_moves(from) {\n                    result.push((self.walk(from, to), cost(from, to, char)));\n                }\n            }\n        }\n\n        result\n    }\n\n    fn possible_moves(&self, point: Point) -> Vec<Point> {\n        let mut result = vec![];\n\n        if is_room(point) && !self.should_stay(point) && self.can_exit(point) {\n            (1..point.1)\n                .rev()\n                .filter(|&y| !is_entrance(y))\n                .take_while(|&y| self.maze[1][y] == b'.')\n                .for_each(|y| result.push((1, y)));\n\n            (point.1..=11)\n                .filter(|&y| !is_entrance(y))\n                .take_while(|&y| self.maze[1][y] == b'.')\n                .for_each(|y| result.push((1, y)));\n        } else if is_hallway(point) {\n            let char = *self.at(point);\n            let y = dedicated_room(char);\n\n            if let Some(x) = self.room_slot(char) {\n                if self.can_cross(point.1, y) {\n                    result.push((x, y))\n                }\n            }\n        }\n\n        result\n    }\n\n    fn at(&self, point: Point) -> &u8 {\n        &self.maze[point.0][point.1]\n    }\n\n    fn at_mut(&mut self, point: Point) -> &mut u8 {\n        &mut self.maze[point.0][point.1]\n    }\n\n    fn room_slot(&self, char: u8) -> Option<usize> {\n        let y = dedicated_room(char);\n        if !(2..=self.depth())\n            .map(|x| *self.at((x, y)))\n            .all(|c| c == b'.' || c == char)\n        {\n            return None;\n        }\n\n        (2..=self.depth())\n            .take_while(|&x| *self.at((x, y)) == b'.')\n            .last()\n    }\n\n    fn can_cross(&self, from: usize, to: usize) -> bool {\n        if from < to {\n            (from + 1..=to).all(|y| is_empty(*self.at((1, y))))\n        } else {\n            (to..from).all(|y| is_empty(*self.at((1, y))))\n        }\n    }\n\n    fn depth(&self) -> usize {\n        self.maze.len() - 2\n    }\n\n    fn walk(&self, from: Point, to: Point) -> Game {\n        let mut new = Game {\n            maze: self.maze.clone(),\n        };\n\n        *new.at_mut(to) = *self.at(from);\n        *new.at_mut(from) = b'.';\n\n        new\n    }\n\n    fn should_stay(&self, point: Point) -> bool {\n        let char = *self.at(point);\n        let y = dedicated_room(char);\n\n        point.1 == y && (point.0..=self.depth()).all(|x| *self.at((x, y)) == char)\n    }\n\n    fn can_exit(&self, point: Point) -> bool {\n        (2..point.0).all(|x| self.maze[x][point.1] == b'.')\n    }\n\n    fn is_solved(&self) -> bool {\n        (b'A'..=b'D').all(|char| {\n            let y = dedicated_room(char);\n            (2..=self.depth()).all(|x| *self.at((x, y)) == char)\n        })\n    }\n}\n\nfn parse_input() -> Game {\n    let maze = fs::read_to_string(\"../inputs/23\")\n        .unwrap()\n        .lines()\n        .into_iter()\n        .map(|line| line.bytes().collect())\n        .collect();\n\n    Game { maze }\n}\n\nfn solve(game: Game) -> Cost {\n    let mut heap: BinaryHeap<Reverse<(Cost, Game)>> = BinaryHeap::new();\n    let mut costs: HashMap<Game, Cost> = HashMap::new();\n\n    costs.insert(game.clone(), 0);\n    heap.push(Reverse((0, game)));\n\n    while let Some(Reverse((cost, game))) = heap.pop() {\n        let moves = game.all_moves();\n\n        if game.is_solved() {\n            return cost;\n        } else {\n            for (new, delta) in moves {\n                let incremental = cost + delta;\n                let previous = *costs.get(&new).unwrap_or(&Cost::MAX);\n                if incremental < previous {\n                    costs.insert(new.clone(), incremental);\n                    heap.push(Reverse((incremental, new.clone())));\n                }\n            }\n        }\n    }\n\n    -1\n}\n\nfn unfold(game: &Game) -> Game {\n    let mut maze: Vec<Vec<u8>> = vec![];\n\n    for line in &game.maze[0..=2] {\n        maze.push(line.clone());\n    }\n\n    maze.push(\"  #D#C#B#A#\".bytes().collect());\n    maze.push(\"  #D#B#A#C#\".bytes().collect());\n\n    for line in &game.maze[3..=4] {\n        maze.push(line.clone());\n    }\n\n    Game { maze }\n}\n\nfn main() {\n    let game = parse_input();\n    let unfolded = unfold(&game);\n\n    println!(\"first  = {}\", solve(game));\n    println!(\"second = {}\", solve(unfolded));\n}\n"
  },
  {
    "path": "advent-of-code/2021/day24/Cargo.toml",
    "content": "[package]\nname = \"day24\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day24/src/main.rs",
    "content": "use std::fs;\n\ntype Num = i32;\n\nfn main() {\n    let digits = [1, 2, 3, 4, 5, 6, 7, 8, 9];\n    let fns: Vec<(Num, Num, Num)> = fs::read_to_string(\"../inputs/24\")\n        .unwrap()\n        .lines()\n        .map(|line| line.split(\" \").nth(2).unwrap_or(\"\"))\n        .collect::<Vec<_>>()\n        .chunks(18)\n        .map(|block| (block[4].parse().unwrap(), block[5].parse().unwrap(), block[15].parse().unwrap()))\n        .collect();\n\n    let mut stack: Vec<(usize, Num)> = vec![];\n    let mut pattern: Vec<Vec<Num>> = vec![vec![]; 14];\n\n    for (i, (a, b, c)) in fns.into_iter().enumerate() {\n        if a == 1 {\n            stack.push((i, c));\n        } else {\n            let (dep, other) = stack.pop().unwrap();\n            for (x, y) in digits.iter().flat_map(|&x| digits.map(|y| (x, y))).filter(|&(x, y)| x == other + y + b) {\n                pattern[i].push(x);\n                pattern[dep].push(y);\n            }\n        }\n    }\n\n    println!(\"first  = {}\", pattern.iter().map(|p| p.iter().last().unwrap().to_string()).collect::<Vec<_>>().join(\"\"));\n    println!(\"second = {}\", pattern.iter().map(|p| p.iter().nth(0).unwrap().to_string()).collect::<Vec<_>>().join(\"\"));\n}\n"
  },
  {
    "path": "advent-of-code/2021/day25/Cargo.toml",
    "content": "[package]\nname = \"day25\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "advent-of-code/2021/day25/src/main.rs",
    "content": "use std::fs;\n\nfn main() {\n    let mut map: Vec<Vec<u8>> = fs::read_to_string(\"../inputs/25\")\n        .unwrap()\n        .lines()\n        .map(|line| line.bytes().collect())\n        .collect();\n\n    let mut steps = 0;\n    let h = map.len();\n    let w = map[0].len();\n\n    loop {\n        steps += 1;\n\n        let mut horizontal = vec![];\n\n        for x in 0..h {\n            for y in 0..w {\n                let adjancent = (y + 1) % w;\n                if map[x][y] == b'>' && map[x][adjancent] == b'.' {\n                    horizontal.push((x, y, adjancent));\n                }\n            }\n        }\n\n        for &(x, y, a) in &horizontal {\n            map[x][y] = b'.';\n            map[x][a] = b'>';\n        }\n\n        let mut vertical = vec![];\n\n        for x in 0..h {\n            for y in 0..w {\n                let adjancent = (x + 1) % h;\n                if map[x][y] == b'v' && map[adjancent][y] == b'.' {\n                    vertical.push((x, y, adjancent));\n                }\n            }\n        }\n\n        for &(x, y, a) in &vertical {\n            map[x][y] = b'.';\n            map[a][y] = b'v';\n        }\n\n        if vertical.is_empty() && horizontal.is_empty() {\n            break;\n        }\n    }\n\n    println!(\"final = {}\", steps);\n}\n"
  },
  {
    "path": "advent-of-code/2021/inputs/01",
    "content": "103\n106\n107\n110\n121\n132\n147\n148\n144\n141\n147\n149\n156\n152\n155\n156\n157\n145\n144\n145\n147\n153\n155\n175\n170\n173\n171\n205\n208\n216\n219\n222\n223\n226\n217\n233\n235\n237\n238\n239\n247\n257\n262\n280\n284\n285\n287\n288\n290\n298\n313\n318\n299\n312\n311\n315\n313\n306\n289\n292\n297\n300\n301\n334\n337\n338\n339\n349\n350\n351\n373\n379\n383\n385\n412\n419\n425\n421\n418\n420\n418\n428\n438\n446\n448\n451\n453\n462\n476\n480\n479\n487\n497\n505\n529\n531\n533\n540\n537\n534\n545\n546\n549\n550\n557\n562\n570\n580\n586\n606\n610\n611\n609\n612\n623\n643\n663\n687\n686\n693\n694\n700\n701\n707\n709\n723\n724\n731\n770\n775\n787\n788\n805\n819\n828\n829\n835\n836\n833\n834\n837\n839\n879\n881\n887\n891\n908\n909\n908\n929\n930\n939\n940\n934\n895\n898\n903\n904\n908\n912\n918\n920\n921\n951\n946\n958\n962\n964\n965\n969\n970\n978\n982\n986\n988\n989\n985\n986\n1007\n1014\n1012\n1006\n1007\n1009\n1029\n1031\n1026\n1034\n1053\n1054\n1064\n1085\n1092\n1090\n1092\n1102\n1106\n1125\n1137\n1149\n1148\n1155\n1171\n1173\n1152\n1147\n1152\n1159\n1163\n1147\n1153\n1154\n1176\n1188\n1201\n1173\n1177\n1178\n1185\n1202\n1209\n1211\n1215\n1240\n1212\n1209\n1213\n1212\n1222\n1223\n1224\n1251\n1271\n1277\n1284\n1286\n1287\n1290\n1297\n1298\n1292\n1293\n1295\n1294\n1302\n1298\n1286\n1291\n1292\n1294\n1295\n1308\n1309\n1307\n1308\n1320\n1349\n1350\n1354\n1363\n1352\n1353\n1354\n1360\n1361\n1357\n1366\n1367\n1368\n1369\n1375\n1376\n1383\n1381\n1382\n1383\n1384\n1394\n1395\n1404\n1405\n1419\n1421\n1433\n1450\n1443\n1445\n1460\n1474\n1470\n1472\n1475\n1485\n1490\n1489\n1490\n1491\n1495\n1496\n1501\n1536\n1538\n1539\n1549\n1576\n1578\n1583\n1609\n1612\n1613\n1614\n1607\n1608\n1609\n1602\n1614\n1616\n1630\n1648\n1650\n1653\n1654\n1666\n1668\n1676\n1683\n1709\n1711\n1712\n1713\n1712\n1716\n1717\n1718\n1717\n1718\n1720\n1723\n1726\n1732\n1722\n1720\n1732\n1746\n1758\n1765\n1769\n1774\n1790\n1791\n1792\n1807\n1815\n1831\n1832\n1856\n1857\n1861\n1858\n1834\n1817\n1837\n1851\n1850\n1861\n1862\n1860\n1859\n1873\n1874\n1876\n1877\n1887\n1889\n1915\n1920\n1922\n1925\n1924\n1933\n1934\n1935\n1936\n1945\n1946\n1945\n1949\n1953\n1960\n1959\n1966\n1970\n1977\n1989\n1992\n2009\n2028\n2040\n2039\n2037\n2040\n2044\n2081\n2085\n2082\n2087\n2088\n2098\n2119\n2127\n2143\n2124\n2125\n2127\n2137\n2170\n2172\n2173\n2174\n2175\n2179\n2174\n2176\n2177\n2178\n2193\n2194\n2195\n2198\n2195\n2198\n2199\n2191\n2193\n2205\n2221\n2222\n2195\n2196\n2206\n2211\n2219\n2220\n2221\n2224\n2219\n2200\n2220\n2225\n2224\n2225\n2226\n2237\n2238\n2253\n2255\n2268\n2274\n2294\n2295\n2298\n2321\n2323\n2304\n2315\n2313\n2309\n2308\n2310\n2329\n2333\n2340\n2337\n2336\n2335\n2345\n2346\n2358\n2365\n2366\n2365\n2369\n2368\n2361\n2362\n2387\n2378\n2384\n2393\n2392\n2393\n2376\n2404\n2423\n2419\n2422\n2425\n2427\n2428\n2433\n2438\n2435\n2445\n2451\n2459\n2461\n2462\n2463\n2458\n2461\n2469\n2470\n2505\n2532\n2533\n2534\n2537\n2538\n2539\n2541\n2532\n2531\n2545\n2546\n2554\n2571\n2578\n2569\n2585\n2596\n2602\n2600\n2601\n2602\n2611\n2613\n2615\n2618\n2614\n2621\n2623\n2627\n2650\n2660\n2665\n2666\n2667\n2672\n2687\n2664\n2656\n2654\n2656\n2649\n2669\n2672\n2676\n2677\n2673\n2674\n2680\n2682\n2683\n2690\n2691\n2692\n2679\n2686\n2687\n2705\n2697\n2698\n2708\n2727\n2724\n2731\n2737\n2739\n2743\n2749\n2728\n2734\n2738\n2735\n2746\n2749\n2750\n2751\n2754\n2762\n2782\n2789\n2797\n2814\n2822\n2843\n2844\n2847\n2854\n2855\n2864\n2877\n2878\n2879\n2883\n2884\n2908\n2909\n2941\n2943\n2941\n2928\n2929\n2951\n2953\n2960\n2964\n2967\n2968\n2995\n3004\n3024\n3031\n3066\n3067\n3077\n3099\n3102\n3103\n3106\n3107\n3115\n3122\n3123\n3124\n3131\n3135\n3136\n3138\n3139\n3140\n3156\n3158\n3159\n3162\n3171\n3172\n3177\n3178\n3184\n3193\n3203\n3212\n3211\n3213\n3223\n3240\n3241\n3246\n3262\n3261\n3266\n3268\n3285\n3286\n3307\n3312\n3316\n3322\n3323\n3314\n3321\n3328\n3327\n3328\n3342\n3360\n3367\n3369\n3368\n3374\n3376\n3366\n3372\n3378\n3382\n3397\n3401\n3404\n3406\n3388\n3393\n3396\n3422\n3420\n3431\n3432\n3430\n3444\n3446\n3465\n3469\n3486\n3490\n3487\n3506\n3502\n3503\n3509\n3518\n3489\n3499\n3500\n3499\n3508\n3517\n3524\n3525\n3542\n3563\n3565\n3570\n3571\n3574\n3584\n3587\n3588\n3589\n3574\n3589\n3623\n3631\n3638\n3640\n3647\n3662\n3663\n3664\n3665\n3683\n3703\n3721\n3731\n3735\n3738\n3735\n3723\n3731\n3732\n3740\n3746\n3756\n3758\n3764\n3767\n3775\n3777\n3779\n3795\n3796\n3794\n3796\n3797\n3809\n3794\n3795\n3804\n3826\n3828\n3839\n3841\n3832\n3869\n3860\n3869\n3868\n3883\n3901\n3909\n3910\n3919\n3924\n3934\n3962\n3968\n3973\n3988\n4005\n3989\n3992\n4002\n4003\n3994\n3996\n4004\n4012\n3992\n3999\n4031\n4034\n4043\n4046\n4053\n4057\n4061\n4065\n4068\n4084\n4087\n4092\n4093\n4095\n4103\n4113\n4114\n4122\n4120\n4125\n4118\n4126\n4131\n4140\n4161\n4162\n4163\n4177\n4184\n4193\n4194\n4195\n4200\n4202\n4200\n4201\n4202\n4199\n4223\n4230\n4232\n4233\n4234\n4226\n4233\n4235\n4236\n4237\n4245\n4260\n4268\n4292\n4294\n4273\n4275\n4276\n4270\n4278\n4279\n4293\n4306\n4330\n4337\n4343\n4342\n4349\n4355\n4377\n4378\n4379\n4380\n4384\n4388\n4394\n4395\n4396\n4401\n4405\n4410\n4408\n4405\n4410\n4411\n4412\n4414\n4421\n4425\n4428\n4440\n4424\n4428\n4436\n4439\n4440\n4441\n4444\n4445\n4446\n4447\n4448\n4458\n4460\n4461\n4457\n4467\n4478\n4471\n4484\n4485\n4486\n4490\n4492\n4497\n4501\n4515\n4517\n4518\n4517\n4522\n4523\n4526\n4542\n4543\n4533\n4534\n4537\n4536\n4544\n4547\n4548\n4557\n4559\n4560\n4565\n4567\n4572\n4568\n4570\n4575\n4579\n4580\n4578\n4602\n4593\n4581\n4595\n4601\n4641\n4658\n4659\n4661\n4663\n4660\n4661\n4665\n4668\n4683\n4694\n4710\n4712\n4726\n4730\n4732\n4733\n4738\n4762\n4769\n4767\n4768\n4781\n4783\n4796\n4807\n4809\n4819\n4816\n4821\n4823\n4830\n4833\n4840\n4849\n4851\n4856\n4857\n4855\n4857\n4862\n4865\n4864\n4877\n4888\n4900\n4910\n4928\n4933\n4941\n4942\n4953\n4967\n4942\n4947\n4946\n4949\n4956\n4958\n4974\n4976\n4985\n4984\n5001\n5026\n5027\n5029\n5030\n5031\n5045\n5050\n5051\n5059\n5065\n5078\n5079\n5098\n5099\n5100\n5104\n5109\n5098\n5120\n5146\n5147\n5149\n5144\n5161\n5163\n5164\n5178\n5195\n5194\n5215\n5220\n5224\n5232\n5233\n5235\n5240\n5226\n5230\n5249\n5251\n5246\n5247\n5256\n5265\n5272\n5276\n5278\n5277\n5293\n5296\n5297\n5300\n5293\n5327\n5329\n5364\n5369\n5370\n5371\n5380\n5384\n5385\n5395\n5403\n5405\n5408\n5411\n5415\n5411\n5413\n5414\n5415\n5416\n5417\n5441\n5439\n5443\n5450\n5458\n5459\n5463\n5468\n5467\n5501\n5502\n5512\n5501\n5502\n5514\n5515\n5523\n5525\n5527\n5528\n5545\n5546\n5547\n5555\n5556\n5563\n5589\n5590\n5599\n5612\n5602\n5611\n5621\n5622\n5619\n5629\n5630\n5639\n5635\n5642\n5647\n5633\n5643\n5644\n5650\n5651\n5652\n5654\n5657\n5687\n5688\n5690\n5691\n5697\n5717\n5719\n5734\n5741\n5739\n5738\n5739\n5764\n5765\n5766\n5777\n5779\n5784\n5785\n5797\n5791\n5800\n5816\n5815\n5808\n5810\n5786\n5768\n5784\n5785\n5803\n5806\n5795\n5805\n5809\n5821\n5835\n5860\n5871\n5878\n5879\n5880\n5899\n5901\n5900\n5904\n5905\n5900\n5902\n5873\n5876\n5881\n5882\n5891\n5894\n5896\n5898\n5916\n5917\n5920\n5926\n5935\n5936\n5937\n5938\n5939\n5949\n5979\n5982\n5984\n5997\n6010\n6012\n6015\n6016\n6022\n6024\n6032\n6041\n6038\n6046\n6050\n6062\n6063\n6092\n6093\n6080\n6084\n6093\n6104\n6114\n6117\n6115\n6134\n6122\n6123\n6126\n6127\n6130\n6128\n6130\n6127\n6142\n6144\n6150\n6152\n6153\n6152\n6154\n6160\n6163\n6166\n6156\n6163\n6181\n6198\n6202\n6211\n6212\n6211\n6220\n6216\n6228\n6230\n6233\n6232\n6243\n6261\n6257\n6263\n6265\n6278\n6259\n6274\n6280\n6272\n6262\n6264\n6286\n6280\n6292\n6296\n6297\n6306\n6307\n6312\n6313\n6323\n6324\n6334\n6335\n6344\n6345\n6342\n6338\n6349\n6357\n6359\n6391\n6393\n6396\n6400\n6402\n6398\n6400\n6404\n6414\n6426\n6447\n6449\n6447\n6448\n6453\n6460\n6464\n6466\n6471\n6470\n6471\n6496\n6512\n6513\n6524\n6516\n6519\n6522\n6500\n6510\n6512\n6515\n6535\n6536\n6537\n6546\n6547\n6550\n6556\n6557\n6550\n6549\n6531\n6533\n6532\n6533\n6532\n6541\n6543\n6535\n6545\n6550\n6559\n6583\n6584\n6583\n6585\n6593\n6596\n6600\n6603\n6605\n6614\n6615\n6616\n6618\n6639\n6641\n6652\n6653\n6681\n6696\n6709\n6703\n6706\n6707\n6697\n6695\n6706\n6699\n6704\n6705\n6721\n6723\n6729\n6742\n6744\n6747\n6748\n6750\n6751\n6752\n6747\n6750\n6752\n6755\n6756\n6758\n6760\n6774\n6798\n6800\n6802\n6806\n6783\n6798\n6800\n6823\n6848\n6855\n6858\n6856\n6857\n6858\n6872\n6873\n6874\n6875\n6879\n6884\n6890\n6891\n6889\n6892\n6883\n6884\n6893\n6905\n6897\n6902\n6904\n6909\n6914\n6916\n6905\n6907\n6908\n6910\n6894\n6918\n6919\n6932\n6946\n6922\n6943\n6944\n6943\n6946\n6963\n6972\n6977\n6978\n6982\n6984\n6992\n7001\n6993\n7007\n7001\n7011\n7015\n7017\n7018\n7019\n7021\n7028\n7029\n7057\n7065\n7066\n7065\n7078\n7089\n7090\n7092\n7093\n7094\n7095\n7098\n7100\n7122\n7126\n7130\n7125\n7132\n7131\n7132\n7114\n7115\n7118\n7119\n7132\n7134\n7156\n7161\n7163\n7164\n7165\n7172\n7186\n7189\n7192\n7193\n7191\n7192\n7195\n7203\n7205\n7212\n7214\n7217\n7222\n7223\n7224\n7225\n7227\n7264\n7268\n7289\n7290\n7299\n7300\n7305\n7306\n7307\n7313\n7328\n7318\n7323\n7332\n7335\n7355\n7360\n7384\n7387\n7389\n7395\n7403\n7405\n7427\n7448\n7446\n7448\n7447\n7446\n7460\n7464\n7465\n7469\n7470\n7477\n7480\n7479\n7483\n7488\n7475\n7482\n7474\n7475\n7476\n7486\n7489\n7487\n7490\n7492\n7512\n7515\n7514\n7518\n7526\n7535\n7536\n7535\n7549\n7551\n7552\n7554\n7556\n7541\n7536\n7545\n7550\n7559\n7554\n7555\n7562\n7568\n7566\n7582\n7583\n7584\n7598\n7618\n7619\n7628\n7629\n7633\n7634\n7636\n7635\n7633\n7636\n7635\n7637\n7639\n7630\n7631\n7637\n7649\n7650\n7651\n7661\n7656\n7652\n7654\n7659\n7674\n7681\n7679\n7680\n7696\n7708\n7709\n7719\n7721\n7728\n7729\n7722\n7749\n7754\n7757\n7758\n7760\n7761\n7764\n7762\n7766\n7765\n7766\n7763\n7764\n7767\n7786\n7790\n7797\n7817\n7816\n7823\n7822\n7826\n7843\n7844\n7856\n7857\n7858\n7878\n7880\n7889\n7890\n7891\n7932\n7934\n7949\n7956\n7957\n7958\n7962\n7960\n7961\n7962\n7964\n7968\n7978\n7991\n7997\n8015\n8018\n8019\n8029\n8032\n8026\n8029\n8030\n8033\n8044\n8046\n8044\n8063\n8068\n8070\n8073\n8074\n8077\n8080\n8081\n8083\n8084\n8118\n8116\n8129\n8131\n8138\n8128\n8106\n8120\n8124\n8155\n8158\n8166\n8167\n8168\n8167\n8166\n8159\n8162\n8163\n8166\n8180\n8159\n8174\n8182\n8185\n8183\n8206\n8209\n8212\n8213\n8214\n8237\n8239\n8240\n8243\n8249\n8258\n8259\n8260\n8271\n8275\n8277\n8286\n8295\n8299\n8304\n8305\n8307\n8319\n8292\n8299\n8302\n8320\n8321\n8327\n8336\n8337\n8355\n8371\n8388\n8389\n8394\n8393\n8395\n8386\n8403\n8408\n8409\n8429\n8437\n8455\n8456\n8457\n8481\n8485\n8486\n8487\n8489\n8495\n8509\n8514\n8518\n8554\n8555\n8560\n8561\n8568\n8569\n8575\n8578\n8579\n8580\n8585\n8586\n8587\n8599\n8600\n8610\n8611\n8612\n8639\n8640\n8645\n8648\n8649\n8658\n8666\n8667\n8672\n8674\n8672\n8675\n8677\n8682\n8684\n8686\n8694\n8696\n8697\n8705\n8679\n8680\n8684\n8685\n8686\n8692\n8693\n8694\n8695\n8715\n8720\n8731\n8732\n8735\n8734\n8738\n8756\n8768\n8769\n8773\n8778\n8780\n8763\n8789\n8788\n8800\n8799\n8804\n8810\n8814\n8813\n8817\n8820\n8823\n8827\n8829\n8839\n8840\n8843\n8845\n8846\n8865\n8868\n8874\n8870\n8875\n8876\n8877\n8878\n8904\n8905\n8907\n8908\n8909\n8923\n8925\n8931\n8932\n8936\n8930\n8936\n8937\n8954\n8986\n8994\n9011\n9016\n9021\n9027\n9035\n9048\n9057\n9071\n9072\n9076\n9090\n9095\n9096\n9115\n9117\n9136\n9138\n9135\n9143\n9145\n9146\n9147\n9149\n9147\n9148\n9152\n9153\n9166\n9175\n9182\n9185\n9186\n9190\n9191\n9183\n9158\n9161\n9167\n9168\n9169\n9177\n9178\n9185\n9188\n9190\n9197\n9200\n9204\n9205\n9206\n9207\n9224\n9225\n9235\n9254\n9258\n9259\n9266\n9282\n9283\n9284\n9286\n9285\n9284\n9281\n9284\n9285\n9286\n9288\n9293\n9294\n9310\n9321\n9356\n9338\n9347\n9370\n9380\n9370\n9371\n9372\n9371\n9374\n9375\n9382\n9386\n9391\n9393\n9394\n9395\n9396\n9403\n9404\n9409\n9408\n9412\n9413\n9411\n9420\n9430\n9435\n9448\n9450\n9451\n9455\n9444\n9445\n9470\n9472\n9479\n9488\n9489\n9482\n9488\n9496\n9502\n9503\n9506\n9508\n9524\n9519\n9524\n9528\n9529\n9531\n9532\n9538\n9548\n"
  },
  {
    "path": "advent-of-code/2021/inputs/02",
    "content": "forward 8\nforward 3\ndown 8\ndown 2\nup 1\nup 4\ndown 9\nforward 3\nforward 4\nforward 5\nforward 1\nforward 1\nup 8\nforward 2\nforward 9\ndown 2\nforward 8\ndown 5\ndown 3\ndown 8\nup 1\nforward 1\ndown 8\nup 7\ndown 8\ndown 9\ndown 4\ndown 7\nforward 7\nforward 9\ndown 2\ndown 5\nforward 1\ndown 1\nforward 2\nup 8\ndown 8\nforward 2\nup 5\ndown 6\ndown 5\ndown 2\nforward 5\nforward 4\nforward 6\ndown 4\nup 1\ndown 8\ndown 7\ndown 3\ndown 4\ndown 5\nforward 7\ndown 3\ndown 3\nforward 3\ndown 2\nup 8\nup 8\nforward 2\ndown 8\ndown 8\nforward 3\nforward 9\nforward 3\nforward 2\ndown 9\ndown 3\nforward 4\nforward 1\ndown 7\nforward 5\nup 2\ndown 6\nup 4\ndown 2\nup 5\nforward 6\ndown 6\ndown 1\nforward 5\nforward 4\nup 8\nup 5\nforward 2\ndown 5\ndown 4\nup 1\nforward 9\nup 5\nup 5\nforward 3\ndown 6\nforward 7\ndown 2\nforward 1\nforward 4\nforward 4\ndown 2\ndown 6\ndown 3\ndown 1\nforward 1\ndown 8\nforward 2\ndown 1\ndown 2\nforward 6\nforward 1\nforward 7\nforward 2\ndown 2\nup 6\nup 2\nforward 7\ndown 6\ndown 1\nforward 5\nforward 3\nforward 1\ndown 3\nup 1\nforward 3\nforward 1\ndown 2\ndown 5\nup 8\ndown 8\nforward 3\ndown 9\nforward 8\ndown 8\ndown 5\nforward 2\nup 1\ndown 3\nup 3\ndown 5\ndown 7\ndown 8\ndown 8\ndown 1\nforward 9\nup 4\nup 4\ndown 5\nforward 6\nforward 1\nup 6\nforward 5\nup 6\nforward 1\nforward 9\ndown 3\ndown 8\nforward 6\nforward 6\nup 1\ndown 6\nforward 2\ndown 7\ndown 2\nforward 4\nup 4\nup 2\nforward 8\nup 6\ndown 8\nup 3\ndown 5\ndown 3\nforward 3\ndown 8\nup 4\nup 5\ndown 1\ndown 7\ndown 7\nforward 6\nup 6\ndown 1\nforward 7\ndown 2\nup 7\nup 3\nforward 9\ndown 3\nup 4\nup 1\nforward 8\ndown 4\nforward 9\nforward 8\ndown 4\ndown 3\ndown 1\nforward 8\nup 7\ndown 3\nup 5\ndown 3\ndown 9\ndown 9\nup 9\ndown 9\nup 4\ndown 5\ndown 5\nforward 8\nforward 1\nup 3\ndown 9\ndown 8\nforward 2\nforward 1\nup 6\ndown 3\nforward 1\nup 6\nforward 9\nforward 3\nforward 3\ndown 2\ndown 7\nforward 1\nup 9\nup 3\nforward 1\nforward 2\nforward 7\nforward 8\nforward 2\nforward 3\nforward 1\nforward 7\ndown 1\nup 7\nup 3\nforward 3\nforward 9\ndown 7\ndown 3\nforward 2\nforward 8\nup 1\nforward 2\nforward 3\nup 2\ndown 1\ndown 9\ndown 4\nup 3\nforward 3\ndown 6\ndown 1\nforward 2\ndown 8\nforward 3\nforward 9\nforward 1\nforward 6\nforward 5\ndown 5\nforward 2\nup 7\nup 7\ndown 8\nforward 9\nup 1\nup 5\nup 8\nforward 5\nforward 2\ndown 5\nup 5\ndown 3\nforward 6\ndown 9\ndown 7\nforward 2\nforward 8\nforward 3\ndown 7\ndown 8\nforward 9\ndown 3\ndown 3\nforward 1\nforward 4\ndown 2\nforward 1\nforward 3\nforward 5\ndown 9\nup 3\ndown 5\nforward 8\nforward 3\ndown 5\nforward 3\nforward 7\ndown 3\nforward 8\ndown 1\ndown 3\ndown 4\ndown 2\nforward 8\ndown 2\nforward 5\ndown 2\nup 2\nforward 8\nforward 9\nforward 3\nforward 2\nforward 3\ndown 2\nforward 5\ndown 1\ndown 9\nup 1\ndown 6\nforward 2\nup 1\nforward 6\ndown 2\nforward 2\nforward 1\nforward 4\nforward 4\nforward 9\nforward 2\ndown 5\nforward 9\nforward 1\nforward 7\nforward 1\ndown 7\nforward 7\ndown 4\ndown 8\ndown 8\ndown 1\nforward 4\ndown 5\nup 3\ndown 5\nforward 6\ndown 6\ndown 4\ndown 9\ndown 4\ndown 5\nforward 7\nup 4\nforward 6\ndown 9\ndown 5\ndown 5\nup 2\nforward 8\nup 5\ndown 1\ndown 2\nup 6\ndown 7\nforward 7\nup 5\nforward 4\nup 5\ndown 3\nup 7\nforward 4\ndown 4\ndown 5\ndown 7\ndown 3\ndown 9\nup 8\ndown 9\nforward 6\nforward 2\nforward 2\nup 8\nup 2\ndown 4\ndown 4\nup 7\nup 9\nforward 2\nforward 8\nforward 4\nup 8\nforward 8\nup 2\ndown 3\nforward 9\ndown 1\ndown 7\nforward 4\ndown 2\nup 6\nup 6\ndown 9\nforward 6\nforward 9\ndown 3\nforward 8\nup 1\ndown 5\nforward 1\ndown 6\nup 8\nforward 2\nup 7\nforward 5\ndown 5\nup 3\nforward 2\nforward 1\nforward 4\ndown 6\nup 9\nforward 9\ndown 8\nforward 2\ndown 1\ndown 3\nforward 2\nforward 9\nup 1\nforward 9\ndown 4\nforward 2\nforward 7\nforward 1\nup 2\nup 2\ndown 9\nforward 3\nforward 2\ndown 6\nup 8\ndown 4\nforward 8\nup 9\nup 6\ndown 5\nup 1\ndown 9\ndown 2\ndown 1\nup 8\ndown 1\nforward 3\ndown 7\ndown 7\nforward 8\ndown 4\nforward 1\nforward 4\nforward 5\ndown 8\ndown 2\ndown 9\nup 5\ndown 8\ndown 8\ndown 3\nforward 2\ndown 5\nup 5\ndown 1\ndown 2\nforward 9\ndown 7\ndown 7\ndown 1\ndown 6\nup 6\nup 7\ndown 1\ndown 3\ndown 2\ndown 5\ndown 9\ndown 4\ndown 5\nforward 1\nup 7\ndown 7\nforward 6\nforward 4\ndown 3\nforward 3\nforward 6\nforward 7\ndown 3\nforward 1\ndown 6\ndown 8\nforward 3\nup 3\nforward 4\nforward 3\ndown 6\nup 7\nforward 8\nforward 4\ndown 7\ndown 6\ndown 8\nforward 9\ndown 6\ndown 5\nup 4\ndown 6\ndown 8\ndown 5\nup 4\nforward 2\nforward 8\nforward 9\ndown 2\nforward 5\ndown 9\ndown 2\ndown 7\nforward 2\ndown 2\nup 7\ndown 2\nup 5\nforward 3\ndown 8\nforward 3\nforward 8\nup 3\ndown 6\ndown 1\nforward 2\nup 7\ndown 8\nforward 8\ndown 2\ndown 3\ndown 5\nforward 4\nforward 5\ndown 2\nforward 2\ndown 5\ndown 9\nforward 4\nforward 3\nforward 2\ndown 9\nforward 2\nforward 9\ndown 5\ndown 9\ndown 6\ndown 6\ndown 3\ndown 1\ndown 7\nforward 7\nforward 2\nup 9\nforward 4\nup 7\nforward 3\ndown 2\nup 8\nup 3\ndown 4\nup 9\nforward 1\ndown 1\nforward 4\nup 4\nforward 4\nup 8\nforward 7\ndown 3\nforward 1\nup 3\nup 1\nup 2\ndown 3\nforward 5\ndown 6\ndown 1\ndown 2\nforward 2\ndown 3\nup 1\nforward 4\ndown 2\nforward 8\nforward 3\nforward 7\nforward 7\ndown 5\ndown 7\nforward 8\nup 2\ndown 6\nforward 1\ndown 4\nforward 5\nforward 8\nforward 9\nforward 7\ndown 1\ndown 3\ndown 1\ndown 2\nforward 3\nup 3\ndown 7\nforward 9\nforward 2\nup 8\nup 6\nup 3\ndown 5\nforward 8\ndown 8\ndown 6\nforward 4\ndown 2\ndown 8\nforward 8\nup 7\nup 4\nup 5\ndown 4\nup 6\nforward 2\nforward 9\ndown 9\nforward 6\ndown 5\ndown 7\nforward 5\nup 5\nforward 2\nup 7\nup 3\ndown 8\nforward 8\nforward 3\ndown 2\ndown 5\nforward 4\ndown 8\nforward 5\nforward 4\ndown 9\nforward 1\ndown 4\nup 5\nforward 5\ndown 1\nforward 4\ndown 4\nforward 4\ndown 8\nup 5\nup 4\nup 9\nforward 2\nforward 3\ndown 3\nforward 2\ndown 6\ndown 6\ndown 5\nforward 8\nforward 3\nup 1\ndown 9\ndown 4\ndown 1\nup 4\nforward 2\nforward 3\ndown 4\nup 4\nforward 5\nforward 2\nup 2\nforward 4\ndown 2\ndown 3\ndown 6\nup 2\nforward 8\nforward 9\nforward 1\ndown 1\nup 7\nup 4\nforward 2\nforward 4\nforward 2\nforward 8\ndown 9\ndown 5\ndown 1\ndown 1\ndown 6\nforward 1\nup 6\ndown 4\ndown 9\ndown 2\ndown 2\ndown 5\nup 6\nforward 4\nforward 1\nforward 2\nforward 8\nforward 2\ndown 6\nforward 1\ndown 8\ndown 1\nforward 2\nforward 3\ndown 9\ndown 7\ndown 5\nup 1\nforward 1\ndown 5\ndown 4\nforward 8\ndown 9\nup 7\nforward 6\nforward 2\nforward 8\ndown 9\ndown 1\nup 5\ndown 5\ndown 3\nforward 6\nforward 5\nforward 2\nforward 6\nup 4\nforward 1\ndown 9\nforward 5\nup 1\ndown 5\ndown 6\nforward 8\ndown 4\nup 9\ndown 6\ndown 9\ndown 7\ndown 3\nforward 7\ndown 5\nup 6\nforward 3\nup 4\ndown 5\nup 5\nup 9\nforward 9\nforward 8\ndown 9\nforward 9\ndown 2\nforward 5\nforward 5\nforward 9\ndown 3\nup 8\ndown 7\nup 9\nforward 8\nforward 8\ndown 1\ndown 5\ndown 4\nup 8\nforward 4\nforward 7\ndown 2\ndown 7\ndown 6\ndown 9\ndown 7\nforward 5\nforward 7\nforward 5\nforward 2\nforward 7\nup 2\ndown 8\ndown 9\ndown 5\ndown 9\nforward 5\nforward 8\nforward 9\nup 5\ndown 9\ndown 7\nforward 4\ndown 6\nup 5\nup 8\ndown 3\ndown 2\nup 7\nforward 9\ndown 3\ndown 2\ndown 7\ndown 4\nup 6\nup 4\ndown 7\ndown 4\nforward 5\nforward 6\nup 6\ndown 7\ndown 9\ndown 9\ndown 6\nforward 8\nforward 3\nforward 5\nup 1\nup 8\nforward 4\nforward 6\ndown 5\ndown 4\nforward 5\nforward 9\ndown 4\nup 3\nup 8\ndown 7\nup 8\nforward 5\nforward 3\nup 4\nup 9\nforward 6\ndown 1\nup 6\ndown 5\ndown 4\ndown 3\ndown 8\nup 1\ndown 1\nup 8\nup 8\ndown 6\nforward 4\nforward 9\ndown 4\ndown 7\nforward 9\nforward 8\nup 6\ndown 9\nup 3\ndown 8\nforward 4\nforward 6\nforward 9\nup 7\ndown 2\nforward 2\nforward 1\nforward 5\nup 9\nup 7\nup 5\nforward 4\nforward 5\nforward 4\nup 5\nforward 4\nup 6\ndown 5\nup 2\nforward 5\nforward 5\ndown 9\nforward 7\ndown 9\nup 4\nup 9\nforward 6\nforward 7\ndown 2\nforward 4\ndown 9\ndown 6\nforward 1\nforward 7\nup 3\nup 3\ndown 6\nup 6\nup 2\nup 3\nforward 7\nup 4\nforward 1\ndown 1\nforward 2\nforward 4\ndown 1\ndown 8\nforward 5\nforward 8\nup 7\ndown 3\nforward 3\nforward 6\ndown 8\ndown 7\nup 9\nforward 3\nup 1\ndown 8\nforward 4\ndown 9\nforward 3\nforward 8\ndown 4\nforward 4\nforward 1\nup 6\ndown 1\ndown 7\nforward 8\ndown 9\ndown 8\ndown 7\nforward 5\nup 6\nforward 5\nup 1\ndown 3\ndown 7\ndown 4\nforward 6\ndown 4\ndown 7\nup 9\ndown 6\ndown 7\nup 3\nup 8\nforward 3\nforward 1\nforward 5\ndown 5\nforward 5\ndown 1\nforward 9\nup 5\nforward 4\ndown 1\ndown 8\nup 1\nup 3\nup 8\ndown 3\ndown 5\nup 7\nforward 4\ndown 7\nforward 9\nforward 7\nforward 9\ndown 9\nforward 3\nforward 6\nup 3\nforward 4\nforward 4\n"
  },
  {
    "path": "advent-of-code/2021/inputs/03",
    "content": "110001010111\n011011110010\n110011110011\n101000010111\n011101100100\n111001011100\n011100000101\n011110110011\n001001111111\n111000010000\n001000101100\n011100111010\n011100111000\n011100010001\n100001100000\n111010111110\n100011000101\n010111000101\n100110110011\n101010110011\n110101110010\n110111100010\n000001100100\n010010011010\n001001001100\n101000000111\n100100110011\n111111100011\n110010001010\n100010110011\n111101101001\n101001001101\n110111011101\n100100101101\n111111000011\n001110010110\n010110110010\n010011100000\n110011100011\n111101001011\n100001101000\n100101100011\n010101100110\n101000001001\n010001011100\n111001010010\n000110000110\n110110111111\n111111010000\n110111110011\n110110010010\n000001001111\n010001000111\n101101100110\n110011100100\n101000010100\n010100010000\n100011001001\n011000111101\n000101011101\n000110111110\n011000101100\n110101101001\n100011110011\n110101010001\n100010100000\n110010010001\n000101101011\n101100111011\n111110110001\n011001000100\n001101111000\n100100100101\n101111001000\n011010110110\n001110011111\n101011001001\n110000100010\n011110100110\n001100101100\n000110000001\n011111001111\n011000110010\n001100011111\n111100010100\n010011111000\n000100101010\n101111100101\n010000001100\n100100101111\n100011101100\n000001111000\n001110000011\n011101011001\n000001111101\n000011001011\n111111000110\n000001011100\n011001100000\n111001011101\n011010000011\n101010101110\n010110010101\n000011101101\n010010011000\n000010100111\n001000000111\n111111011100\n101010010000\n101001001100\n000000100111\n101010101100\n010110100111\n001010001101\n111000000101\n111001101100\n011110010001\n011001111010\n010010011011\n011110111000\n010111110000\n001110001011\n010001001011\n011001001010\n011001001101\n001101011101\n100110100000\n100001111110\n101110100011\n100010111111\n001010010011\n000010011001\n011001111101\n000100000010\n100110010011\n001111001000\n110001011101\n000100011000\n111110000000\n111001101000\n100111000100\n010000010100\n011000110111\n000110001101\n101100110010\n011111101001\n000000100010\n000001101000\n111001111101\n111100010111\n110000010101\n110000101100\n101111010011\n000100010101\n100111100011\n110100101111\n101000001000\n001000100000\n100111111010\n001101111101\n000000101000\n100111101100\n100111010100\n111100010110\n100001010011\n010010001000\n111101010101\n101110101010\n111110001110\n001010111010\n100110001000\n101111001111\n110010011101\n110001110101\n011101000000\n010011110110\n001110101001\n011110011010\n110010111100\n010000100001\n010010000100\n111111000101\n010111100111\n101010110010\n100010010011\n101011010000\n000101100000\n011001000011\n010110000000\n101011101111\n001101001110\n001100100110\n011111110011\n010000101101\n000111101101\n111100101101\n000011001101\n110011111100\n011000110000\n000001010010\n111100111111\n001010000100\n000011010010\n010001000001\n111010111000\n110001010011\n000000101011\n011110011011\n100110111000\n010010110010\n000010111110\n110010001001\n000111001001\n001000011100\n111111011010\n000000110101\n111011111011\n100001110111\n010001110000\n010101100100\n011010100001\n111000101101\n001100110110\n010001111110\n100000101011\n011111111001\n111000001100\n011111100011\n110110110000\n011000101010\n101000000011\n101111110100\n011000101101\n001000011010\n101001100111\n101100001101\n100100101100\n001101011001\n001111100111\n011100101001\n110010000000\n010100111000\n000011010111\n000000100110\n101001000000\n000110100100\n110001110011\n001011001101\n100000111100\n101011011111\n000010110110\n010101110100\n111100111001\n111010101101\n101100001001\n011111000111\n010001101000\n100000001111\n011111101100\n011111100111\n111101111110\n110110100101\n011110001011\n100111100001\n000001101101\n100110101110\n100000010011\n110000000001\n001001101001\n000001111111\n111001001010\n101011100101\n100100000000\n110001101011\n011111001011\n010010001011\n000101010011\n110010110100\n101010101011\n100100001100\n000001100011\n101010000010\n111101100100\n001011010111\n000001010001\n001010001011\n100110000011\n000010101010\n110111011100\n001100111000\n111011010111\n100100110000\n000010111010\n000011010001\n100001111111\n111111000100\n010111111000\n100101010010\n001111111010\n001111011100\n111101100111\n111011011011\n111000100110\n011101001011\n010100101010\n010100001111\n010000001111\n000000000010\n010011010111\n001101001011\n101011001011\n011001101101\n100000000111\n100110011010\n000101000110\n101100010011\n101011011100\n001101010100\n110101110111\n001100001000\n001001100100\n111101011010\n001100100100\n100000100010\n001110111001\n101101001110\n001101110111\n010101100101\n000011111110\n001000111101\n110011101011\n110101011000\n000000100101\n100110100001\n111111101101\n010100101111\n110101011010\n011010011100\n101101010001\n101001010011\n011111001100\n101001010111\n011100100011\n101011110000\n010111001010\n111011000111\n100111001101\n001110111010\n100001111000\n111011010011\n110000101010\n011010000000\n110001111010\n100101000100\n010000110100\n101000101010\n011010101110\n010000111100\n101011100100\n101101111010\n111011111110\n000101010111\n000010111000\n011101101010\n101110100110\n010000011010\n101100100000\n010011010101\n101100011100\n011010101010\n010111101010\n111011100111\n111111110010\n101101100100\n111001010100\n011000001110\n110110001110\n111110100110\n001011011100\n101000010010\n100000101010\n010000011110\n001001110111\n001001001011\n110010011110\n001111001100\n110110100010\n111100000111\n010101101011\n001111111001\n101011000000\n011100011000\n000001000000\n100101001100\n110010011001\n111100111110\n010000110110\n110000111000\n110111100001\n000100100010\n100010001110\n010000111101\n111100011000\n110000000101\n000000000001\n010011111100\n011011111101\n111001111010\n001001001001\n010101011010\n011010011111\n001111000011\n101111111111\n000111101000\n011000111110\n001100101101\n101000000110\n000100001010\n111110010101\n000011101000\n011010101000\n100111100000\n111001111111\n010101000111\n011000100101\n001001110001\n101101011011\n001000001100\n111110111010\n011110111010\n111101100001\n011111101000\n110100010100\n010001110011\n000011010011\n010000110010\n000011111011\n101111011000\n010101111110\n100100101011\n001000011011\n011000100000\n100100111101\n001010110011\n000000000000\n000110111011\n001001011001\n011101010010\n000111000011\n010001000100\n011110011111\n010010111011\n100000000011\n001100111101\n000001000110\n000010000010\n101111001010\n000111000001\n100101011100\n111001110100\n100111001111\n011110111111\n010101011110\n101010011011\n101000010101\n101001101000\n001001011101\n010110101100\n101110111100\n000111011110\n010111001101\n001101100010\n011101001111\n100111111111\n000110101110\n011110001110\n110011100111\n010011100101\n100101000011\n100101010011\n111000110110\n110111011111\n000100011110\n100000000001\n010111111111\n100000100011\n110010011111\n111101110110\n001000001001\n001100011001\n111100110001\n100110100101\n010111101000\n000000000110\n000011011001\n100100001111\n001111100100\n001011010011\n001000110011\n110100010010\n011100110111\n011010110010\n011001110110\n011011100010\n001110101011\n101101100111\n101101111100\n000110000101\n000001110010\n001101110010\n101011000100\n000110000000\n001001011111\n100101101011\n001010100001\n110000111110\n011111101111\n110110111100\n001000010110\n000101111110\n111001000001\n000100110011\n110110000101\n101100101011\n101110000010\n011101100001\n010011000001\n010111000011\n010111011101\n101010100001\n000111011011\n101110010000\n110000000010\n101100011101\n011000011000\n001111101101\n101000001010\n101011010001\n011111100001\n101001011110\n100101011000\n011110001100\n111100011110\n010011101110\n001001110000\n001001000011\n100001010000\n000110010000\n110111010111\n000100110101\n001110101000\n101011000011\n001011100000\n111111111111\n111111011110\n110001100001\n001000001111\n101000100100\n001011001001\n110110001101\n000100000000\n011100001101\n110011001000\n001111011101\n010000111111\n010110011110\n011110111011\n101111011101\n001100011000\n001011111001\n000110001011\n011011010100\n111110001011\n010000110111\n001100011101\n011110111001\n000010101001\n001110000001\n011111010101\n000010010100\n000101011001\n100100000001\n001111101011\n111110010011\n000111111011\n001101010110\n001100111001\n000100011101\n111010010111\n000100000001\n001011101111\n101001110011\n001011110101\n011000001101\n110011001011\n011110111100\n110110101000\n011010001101\n110111001000\n110010010101\n011010001011\n000011100111\n011000110001\n001100001111\n110010011010\n101100101100\n001100000110\n010101001111\n000011000100\n110001000111\n001001011000\n001001001000\n000010111101\n100101001010\n011100111100\n101000011011\n101011010111\n111001000011\n100100100110\n011001011011\n000011110011\n001101000111\n011010010100\n101010101000\n100010110000\n100001011110\n100000110110\n001011101001\n000110100011\n111000101010\n111001011001\n101111010010\n011100101010\n100010111000\n010100101110\n011001110000\n000010001101\n101110000111\n011011001111\n011110001000\n010010100011\n110001100010\n001101011011\n110100000101\n101110100111\n001110111011\n000110100101\n100100100001\n101000111100\n100011101110\n110010000101\n101100011001\n100000010111\n011100100101\n000010011011\n001011001100\n011001000000\n000101000101\n100001001100\n000001101010\n110111101100\n111001101010\n110000110111\n000110010001\n011100000000\n010000111010\n000101000000\n010000101010\n010011110001\n101011010101\n100000110111\n101001110010\n100011011100\n010011100011\n100000100111\n110100110000\n000100001011\n101101011000\n010110011001\n010110111111\n101110010101\n011110001101\n110001001000\n001001101100\n100111010011\n001100010011\n110101111001\n100010101011\n111010001110\n110001100111\n111000010010\n001000001011\n111001000010\n100100100100\n110010101001\n111101101010\n111111100101\n100010010001\n001010010110\n111101011000\n001010111100\n001001111110\n100010100110\n100001110100\n001111001101\n101100100111\n101101100101\n100101110111\n000111110111\n000111001000\n010101000010\n011000111100\n001001001110\n111101010001\n001011010101\n100011000111\n100000001001\n011100011110\n010111011011\n011000010011\n101101011110\n000000100011\n111110010010\n111010011101\n001000100100\n110101100001\n100101101000\n001110111111\n010001000101\n111110000101\n101000001101\n110101010000\n111110101110\n011111011000\n001001001111\n000101010110\n001100110000\n001111101000\n101000100101\n010000000010\n110011000010\n000000001100\n010000101011\n010101011011\n101011010100\n010001011011\n111100011001\n100000111110\n110001101010\n100111101001\n100110001110\n110001010101\n101100001000\n100001000010\n000110100001\n001010000000\n011111100000\n111110101111\n000001101001\n000000111110\n101111101001\n001010000010\n011110010010\n101111000111\n111110101010\n000100001000\n000111000000\n110010010110\n000001111110\n010110101010\n001010100011\n001111011001\n111001001111\n100100010111\n101100001011\n100111000110\n111010111101\n010001011110\n101110000011\n010111000010\n110110001011\n111010100011\n111100011101\n101101101001\n110100001000\n110001011001\n110010100001\n111110010110\n010100100011\n001000011101\n001011001010\n011100111011\n001111100110\n001101100110\n001011000001\n010100100110\n100100100111\n010100011011\n000101110001\n010110011111\n000001011101\n110101011001\n001101101010\n011111111010\n111001100011\n100001000111\n110110011111\n100101010001\n011100100010\n100100011000\n101111001011\n111001011000\n110000101110\n010100100101\n110011101000\n001101000011\n111101100101\n011010011011\n100110001101\n111001111100\n001000100010\n000101111101\n101110011000\n001011111010\n111100101001\n011000101001\n001111010111\n001100110010\n011000011011\n110111011000\n100100000110\n011010110000\n110111101111\n111000111101\n111111100110\n000101010010\n010101001010\n110100110101\n011011100101\n110110111011\n100010111110\n100110111010\n100011001010\n100100100000\n101000110110\n001010101010\n011001101111\n001110110000\n010001100100\n011000100100\n001011001011\n110111100110\n010110010111\n001011011010\n111100001010\n000010001100\n011010001111\n100100001101\n100010011100\n000010001000\n101001010000\n110101001101\n010110111100\n101001100100\n100000111010\n010000010001\n011101011101\n100011110010\n100100011111\n100011100101\n001010010010\n000110011111\n010000000111\n111001101101\n010011000010\n000001111010\n010010001111\n101011100001\n101100111100\n100001000000\n110111110010\n100110000111\n100000111011\n111010011110\n011011011011\n101011000110\n011100011001\n000101011100\n010000101111\n100010100001\n111000100101\n011010010001\n110110100011\n100000011100\n101110101101\n000010110100\n101011111110\n001000100111\n101001001010\n001111110101\n001001000010\n001100101110\n111000001000\n000000100000\n000100111110\n111111110100\n110101001100\n001100000010\n100011011001\n000110000010\n100010101101\n111110101011\n110100000000\n000100111001\n001111001011\n110111011011\n001111100010\n101111011010\n111010011011\n100111101010\n011011011001\n010100000011\n001111010001\n101010101101\n110000011111\n001111111111\n000110000100\n101111101010\n101011011101\n010001011010\n001001011011\n101011010010\n111010000010\n011100101000\n101001011010\n000111110101\n110011011101\n101010010011\n101100001111\n111001010001\n100100010110\n010100100001\n011110110101\n110100000111\n110101001000\n101000010000\n110000000011\n011111110110\n100001010100\n011111000101\n010010101001\n000111100100\n001010000110\n100100110110\n110010101101\n010001111101\n101100000000\n001100000000\n011111111110\n110001100101\n000111001100\n011101111110\n000100110000\n111111111000\n101110010001\n100111000010\n100111011110\n000100111010\n110101011011\n001000111110\n101101110110\n110110010011\n011010100101\n001010101111\n100110111001\n010001111100\n010110101000\n011000000000\n010001011111\n010101101111\n111001010110\n100001001011\n110000100111\n011100000001\n110101100000\n110010110010\n111010111001\n011010111000\n101100000110\n010100011111\n001010111000\n101100101101\n011000111010\n000001001100\n001111010010\n011010100000\n110100110111\n101101000100\n001110001101\n111001101111\n"
  },
  {
    "path": "advent-of-code/2021/inputs/04",
    "content": "99,56,7,15,81,26,75,40,87,59,62,24,58,34,78,86,44,65,18,94,20,17,98,29,57,92,14,32,46,79,85,84,35,68,55,22,41,61,90,11,69,96,23,47,43,80,72,50,97,33,53,25,28,51,49,64,12,63,21,48,27,19,67,88,66,45,3,71,16,70,76,13,60,77,73,1,8,10,52,38,36,74,83,2,37,6,31,91,89,54,42,30,5,82,9,95,93,4,0,39\n\n57 19 40 54 64\n22 69 15 88  8\n79 60 48 95 85\n34 97 33  1 55\n72 82 29 90 84\n\n19 17 62 78 27\n61 13 30 75 25\n14 66 72 37 79\n49 91 97  0 23\n12 52 41 92 18\n\n52 17 62 49 76\n 8 78 93 37 12\n 9 40 59 75 94\n45  2 81 44 63\n73 18 48 11 90\n\n59 75 55 74 43\n 1 17 89 36 91\n87 52 45 83 22\n 9  3 15 11 53\n94 72 68 29 20\n\n71 97 74 32 17\n31  5 43 83 38\n85 27 37 14 65\n23  0 61 33 82\n41 63 70 60  6\n\n58 24 28 42 73\n80 52 97 68 53\n30 40 45 18 13\n94 12  7 77 98\n72 14 34 21 23\n\n97 93 21 99 35\n31  8 73 15 74\n67 60 44  1 18\n68 61 64 82 86\n76 47 22 63 78\n\n49  6 93 20 95\n96 50 57 71 70\n90 42  7  2 27\n38 78 56 21 82\n55 98 72 40 66\n\n43  5 11 46 24\n30 45 91 50 72\n27 53  0 10  7\n15 35 73 96  9\n 2 67  1 17 32\n\n48 45 91 41 65\n72 63 33 49  8\n10 39 96 61 14\n26 58 16 74 34\n79 60 40 30 35\n\n71  0 52 48 32\n92 85 38 20 84\n68 24 13 74  2\n42 60 96 16 17\n59 67 69  8 65\n\n11 79 91 16 87\n82 39 77 24 32\n67 45 22 86 31\n84 56 54 55 75\n 5 41  3 70 40\n\n55 15 20 43 96\n63 47 13 18 91\n28 66 14 21 52\n59  9 12 97 58\n83 81  8 36 44\n\n 7 75 86 59  2\n47 14 87 19 49\n64  3 52 91 40\n11 43 35  1 44\n78 29 56  5 36\n\n46 32 44  4 30\n77  6 63 13 74\n71 23 53 56 27\n84 93 19 83 81\n16 97 99 34 92\n\n 6 87 56 63 39\n93 51 71 92 40\n81 14  9 26 24\n80 66 88 89 44\n18  1 29  7  8\n\n74 61  9 83 18\n57 95 79 35 47\n81 72 80 12 37\n 1  8 71 54 86\n40  2 97 19 17\n\n80 12 74 16 92\n99 26 49 79 28\n39 31 83 64 54\n14 90 42 96 81\n27 11 33 36 35\n\n80 26 21 49  9\n79 47 74 75 77\n78 16 89 55 43\n27 28 95 71 57\n81 36  0 87 66\n\n16 65 29 94  9\n71 56 39 30 23\n74 49  2 63 13\n54 45 48 66 64\n70 21 44 57  0\n\n16 72 74 15 79\n66 12 45 70 18\n44 51 98 11 26\n64 68 28 49 27\n48 69 52  7  2\n\n72 54 71 43 92\n83 95 58 36  1\n96 35 62 46 18\n16 29 30 28 21\n99 87  6 64 11\n\n61 34 54 25 91\n90 33 44 22 10\n58 37 59  3 28\n20 18 98 38  2\n95 99 69 50 14\n\n71 72 25 17  4\n70 37 92 85 51\n78 28 82 48 89\n12 52  7 13 21\n74 73 44 46 36\n\n21 99 48 77 34\n51 67 14 83 89\n 7 91 22 63 97\n 4 82 42 11 23\n 2 27 45 13 94\n\n83 23 72 22 24\n13 27 70 20 15\n 0 56 41  1 19\n62 68 75 21 67\n90 12 77 98 14\n\n56 63 78 71 51\n22 18 33 92 65\n89 12 45 82 73\n13 34 37 48 97\n42 85 54  4 53\n\n74 70 52 96 41\n93 36 73 81  4\n63 71  0  3 57\n51 54 94 25 24\n88 80 22 17 16\n\n 0 70 60 17  3\n66 80 73 84 99\n34 69 22 90 72\n15 41  6 39 76\n94  9 98 91 75\n\n17 20  4 19 79\n30 42  0 11  2\n37 28 95 14 71\n61 81 39 12 82\n33 44 69 29 26\n\n87 98 74 96 15\n 2 61  1 52 23\n49 81  0 99 69\n47 35 55 60 36\n94 19 29 63 53\n\n84 95 22 54 93\n98 94  7  5 30\n 4 46 28 68 90\n15 29 71 73 66\n42 44 45 82 10\n\n28 66 41 39 92\n61 63 27 40 38\n42 73 53 52 81\n62 78 96 82 51\n59 68 64 93 16\n\n48 49 51 85 12\n90 81 18 73 30\n67 46 38 60 17\n10 86 62 66 84\n98 36 99  8 45\n\n11 53 78 32 83\n94  0 80 67 37\n76  7 34 20  1\n12 25 73 71 28\n48 14 29 40 23\n\n35 98 14 33 11\n19 66 96 77 44\n32 50 15 49 70\n75 59 90 43 58\n23 45 78 18 95\n\n35 49 20 72 56\n12 70  3  5 58\n83 60 61 73 63\n45 78 98 95 19\n80 11 92 82 13\n\n69  0 37 63 41\n75 70 34 64 54\n10  1 59  9 65\n90 78 87 71 66\n74 35 29 58 20\n\n60 39 66 68 28\n90 64 36 93  2\n37 57 69 91 20\n73 96 50 86 77\n87 14 63 38 98\n\n43 89 14 74 12\n65 94 71  2 93\n76 37 96 47 92\n55 25 90 83 88\n79 11 59 50 81\n\n62 85 98 67 19\n79 17 71 53 93\n13 50 88 28 58\n36 20 52 66 27\n89 48 24 12 77\n\n73 13  3 97 16\n40 14  4 47 88\n12 79 56 80 60\n27  6 94  1 75\n72 22 44 62 24\n\n29 77 70 61 95\n63 57 41 12  7\n22 99 58 31 81\n15  3 48 20 36\n 8 76 87 23 91\n\n61 79 53 73 59\n67 34 37 54 15\n29 50 64 56 44\n93 51  0 18 17\n27 35 89  3 60\n\n79 23 31 48 12\n37 96 74 63  4\n98 18 69  6  0\n47 54 34 82 46\n 5 86 64 60 99\n\n44 70 50 53 62\n15 61 45 74 52\n35 48 99 12 49\n91 26 47 78  0\n58 82 94 73  7\n\n 2 64 81 48 83\n66 85 91 26 47\n50 95 70 54 13\n39 89 44 67  6\n22  0 40 21  1\n\n86 63 21 73 61\n91 33 68 66 36\n77 53 16 51 85\n11 57 12 22 80\n99 40  8 30 81\n\n27 35 60 28 95\n44 34  8 73 81\n11 26 90 32 10\n 0 49 98  7 18\n55 42 86 72 77\n\n16 15 65 86 88\n21 98 74 93  3\n18  7  5 35 73\n62 84 42 60 81\n48 34 39 57 99\n\n45 60 95 62 18\n82 86 99 39 77\n48 54 97 16 25\n40 56 23 47 37\n83 68 51 90 13\n\n80 72 81 78 69\n74 76 33 51 91\n54 86 60 35 17\n70 61 43 97 49\n21 26 28 85 57\n\n19 45 43 59 10\n46 20 44 67 94\n70 53 96 78 76\n17 18 54 39 38\n66 40 33 71 83\n\n 0 42 60 99 41\n14 96 75 93 74\n11 90 62 37 38\n29 64 27 53 85\n94 28 31 32 24\n\n14 19 83 98 53\n24 78 25 85 37\n39  2 41  4 32\n45 79 26 36 96\n64 80 73 13 28\n\n77  1  9 26 10\n37 60 69 72 81\n16 35 61 75 29\n42 53 82 67 36\n98 89 21 87 15\n\n45 73 88 75 46\n83 59 20 37 26\n62 42  9 78 17\n60 84 32 90 64\n40 99 61 80 48\n\n13 59 79 20 91\n64 65 21 82 44\n98 62 33 96 48\n46 37 40  8 70\n28 90 27 45 68\n\n48 94 58 96 81\n33 75 73 52 64\n23 36 67 27 54\n80 68 87 37  2\n34 47  6 30 60\n\n44 52 99 65 58\n77 78 68 48 94\n84 81 53 20 79\n14  7  3 46 42\n24 19  8 16 27\n\n42 89 86 46 83\n43 11 25 56 59\n69 82 65 55 34\n22 93 73 74  3\n26 30 60 29 45\n\n 9 43 72 89 42\n39 24 25 28 69\n 8 51 59  7 13\n64 94 30 99 65\n 2 56 55 38 15\n\n54 83 69 44 27\n52 25 17 20 28\n59  6 79 13 21\n34 14 61 84 67\n71 26 80 41 18\n\n96 33 72 16 93\n35 18 99 67 68\n47 27 32 94 12\n10 45 20 91 11\n66 52 15  2 13\n\n43 80  4 79 17\n89 66 20 82  3\n37 12 76 90 35\n52 77 63 48 44\n58  6 39 71 95\n\n68 56 49 17 61\n59 39 34 70  6\n75 13  4 26 41\n54 29  2 92 24\n65 31 60 90 72\n\n74 71 21 86 18\n63 30 53 73 48\n36 55 87 96 79\n32 89 49 81 83\n45 26 28 22 62\n\n59 47 97 77 75\n25 78 24 66 95\n63 16 93 22 32\n88 61 76 40 45\n18 28 51 55 20\n\n39 23 29 57 49\n22  6 74 71 25\n80 27 65 69 64\n41 21 12 58 95\n 5 43 11  4 36\n\n97 34 31 96 67\n86 24 30  6 69\n16 79 12 56 93\n18 35 58 90 11\n29 81 85 98 23\n\n16 40 59 19 87\n42 88 30 32 82\n17 93  1 50 56\n18 13 78 38 80\n51 14 73  8 22\n\n83 15 88 81  7\n99 51 13 92 31\n24 39  0 10  3\n95 72 33 73 44\n19 34 37 47 42\n\n67  3 65 91 32\n63 82 45 96 11\n33 78 66 43 83\n49 60 62 51 47\n34 48 26 27 54\n\n 1  0 53 40 28\n21 30 50 74 63\n48 49  6 55 57\n66 23 45 98 39\n95 54 86 38 90\n\n29 80 13 87 76\n75 10 43 95 83\n61 20 48 54 18\n21 37 63 68  2\n14 73 27 31 25\n\n17 70 57 33 22\n66 48 53 46 75\n74 73 84 63 14\n71 72 59  3 92\n43 30 94  8 69\n\n76 44 40 87 46\n13 83  0  6 17\n47 81 77 86 60\n38 23 55 89 82\n73 42 54 35 52\n\n13  1 45 96 89\n57 65 28 27 32\n22 26 46 86 10\n20 52 76 94 37\n92  0 64 55 16\n\n28 11 26 64 78\n15  7 75 96 61\n35 83 18  8 53\n57  1 13 66 79\n84 47  6 43 80\n\n25 80 70  2 59\n44 36 98 85 76\n87  7 42 83 94\n62 40 81 33 52\n10 65 14 60 26\n\n19 83 26 87 91\n23 57 40 36 15\n 1 54  8 49 31\n64  5 59 88 45\n69 18 58 11 62\n\n92 65 73 33 12\n13 30 18 66 11\n55 51 97 99 26\n57 31 71 49 41\n 6 95 19 35 25\n\n64  9 77 92 43\n88 80 75 58 32\n33 97 53 27 23\n85 14 35 42 45\n44 95 89 61 40\n\n22 68 27 75 76\n95 45 80 10 14\n24 19 71 11 50\n74 41 88  8  0\n99 42 13 90 77\n\n83 59 56  8 58\n30 73 67 82  1\n51 84 44 33 57\n76 16  4 13 87\n 6 95 72 27 38\n\n60 14 37 78 73\n80 40 58 30 64\n77 92 81  1 45\n79 26 11 12 51\n25 56 68 67 61\n\n 5 20 59  4 96\n 6 78 60 73 50\n88  7 48  2 35\n30 87 10 81 40\n 1 84 83 22 75\n\n20 91  9 21 59\n30 69 60 55 37\n63 57 77 12 45\n28 64 56 95 22\n33 84 92 48 86\n\n75 62 83 32 91\n93 44 22 84 76\n74 34 90 59 33\n78 54 71 12 25\n10 95 14 43 28\n\n48 36 10 85  5\n40 69 91 72 63\n37 22 55 94 93\n16 26 21 38 35\n31  2 52 20  1\n\n28 85  3  4 27\n77 18 26 50 62\n78 86 52 79 59\n58 48 54 64 41\n25  2 57 44 10\n\n15 35 22 41 26\n 2 39 88 69 84\n45 44 33 99 11\n91 20 85 32 46\n83 66 61 30 89\n\n14  0 97  1  7\n49 15 85 93 35\n73 90 61  8  6\n52 17 16 67 39\n91 84 25 24 66\n\n68  3 15 90 51\n59 62 11 61 83\n97 84 94 55 20\n71  8  1 70 73\n88 43 89 57  4\n\n61 30 53  8 70\n47 25  2 41 43\n99 65 96 68 66\n90 78 57 64 52\n42 95 48 40 86\n\n44 27  1 25 62\n92 81  5 11 40\n24 33 34 37  3\n47 28 94 58 26\n72 80 71 57  7\n\n54 55 73 99  9\n26 88 48 75 12\n65 84 71 85 96\n72 87 28 66 35\n89 63 15 44 69\n\n92 36 31 72 85\n33 93 69 65 84\n74 77 11 59 52\n 6 12 34 10 45\n63 30 55 46 15\n\n 1 59 15 45 75\n25 31 70 78 11\n36 12 34  8 79\n99 57 20 95 72\n23 50 19 73 22\n\n38 66 51 93 39\n12 96 99 36 97\n40 21 95 10 94\n 3 22 18 26 49\n91 61 73 70 47\n"
  },
  {
    "path": "advent-of-code/2021/inputs/05",
    "content": "194,556 -> 739,556\n818,920 -> 818,524\n340,734 -> 774,300\n223,511 -> 146,434\n841,47 -> 122,766\n323,858 -> 859,322\n277,205 -> 85,205\n782,901 -> 782,186\n969,96 -> 969,648\n504,971 -> 989,971\n926,151 -> 926,480\n722,895 -> 722,488\n15,14 -> 987,986\n378,486 -> 267,597\n732,418 -> 157,418\n252,515 -> 257,520\n61,828 -> 659,230\n116,652 -> 893,652\n827,196 -> 827,564\n677,515 -> 677,257\n380,897 -> 132,897\n812,959 -> 812,23\n989,382 -> 294,382\n973,89 -> 81,981\n292,920 -> 987,225\n441,394 -> 441,469\n502,662 -> 502,213\n609,570 -> 609,58\n559,47 -> 208,47\n77,192 -> 277,192\n229,588 -> 66,588\n705,363 -> 705,161\n944,51 -> 78,917\n699,889 -> 699,354\n90,48 -> 955,913\n166,491 -> 24,633\n154,482 -> 113,441\n989,989 -> 10,10\n421,414 -> 791,44\n360,272 -> 966,272\n264,631 -> 630,631\n541,50 -> 541,911\n17,475 -> 289,203\n226,772 -> 697,301\n163,625 -> 163,513\n642,971 -> 642,754\n975,329 -> 793,329\n793,878 -> 793,938\n10,95 -> 175,95\n352,903 -> 352,176\n914,92 -> 91,915\n649,768 -> 649,136\n347,492 -> 347,977\n372,839 -> 372,741\n587,534 -> 526,534\n563,936 -> 102,475\n126,708 -> 362,708\n326,869 -> 326,640\n358,959 -> 358,408\n221,99 -> 221,659\n572,405 -> 906,71\n592,664 -> 687,759\n618,457 -> 388,687\n712,850 -> 245,383\n981,22 -> 45,958\n107,884 -> 340,651\n17,896 -> 642,896\n488,135 -> 851,135\n54,76 -> 184,76\n290,596 -> 290,478\n468,427 -> 468,316\n412,434 -> 412,581\n899,681 -> 238,20\n647,231 -> 542,231\n54,374 -> 302,622\n586,555 -> 13,555\n875,930 -> 26,81\n875,115 -> 127,863\n863,42 -> 45,860\n708,862 -> 100,862\n190,490 -> 26,654\n347,944 -> 711,580\n259,533 -> 259,516\n833,790 -> 891,848\n556,583 -> 921,948\n745,929 -> 745,569\n111,100 -> 499,100\n638,903 -> 525,903\n726,388 -> 973,388\n335,504 -> 638,504\n628,29 -> 159,29\n375,406 -> 200,406\n12,819 -> 945,819\n660,330 -> 318,672\n436,477 -> 436,988\n925,41 -> 464,41\n868,485 -> 868,109\n130,859 -> 979,10\n895,50 -> 895,568\n582,943 -> 582,904\n589,616 -> 589,590\n773,359 -> 441,691\n396,22 -> 396,730\n862,947 -> 30,115\n573,543 -> 40,10\n726,743 -> 726,934\n360,170 -> 360,187\n597,287 -> 982,287\n537,112 -> 838,112\n702,683 -> 151,683\n770,792 -> 752,792\n964,60 -> 896,60\n53,642 -> 278,642\n414,871 -> 798,487\n96,950 -> 96,983\n251,65 -> 289,65\n797,666 -> 797,200\n582,157 -> 582,538\n107,398 -> 594,885\n96,66 -> 806,776\n124,911 -> 347,911\n974,538 -> 974,318\n45,966 -> 226,785\n39,960 -> 827,172\n163,939 -> 709,939\n351,540 -> 351,954\n656,894 -> 220,458\n278,314 -> 278,146\n637,784 -> 637,283\n83,690 -> 899,690\n16,48 -> 884,916\n681,865 -> 310,494\n333,631 -> 333,832\n527,652 -> 527,836\n352,343 -> 352,623\n256,316 -> 479,93\n450,86 -> 489,86\n814,834 -> 814,494\n406,947 -> 783,947\n811,643 -> 318,643\n240,651 -> 366,651\n902,618 -> 303,19\n843,939 -> 729,939\n901,149 -> 131,919\n365,459 -> 222,459\n909,218 -> 426,701\n746,415 -> 746,199\n249,327 -> 807,885\n760,923 -> 860,923\n506,259 -> 506,357\n933,892 -> 143,892\n88,589 -> 88,77\n597,554 -> 810,554\n505,574 -> 505,812\n211,786 -> 906,91\n387,238 -> 480,238\n394,729 -> 422,757\n526,436 -> 526,12\n660,397 -> 660,290\n856,469 -> 176,469\n653,731 -> 370,731\n542,241 -> 542,32\n471,734 -> 471,384\n975,468 -> 783,468\n25,578 -> 580,578\n52,632 -> 551,133\n150,791 -> 672,791\n643,348 -> 643,869\n893,514 -> 893,422\n400,463 -> 335,463\n564,917 -> 676,917\n166,433 -> 166,246\n798,36 -> 69,765\n118,977 -> 882,977\n718,415 -> 75,415\n690,807 -> 690,659\n163,809 -> 269,809\n715,238 -> 715,314\n970,924 -> 104,58\n683,762 -> 683,467\n554,375 -> 980,801\n361,130 -> 361,66\n879,491 -> 879,843\n515,700 -> 515,454\n465,432 -> 465,444\n250,239 -> 216,273\n894,818 -> 163,818\n190,790 -> 190,616\n384,263 -> 384,84\n63,875 -> 851,87\n154,293 -> 278,417\n21,592 -> 883,592\n372,286 -> 588,70\n972,447 -> 972,639\n838,60 -> 681,60\n38,366 -> 38,907\n746,65 -> 459,65\n138,640 -> 66,640\n536,309 -> 536,109\n772,634 -> 772,566\n43,949 -> 945,47\n914,85 -> 395,85\n25,12 -> 977,964\n679,455 -> 679,439\n420,492 -> 614,492\n823,658 -> 823,634\n45,332 -> 45,943\n807,344 -> 807,756\n634,974 -> 634,892\n26,26 -> 988,988\n628,772 -> 15,772\n829,614 -> 550,614\n513,649 -> 513,369\n607,923 -> 607,801\n809,340 -> 450,699\n550,193 -> 666,193\n175,961 -> 902,234\n467,146 -> 500,146\n543,510 -> 543,626\n667,52 -> 667,161\n635,299 -> 375,299\n278,807 -> 904,807\n269,290 -> 644,290\n630,268 -> 630,440\n241,929 -> 882,288\n864,907 -> 360,907\n455,894 -> 455,265\n257,43 -> 257,519\n414,83 -> 360,83\n237,64 -> 237,612\n260,541 -> 260,927\n323,909 -> 323,583\n929,354 -> 929,695\n912,914 -> 40,42\n579,401 -> 392,401\n389,222 -> 895,728\n831,696 -> 831,707\n871,304 -> 212,304\n207,333 -> 621,333\n225,897 -> 355,767\n883,68 -> 84,867\n115,397 -> 115,208\n889,217 -> 985,217\n793,402 -> 250,402\n555,367 -> 61,861\n732,954 -> 466,688\n39,564 -> 39,481\n283,816 -> 346,816\n383,506 -> 276,506\n394,661 -> 394,143\n988,983 -> 66,61\n652,638 -> 652,569\n185,64 -> 487,64\n354,935 -> 251,935\n201,460 -> 201,552\n836,285 -> 836,666\n878,312 -> 359,831\n443,684 -> 887,240\n221,49 -> 948,776\n243,959 -> 22,959\n573,323 -> 834,323\n745,734 -> 456,734\n594,244 -> 908,244\n583,360 -> 578,355\n288,38 -> 288,364\n565,339 -> 251,653\n215,196 -> 215,476\n270,705 -> 586,705\n749,477 -> 749,658\n917,838 -> 511,432\n935,187 -> 935,381\n181,190 -> 323,48\n399,491 -> 399,779\n861,798 -> 91,28\n160,115 -> 58,115\n940,68 -> 940,590\n806,958 -> 35,187\n184,538 -> 438,284\n283,904 -> 283,114\n344,935 -> 222,935\n435,962 -> 367,962\n837,768 -> 837,583\n100,423 -> 826,423\n299,172 -> 465,172\n130,136 -> 181,187\n969,759 -> 55,759\n936,711 -> 521,711\n268,619 -> 349,619\n946,119 -> 108,957\n940,25 -> 10,955\n867,494 -> 652,279\n535,202 -> 321,202\n876,14 -> 24,866\n887,208 -> 887,265\n129,12 -> 42,12\n514,800 -> 940,374\n722,306 -> 722,418\n24,928 -> 935,17\n798,279 -> 798,293\n384,701 -> 193,701\n100,644 -> 593,644\n818,48 -> 216,48\n51,984 -> 949,86\n843,494 -> 843,723\n809,156 -> 129,836\n500,38 -> 656,38\n311,705 -> 311,101\n21,850 -> 21,316\n530,628 -> 511,628\n106,366 -> 415,675\n542,882 -> 325,665\n987,937 -> 987,793\n926,260 -> 264,922\n768,149 -> 914,149\n548,71 -> 548,812\n51,946 -> 812,946\n430,439 -> 954,963\n529,301 -> 133,301\n282,890 -> 720,890\n876,231 -> 336,771\n489,471 -> 934,471\n585,174 -> 100,174\n284,489 -> 163,489\n989,983 -> 33,27\n31,213 -> 662,213\n133,832 -> 559,406\n730,345 -> 730,194\n860,288 -> 736,412\n110,351 -> 581,351\n417,151 -> 77,491\n674,671 -> 674,711\n514,867 -> 514,100\n885,595 -> 885,680\n44,31 -> 928,915\n969,347 -> 69,347\n597,227 -> 357,227\n347,443 -> 347,216\n781,736 -> 781,93\n968,559 -> 968,81\n35,93 -> 232,93\n273,837 -> 97,837\n949,833 -> 748,632\n712,773 -> 221,773\n194,884 -> 978,100\n217,816 -> 217,861\n651,122 -> 71,122\n166,551 -> 166,892\n285,193 -> 883,193\n858,934 -> 125,201\n180,190 -> 577,190\n491,685 -> 690,486\n666,598 -> 337,269\n455,571 -> 753,571\n11,769 -> 11,507\n391,663 -> 323,595\n70,740 -> 70,928\n205,525 -> 534,854\n890,851 -> 151,851\n382,662 -> 849,195\n201,870 -> 201,506\n549,549 -> 549,528\n343,172 -> 601,172\n22,732 -> 750,732\n221,689 -> 881,29\n628,559 -> 747,559\n668,879 -> 437,879\n712,139 -> 38,139\n547,322 -> 905,322\n872,304 -> 719,304\n469,604 -> 389,524\n256,91 -> 746,91\n881,548 -> 641,548\n683,417 -> 683,800\n811,917 -> 646,917\n578,556 -> 207,185\n732,343 -> 260,343\n86,869 -> 882,73\n370,587 -> 765,192\n649,621 -> 649,165\n298,339 -> 298,523\n131,771 -> 803,99\n934,791 -> 934,29\n782,13 -> 782,741\n852,808 -> 852,594\n390,217 -> 153,217\n858,980 -> 94,216\n832,467 -> 783,418\n188,49 -> 981,842\n438,467 -> 76,829\n47,911 -> 164,911\n670,414 -> 533,414\n58,61 -> 740,743\n264,686 -> 264,799\n506,300 -> 64,300\n509,717 -> 509,952\n81,819 -> 81,694\n512,543 -> 427,543\n235,78 -> 788,78\n952,133 -> 644,133\n188,302 -> 695,302\n272,868 -> 845,295\n288,413 -> 704,413\n774,671 -> 774,24\n296,932 -> 296,16\n99,789 -> 300,789\n630,560 -> 630,896\n328,289 -> 280,289\n786,772 -> 294,280\n437,747 -> 437,110\n537,709 -> 42,709\n655,924 -> 655,117\n185,65 -> 963,843\n70,87 -> 274,87\n516,727 -> 183,394\n322,128 -> 781,587\n147,278 -> 482,278\n188,793 -> 761,793\n702,441 -> 702,27\n686,18 -> 686,275\n510,254 -> 510,862\n666,204 -> 12,204\n677,63 -> 677,78\n868,950 -> 868,110\n42,845 -> 739,148\n343,279 -> 758,279\n182,792 -> 727,792\n346,238 -> 493,238\n467,493 -> 467,273\n823,68 -> 823,886\n686,302 -> 39,302\n984,345 -> 984,936\n11,480 -> 11,675\n989,478 -> 695,772\n568,235 -> 535,235\n203,41 -> 93,41\n463,569 -> 304,569\n909,629 -> 207,629\n792,678 -> 792,909\n486,924 -> 486,948\n611,79 -> 611,303\n762,136 -> 139,759\n808,872 -> 726,872\n22,403 -> 22,401\n774,134 -> 369,134\n131,282 -> 131,849\n912,245 -> 912,385\n338,396 -> 768,396\n944,978 -> 20,54\n623,897 -> 623,10\n103,402 -> 207,298\n39,50 -> 971,50\n770,423 -> 882,423\n195,873 -> 195,40\n119,659 -> 119,374\n678,962 -> 698,962\n946,64 -> 946,202\n790,780 -> 790,66\n565,21 -> 614,21\n617,20 -> 640,20\n697,773 -> 697,915\n467,167 -> 208,167\n567,713 -> 567,873\n120,98 -> 557,98\n103,395 -> 103,159\n148,734 -> 723,159\n730,949 -> 730,33\n322,628 -> 322,272\n649,57 -> 44,57\n261,513 -> 624,513\n550,414 -> 738,226\n774,183 -> 471,486\n146,659 -> 146,581\n599,751 -> 599,320\n936,225 -> 226,935\n378,31 -> 222,187\n871,691 -> 502,691\n195,963 -> 335,963\n513,465 -> 382,334\n620,801 -> 673,801\n187,428 -> 318,428\n572,836 -> 441,836\n305,398 -> 305,951\n978,703 -> 927,703\n99,219 -> 846,966\n952,971 -> 26,45\n859,775 -> 859,663\n144,777 -> 144,390\n792,859 -> 441,859\n513,672 -> 982,203\n613,342 -> 671,400\n802,498 -> 811,498\n197,240 -> 197,216\n45,908 -> 881,72\n860,573 -> 12,573\n817,145 -> 755,83\n565,562 -> 660,467\n918,952 -> 918,111\n936,174 -> 936,97\n630,759 -> 630,89\n329,762 -> 608,762\n"
  },
  {
    "path": "advent-of-code/2021/inputs/06",
    "content": "5,1,2,1,5,3,1,1,1,1,1,2,5,4,1,1,1,1,2,1,2,1,1,1,1,1,2,1,5,1,1,1,3,1,1,1,3,1,1,3,1,1,4,3,1,1,4,1,1,1,1,2,1,1,1,5,1,1,5,1,1,1,4,4,2,5,1,1,5,1,1,2,2,1,2,1,1,5,3,1,2,1,1,3,1,4,3,3,1,1,3,1,5,1,1,3,1,1,4,4,1,1,1,5,1,1,1,4,4,1,3,1,4,1,1,4,5,1,1,1,4,3,1,4,1,1,4,4,3,5,1,2,2,1,2,2,1,1,1,2,1,1,1,4,1,1,3,1,1,2,1,4,1,1,1,1,1,1,1,1,2,2,1,1,5,5,1,1,1,5,1,1,1,1,5,1,3,2,1,1,5,2,3,1,2,2,2,5,1,1,3,1,1,1,5,1,4,1,1,1,3,2,1,3,3,1,3,1,1,1,1,1,1,1,2,3,1,5,1,4,1,3,5,1,1,1,2,2,1,1,1,1,5,4,1,1,3,1,2,4,2,1,1,3,5,1,1,1,3,1,1,1,5,1,1,1,1,1,3,1,1,1,4,1,1,1,1,2,2,1,1,1,1,5,3,1,2,3,4,1,1,5,1,2,4,2,1,1,1,2,1,1,1,1,1,1,1,4,1,5\n"
  },
  {
    "path": "advent-of-code/2021/inputs/07",
    "content": "1101,1,29,67,1102,0,1,65,1008,65,35,66,1005,66,28,1,67,65,20,4,0,1001,65,1,65,1106,0,8,99,35,67,101,99,105,32,110,39,101,115,116,32,112,97,115,32,117,110,101,32,105,110,116,99,111,100,101,32,112,114,111,103,114,97,109,10,161,185,311,752,668,728,210,741,636,381,1222,509,282,156,806,624,31,300,711,128,146,368,306,239,7,519,441,368,179,155,704,274,237,710,164,55,217,1007,0,701,812,713,127,536,320,163,454,310,726,433,426,102,1350,736,408,951,307,15,333,462,755,797,265,540,680,357,914,195,468,1034,583,413,1293,450,88,2,208,1006,336,98,17,164,95,455,511,113,710,636,308,330,479,62,197,591,390,148,933,1060,10,564,137,422,1756,494,1205,79,13,1257,205,738,245,462,313,249,1580,929,914,512,370,152,413,6,223,197,777,885,1387,52,824,1308,422,728,298,123,922,234,33,109,747,231,916,1452,432,397,222,857,113,119,437,1474,129,1214,69,595,347,293,885,363,72,315,77,1131,55,1541,1244,37,724,553,65,327,341,619,800,547,104,33,272,1557,1316,141,476,510,505,188,1734,175,52,222,1392,732,303,959,75,432,224,293,112,99,923,396,1069,241,246,1146,823,961,593,367,394,324,390,20,63,403,602,571,125,649,60,327,190,1661,140,486,420,833,1464,218,80,74,345,366,191,119,109,399,1596,431,445,1179,1195,144,136,51,215,19,106,998,664,89,49,1041,101,814,995,279,810,702,738,471,315,217,60,24,272,490,7,1294,322,594,804,165,130,125,18,1422,208,0,148,544,901,1530,50,207,364,904,197,585,153,536,1014,571,1086,782,727,125,1174,453,1773,0,106,790,634,385,39,91,599,48,98,128,562,595,901,1269,108,219,583,162,101,182,645,371,17,872,73,156,313,243,678,75,727,566,282,193,28,75,576,394,176,132,172,27,758,496,57,32,73,1791,208,1660,429,38,1518,419,1748,52,1193,353,175,198,186,105,195,75,867,380,417,341,574,628,1076,116,1441,1353,528,530,205,0,1434,827,556,493,884,172,187,441,182,227,954,1016,3,336,786,947,155,373,52,26,969,686,837,477,8,31,288,952,574,159,511,351,440,774,948,213,45,773,294,75,742,300,686,395,315,1658,264,119,28,993,392,99,759,384,317,1105,562,324,416,375,938,329,988,1334,439,1284,557,28,225,438,216,501,358,743,206,1150,378,30,850,1149,296,279,132,387,64,895,157,528,138,12,688,1045,153,42,54,1281,535,427,297,1037,253,68,424,428,205,138,93,82,383,93,1061,1116,287,888,204,777,35,548,784,268,897,1167,201,532,151,198,388,3,306,1689,555,207,852,723,173,655,535,963,46,54,1705,490,244,67,299,543,333,185,196,361,147,891,370,797,195,386,371,1111,156,1587,641,1252,430,40,715,930,1560,774,227,122,179,45,72,744,27,6,1479,1178,969,108,395,37,31,426,1131,495,246,36,63,121,286,594,856,2,1773,1724,5,421,51,344,1312,382,24,15,246,921,562,20,818,493,44,239,1047,368,37,245,245,851,35,2,442,792,235,516,450,282,812,510,161,731,788,93,475,205,222,1005,1002,358,860,875,1330,354,724,114,207,956,597,234,206,55,637,7,48,751,123,241,858,255,508,200,1064,79,169,85,768,255,21,708,340,145,385,1130,281,39,1072,100,285,1355,360,283,560,153,488,689,319,929,309,1013,95,88,843,208,126,146,3,328,75,251,18,1053,782,556,94,743,299,66,311,18,789,1323,45,777,281,75,676,741,340,1055,870,1935,203,80,93,1372,747,6,79,560,33,67,1,197,193,1245,40,466,1144,557,16,664,144,984,590,1105,165,131,41,455,77,33,572,477,854,18,157,48,453,487,25,423,181,800,615,25,374,183,380,262,219,81,466,691,119,754,122,918,920,410,1102,156,1355,101,395,1837,89,40,341,264,393,547,564,480,13,24,259,1054,19,390,1199,664,205,645,274,43,115,354,329,473,812,1302,771,308,94,838,593,942,1107,153,394,596,194,119,719,1392,1094,26,252,1276,162,310,23,1681,106,160,1206,509,684,432,1659,129,172,99,630,417,151,69,211,874,310,1109,740,589,496,508,742,407,1156,1920,209,218,375,468,971,705,68,1603,158,236,121,63,1615,822,198,322,946,368,128,231,125,125,41,278,574,359,28,20,322,785,382,990,266,1586,324,710,159,727,28,11,15,211,620,762,73,1,75,33,239,327,1105,228,4,1256,1578,729,1164,44,222,1177,186,1593,605,43,239,1353,877,300,75,54,324,1487,1655,715,597,540,202,266,1030,576,251,14,669,833,66,1285,170,109,433,1760,60,948,542,129,5,165,173,659,743\n"
  },
  {
    "path": "advent-of-code/2021/inputs/08",
    "content": "febca cfagb ecbafd efdcbg cbegdfa fg bgafec gfae acgdb gfc | cgf facdeb ecgfdb afcbge\nacbed dcagb cfbega ecgdab be deafc bfgdca abe edafgbc debg | dceab dgbca gedabc fecabgd\ndecfb bgadec dgefa bcgfade cae adecf ca eacfdb bcaf dfgbec | bfca fdacbge cedfb dfebac\negd agdcfe gedbfa gbcfae ed dafgebc bdcgf gdbfe fgabe dbae | cefbga egfcba dbfeg ed\nbfeca beadgc gdfeacb aebcfd eg aefg cgefab ebgfc gbdfc beg | bedacf eg dabegc bfeac\nfcd fd fgdceba edgac cegdbf gcafdb agdfc cafbg beagfc dfab | dacbfg gfacb fcd fd\ncfbgeda gdfae abdfg dfceg edagfb geba bfcaed fcdbag ae aef | dcbefa dagfb dcefg abgdef\nedafbg ebg gbdea cdbefga bfgcea ge egdf aedcb gfadb gbcfda | degbaf dbgafe ecdab dagbf\nadecfb aebdc ab efbagd cfbed cagde baecgfd egdbfc bad bcaf | cbaf beadfgc febcd gaecd\ngfdacb bgdace gb cdfbg fcbde fdgeac bgfa dgb acfgd bdcefag | bg dbegac fbdegac agfb\nbfdace bdcfa ebcag egcdbfa dbg dg fbegdc bcgda fgabdc gfad | cadgb abcdg eagbc dagf\nbed faegcb fedcba dgbcea feabc cdefb bd bcdfgea edgcf afdb | dgcfe adfebgc ebgcad cfebd\ncfead dc dagef gfdc cgdefa acdbeg cad egfabcd bgeafd aecfb | dafge fdgeba faecd cbaef\nafgbde gebca ecbdaf caedb faceg abgcedf cdbeag cbdg bg agb | bg bcaed aecgb cgbae\ndfab dfgae bcafge cbefagd fdbeg fa fea fcbdge aegcd bdeagf | gfaedb af acbgfe faecgb\ndecafg cadef fadecb dfeba aecbgd gefbd aeb ba ebfgdca abfc | gbfaedc bdefg acbf gcafde\nefgbd efdacg cd gefcd becagf dgc edca egdbafc cegfa fgdbca | eacgf bgafcd bfaegc dc\ngabed gdacfe egabcdf cdaf fdg acgfe fgdea gafbce degbcf df | fcaeg cefag bfegdc dfg\ngd badgcf cdg gbdcae cbdea dgfceba bfadec gdbe geadc acefg | gdc ebdg dg aegcf\ngbae fedcag bg ecgbda bfecd dcage fecgbda bgdce acfdgb gbd | cbgafd edcfb dbg bedcg\nabcgdf cfgae cebag gedbafc dcgbae abg decfbg gcebd ab dabe | gdbeac ab ab dcfbga\ngab efgbd gbcfad edgfac ba gaced dgcbae edbag fcgedab aecb | gfdace adebg ba cgbdfa\nacebg aedbfg deca ad dcaebg cgfbd abd cdabg dbecgfa agfceb | ad fadegb dcae cbfgd\nfdagcbe ebgdac ecfgbd fbc fc cbged fbegc cdef cfdgba agbfe | bfgce begcf cdfe cbf\ncbd fadgb dceag cb gfadeb begfcd cafb cgfdba gbadc cegdbaf | bdc bc adcbfeg dgace\nbgdefca cbgadf ebacf dfbac gedcfa cef fe gcbae fbed fcdbae | fe cadbfe ebfgacd cdbafg\nacfde cgeabd cag gfcb adgfc fdgbae fbdag cgefabd dgbacf cg | fgadc dcbgae ebdagf gbacfed\nebdcg cfdbage cefbag cb ecb dabc cagdeb gbefd afdcge adegc | dgbafec dcfgea dgbef aecdg\nacd bfcged aedgfcb afdbce efcdb cfdae cbae cdafgb gdefa ac | aceb ecbgfad bdaefc efbcd\ncebd aefdgcb bafecg bfagd adfecg dcgab gcd cd ebcadg cebag | cdg cdg gcdba dafgec\naecgbf bgfae gbcfeda fba abce gebfcd ab gcebf gcdfab gdafe | begcf baf baf fbgcae\nacdgfb bgedfa cbadfe degf gbeac gd adg dbgcaef abged febda | dg dg ebdfca fgacbd\ncfb fbdgac gcdaefb dabec fbcda fagbd cf cdgf bacfge ebfagd | bcdae bgdeafc acegbdf cf\ncaegdb acgbf abdcgf fgebd afcd cd ecafgbd gcbdf dgc fbgace | acfbg efacdbg bcfgd fbcgad\neab fecbdg dcfab fdcgaeb gdebc cegadb bcaed bfgace ea aegd | ea bfadc bcgdae becfag\ncg fdbeg eafcb bcefda cabfdeg cbfgae bfecg bagc gec dfgaec | bagc ecg cg abcg\nceafg dgeab ecd fcbedg edcgfa agdbfce dafc bcfage agcde cd | ecdga gecad cdaegf dafc\ngedcf bcad abcfgd bd dcfbg bfgac fecgab bfd efgdcba faedbg | bd bd dacb cfgbd\ndcgfab fabed decbf gebcdf da efbag deca acfbegd dba fadcbe | ad abgef efdba debfc\ngadcfe gefdbc faced cfa geac afcgbd efbacgd ac cgdfe baedf | ca afc fcegd gedfca\ngefca ecdagb bg ebadf dbfg eagbf fbegdca cefbda beg fbedga | gb fabge gaebf ecbdag\nabd gdecbf da ecfbd afgbde ceda abdcf dfbcgae dbacef facbg | dafcb bda dgaebf gfabc\nafbegc cdgea aedfbg cgdb bgcaed egcdbfa cfeda cg dagbe gec | agedfb fabdge fegbda ecg\nac acdbge dgbefa abc dbecfa cabgefd fegbc fbace eadfb fdac | ecbaf ca cgebadf afcd\nfdgcb cebf dcfbge cbdag gdbef acgdfe adgbecf fgc badfeg fc | ebcdgf cfg bgdac gfdeab\ngefc ecadgb efcabdg fca ecgad fc ceadgf bdfacg afebd cdaef | fca bgdeca efbad cf\ngcbfd ecdbf cfdgab gacfb dg gbda efcgba gfd egdcaf ebcadfg | gd gbacf facgb fcbed\necfa edfgcb bgdae abcdef ac debfc cad acbed febdgca bfcgad | edabc ca acd eadbc\ndbceaf cbagfe bdcgae bdc cdag debgf abcge bdgcaef dc cdebg | bdface gadc bgaec cebgaf\necf dfbae aecbf gabcf bfgdca cbegfd ec gcea cebfag cedabfg | afdeb efbca dbfea afbcdg\nbdagcfe gd debgca dgfc gbaef adbfce fcdbga gad dabcf fbagd | gdbeca dga cdbafg deabfc\negabfc fdeb dcbae cfdea aeb be dabgc abcdef cagedf fegbacd | bdfe cedfag edbf gaefcd\ndecfgba efgdc befdc dcabf ebc gbacdf acgbfe abedfc be deba | fdebc bec eabd fdagceb\nefbag gdae dgcbaef cdfbge gbfed gdcabf fedgba bag ag acebf | gbedf bafdcg cabdfg dgcfaeb\ndcfb agcdb aedfcg gfbdae fbgad dac cbeag dfbecag dc fdacgb | cagbe gadfbe dcfbga bgcad\ngefcb edcfg bega befdac bagfec cadbegf bce bcfag dcgafb eb | gbceaf bgcfa acefgb abfcg\nbgfce agbfc fga dabceg bdagfec afdcgb gcdba adfc fa baefgd | gfacbd fa agf gacbde\ngbfa bef bgeda cbeadg begdf gfcdaeb egcdf dfcaeb bdfage fb | fb dfbeca gfecd abgf\ndbfeac ecbfg ec dceg afbdcg gefbcd dbcfg geafb ecb bdegfac | fagdebc cadgbf gbdfc ec\nfgdbe beadfgc dfeab gbaf gf gdefca degcb aefbdg facbed gfd | fdcgae dgfbe fgd bfdae\nbaecfd aeb cfae ae dgbaefc facdbg fbgead gbced bfdca bdeac | afce caef ecbda ea\naedgb agf abefgcd fabgd afgebc faed dgfaeb bgfcd edbcag af | af adefgb adfe abdgec\ngdaecb gbcad gbcae cgfabd ebgfc ea bagcfed gae dbfage cdea | abdcg gadbc eacd adbegc\nfcdbe febacg gcfd egf ebgdf fecgdba cfdeba gf agbde fbcdge | gfe abged efg cdfg\ngb gdceafb bceaf cebgfa aedbcf fgb acgfb fcdag eagb cfbdge | efagbcd agdcbfe fbdegc abge\nebfac cbeafg df dcbag acfdbe cfdbeg dfb gecfadb feda fdbac | gdcba gedfbc gedabcf cagbd\ncbfdg gbacf gdab bcdfeag dbf fgdec cfdabe dgbfac fgaceb bd | dcefba fgdce edfcg bafcg\nec dacfeg aebc dfaegb eagdb gefcabd aedgcb dbcfg dec egbdc | fbadecg dfecag efgcdba dfbaeg\ngafbdc cbafde cfgebd gabcd cebag ad cad cafdebg bcgdf dgaf | fagd efcdbg acd bfdceg\ncde afebcdg bagcd ce fagedb dcfgea afbced efcg cgeda gfdae | acedbgf cabfed cefg dce\ncabg geabf gfbeca dfgea gfbeacd dgfceb gbe dcbeaf befac gb | agdfe dcfeab adefg eafgd\ndebgacf edgab agedcb fdega ab cadfbg bad cbea bgecd dfbcge | adbge dabegc fagde abd\nbdefac afgbc abcef ce bdefga dfbea cef bgdfaec ecdb agfced | dcbe caebfd dgafec acbgf\naecfbg gdaefc becgadf bdgfa cg efbcad decaf fcg acgfd edgc | cfbdgea cg cefdga cfg\nfd dgfcaeb fedg dcgbe bdgecf bfcde abcfdg dbf becaf bgeadc | cdgbea df egdcfab cdbfe\naedcfb bdecg bcdefg cd fbadcge edc gdcf gbdef bfagde begac | befadc bfeadg fgdbe dc\nde cgadf gde gecfb egfbac bfde dcabeg ecbdgf efdacgb dcgfe | defb bgefc ged cbagfe\negdfba cdafbge gfa dfgab cbdaf becgad bcgafe gfde bagde fg | bfcedga bacgde geabd cfbda\nbacgfd gec cbfeadg gdeaf afceg ec dagecb gacbf egafbc cefb | abgfcd fdabcge egc abcgfe\nedbgac fecbg adcgef fdbgc cbaeg feab bceafdg cgbfea fe efg | abfe fdbgc aebf cgadfe\nafbdcg dacbf cdbgf acdfe ebafcg ab beadfcg cfgbed cab dbag | becfgd abcdf bdcfaeg egbadcf\ndafceb gebfad cebg gbdfeac dfcga dgbac acedb gbd ebgcda bg | deabcg bcgade egcabd bdcafe\ngfa agcfe fbcae cedbaf cdfge ga gcfaedb afbedg cgba bgaefc | bagcfe ga fbace fceba\neg cbaefgd dagfb adcbeg aeg cefabd bgec dgeafc abdce dbaeg | fcagde bdcage gabfd acdegb\ndfeagcb ebf eagfc gbefac cgdfea dbfag eb dcbafe gecb egfab | eb dgafb faecg eafdgc\nbefdc gfbceda ecdgba bfdacg cde gecfb deaf bedafc ed cbdaf | becfd bdacgef eacgdfb gbdace\nagdb cdafegb cfabd cedbgf cdafeb fbgac bgc gb adcgbf faegc | cbgadf dabg fgeca cbgfa\ncfeabg cfeab fbge gcdae fgc aefdbgc gf gaefc dcgfba ebdfca | abefc cgf fbdaecg bafce\ncbfgda ebfdcg dgbfa bd fgdca abecgdf dgb cegfda bgfae cbda | gdcaf fdgab cbfaedg cgaefdb\nef cbfgae abcdf adecfbg gacbe abecf agdbec ebgf dfceag cef | efc ecf dcbaf cbaeg\ndgcaf bgfd aebcd ebacgf cdafb fdabecg bdafgc adecfg bf fcb | afcdb fcadg fcadg adgefc\nafcgeb fdgc bcaefdg egacf ged gd faebdg cdaeg badce cfaged | cedba egcbaf dfbagce eagfc\nedgaf aegdfc dgcfba befdag cd cafdbeg cged facde eafcb fdc | gebfad gefda fcd agdfe\ndebfa dcgbefa gdcbae cdfbae ab bdcegf cebfd bea cfba agedf | fgecdb bcaedg feagcdb fecbd\nabfecg fdegca dag cead dbfge gaedf da afcge cdgfba gbdcafe | gfedb bgfdac dag agdfe\nacedgb dagcebf abgcf acgbd fbgd afb cgadfb ebfcda fgcae bf | agcfe fgeac ebfdac bdcafe\nadecfg cbda ecabf egcbdaf fgaedb gcbef cfbaed bfa ab efdca | fbcae fcaeb dbac cfadeb\naecgdf bgcea dbc facdgeb efdb db edgcb cdgfe cgdfba gcdfbe | fdgec bd gcdabf dbecg\ncbgdfe gbdfa dbe bfgdeca cgbdae cbefag becag ed aedc agebd | ecgab fgbdce aecd dace\ncfbed gfcbea abdefc gbfcd eabd dce de geadfc cbgdaef febac | ed egcafd cde edc\nfgcde fcbad fdegca ae fdcea dcegbf geaf eac badecg aecgbfd | egdcfa dbfac gafe ae\nbgadcf acgdf afgedc bdgeacf bfd cbaed fcgb agfdeb fb adbcf | fdbgca fdbcag acdegf cagfde\ngacbfde ebgdcf eabcfd fae fa bfead cabf cbefd gfcaed gaedb | fa fcdeb fecagdb bfac\nadecf cafbd bcdagf gbadc bf dbf gdebca edfagbc bfga dgcebf | fadbc dgcfbe dfb feacd\ndfgae fgcedba ge bcfade caedfg dfbga fdcea gaedcb gea gefc | cfeda fbagd gea eag\ndafceg dfba cdeabf da bedgafc adecb gecab fdecb febdgc cad | caebg cbfde abdf ecgab\ndaebg cebg bcdae gb bdg cdfgba bfcagde dbaceg fdecba fdega | geadf dabge gebda ecabgd\nafedbg feb bf acfb dbeca bfegcad cdefg ecfdba dcfbe bedgca | facbedg cfegd cfba ecfdg\nbd abgcf cfgebd cfgdae abde dafceb fdb daecfgb fcdab cdaef | bd cbfda cabgf daeb\nge cdfga edga caedfbg edbgfc dagfcb efcga cfagde feg faebc | gef eadg fcbagde efgbcd\ncabegd bec eafbd bagc dfcaegb dcgae cb ecdba bdgfec egfcda | cegdfb dgcae decfgb bcdea\nfcbgead af cdbga fabegc cbafd fead cefbd fbcdae gdebfc baf | cadbf cfdab efbdc baedcf\nedfbag bgc cfba ebgcaf cegdfab gfbae eadcgb fecgb fedgc cb | bdgeca cb cb dfgce\nbfadecg fad baedfc cabef gacfbe agecdf cgdfb aedb da acfdb | acebfgd aecfb efbca agbfdce\ndefbca ebcdgaf fgbe gdcfa degcba decbgf fe defcg ecf bdegc | eadbgc fgbe gedfc dcegb\nbagecf bga gbde gb dacbf gefacdb edcagb cfgeda gdace cadgb | dgacb bg bdeg acdeg\nbdc dgbafe cabdeg bfgde befac defbc cd fcdg afgecbd gbfced | cbadeg cdfebg gaebcd gefdb\nafgce dc fabged gbafd fgcda gecdbf badc fdcebga cdf adcfgb | cfbdge dabc dcagbf dgfabe\ncdafeb egf afbeg dagbef cfbgead edag cgebdf gbcfa daefb eg | dabfe fbacg efg eagbf\nedbf afcbedg eacbgf fd efadc fagbdc abfcde daf becaf acdeg | cgfdba efabc adf fgcbda\ngcabe bcadeg dag dgafcbe agdcb faegcb dcbaf afebdg egcd dg | gdfeab cagbd bfceadg gda\ngafcd cbgafd gbafec fcgade bcfgeda cdea bedfg ea fae eagdf | acgdfe deacgf efgdb fdgac\nfecagb ae cgfbe gdafb fecdbg faegb gbcefda aefc aeg gecbda | gae ebgfc edgcfb adbegc\nfgced gcdfbae fec edcb ce bgdfe dfagbe acgdf cbaefg gbcdef | cdafg gaefcb becd cef\nbegdc bacegfd cadfeg afbgc cbdagf egbcf feg bgacfe feba fe | fcbeg gbcaf egf fe\nbed eagdb fagdb efadbc aefbgc ecgd ed gbcdea cadgefb bgaec | bde de ed ecdg\nedbgfc ebfacg cdgef ga daegcf gfa bfacd aegd fgadc befgcad | cdbfa cfedabg dagcf gfbaecd\ngdacb bcdgfa egacdb facb cf cfd cgdefa gbfde egcafbd bcgdf | cfd aegcdb fdc cbfa\nfdca cagfb ac gcdbef bcfgade ebafg bdgcea abc cgfabd cgdbf | fgcbd febdagc bdgaec gbedfca\nca dgcfb fgead gca edcgfa fagcd gecfba aedc dfeagb acegdbf | ac cga cade ca\ndef gfbdc ebdgaf cbde gdcfe eabcdgf ecgfbd dbfgca gfcea de | dbec fecga dfbgc dcfeg\ndacfb bed gcbaefd fbcdag afdecb befc edfab agefd dabecg eb | dbe bdgfac abedcf cdbgfa\nabf cbadf cfagdb acgf fa fdbcg bfagde befcdg dcegabf cabde | agcf fa bdaec cfagbde\nedbcag aebcf afgb fcgbde beagcf bea cgefb ba edgfacb faced | aeb gbcdae ecbfa decbgf\nad adgfcb afgdc ebafcg eadgfcb facgb ecgfd acdb gda gdeabf | fcegd cdgfa abefcg dcafg\ncfebd gfdec feadg gec gfabed cefdga cg gdca gebcfda aecbfg | cbfeag dcag gc cabdfeg\neafdc fac af ebdcf bagcfd gfae eagdc bcfegad gebdca gcdefa | fcbgda dfebcga gdbace defcb\ndagcf aecdgbf bedfgc bafedg adcbg gdcbea cgb dabge cb ebac | fgdebc edfabg fdcag ebac\nbgdaf cbdgef bdcag ac abgedc afgceb cdegb acde ecgbfad cga | adec gbcda dbcge edac\ngbafe gabecf gaed edbgf ed abedgf bdgcf baefdc def cbgefad | febga agde fed gfdcb\ngefcba fgb gf eabdf gcabd edfacbg bcfadg dgfc dfgab gdeacb | fgadb gcdabf fg gfb\ngbadce cbdafeg ce egcdfa agdeb fbdac ecgb ebgdaf ced acedb | bcafd ecbg bcadf gedbacf\nag fbcgead baefcg cfbgd feadc adge fgacd dcagfe dcafeb fga | gaed abdfce ag ecfbga\nefbgdc cbagf gcdabef fegcda gcdaf daeg gd deacf fgd acedfb | fadgc fgabc befdac dg\ned gcefa dcefga fcdbgae dcgea efbdac acgfbe dbacg aed gfde | ed efcgba adgce de\nafceb adbfge beafg bga bedfgc ag bcadgef dgbfe gdaf geabdc | ebgcdf gfcbde ga edbfg\ngafcde agcfeb fdcge ebdfc gebfcda gef gf fgda eagcdb edcag | fabceg bgcfea fagd ebcdf\necadbf bedfg da dgfbcea bacfge ebfad bcaef deagbc adfc ead | dae fadc fdgceba debgf\nadb fbcae ad acfebd gefcbad cefgab bcdaf gdfcb ebagfd eacd | dbfca fdegbca abfecd cdbfg\nfbdcga ebfcd fbadc ca fabgdec bca bagfd bcgeda agfc bgefad | gafbcd cbedf afbdg afbdgc\necfdba cd facegb gbacde gcbed dce cegba bcdegfa befgd cgad | ced cd fcagebd dce\nebdca fcabge dceagbf dgef fbedc ef feb cdfgb cdbfge cgafbd | bcade gfbcae cfgdeb efb\neda egabfd egfacb da fdbegac gdecb adfc dacegf acdeg feacg | dcage cgbde faceg gcefa\nefcgda fgec dafebg agfcd aefgdcb gf ecadbg cgead fga adfbc | fegcda afdebg dbafc fag\ngbdaec gaecfd cbdag acfbd cfegabd fd fcd cgfadb fdbg fbcea | fd ecbagd fdgbeca ebdcfag\ndbgacf efgad abcf dcebagf ebgacd cfbdg dgcefb ab dfbga abd | dbgeacf cfdgba gbdecf gbfad\nabegfd cdafb bdfag ecagdf ag acegfdb ebdfg fag cdbfge bgea | fga dcegfa dgfeb fceagbd\ncd acbefg cdfge dfaceb gcaefbd cfd fcaeg egdbf dacg daegfc | egcfba cadg cd dcf\ngebdfca cdbefg afcg gecbf ag debacg dbaef fabge aeg gbcfea | cgbeda gfecdb ga cgebad\ncgdfeb dfacbg ecd cadfg cadbgfe aegdb fedgca acef cadeg ec | cgdae agbde dfcebg cgfdeba\nfg bdcagf ebacfg gbacd cgfd gfa dgbfa adcbeg edbfa dfabegc | aefbcg agbdc fdcg agcdfeb\nba cbgefd fgace bae cadb edbfc abfedg caefdb caebf gaebcfd | bae cadgefb efdbc ba\nedcfb cdabe gacdeb dabfecg gefacd aedgbf dac bgac ca edbag | facedg dfeagc daegcb gdabce\nafbdce gfc fecagdb egdaf gfbaec bdcfe bcdegf efgdc cg bcgd | gbcfea dfgebc cdefb cg\ncgdaeb dfbacge cgdbe acb gcdfeb dfcga ba fcadbe gbae bcdag | fadbec cadgf ba ba\ncgdeb ebfcag gbdafc bgfde gecdba ec abgdc bce dgecafb cade | cdgafb dcea gdabfc bcagdf\nfadbec gecfbd deg ge afdgce bdfec agbcd ebfg cbedg fbedcag | bgef abcdef cgbde cbefgd\naegdb befgcd gec ecgba aecd cfbag bdefga ce gacdeb dgecabf | eadc gbfced bgcae dgaeb\ncfabd fbedac cadfgb eb bce cdegf decgab eafcgdb cfbde afeb | fdbec fbacd be ebcadfg\nbdecga gdac cdbefg dc bcd baecg bdeac efabd fgceab dbacfeg | bedac faebd baced egbdca\ncg cafgdb bacfde gfaeb cfadb bagfc fcg ecbagfd fdcega dbcg | febag fcg bgcfad gadbcf\nfbde fgd df bagef gacdebf cefabg agdec gdafe gaebdf bcdgaf | efdb abfeg febd debafg\naebcgd abcdfe bdfeg eaf dagecf cgaf bfacdeg fa gdeaf gedca | cedag gedfb agbecd afcg\nfedbcag cgfabd gba faegd eadbgc gceb bgeda bdcea gb aedbcf | beacd ecbg bdaec adgbec\ncfge gc gebfcda fbadc fdbcg degfb gebdac gdeafb dcg fcegdb | dcbgea debgf cdbaf bgcfd\nceafb fegbdc bcfed ecd daefbg dfgecab cgfd dc aedgbc begdf | edbfg efcab cdfg bdgef\necag fegcba bfgac cdbfg efabc befdca afg gcbaedf abefgd ag | fedcba fgcbd ga acge\nbadgf cgaeb ebdga afcbde ebdgaf fged acfgdbe de ebd fdbacg | gfdbea badefg dgeba beagc\nbeagcd cga cafgedb ac febga fgcba cgfbd dgfcab gcefdb cfda | ac fcda agc ac\ndabefc abgfdce decfb gf gfed cbdgf bdegfc gfc gafcbe cagbd | cfg dcfeb bcefd edfcb\ngedab acd ceba agdcb bagdce fcgdb ca dgaebfc dfgbea fecagd | adc acd adegfc cda\ndg eafdg gcbeaf dcfaegb acgebd fadgbe dgbf daecf fgabe deg | gdfae bgfae fgbdea becdag\ndecgfb bcgfdae agcbd afcdb fb ebaf fbd cedabf ecdfa ecfdga | dfeac fbae fb degabcf\nfeabgdc gfdbe bgcad cf geacfd dafbcg cbgaed fabc cfg cdgbf | dbcag cf cebagdf gfdbe\ngdbef ecdgb efcd cdgba fabdeg fdcbeg faegcb ecg fdegcab ce | bgefcd gcdba bgdef egc\ngfebd abd cdfbga gcdea edcbfg abfe ba gebda dbeacgf eafdbg | beagd egdba ebdfg fdageb\ngafbcd bc bac fgeba fbdega agbec febc egadc bcfgaed beacfg | agbfe cfbeag gceda adegbf\ncdbg gfcead db gcbfde bdefc gefdc bdf fcdbega fecba dagbfe | dcabgef fegcd bgdc cgfbead\nbagcde efbcgd adgef fgaecdb bfeacg eabfg cebfg eab ab cfab | eafgb bacf ab eba\ned dcfbeag dfcga cedb cbfae fgdabe dbcefa fbagce dfe dacef | afbgec de cadfg de\ndgc abfedg bdgea cbfde dfcgab ecag gbcdae cg gdfbcae gcbde | afbdeg dgabec begad gdc\nbefcd dg bgacf fbcegad dgb gcad gbcdf fagdbe bfcage gfdcab | gdabef fdecb gcda agcd\ncb bgdcfe bgacefd fdgbe edcgb cegad cbagfd dbefag bdc efbc | cgade gbfaecd bcd cbdge\nadfcge afgd acfeb efcda da gdefc cegfbd bcegad fdbcage cad | defgbc aebgdc dgfa cadfeg\ngacdf bdg aegbdc bg debaf bfeg gadfbce gfbdea cfbeda gdfba | bg fgdca bg gb\nadbecg dfa fd gafbe gefda cefgda ecdag efdc abdfcg egbcdaf | fegba gfadec fadeg efcd\necfgad gbae ecdag ba agbdec bac fdabgc edabc cdgeabf cbfed | dcfeag cbegad cefadg gdebca\nfgbca cge gcefb gadebcf eabcfg gcadbf feag eg fecbd egdabc | ge afgdbc fgdbac egc\neadg eadbc gfbcda badefc gdc fcgbe dcbge acfgbde dacgbe dg | cgd egbcd gcdfba agdbce\nga befgac fcgedba fabced agfce edgfc gbea aebcf acg cagfdb | gecdf afebcd bgdfac cga\n"
  },
  {
    "path": "advent-of-code/2021/inputs/09",
    "content": "9987675345698765453987654321234589999899878923493212345678999998656782467898999899878301234578998787\n9876543234789765322398743210123567898789767899986101239899789876543101567897898798763212355989987656\n3987784014897654310987654331235679965697644998765232345997654989765212799956999679854343466799976545\n2199875323998765421298776542346789434595433498754345456789543499876353489549876542975858977899876439\n1012965439899896432359987667457896546789322349987656987898932445987454578932987621986767898943989598\n2125976598798989943467898876589999858899910959898767898976101234598966689431298320987898999432399987\n3234987987656579894578989987679998769999899898769879999965422345679298995420139434598999896543459875\n4346799876545456789679877898789769878989798799656989899876563496799109989591298548999689789656598764\n5956998765434345698989765679895456989678679678943496789988689989898997979989987657987565698787989543\n6899898764321234567999876989954345696534598789432134679999799976987656765778998769766464989999865432\n7987679653210155789999997899875456789323999899521012345899899765698943254667999898954353578999654321\n9696598654323234589788998998986567898919894958933423456789999753459892123458998987893212467898765432\n8543498765434545679567899987987679987898743147894934567898989432398789334767987876789101298989876543\n7656789878545656789338989876598789986797654235679895678997878941987678975879896545698914345678987654\n9868998989656877892129678965439899975498754346998796789986867932954569986798765434567895458989998765\n8979987798787898921012567894321999874329985459876589899985457899873458987987654323469986567899869876\n7899876549898959999923456789432398765909876567987678999875322987654567898998773212378997698998754987\n6534997831999943987894567897543999899899987878998789789964201298765678919679654323456789799987632399\n5424598942689899876789678987659899988788999989019895699865362349986989103498795434567899899996549989\n4212349653498789765699989798798789877697898999999924789976457899798993212379986747698946999897998878\n5334569878989678934998995679987678954545987899789935689987567987649898763467897858789235798789887867\n6446878989876569976897893459876567893239876797689898789397679893234789654598998979999546999698785458\n7557989199987457898956789998984348994124965323486789895498798789123569875989109989898969898598654345\n8998994398796346899545699876543236789549876412345678979569987679023456989878992398767898767469643234\n9999689987654235695434689987652125678956987954456789768979876568994568999867989987659999955398759345\n7887578976543123489545679698983234789768998765677993457899765456789878997654878998767899843229898956\n6543469998768245678956789529865445899879999896798912349998987347899989989653467899879998732019987897\n7672398999875456989767895439876556789989989999899102356987798456789899878932356789989987643498976789\n8954987899986567899878976546989667993498979978976212469996549567895798969991245699899998754987685698\n9769876989987898901989997656898789101997768769895433498765439878934987656789346789788999869876564567\n9898765778998979312397899767999893249876753656789656569976524989423976546789498997697986998765473456\n3987654569789765434456976978999974756965432345678987678987734694319887635689989998456894219874321567\n2198733477678978645797895989989865669876543766799998789599848789998765212678979999367975323985432378\n3989821234568999756898934599878976798998754567898999897679959899899874323599867895459876434596543458\n9876432347679549887969423498969987897989865698997899979898767998798765435679756899567987546987654567\n9876543489789832998953210987658998996579878789876588965939989987659987546789645688979987657898785678\n3987654579898721239998723976547899987467989999995477894321098765545698687895436577898998898999896789\n2398766789989654359899644597656999876345697679654356965434197543434989798954323456987899939998987893\n1239887894678965498788987698987999765234789598765467896545976532129879899996534567896789123976798912\n0945998923567896997687898999298987653123696439876588987679876549098765945987965778945693239875459901\n9896789434678999876575999899399199762064594321987678998789989698987654326599878989238789459954345899\n6797898645789998767434598798989349872165689410198989769899898997898543212367989994345678998986254678\n5789949756894987654323497687878959989278796521239797653998767876799654302456999965456899987432123689\n4569439887893998799934598576967898995478897432345698992989545665698775212567899876697899876543234567\n5678921998969899987899974475459997898567998945456789989878932124569854323498976989989965987654345678\n6799990199656789876798863212349976987678999896897899879767893234698765434578965699878974598785458789\n9899989989543298765987652101267895999799998789998998968456789345999879545679854598767943459987569893\n3998979678932129894598543323458934889934987698999987654345895469876997656789765987659894567998678942\n1987667569892099989679656445667895679899876597896596543256896567989998789899876798547689978999789531\n9876553456789989878998767986898996798788995456789987752125789678998999897999987899534567899989898940\n8765432345679878967999899597959789987576789347899876543234589789987899975689999987656789929876967891\n8764321234698766556899995329345678987455678956789989684348678999876798764567898998769893212975456932\n9863210123459654345688989910258789876323589969894398765457789998765679923459987869878999109864349894\n9854525234598743234567979891345897995474567898989239878767899997654567895678996555989998919753239789\n9765434545987655455679865789457896986567678967878946989878959876543456789789789434599987898954398679\n9896565656898766767999954567978965497678989656567898998989245988652346799894698765679876767895976532\n9987879768999879879878323489989654398789893432349899987690159899721278967923989876798965456987987699\n8998989879988989998965412397898765219899762101234789996521998798754367899999878987987654347898998987\n7659395989876897987654323456789898323998753242345678989439887699865456899989769999876543236789019986\n8543214598765456798987654589896987536789894355456989879598754589876967999877658999997655345678998965\n7654323679876578969999865678945698545678976566567898769987653479989898998766546898998786457799987654\n8795498793997989657899976789234987657799987677678965657898794567998789987653234567899898568899998723\n9989989932398996546789989890123498968989998788789654346789887679899678996442123458901987678999899812\n9878879993989875237899999989254989979878999899898766869895998997676567894321015667892398789999798923\n7767767989878943123978999878969978998967899922939878998953219876565456976534124578943469999988697654\n6553459876767894234568986767898767987656789210125989987994101985432389997645234567894590129876598785\n5432345985458995679799875456989659876545456991234899876789919996676569987656545678965989239988439986\n4321359894346789789987654345678943965434345789546799765679898987787878998787656989879879998895321298\n5430198765497899894298763234567899876521234899987987654598787999898989109898767899998967897654210129\n6541679876989945999987654345678989987752345678999999766987656579999793212999878999987656789775323234\n6432589989877899998998765476989978998843459789998939878996545468989654329989999998798787894989876545\n7543458998965778987679976687898767898754678999987923989876432345678976498978989987659898943497987676\n8654567987854567896563987798998656899865789019876894599987321238789098987967878998743989932346798888\n9766779876543488997432398899987745679877892198765789998765450139989129876754568999974567895459999999\n9877898765632356789543459921096434567988943989654567899986521234678998765323467899865679976598897912\n9988987654521237989699567899987558978999659876543457899987634656899986544212456789877889987987656893\n9999996543210357678987998998998667989431968997652346998998785667901997432101348995998994398996545789\n8932987987631234589476789987689978999599878994321345997899996778929899546712467894239987469997434679\n7891098876546349679345678965578899998989989989935459876979897889298778994324578943190296599989323567\n6989129989865478993234567893456799987878998776896567965468789990199656989435678954989987989978934569\n5678949999976569310123689932345689876569899565789778984345688999987645678945789769979999878767897698\n4567898999987679453294594321017992985498765434698999993234567898765434899656899998768999765457898987\n7698987898799789564989695532399891996309899323456789832125678919876325999797999887657987654346789876\n8999876789654998679879989649989799876212987437899898761012348901985476789898998765431298743235689985\n9899965689543249998765679998767678965429876556945987652125667899876787899979459963210139852123798954\n8788754799932129879654587789656567896578987987899876543234799998989898998764349854321298764234567893\n7656543458794298965443445678932456789789598998901997654345678997693939789943298765432359879876899952\n6543252345679987654352237899751577899895459789212398897656889986542124599892109887545456989987896541\n8432101489989999875210128932967698998901345699924569998767994987431023999789213998676569995699965430\n7654312678999998996321239999878789767892396989895678989879993976545129897678954598789678934567976521\n8976433589998767987542356789999891557789989978789789467998989897685398789569899989899789325679897432\n9987544567899655698653468999987910345679878765678992345987878799896987667348798976949895434599789545\n9999655778999543219766567899876621234598765454567891249876567689929876543237667895435976565987679656\n8798789989988959309877678999765432545699654323479910134995456578912997632123456789523498878996598977\n6549891299876898912988989789876547686987543212567891239984323469329876321014567898654569989985456799\n1234932997764667893499995678987658798998654403459932398765012478998765432125678979866789699876345678\n0356799876543456994567894567898967899019873212378993987654139989219876843336789565977896579843234589\n1235789987532345789978943456899878978929764323456789398543248892101998765459895434598965498765445678\n2356897698421234567899432346789989767899875435668891239654356789432789887567976323699654329876786789\n3567896543210246788987541457892499848921986546879910129767568996545699998678988434789543210989897899\n"
  },
  {
    "path": "advent-of-code/2021/inputs/10",
    "content": "[[<[<{[<{{<[{(()[])[[]()]}[((){})<[]{}>]}<<{[]{}}<(){}>><([]<>)>>>[[[<<>>[<><>]][<<>>(<><>)]][{\n((<[(<<(<{<((<()<>>{()()}){<<>><()[]>})([{<>{}}(()[])]{(<><>>})>(<((()())<[][]>)>([(<>{})({}())][<\n<<<(<<[[((({<([]<>)[[]]>{<{}>{(){}}}}{[<[][]><<>[]>]({<><>}{()<>})})[<<({}())(()<>)>[([]{})<[]()>]>({[[]\n<(<<<[((([{({((){})<<>{}>}[<(){}>[<>()]])[[<{}[]>({}{}]](<<>[]><[]<>>)]}](<[({[][]}<()<>>)<[\n{<<<{[({{(<<(<<>[]><[]()>){<[][]>{<>{}}}>((({}())([]<>))[<{}{}>({}())])>(<<<()[]>><<<>{}>(()<\n{<{<<[[(<<[{<<{}[]>>([<>()]{{}{}})}]<(<{<>()}{{}()}>{({}[])<<>()>})>>>){[{[{<[[]{}][<><>]>}{(<{}(\n(((([(({((<[<(<>{})[{}{}]>](<[()<>]{<><>}>)><<[<[]{}>((){})]<[()[]]>>{[{<>()}((){})]({()[]}(()[]))}>))}(\n<<[(({({(<{{((<>[])[[]<>])([<>]{()()})}<<{<>[]}><<{}()>>>}>)(<(<{<()[]><(){}>}{{(){}}[{}<>]}>{\n(([[{<[<<{[<{<()[]>{<>[]}}{<{}{}>{[]<>}}>[{<{}{}>(<>[])}]]{<<({}[])>(<[]<>>[{}])>({{<>()}(<\n(<{{(<<{[([<<{()[]}>{({}<>){<>[]}]>((<[]{}><{}{}>))]([{(()<>)(<>[])}]<<((){})<<>{}>>[(()[])\n{{[[<<{<{{{([{()[]}[{}()]]{(<>{}){<><>}}){<[[][]][()[]]>}}<{{<[][]>[{}[]]>(<<>{}><{}{}>)}>}}<<{[{([](\n{[<({{{[<{<{[([][])]{({}())<[][]>}}((<(){}>{()<>})<<<>{}>>)>}(((<{<>{}}<{}()>>)[((()()))[<<>{}>(\n{{{[{{[(([{{[[{}<>]([]<>)]([(){}][[]()])}[{{[]<>}[{}()]}(<<><>>]]}][[([[[]<>]<<>{}>][{[]{}\n<<{{{[{{[<({<<[]<>><{}<>>>}[[{()<>}{[]<>}]({(){}}{{}()})])[[(<<>[]>[[]])[{{}{}}[[]()]]]<((\n({{[{{{{<[[({[{}{}]{[]<>}}<<()<>>(()<>)>)<{{(){}]<()()>}{{(){}}[<><>]}>]<<({{}{}}<(){}>)([{}\n{([[[<<([[{{[<()<>>(()<>))({<>[]}(<>{}))}{(<{}()>{()[]})}}([[{{}[]}<[]>]<([]<>){<>}>])]<{[[([]{})]{(<><>)[[]<\n([<<([<[[({((({}[]){[]{}}){({}[])({}<>)})>)[(<{{{}{}}[(){}]}(([][])<{}<>>)><[[<><>]{<>{}}]{{{}[]}{[][]}}>)<[[\n{[<<{[<{[<{[[({}[])({}<>)]<<{}{}>{{}()}}]{[[<>{}]<[]{}>]}}(([(<><>){[][]}]([<>()]<()[]>))<[<()<>>(<><>)\n(<[<[(({{<{<<[{}()]>(([]())<<>[]>)>}[{<[[]{}]([]<>)><{<><>}[()<>]>}{{{(){}}{[]{}}}}]>}}){{<{([<([]())({}())\n<<{({{<[<[{([{{}<>}{<><>}]([(){}](()[]))){[{()[]}<<>()>]({()()}({}()))}}]<[<<(())(()[])>>{(<{}<>>{\n{{{(<<[(<[([[[()<>]<()[]>]]{[[[]{}]{<>{}}]((<><>)({}{}))})]([(<{<>()}{[]{}}><<{}{}><<>[]>>)[<<()[]>((){\n[{(<<{[<<([{[<[][]>][{()()}({}())]}]([{([]{})<{}<>>}(<()>[{}])]{<([]<>)<{}{}>>(({}<>)<<><>>)}))>([[((<<>{}\n[[(<({{(({{(<[{}<>]([]{})>{[<>[]]([][])})[(<[]<>><{}()>)[<{}()>(())]]}<[<[[]{}]<{}{}>>{<()()>({}<>)}]<\n([(<({(<{{(((<[]<>>{<>()})<{[]{}>([]{})>)[<[()<>]({}[])>[(<>{})(<>[])]]){<((<>{}){()[]})><{<[]<>><<><>>\n({{<({(<<({[[{<><>}]<<<><>>({}[])>]([<[]<>>[{}()]]{{<>{}}({}[])}}}<{({[]<>}({}{}))[(<>())(<>())]}((([]{}){[][\n(((({[(<([<[(<<>>[[][]])<{<><>}[{}<>]>]{({<>()}(<><>))(({}<>))}>])<([[<<()<>>{[][]}>]<[[[][\n[<<(([({((<<{({}())}[(()()){[]<>}]>>){({<[{}{}]<<>()>>{<{}()>}})})})])[[<((<[{([<>()][{}[]])((()[])\n{{{<{[[(<[{{<<{}()>[{}<>]>{({}{})<()>}}(<[(){}]>(<(){}>[[]]))}(<<[[]{}}({})><[<>[]]{<><>}>><[<[]<>>{<><>}](((\n{<[[<[{{<((<[<<>()><[]{}>][<{}()><{}{}>]>)[[[[[][]]<()[]}][([]{})(()())]]])>[[((<{[]<>}<()>><[{}[]](<><>)>\n<{([{[{[{([({<{}[]>([]<>)}[[[][]]<()()>])[<[{}()]>{<<><>>(()<>)}]]){({(<[]<>>([]<>))[(<>){\n[{{<(({<{[{<{({})(<>[])}({<><>}{[]()})>(({[]<>}(<>{}))[{()()}{{}<>}])}{<{{<>()}<[]{})}(<()><(\n{(<[{[[{{<(([{{}{}}<()[]>]<[<><>]>)([(<><>)])){<<{[]{}}[[][]]>{[[]<>]{<>{}}}>[<<[][]><<>()>><<{}<>>[<>()>>]}>\n<[{{(<<{{{[[{<[]<>>(()<>)}<{()<>}{<>[]}>]<[<()()>]{<<>>([]())}>]{([<<>{}>({}<>)])[({{}}{[]<>})[\n<<[[<<[(<{{{[{()[]}([]())][[[]]((){})]}}(([{[][]}[()()]]<<()>[{}[]]>))}>)<{({{<[[][]]{()()}><<{}{}\n{[<(([([{({([({}()){<><>}][((){})([]())])[<<()<>>(<>())>{[[]()}(()[])}]}<{{<(){}>{()[]}}((<><>){{}<>})}((\n{(({([[{{((([<()()>([][])]<<{}[]>[<>]>)(<{<><>}[{}{}]>[[<>{}]]))[{<<[][]>[()]><[{}{}]>}{<([]<>)([]<>)>}]\n(({[[<<<{[{([(<>[])<()[]>])(<([])({}{})>)}[{(<<>{}>({}<>))}<<[<>[]>[(){}]>(<{}{}>)>]]{([[<<>()>\n[{[[{([({[{(({()[]}[[]<>])<[[]<>]([])>)([{{}{}}[{}[]]]<{{}<>}>)][<(<<>[]>{<><>})<(()<>){[][]}>>[[{[]{}}([]())\n([[{({([({<<(<[]<>>)[{()[]}<<>()>]><<{<>()}<<>[]>>[[<>{}]<<><>>]>)<<<<<>[]><<><>>>[[[]]]>[{\n[{{([(<[[<{((([]{})[()()])[<[]{}>[<>()]])<[{()()}(<>{})]({[]}[<>{}])>}((<{[]()}>)({<{}{}>[\n[[[{{[[[<<(<(({}())[<>{}])<{{}<>}(()())>>[[((){})][[[]{}]{()}]])>>{[(<([{}{}]({}<>))([{}()]<<>[]])>({<\n{<{({(({{{[{<(<>{})>{<{}<>>(<><>)}}<(<[]()>[[][]])<[{}()]>>]<{{<()[]>{{}()}}{<{}[]>{{}{}}}}{{<()<>><<>\n[{[<{[<<({(<{{<>()}({}<>)}<(<>[])[()()]>>{{{<>()}{()[]}}})<{<({}()){<>{}}>({<>[]}({}())]}>}(\n[[{<([((({([{{()[]}<[]{}>}({<>[]}[<><>])]{{<[]<>>[<><>]}[{()()}[<>[]]]})}[{[<{()()}(<>))<({}){()<>}>]([\n(<(<{[{<({[{{{[]()}({}{})}{<{}[]><<>{}>}}]})>}<{[[(<[<[]{}>([]())](<{}>[()()])>)][(([{[]<>\n<<<<{<{<<[<({<[]>({}<>)})<[{[][]}[[]()]][[{}<>]<{}[]>])>([(([][])[[]()])<[{}[]]{[]{}}>](<[{}()]{{}()}\n({[[([([<{[[({()[]}[<>[]])[<[][]><<>{}>>][(({}{})(<>[])){(<>[])}]]<{{{{}()}[<>[]]}<[[]<>]([]())>}>}{<{({\n((<{<{{[((<<<(()<>)<[]{}>>[<[][]>[(){}]]>>)){([[[[<>]({}<>)]{{{}<>}([]{})}]<[<<>()>(()())][{[]{}}{[]<>}]>]\n{<<{{[({[<{{(<{}[]><<>[]>)([[]()])}<[{{}{}}{<><>}]<({})<{}()>>>}<[([{}<>][<>{}])](<<{}[]><<\n{[{[[<<[(({[(((){}){<>[]})]([[<>[]]][<<>{}>[<><>]])})({<[({}[])<{}[]>]>}<(<(()<>)[[]{}]][[()()][<><\n((<<[({<{[[({<[]()>([]())}[<[]{}>(()<>)])]<<{[{}[]][<>()]}><<{<>[]}[()<>]>[<[]{}>{[]()}]>>][(({[<>\n{{<[{<([({{([<<><>>{{}()}][<[][]>{[]()}])[<[[]]{[]<>}>]}(({<()[]>[{}()]}<[[]<>]{<>()}>))})])<{[{<[<[{}{}]\n[(({({[[<{(<{{<>[]}[()<>]}((<>{})<<>[]>)>{[<(){}>{{}<>}]])[<{(<>[]){{}[]}}([()()][<>[]])>((({}())\n{(([<{([[{([<<{}()><[][]>>[(<>()){()[]}]]<[<()()>[{}]]([{}<>][{}[]])>){<{[[]<>]<<>{}>}{([]{})}>[([\n<{[{({([(<<{<[()<>]<(){}>>(<()>{[][]})})>{[([<{}{}>[<>()]])[{([]()){<>{}}}<<{}<>>>]]})])([<(([{<(){}>[{\n<<<(([<[{[[<{({}()>{[]()}}>]]([<[[()][{}[]]]<[()()]{(){}}>><<({}[])(()<>)>{(()[])}>]{[(<[]()>)[{[]{}}\n(({(([[<{(<{[(<>[]]]}<(({}{}))([[][]]([][]))>><[{(()())[()<>]}<{(){}}>]>)((<{{()[]}{<>()}}<([\n[[[{<[{<[<[[{(<>{})<[]()>}{(()[])[<>()]}][<({}()>[<><>]>{<[]{}><[][]>}]]><<{[{(){}}{{}{}}][<<><\n((([<<((<[{(([<>[]]([]{}))([<>]{<>()})}([[(){}][[]()]][(<><>){{}()}])}{[<[()<>]({}<>)>[<{}{}>]][<(<>())<[]\n{<<{([(((([{<[()]{(){}}>{{{}[]}}}[{(()[]){()<>}}{<<>>[<>{}]}]]<[{(<>())(()[])}]>){[[<({}{})[()[]]>{[{}(\n([{(({([([(<<{<>[]}<{}<>>>[[[]{}]<[]{}>]>((([]<>)<<>[]>)[[(){}]]))[<{{<>{}}}[(<>}{()()}]><{<<>{}><\n{(<[<{({([{{([[][]]>({()()}[[][]])}[<(()())([]())><(<><>)([]{})>]}[(({{}{}}{{}<>})([<><>]<()[]>))]\n((<(<<{{{{<{{(()<>)({}{})}{{<>[]}<()[]>}}<<<[][]>(()[])>[[()[]][[]()]]>>[[{{[]{}}[[][]]}][<[()[]]{[]<>}>\n(((<(<<<{{<{<{{}{}}(()<>)>[((){})[()[]]]}{[[<>[]]{{}()}][{()[]}({}{})]}>}}>{[{<<{[{}()]}<[[]()]\n({(([[<{[{<(([[]()](<><>))[<{}[]){{}()}])(<[()[]]<[]()>>[<{}<>>[()<>]])>[<[[()()]<<>[]>][([]())([]{})]>{{<<>(\n[[(([((([<[[<{{}<>}({}[])>[([]<>)[()[]]]]<[(()())({}<>)](([]<>)<[]()>)>]>[{{{(()<>)}<{[]()}\n(<(({[<<{((<[[[]()]{{}<>}]<<{}()>({}[])>>)<{{({}){()()}}<{[][]}>}>){[(<<[]<>>[{}{}]>{{(){}}{[\n{<(<(<<{<(<{{[{}[]]([]{})}([{}[]](<>))}[([<>()]{[]{}})<({}<>){<><>}>]>[{<[[][]]>}[<[<><>](()())>(([\n{(<(<{<(<<{{{<(){}>}({[][]}{{}{}})}}<(<<<>()>[(){}]>(<{}()>{{}}))>>[{{[{[]{}}(()[])]}[((<>())<<\n([((([[{([{<<((){})>{{<>}{[]()}}>{[((){})<()[]>]<{[]{}}[(){}]>}}{((<{}()><{}>)){{<{}[]>[[]\n{{{(<<{((([[{(<>{})({}())}[<[]()>({}{})]]<<[{}]>{[[]()]{()[]}}>]{({<()[]>((){})})<{<[]<>>{{}{}\n(<<[[([{{(<<({{}}[{}{}])<([]{}){<>()}>>>(({<()()>({}[])}<<{}()>[(){}]>)))[{([{<>[]}([]())]([()()][<>{}])){\n<(<(<<<([[[(<{{}[]}{{}[]}>[[<>()]{()[]}])]<{({{}()}{{}<>})<({}[])([]<>)>}{(({}[])(<>{}))((()<>)<[]()>)}>](<\n<<{(([<([[[[<{<>()}({}[])>{((){})[{}()]}]}[<{<<>[]><[]<>>}<[{}<>]{{}()}>>{{(()())[()[]]}{<()<>\n(({<<[{([{<(([{}[]][(){}])[<[]()>(()<>)]}>}<[(<{{}()}{{}<>}><[[]()][[]()]>)]<(<(<>())>({<>[]})){[{(){}}<{}{}>\n({[[{[{{<(([[[{}{}]<(){}>]((()[])(()[]))]({([]<>)({}{})}{<<>{}>{<>}}))<{(<[]{}>(()()))[[()[]](<><>)\n([{[{{<{{(<[((<>){[]()})(({}())[<><>])]>({[(<><>}{{}[]}]{(()[])[()]}}{([[]{}](<><>))<<{}[]>(<>())>}))\n<[(([[[<{[[(({()[]}<<>[]>){{<><>}<(){}>})<([()]{<>[]}){{<>{}}}>]]<[{{([]())({}{}>}<{[][]}<<>{}>\n({(<{<([[<{[<{[]()}[{}<>>>[[(){}][[]{}]]][{[()<>][<><>]}{<()()>}]}<({{(){}}<()()>}{[<><>](<>())})[(\n([({<[<[{({<<[<>{})[<><>]>{{[]{}}}>[[{()<>}([]{})](({}<>)<<>>)]}<{<<<>>{()[]}>}<{<[]()>}>>)(<<<{\n({<{[[({[([{[{[]{}}{[]<>}](((){})({}()))}]([<{<>{}}{()<>}>{({}{})(()())}])}]<{({{<()[]>{()}}\n({[[{[((<[[[{<<>[]>(<>[])}]]{<({{}[]}){[{}{}]<<>()>}>[([<>()]{{}()})(<()()><<>[]>)]}]>(<([{<[]{}>(()())}<{[\n[<<<{<({({{<{[<><>]{{}<>}}{<(){}>}>}})})[<<[{[{({}{})<<>>}[{[]}(()())]]{{([]())([]())}{({}[])[<>\n<<<[[((<{{<(((<>[])(()))<<<>()><<>{}>>)<[{<>[]}{(){}}]{[{}]({}())}>>}}[[((({()}{[][]}){<{}[]>}\n(<[<({[[{[<<[(<>[])]([[]<>]<[]{}>)>({(<>[])([]())}<[{}<>)<<>{}>>)>[{<[[][]]><[{}<>]<[]()>>}<<[\n{[({<<<<(<([{{[][]}}]{<{<>()}<<>()>>[({}())<[]{}>]})>)>>><<<{{((([{}[]]<<><>>)[[[][]]({}[])])<{<{}{}>(\n[[[({((({<([({[][]}{[]})<({}[]}[{}{}]>][([[]()]([]()))<<()<>>>])<[<<()[]><()[]>>]>>([<<{[]()}{[][]}><\n[{{<<<({<({(<<<><>>>{(<>[])[<><>]})<(<<>{}>(()()))[{{}()}{(){}}]}}[(<{[]()}<[]<>>>({<>{}}[{}\n([<<{<[{([<[<{<>{}}<[]{}>><([][]>>][{([][])[()()]}<<[]<>>>]>][{<({<>()}<[][]>)[[[]<>]{()<>}\n({<<[<(<<<(<((()<>)<{}<>>)>)<<([<>{}][<>[]])<<()()>({}[])>>([(()())(()<>)]{{{}<>}<[]{}>})>>>>[\n<{[{<[[<[(<{({<><>}{[]<>}){<[]{}><()>}}({({})[[]{}]})>{(<{[]<>}{<><>}>([{}[]]{<><>}))(<<{}()>[\n<{{<[[({{{<({<[]()>[{}[]]}<{<><>}{()<>}>)[<<[]{}>{{}<>}>[<<>[]>((){})]]>}}(<[[(([][])[{}<>]){(()<>)[()[]]}]((\n[{[{<[(({{({<{{}{}}<()()>>(<[]<>>{<>[]})}(<<()[]>{()<>}>))<<<[{}{}]<<>[]>>>[[{[]{}}]((()<>){<>\n{[[<{({[<(<((<{}[]>){[{}[]]})[{[{}{}]({}())}]>(<{{()<>}(<><>)}[(<><>)<[]{}]]><{<()[]>([][])\n"
  },
  {
    "path": "advent-of-code/2021/inputs/11",
    "content": "4836484555\n4663841772\n3512484556\n1481547572\n7741183422\n8683222882\n4215244233\n1544712171\n5725855786\n1717382281\n"
  },
  {
    "path": "advent-of-code/2021/inputs/12",
    "content": "BC-gt\ngt-zf\nend-KH\nend-BC\nso-NL\nso-ly\nstart-BC\nNL-zf\nend-LK\nLK-so\nly-KH\nNL-bt\ngt-NL\nstart-zf\nso-zf\nly-BC\nBC-zf\nzf-ly\nly-NL\nly-LK\nIA-bt\nbt-so\nui-KH\ngt-start\nKH-so\n"
  },
  {
    "path": "advent-of-code/2021/inputs/13",
    "content": "792,394\n1124,850\n1208,850\n721,173\n1057,252\n1119,182\n1017,402\n485,58\n773,880\n1171,197\n661,546\n218,628\n574,693\n673,316\n393,157\n1071,822\n898,826\n152,574\n1114,791\n107,777\n669,264\n1292,54\n1092,628\n415,31\n387,733\n234,576\n652,742\n599,40\n308,327\n147,640\n219,635\n831,310\n246,604\n725,49\n103,761\n756,0\n562,352\n47,17\n725,364\n70,310\n218,180\n68,453\n1310,100\n1134,175\n738,340\n586,5\n902,610\n1064,540\n900,803\n1002,392\n151,282\n1174,357\n464,406\n560,385\n656,732\n585,754\n805,189\n813,197\n669,581\n816,322\n191,712\n396,495\n643,394\n956,462\n341,182\n591,372\n654,856\n174,571\n955,352\n678,268\n162,754\n92,318\n231,544\n681,425\n683,640\n698,271\n756,217\n69,306\n1054,544\n591,820\n1168,632\n293,868\n70,584\n796,44\n607,60\n639,494\n47,381\n984,431\n248,864\n915,432\n151,476\n84,628\n924,77\n1305,703\n246,156\n1161,252\n1250,686\n177,301\n351,731\n1228,773\n743,290\n928,266\n1258,749\n771,633\n701,218\n386,525\n315,534\n557,176\n1230,610\n846,14\n671,481\n561,546\n97,88\n629,148\n1017,625\n684,749\n1133,700\n244,803\n1241,754\n678,593\n956,432\n749,58\n895,415\n969,805\n156,93\n738,380\n518,537\n989,546\n815,138\n190,425\n354,432\n1213,168\n8,627\n175,870\n792,842\n812,530\n982,431\n1218,679\n852,567\n607,821\n244,106\n15,323\n738,513\n658,742\n711,696\n490,243\n674,105\n1295,123\n1230,121\n812,205\n512,607\n1053,770\n166,124\n18,54\n354,462\n130,852\n1089,260\n949,868\n102,436\n514,850\n969,294\n515,249\n894,166\n321,796\n1228,65\n0,319\n831,472\n567,256\n259,14\n1208,44\n1087,285\n572,737\n494,180\n346,327\n574,816\n739,14\n1054,360\n159,586\n1289,784\n1227,14\n313,294\n830,324\n224,281\n731,722\n1084,252\n1047,225\n1049,280\n1241,724\n833,252\n97,168\n810,674\n0,78\n798,607\n1039,422\n1079,817\n1191,411\n1178,456\n69,276\n955,800\n503,724\n995,534\n1230,773\n641,40\n995,170\n783,397\n52,145\n1120,425\n218,266\n341,406\n989,572\n1046,588\n798,847\n308,565\n468,850\n689,44\n353,298\n1302,575\n1241,276\n184,849\n654,879\n874,189\n242,236\n798,728\n348,38\n314,362\n185,222\n189,329\n639,379\n933,777\n97,768\n1006,828\n1203,777\n756,677\n909,700\n308,329\n75,172\n703,60\n1205,186\n1235,274\n328,185\n1283,248\n0,812\n574,793\n524,791\n190,388\n119,483\n20,856\n771,261\n12,847\n1099,274\n637,871\n661,309\n753,768\n1213,840\n557,54\n55,441\n895,31\n1255,483\n905,868\n100,448\n1001,578\n425,54\n585,364\n492,306\n490,94\n684,145\n567,514\n759,313\n107,35\n982,157\n498,364\n82,592\n775,483\n960,716\n716,830\n1031,610\n591,746\n716,840\n815,756\n1006,77\n874,628\n927,259\n720,408\n820,778\n1213,768\n1241,618\n1231,882\n629,597\n1136,324\n422,161\n835,494\n58,390\n949,381\n656,856\n420,766\n1111,397\n162,530\n579,172\n989,479\n1235,172\n875,323\n736,688\n1247,148\n144,567\n239,72\n341,145\n525,599\n1299,394\n267,385\n68,47\n15,571\n950,7\n304,828\n970,850\n569,868\n1029,852\n889,388\n263,673\n584,103\n479,472\n715,609\n144,327\n502,403\n107,117\n164,116\n49,777\n244,66\n560,161\n668,47\n656,879\n222,436\n244,408\n1120,388\n410,829\n1292,567\n341,600\n92,576\n753,270\n1266,511\n803,133\n846,388\n594,840\n465,329\n1121,565\n1235,620\n606,826\n1154,801\n479,310\n560,509\n219,873\n1252,390\n321,770\n668,831\n913,618\n813,479\n407,432\n888,733\n721,273\n391,221\n436,33\n1283,808\n1302,627\n497,124\n1151,586\n326,463\n1033,777\n0,100\n719,746\n1158,570\n1123,197\n1081,54\n421,388\n184,837\n539,485\n551,133\n72,715\n141,248\n980,70\n1066,408\n1131,761\n894,728\n479,24\n1235,243\n970,44\n271,472\n835,718\n825,164\n731,875\n166,180\n224,165\n1213,880\n142,632\n293,298\n157,645\n263,221\n1047,359\n962,38\n818,588\n950,887\n579,203\n377,117\n833,28\n798,632\n13,761\n721,721\n586,441\n1148,82\n654,364\n955,542\n1160,735\n1037,658\n47,205\n574,649\n1150,124\n1300,768\n504,607\n1042,212\n1039,472\n644,403\n324,852\n848,530\n463,182\n584,758\n1057,194\n1092,413\n375,732\n1068,236\n813,322\n400,491\n13,133\n82,554\n1148,100\n328,431\n410,106\n458,119\n571,880\n45,478\n848,476\n656,127\n585,845\n1133,301\n507,472\n242,864\n239,516\n673,871\n436,180\n813,170\n1178,438\n1171,25\n386,56\n426,38\n436,628\n999,805\n142,680\n549,708\n1052,889\n1168,831\n1297,294\n711,521\n743,828\n42,271\n788,8\n1181,564\n1295,323\n187,697\n982,610\n579,143\n895,863\n264,588\n1134,607\n1285,746\n875,635\n477,28\n833,866\n749,721\n667,276\n750,665\n433,858\n621,492\n1169,646\n999,89\n1266,831\n572,65\n726,794\n43,187\n550,593\n557,768\n0,261\n989,25\n805,705\n321,255\n1168,383\n1279,147\n639,413\n386,838\n1240,346\n960,178\n45,676\n462,530\n812,364\n141,646\n1176,754\n1223,72\n293,65\n753,840\n151,394\n572,380\n383,787\n1159,758\n585,140\n570,628\n673,764\n566,504\n661,863\n792,264\n273,684\n748,679\n1150,322\n1156,743\n102,44\n1043,285\n1146,116\n914,495\n785,599\n726,100\n1284,460\n326,157\n79,208\n1208,14\n465,777\n134,413\n656,767\n1263,513\n127,3\n464,506\n253,194\n413,250\n711,5\n490,564\n689,850\n1238,43\n383,259\n175,724\n335,143\n734,42\n915,686\n157,724\n1223,378\n410,381\n724,889\n808,491\n989,869\n704,68\n676,568\n1006,716\n890,548\n60,830\n170,577\n1159,418\n268,369\n169,282\n877,858\n1077,500\n807,700\n65,721\n847,182\n1245,88\n590,856\n494,770\n1168,680\n855,137\n915,208\n1255,889\n621,596\n1115,523\n1088,514\n360,7\n127,845\n266,830\n1159,164\n218,842\n151,730\n792,182\n1154,241\n82,302\n681,148\n1293,871\n520,140\n877,708\n388,837\n80,793\n1203,117\n590,38\n253,700\n572,554\n1305,31\n1205,708\n647,255\n388,178\n807,724\n1056,403\n10,768\n0,816\n458,775\n1228,605\n1202,413\n1043,161\n1261,777\n406,30\n68,889\n711,373\n361,868\n1071,68\n816,770\n147,400\n574,773\n184,57\n1242,47\n79,882\n654,486\n1057,700\n939,259\n561,58\n1210,448\n293,401\n293,268\n1285,148\n151,500\n1042,682\n1216,217\n1265,478\n923,733\n626,537\n431,733\n1053,796\n599,889\n537,880\n890,766\n505,257\n87,290\n909,642\n333,137\n177,28\n835,133\n435,635\n134,637\n1163,494\n1277,492\n518,52\n654,38\n495,756\n628,14\n1176,413\n75,243\n914,5\n522,886\n28,749\n1044,126\n1263,821\n522,438\n60,208\n1059,722\n989,255\n629,425\n681,597\n75,620\n315,360\n373,404\n398,437\n621,850\n494,124\n924,212\n1146,800\n321,415\n42,623\n927,787\n455,3\n25,746\n1017,401\n555,785\n231,817\n816,180\n2,600\n1088,436\n1285,597\n232,161\n97,880\n753,176\n271,295\n26,460\n0,651\n654,767\n401,252\n55,779\n1049,614\n44,383\n937,490\n1305,863\n498,812\n841,222\n903,432\n684,537\n795,645\n924,525\n562,215\n634,568\n989,757\n105,186\n527,891\n488,572\n835,581\n720,856\n1071,516\n758,880\n93,642\n328,463\n790,413\n1088,458\n875,123\n321,25\n1255,779\n190,889\n830,570\n261,280\n1250,830\n1148,794\n490,116\n1302,267\n920,588\n1163,400\n721,621\n340,44\n1124,551\n1052,271\n1002,567\n561,721\n355,103\n689,420\n664,319\n0,162\n592,329\n80,773\n428,194\n1176,140\n1044,840\n576,42\n927,821\n69,124\n1165,316\n663,255\n1071,72\n1076,410\n1265,218\n1145,514\n93,194\n982,289\n397,618\n326,737\n129,564\n797,248\n433,708\n520,418\n898,266\n350,178\n436,861\n179,761\n977,869\n1217,642\n812,812\n1154,93\n1277,599\n552,880\n790,476\n156,129\n676,326\n186,850\n20,38\n626,145\n261,621\n1225,868\n0,530\n957,298\n222,514\n725,845\n375,162\n682,686\n935,162\n408,380\n85,868\n475,581\n902,514\n435,21\n557,278\n271,422\n803,176\n888,161\n1126,849\n514,467\n139,249\n1124,343\n477,642\n527,845\n551,581\n820,330\n176,175\n1245,806\n256,534\n142,383\n140,663\n539,633\n512,632\n390,588\n232,677\n1039,73\n403,751\n584,584\n567,520\n900,856\n498,530\n996,810\n594,656\n954,649\n1240,310\n763,329\n621,44\n6,129\n1217,252\n738,604\n1263,60\n1290,326\n682,432\n673,130\n25,148\n152,324\n65,544\n1171,249\n17,316\n199,399\n654,548\n393,737\n\nfold along x=655\nfold along y=447\nfold along x=327\nfold along y=223\nfold along x=163\nfold along y=111\nfold along x=81\nfold along y=55\nfold along x=40\nfold along y=27\nfold along y=13\nfold along y=6\n"
  },
  {
    "path": "advent-of-code/2021/inputs/14",
    "content": "SNVVKOBFKOPBFFFCPBSF\n\nHH -> P\nCH -> P\nHK -> N\nOS -> N\nHV -> S\nVC -> C\nVO -> K\nOC -> C\nFB -> S\nNP -> S\nOK -> H\nOO -> N\nPP -> B\nVK -> B\nBV -> N\nPN -> K\nHC -> C\nNS -> K\nBO -> C\nBN -> O\nSP -> H\nFK -> K\nKF -> N\nVP -> H\nNO -> N\nOH -> N\nCC -> O\nPK -> P\nBF -> K\nCP -> N\nSH -> V\nVS -> P\nBH -> B\nKS -> H\nHB -> K\nBK -> S\nKV -> C\nSF -> B\nBB -> O\nPC -> S\nHN -> S\nFP -> S\nPH -> C\nOB -> O\nFH -> K\nCS -> P\nOF -> N\nFF -> V\nPV -> B\nPF -> C\nFC -> S\nKC -> O\nPS -> V\nCO -> F\nCK -> O\nKH -> H\nOP -> O\nSK -> S\nVB -> P\nFN -> H\nFS -> P\nFV -> N\nHP -> O\nSB -> N\nVN -> V\nKK -> P\nKO -> V\nBC -> B\nFO -> H\nOV -> H\nCF -> H\nHF -> K\nSS -> V\nSC -> N\nCB -> B\nSV -> C\nSN -> P\nPB -> B\nKP -> S\nPO -> B\nCN -> F\nON -> B\nCV -> S\nHO -> O\nNF -> F\nVH -> P\nNN -> S\nHS -> S\nNV -> V\nNH -> C\nNB -> B\nSO -> K\nNC -> C\nVF -> B\nBS -> V\nVV -> N\nBP -> P\nKN -> C\nNK -> O\nKB -> F\n"
  },
  {
    "path": "advent-of-code/2021/inputs/15",
    "content": "1124751783612228519483416186391693192764152281421133194141163183224351733212394799536339411529842112\n1299938854391228215712461147511117912185733411491416388811646391912138661213722223824151532652174491\n3339197559983134739317425934547716331696227221882122961476799987711635499267472178182145359213635923\n3275111279884782539314241187762113814171394161491634629424134127254634143155261122133724143114517171\n3719252118791433135122231855197812222238914994648147192141951214948299478914959275216261881654181459\n1611117951314292139456114142392662772939225937136486428161234281216234329234315111776511563151948482\n2568826483341639224876553822412669632282339258375519267395999314194775717338955473111882125281113119\n3211535497996954958315977618271374429983722314139733843419727946959246752499319415154271225547899217\n9182381814515842193317619241122295417132515941811977373112934221316141138111911121121111793678163186\n3844189817214722127981149242928145957137126937131386516329118218111198674162815191994371914762733967\n2341991198198671797918854491942998311516141218456591158159195192211227471918835699934872448189793938\n4914562622368117861639397331397217328431182986624263992197435816915439591962133158497224891382954532\n7626651214813838216185911429272999894518636231382989678893369367388711391734813452975811156327428911\n6619547343521975253174481211413831293662121339851815212317311237391545399111182897667911821424149598\n9973191187241313192815214227191649743296915314888729322114168515823743777711899119191553298115729119\n1139287494922611751257731929722771498336139611251121442114394245137973342111145499332316959261235284\n2957197428427162517942347211164151149912112158641321995248419171621811597221619949431227171998811472\n3942647388316719894411111531921126183713231811198382654685441319271454138942281133619242611612293827\n7937119217256311112391437861121498616811956123353462521891125694135126297129995285155114368995531781\n3451961913122271833382989211151286596622992323752134162138122516383189222433812253226845819142198221\n2778119153629891339923532321818124533756116181684147179833125112111826952511175359231299984985971323\n3111241849191534385261731569341927433476113958471723118832747854529179328115274125434719722218912131\n3142339531392581988128137411211196234548128214999949588185228836196627923352221497911291281534111199\n2247331434479875142918842833898559624238445292211715118881294135283574749565172271411631413491566199\n5942278576394177315387294721122691617961774138211922471397191215938266718124567292193989959261637132\n3165937631221963265792414421441393495719931248192344794567976762321141859115829128661211272472736862\n6245216271127518123199222191484234611151315582117171596574729739922992724612599562343116361844622764\n8113544322656226212151951279235114941989556194198115559251582213981835589429635885493383187341531965\n9167334539972119189967382996641594933763662148772253141953186111414742999511119411388291132416516449\n3613823811913288411123382135529243111267199921121439155729919326116169791514491996989971122517181152\n8673611192477161631212112481894911858892968239143914865319658975331149334747126743512225484277694151\n1573562476555619452428261559215411721579288335558515411134313992163812836653437129992833619198146362\n1985275213511588337218921661953495211191671194622531866114745941231929893241192939732541431596251229\n1265136118282217612545222191931962743537199362634214512441818421145212152171522295123221817416511192\n8297798221482948311881157477219864767525628534952929138168821168196211119111519681828383199111919196\n2534111997313111473186996839118152776719511994169115192212165984228917912783244345623614586619121326\n5841498181267192895193154811932281737529524821838531213993721717189699211939288511893237393416182963\n4291365191619323711913413926441339411267931111249294286234263722174939997111633217333235111582923441\n1287162672582123747413148471918114922719181577167138269131143162782619895168443398922587114315692159\n1265925622411611266789112299971891313715613359912627191225939742625214121139321211686759611131173819\n2138953588999163543822384688714958315246965691333881631171314291246656696539111996811849918124146199\n1246641611311144149732152211911939355725818779248359199268117115556131393567479697235189376137881341\n2899323821125691382122622121279464139996512843263627599964991689326381239953514685697311811566519319\n2736949532739218813892326217621918912123391961114292438971239114718244292915281445924621121161621333\n3284227711481113791259114169152546556372395121491214478676766673451539272714243257528999117191132191\n1491645992221246232691159831148693751711539199173418148515113374123227919399121713163369423119344294\n9132112419279766149552388219119879126631964411873291514292382629182256527396923261916197289667422219\n4435263531452645499818123111966429163563711994892138163281911392712947829833494132517185151159797235\n3377999473376535692397871161267942211991447319627223732643859136911321291147933161219919912554143594\n3949323991733462336411199416212721417161994737197381813716349241925143828318311249159179991229329171\n1762136928289612837322111798838212828232194159395467913129898285979511558911359718111211715278482292\n1118257643855683112121972927223668654922187717441698273158822189761169916992651219511457913769191141\n1658133214212128183392871646163111119424394424612113962259435119311183885137744192432918197134375132\n3591713174418138371811543613511348758114531127679321532212958111147949196891591688991927112311822659\n1236514266615278952886111333113128112861958723136379141934411821192618183131222512832888648251713999\n8123213361595969218132551112914729944243931512311795497816271296492513311341682399128274945195119112\n2462825227696446183996491353919233459561152451155132169141431681617413626542619881461141223688519198\n9621989515111471113381577698758628164221411666452251895517161458991756482464135232192737151721333241\n1845633941916891433521922233371928968912324239271162428588753196413672815131973146761647212761387593\n1213191632931181293214711139975148754136566435292974252811697693911887328591189183554433169371667213\n4519131126388191338914531223891121466796183273431621945951424794146112514299112124121572531131372111\n1331344969619935133794416261913442341424183712193444133541852317113515211181326734947129151289182833\n1355758512615534971555911998128211268588155773916181718217932133414645114253821929111112911181223396\n1921812718591189155234925136611421141621741789512111114849236968196293982164297416554297277314296498\n2925818269222199331695127966441449818292484293218699694191219141796929886179788888289778893154112915\n7349332956191336793938825411116431794116518627151175184126599498959181846349128914531693382871224114\n2975711544499872811921879322745419629143299769241363453113298718372441111116129736331374245812629681\n2419398835867978148157517197312837563211153716146118174293922233694112229384117648726494771916746336\n2322473321962284111112435812293374144731592114895311931296931978723998962913118278111921783414789472\n7421933294181593157278951313456166911311561151111468883991937345182554571275781533927232981213941792\n1668835358177241114335636733193482471442299199859434499861711136613117473328576171139593142184617345\n5339642815719926226879311379167325793396941892597215179614941121636812111539912741116971188971946499\n7581333191573246312732795518731212368211299298495989164122116531125184283943222911391615243311251361\n9492966914243222969499792183412424152773224381646928911135496174621299924524112331962952547214129323\n2729194232211462151119459711313211822621531163797412446181172721913949189555142143791213834886518948\n2754215791553781642269915399358262512494443343121198134218639979927842122994421127962456193396136699\n8271611911227341219949383285981988595252121593129637541475392137413899839912239225135459931743267972\n1332131171959982211855642861212718138325111114239233279171544919563891942832117949581464743292494391\n5144166291493181763279457131141327146537961189933599395341461291371919123151359118199368625742376117\n1636191619675379923419873222911119821251129276117414194193998142948136713325351617571519395951914216\n6863238911796142259595658671251783127926389189168272138182549591741951937121824471372228139189226966\n1398611275788896954682838421735924943417195641181143853286733633811931911189111341679192676374118319\n7425912442414194918974222966129621141925526265112323617731363617133673511925955331462169117293471296\n8311915233126172592295451734596934578641991127992454954549337724839691119685881916643781992923996572\n7168461267393883112656311283191232322499117185912521188899182419918914911212513325386275539329721472\n4418929132119621184239621272934448319225211997924183117861911136919317465941177911127948161449124731\n9271153581452542386794695144559617972331134217961265186239771199325391879412411821372724989746391111\n3752522113112162859371199119415298331514424128999524132149996846199915924629121214916277199845231181\n8461129155427192357991128752552628161188794894374724397322312139214838121389889613819783991892292158\n4999141138619713275215481369646529918918936887478711111135124192624311852137911719581517593373711112\n9228956819912994881488113276489314945969876898139152128325918347915249723837311238669717631918756448\n1272313111232619631582529173782417217912411245971957172218911853664936489571219898133821585115925152\n1324983253974657485632276593196749111921819449973115611494598217724911344731933114417612111528118291\n8521515271325847484517496514692991413334913117194153459926716822674627611191634943962214123151399931\n1141639315518932691635973515217951611118329247113938399181114133617465682162932426295992195929458883\n8229351197214731215324515139273121165384915712119675514893281751526119183679227515364941156137548174\n6116894132781317191382191142114151317798773795981911112434921641114411589131331717998932176521898319\n5362677393912312215419378899211815319464811111851912257961211293814411559971191515896993251933358962\n6926527339383986515331739126963132928923957918814875739969162479336291216879152811764569629328261149\n7598541186247351172883789213137911264491891391569216562276119911413437411237411934123311912324427449\n"
  },
  {
    "path": "advent-of-code/2021/inputs/16",
    "content": "40541D900AEDC01A88002191FE2F45D1006A2FC2388D278D4653E3910020F2E2F3E24C007ECD7ABA6A200E6E8017F92C934CFA0E5290B569CE0F4BA5180213D963C00DC40010A87905A0900021B0D624C34600906725FFCF597491C6008C01B0004223342488A200F4378C9198401B87311A0C0803E600FC4887F14CC01C8AF16A2010021D1260DC7530042C012957193779F96AD9B36100907A00980021513E3943600043225C1A8EB2C3040043CC3B1802B400D3CA4B8D3292E37C30600B325A541D979606E384B524C06008E802515A638A73A226009CDA5D8026200D473851150401E8BF16E2ACDFB7DCD4F5C02897A5288D299D89CA6AA672AD5118804F592FC5BE8037000042217C64876000874728550D4C0149F29D00524ACCD2566795A0D880432BEAC79995C86483A6F3B9F6833397DEA03E401004F28CD894B9C48A34BC371CF7AA840155E002012E21260923DC4C248035299ECEB0AC4DFC0179B864865CF8802F9A005E264C25372ABAC8DEA706009F005C32B7FCF1BF91CADFF3C6FE4B3FB073005A6F93B633B12E0054A124BEE9C570004B245126F6E11E5C0199BDEDCE589275C10027E97BE7EF330F126DF3817354FFC82671BB5402510C803788DFA009CAFB14ECDFE57D8A766F0001A74F924AC99678864725F253FD134400F9B5D3004A46489A00A4BEAD8F7F1F7497C39A0020F357618C71648032BB004E4BBC4292EF1167274F1AA0078902262B0D4718229C8608A5226528F86008CFA6E802F275E2248C65F3610066274CEA9A86794E58AA5E5BDE73F34945E2008D27D2278EE30C489B3D20336D00C2F002DF480AC820287D8096F700288082C001DE1400C50035005AA2013E5400B10028C009600A74001EF2004F8400C92B172801F0F4C0139B8E19A8017D96A510A7E698800EAC9294A6E985783A400AE4A2945E9170\n"
  },
  {
    "path": "advent-of-code/2021/inputs/17",
    "content": "target area: x=153..199, y=-114..-75\n"
  },
  {
    "path": "advent-of-code/2021/inputs/18",
    "content": "[[[[2,5],4],[[1,0],[8,3]]],[[2,[2,4]],[1,[3,3]]]]\n[[[2,2],[[4,3],3]],[[[8,6],3],[3,7]]]\n[[[9,[4,1]],[9,0]],[6,[6,0]]]\n[[[3,9],[[4,4],[2,5]]],[[9,[8,4]],8]]\n[[[[0,0],9],[[9,3],[8,2]]],[2,[1,3]]]\n[[[8,4],6],[[5,1],[3,6]]]\n[[[6,[7,6]],[[2,6],5]],[[6,4],2]]\n[[1,[9,7]],[[[5,9],[9,5]],[[7,0],1]]]\n[[[[5,8],[9,4]],[[9,3],[7,8]]],8]\n[[[0,9],[[6,0],7]],[[[7,7],6],[[9,7],[0,4]]]]\n[[[[4,3],[9,5]],[7,[7,3]]],[[[2,8],9],4]]\n[[7,5],[8,1]]\n[[4,6],[[[0,6],6],[7,4]]]\n[[[1,8],[[1,4],[1,6]]],[3,4]]\n[[[6,5],[4,[7,3]]],[[[0,1],[8,4]],[4,8]]]\n[[5,1],[9,[9,[3,3]]]]\n[[[[7,0],[2,5]],1],[9,[[2,7],[4,4]]]]\n[[[[5,8],8],0],[8,[1,[2,5]]]]\n[8,[[5,4],7]]\n[[[9,8],[6,7]],[[2,[2,6]],[9,6]]]\n[[[[2,3],7],6],[[8,6],3]]\n[[[8,[7,2]],3],[[[3,9],4],[6,8]]]\n[9,[[[6,7],[6,0]],[[3,9],8]]]\n[[[7,7],[4,7]],[[[9,8],9],[9,[2,4]]]]\n[[[[5,0],1],[4,[4,8]]],[9,[6,7]]]\n[[[[9,2],5],[1,[5,8]]],[[9,[0,1]],[3,8]]]\n[[[5,[2,5]],8],[2,[0,[9,3]]]]\n[[7,[[8,4],[8,4]]],4]\n[[[[3,3],4],[[0,0],[5,5]]],[4,5]]\n[[[[9,3],[9,3]],2],[5,3]]\n[[[9,5],[1,4]],[[7,1],[3,[6,5]]]]\n[8,[[[1,1],[0,1]],[9,[3,6]]]]\n[[[[4,4],7],[0,3]],[1,5]]\n[[[3,[0,8]],8],[5,[7,5]]]\n[[[[9,6],2],7],[[5,[3,7]],0]]\n[4,9]\n[[[5,[1,3]],[[9,5],6]],[[[7,9],5],3]]\n[[[[3,9],[7,2]],[5,[8,8]]],[1,9]]\n[[[[7,8],8],[[9,0],[5,1]]],[6,[[1,0],[3,3]]]]\n[[[[5,8],1],[[8,6],[2,9]]],[[5,1],6]]\n[[1,7],[[5,[3,2]],4]]\n[[[[3,1],2],[0,8]],[3,[4,6]]]\n[[9,6],[0,[[5,2],[1,1]]]]\n[[[[1,8],8],[[9,0],3]],[[6,[2,8]],[[6,4],[6,0]]]]\n[[7,[[3,2],[9,0]]],[[[3,2],[2,8]],[[5,5],[9,2]]]]\n[[[[2,5],[3,1]],[7,[9,6]]],[[[7,0],7],[2,[9,1]]]]\n[[[[1,6],9],[1,[6,5]]],[[8,[4,1]],6]]\n[[[7,[4,6]],[[2,7],[6,6]]],[8,0]]\n[[9,7],[[[0,7],5],[[1,4],[1,3]]]]\n[[[1,[8,2]],[[0,6],[9,0]]],8]\n[[[4,0],[7,[3,3]]],[9,6]]\n[0,[[[6,9],7],[[0,6],1]]]\n[5,[[4,3],[[8,3],[5,7]]]]\n[[9,0],[0,[[7,8],[1,8]]]]\n[[[[4,3],[5,6]],2],[[2,3],1]]\n[4,[[9,9],[[1,8],[9,2]]]]\n[[[[6,9],5],1],[[[7,4],[8,1]],3]]\n[[8,[5,[2,6]]],[[[2,7],6],[6,0]]]\n[[[[6,8],8],6],[[[5,7],2],[[6,5],[3,0]]]]\n[[[1,[2,5]],3],[5,[4,[6,6]]]]\n[[[[4,9],8],1],[9,0]]\n[[1,[0,[5,7]]],[[1,[5,9]],[[3,2],[1,7]]]]\n[[[[2,9],[2,7]],[[4,2],5]],[[[9,1],[7,2]],[2,[7,5]]]]\n[[[[5,7],[8,9]],[5,[7,9]]],[[7,[6,6]],[7,[8,0]]]]\n[[[[6,6],[4,6]],[4,[7,8]]],[1,[[5,5],[1,9]]]]\n[[[[4,3],8],2],[[9,[4,0]],[8,[7,0]]]]\n[[2,[7,5]],[[[0,1],1],[8,[3,5]]]]\n[[[4,[4,2]],[[0,4],9]],[1,4]]\n[[[5,5],[5,6]],[[0,[4,2]],[[7,8],[5,6]]]]\n[2,[[0,[9,1]],[[1,7],[0,0]]]]\n[[[5,[4,8]],1],9]\n[8,[[2,1],[3,0]]]\n[[[[6,5],[1,1]],7],[[[7,5],3],[0,1]]]\n[[[[0,3],7],7],[[[4,8],[6,1]],[[6,1],9]]]\n[[[[4,8],9],[1,0]],[6,[4,[4,8]]]]\n[[[[8,0],[5,1]],6],1]\n[[[[6,6],[7,7]],[[4,3],[2,6]]],[[3,5],[[7,0],[7,3]]]]\n[[1,[5,8]],[[[3,7],[9,6]],[[4,8],[3,4]]]]\n[[[1,5],[8,2]],[[[3,1],5],[4,1]]]\n[[[[6,3],5],8],[[9,[3,6]],[[3,5],[6,9]]]]\n[[[7,[5,4]],[0,[6,0]]],[[[7,7],[1,1]],[[5,1],7]]]\n[[[1,5],[[8,6],0]],5]\n[[[[0,8],[6,0]],[[3,0],9]],[[[7,1],2],[4,2]]]\n[[[6,[8,7]],[2,[2,0]]],[9,[7,[6,6]]]]\n[3,[[7,[4,5]],[[8,5],4]]]\n[[[[8,0],[8,3]],[[5,4],[1,6]]],[[0,[8,5]],3]]\n[[[7,2],1],[9,[[3,8],4]]]\n[[4,[7,[9,9]]],[3,8]]\n[[[[7,1],9],[[6,9],[9,6]]],[2,0]]\n[[[[6,2],9],[3,[3,9]]],[[8,[3,4]],[3,7]]]\n[[4,9],[8,[5,[9,8]]]]\n[3,[[9,[9,7]],4]]\n[[[[5,9],6],[1,[3,1]]],[4,[1,[3,8]]]]\n[[[[7,6],2],3],[[0,[1,8]],[[4,9],[4,3]]]]\n[[3,[[8,1],[3,8]]],[[[2,0],[0,8]],[[7,0],9]]]\n[[[[9,7],[9,3]],[[5,8],6]],[[[6,2],0],[2,4]]]\n[[[8,[9,7]],[[5,1],[1,4]]],3]\n[[7,[[5,6],[2,7]]],[[[7,3],0],[1,[0,6]]]]\n[[2,[[5,5],2]],[[3,[7,2]],[[7,1],8]]]\n[[[[2,4],[6,8]],[0,[7,5]]],[[3,[2,5]],[7,7]]]\n"
  },
  {
    "path": "advent-of-code/2021/inputs/19",
    "content": "--- scanner 0 ---\n-880,-557,778\n-611,290,670\n598,502,694\n627,-521,631\n-908,-626,915\n-667,517,-416\n653,-608,742\n619,-567,601\n-541,508,-276\n-573,475,-350\n616,389,617\n658,483,734\n-501,223,776\n-92,5,101\n-966,-685,-334\n310,-833,-657\n-879,-602,773\n472,-843,-557\n472,-871,-567\n-510,239,817\n-861,-803,-266\n783,524,-377\n-878,-591,-260\n815,640,-317\n-16,-141,-1\n657,597,-394\n\n--- scanner 1 ---\n-342,623,-335\n437,-326,644\n-751,454,509\n748,716,528\n-785,566,599\n53,-5,-74\n513,-321,703\n-749,-226,-474\n588,626,-626\n-20,119,90\n524,-325,650\n-639,-293,-580\n-436,-750,548\n669,671,572\n-370,554,-472\n-371,599,-477\n528,523,-532\n503,-433,-410\n486,-567,-427\n-541,-724,467\n-433,-711,594\n-689,495,689\n519,-502,-310\n655,503,-676\n-740,-242,-433\n728,797,546\n\n--- scanner 2 ---\n-447,446,-705\n623,695,-536\n-532,-388,322\n349,542,589\n-467,590,-578\n-498,650,320\n761,-419,-459\n298,689,690\n-543,645,321\n534,-478,627\n-93,-60,24\n-570,496,-638\n282,648,699\n48,-137,-88\n567,-404,659\n-567,787,292\n810,-519,-397\n-618,-568,-794\n576,-544,533\n558,812,-569\n489,712,-553\n-744,-394,339\n-625,-611,-753\n819,-575,-440\n-569,-592,-825\n-626,-462,234\n\n--- scanner 3 ---\n339,-815,388\n-500,420,-617\n-495,-671,-609\n-526,333,-506\n-370,-712,502\n719,347,-563\n787,-838,-639\n716,250,670\n-338,-828,442\n717,335,667\n-681,683,692\n-681,655,682\n854,306,-541\n-843,645,782\n-537,-577,-492\n-555,-690,-569\n-496,-785,519\n785,247,-677\n423,-840,474\n329,-909,487\n-534,379,-476\n771,-983,-606\n-33,-41,127\n631,-897,-674\n554,240,687\n\n--- scanner 4 ---\n-107,-126,10\n-622,461,-286\n-558,-808,-479\n-550,-803,612\n-56,0,159\n557,315,573\n-377,758,630\n-675,-766,-385\n647,411,502\n-661,-777,525\n-598,-748,-498\n552,667,-704\n315,-485,663\n-514,730,561\n502,-533,608\n-519,729,606\n467,349,461\n505,-810,-622\n413,-899,-635\n391,-440,662\n-475,360,-235\n425,559,-717\n506,664,-743\n-691,-769,571\n394,-748,-744\n-516,351,-219\n\n--- scanner 5 ---\n-738,-555,723\n-662,510,693\n-694,-436,671\n322,-502,799\n-73,73,-94\n-813,-399,-583\n388,-574,840\n-827,-610,-513\n627,856,-730\n-662,414,-785\n346,-644,754\n724,825,401\n-824,-574,-637\n-653,623,561\n-549,414,-712\n464,-365,-561\n503,-392,-428\n-468,436,-812\n676,746,-667\n701,845,-823\n715,834,446\n557,790,356\n520,-310,-383\n-725,561,553\n-741,-497,785\n\n--- scanner 6 ---\n498,-465,753\n-291,-666,829\n568,-977,-581\n-599,740,826\n708,713,795\n851,686,-818\n-411,-886,-379\n422,-891,-574\n92,-196,0\n441,-978,-422\n-750,631,807\n813,739,714\n816,700,668\n560,-506,573\n-568,438,-378\n-481,-844,-293\n-553,-910,-334\n-389,430,-288\n-5,-12,128\n464,-577,663\n702,614,-783\n-564,308,-288\n-336,-667,905\n-661,618,715\n-384,-612,718\n675,645,-768\n\n--- scanner 7 ---\n650,-645,583\n-548,631,-805\n631,-833,-572\n645,-597,667\n607,449,671\n-856,723,531\n-159,-19,-111\n673,363,591\n-380,-625,689\n663,473,-639\n-506,792,-879\n-445,-665,687\n-932,-509,-946\n695,-721,-572\n-21,-134,12\n-897,783,484\n553,324,644\n485,498,-648\n-743,740,579\n-762,-575,-965\n736,-825,-707\n-394,-443,661\n-834,-564,-882\n-458,582,-873\n813,-587,573\n580,330,-627\n\n--- scanner 8 ---\n-535,-646,373\n49,64,7\n712,545,482\n-413,428,-787\n-564,-583,-650\n-502,520,-774\n845,-611,346\n778,-513,-798\n-872,406,510\n490,330,-589\n-564,409,-896\n-33,-62,-155\n320,432,-615\n-543,-676,419\n-546,-660,-537\n776,-475,287\n620,491,492\n762,-546,-943\n-827,330,511\n-504,-543,-631\n710,-589,387\n-509,-535,460\n469,421,-592\n622,-478,-857\n443,548,498\n-779,517,456\n\n--- scanner 9 ---\n-691,697,-504\n606,-525,-831\n-708,312,884\n604,-422,-859\n-879,-787,632\n-805,-755,599\n582,-530,-757\n-864,331,826\n-672,625,-560\n369,295,745\n394,311,803\n865,-899,630\n-889,-467,-679\n-895,-450,-467\n-715,666,-553\n-764,269,875\n814,-826,548\n-739,-661,641\n669,693,-398\n835,-907,511\n323,329,771\n503,633,-342\n41,-84,54\n459,696,-317\n-821,-362,-561\n\n--- scanner 10 ---\n700,-673,733\n565,566,545\n-655,-386,666\n-35,27,-40\n-440,-441,-330\n-588,352,-383\n432,723,-488\n-529,-330,581\n-528,-379,-456\n739,-726,613\n280,-566,-837\n-500,-339,-395\n733,545,640\n340,-613,-796\n271,797,-446\n614,-753,667\n-435,429,515\n-383,391,594\n-520,-401,719\n590,557,723\n-488,390,504\n-545,334,-423\n481,791,-398\n-646,448,-404\n323,-661,-683\n\n--- scanner 11 ---\n-523,667,-763\n-761,-605,298\n553,-663,332\n748,-670,-550\n427,451,-834\n481,495,-926\n-234,733,382\n-234,552,415\n746,522,514\n876,432,518\n140,27,-65\n-561,474,-740\n-537,-491,-834\n-571,597,-800\n754,432,693\n-690,-669,445\n-325,661,340\n491,494,-716\n751,-761,-571\n-547,-647,-812\n444,-682,483\n-740,-625,380\n-476,-528,-761\n725,-659,-401\n566,-571,421\n\n--- scanner 12 ---\n534,-664,530\n506,566,785\n-651,-482,723\n-531,374,-562\n933,613,-583\n444,-668,400\n-658,400,528\n-749,-896,-575\n535,-821,-794\n-7,-29,73\n-647,251,551\n-534,643,-546\n-559,-571,710\n-749,421,525\n463,684,849\n843,657,-425\n106,-110,-59\n507,776,795\n-670,-633,832\n449,-751,-752\n-673,-941,-574\n490,-679,-818\n-588,551,-556\n888,648,-416\n444,-843,522\n-562,-848,-520\n\n--- scanner 13 ---\n661,639,-831\n-683,-841,-609\n-555,-518,629\n859,376,374\n-559,681,-427\n713,528,-837\n-711,637,549\n-750,-824,-776\n-401,588,-408\n-477,611,-393\n-606,645,684\n787,387,291\n720,-842,-411\n529,-822,-422\n-655,-918,-710\n-638,-661,617\n-670,533,684\n483,-770,383\n6,-65,-36\n531,-980,377\n502,-841,-406\n755,671,-764\n-460,-686,608\n129,9,74\n957,321,310\n573,-819,451\n\n--- scanner 14 ---\n538,411,-771\n-675,874,471\n-837,-690,-720\n348,-523,-489\n316,-298,707\n-523,-771,931\n-731,696,526\n-692,829,553\n431,508,964\n-543,-739,767\n499,501,861\n559,425,-605\n414,-293,789\n386,549,964\n363,-287,605\n-413,-702,878\n-636,-698,-697\n414,-514,-578\n-494,434,-684\n-568,527,-695\n-124,-5,130\n-690,-633,-734\n330,-424,-459\n-519,590,-585\n616,362,-777\n\n--- scanner 15 ---\n-391,431,-743\n592,-436,-482\n-474,-609,-535\n516,-464,478\n706,705,-770\n512,-502,-568\n-7,-73,54\n-789,642,691\n-452,-577,411\n-346,407,-601\n-34,95,-83\n600,-459,526\n732,669,629\n678,679,721\n-699,800,735\n-744,809,726\n893,650,-818\n-305,473,-673\n675,663,452\n-592,-640,462\n817,651,-863\n-422,-653,-654\n610,-296,468\n539,-556,-443\n-360,-656,-596\n-584,-568,524\n\n--- scanner 16 ---\n711,389,-690\n-640,572,459\n-579,475,-510\n-447,-653,-613\n-587,452,498\n-663,480,-462\n690,-772,542\n633,-758,-703\n-667,518,584\n652,640,633\n576,430,-586\n720,-726,550\n655,-799,-838\n643,462,608\n-569,312,-452\n-501,-663,-705\n576,494,-698\n579,-685,516\n631,545,465\n519,-858,-769\n90,60,61\n-362,-635,879\n-504,-647,-436\n-286,-634,834\n-473,-689,786\n\n--- scanner 17 ---\n-670,636,302\n433,641,-915\n-454,541,-877\n-590,-680,-722\n-678,601,506\n-31,3,-135\n741,657,647\n467,-357,313\n685,-356,318\n496,-218,-470\n-673,-537,-710\n-465,488,-838\n877,642,566\n448,-428,-476\n-495,-512,-701\n88,176,-48\n538,-379,-544\n-690,-280,617\n-585,672,383\n473,598,-933\n-718,-357,516\n775,649,632\n-785,-374,683\n494,-376,329\n-544,436,-876\n454,699,-819\n\n--- scanner 18 ---\n484,-782,-326\n-828,475,486\n725,568,651\n-879,557,413\n-467,-815,-419\n-89,-133,-37\n-596,-830,782\n-760,408,-799\n791,526,557\n747,648,-673\n584,-792,-488\n-849,438,405\n824,691,-831\n-618,-932,890\n764,575,-799\n-459,-820,-543\n807,-634,950\n-620,-904,787\n574,-820,-488\n-619,479,-825\n-80,55,77\n881,-540,862\n-435,-841,-339\n875,-752,845\n865,559,525\n-752,370,-817\n\n--- scanner 19 ---\n278,-537,-508\n-527,901,494\n-98,173,111\n-619,812,507\n-666,-665,425\n-521,788,-749\n-585,935,-820\n-86,41,-48\n245,-556,-553\n-508,750,385\n322,542,-664\n561,768,744\n383,527,-541\n-565,853,-799\n508,-459,843\n-539,-557,412\n361,-358,894\n-620,-662,386\n-710,-796,-605\n484,750,631\n323,514,-585\n444,810,650\n402,-349,910\n-723,-641,-724\n420,-563,-614\n-608,-760,-696\n\n--- scanner 20 ---\n431,-704,-682\n-147,26,66\n-696,-545,-708\n426,-620,-634\n445,535,-446\n381,535,-558\n-702,-488,-531\n560,610,790\n-848,614,-306\n505,548,698\n-907,478,-375\n536,492,879\n-483,757,852\n-533,901,844\n-807,592,-441\n-477,-539,567\n414,-641,417\n-625,873,822\n-593,-578,691\n464,-627,539\n-28,-46,-73\n340,670,-454\n263,-610,-692\n520,-680,479\n-466,-669,669\n-712,-542,-439\n\n--- scanner 21 ---\n-266,486,648\n578,-611,-708\n-818,735,-464\n-759,-456,-789\n-691,-545,727\n407,-548,624\n-407,414,606\n496,-666,600\n-706,-562,774\n-278,471,630\n634,761,-544\n747,571,696\n-676,657,-492\n-698,-556,767\n63,-153,67\n807,624,640\n525,774,-558\n626,-676,-624\n624,-631,-871\n-627,-432,-708\n550,778,-542\n-734,-461,-727\n-742,786,-431\n869,585,746\n588,-604,655\n\n--- scanner 22 ---\n-658,443,-873\n688,-773,-852\n94,86,-43\n365,435,679\n316,-602,678\n-101,19,38\n-343,-416,-420\n-561,407,-825\n-462,383,561\n-405,-615,824\n-359,-493,-424\n-404,-525,719\n-443,-536,772\n636,-689,-733\n749,-675,-833\n372,-687,552\n325,374,707\n387,-740,687\n-564,-448,-433\n623,594,-764\n-348,402,662\n531,670,-784\n629,524,-772\n427,309,767\n65,-103,67\n-684,443,-722\n-366,362,619\n\n--- scanner 23 ---\n435,-295,689\n376,-489,-751\n-776,528,-600\n756,497,-606\n-659,601,725\n-827,580,630\n342,-579,-639\n426,-366,551\n-413,-413,-550\n-506,-524,-604\n394,425,766\n-833,-691,657\n-684,592,547\n341,464,755\n-794,-638,537\n785,355,-582\n-750,639,-687\n561,-351,604\n-144,111,172\n-458,-337,-549\n289,426,676\n25,-25,67\n438,-669,-710\n-742,669,-641\n-708,-718,603\n757,492,-651\n\n--- scanner 24 ---\n-111,-95,111\n361,-657,765\n-582,632,729\n505,-558,752\n-589,-581,768\n-530,716,848\n-893,-431,-711\n748,709,611\n-831,683,-691\n657,337,-287\n-853,-492,-683\n-791,-366,-771\n740,-662,-280\n63,-50,-45\n-846,630,-556\n382,-527,879\n737,-458,-369\n819,-451,-281\n656,803,580\n701,756,570\n567,372,-315\n645,506,-298\n-595,-651,760\n-469,618,829\n-902,545,-682\n-687,-727,780\n\n--- scanner 25 ---\n538,-604,597\n-69,170,-40\n486,-485,641\n424,-543,644\n-475,-696,544\n455,-396,-443\n-800,563,438\n-448,-571,490\n498,456,-351\n688,967,784\n369,-466,-485\n-528,-657,424\n-587,479,-752\n-497,575,-823\n410,-538,-419\n598,939,749\n676,956,615\n650,437,-438\n657,583,-352\n63,30,10\n-677,513,-864\n-753,-276,-663\n-642,-369,-717\n-815,698,491\n-871,572,576\n-829,-321,-662\n\n--- scanner 26 ---\n603,-662,-789\n921,616,705\n838,688,716\n-837,496,-760\n528,-777,447\n541,-717,-697\n-711,-791,683\n663,-882,455\n-705,248,837\n-627,-796,635\n-733,234,655\n-634,-758,-538\n902,786,771\n485,-686,-878\n117,-22,-80\n528,-841,559\n613,562,-659\n-731,299,615\n-824,482,-651\n-648,-808,-416\n548,646,-707\n-687,-702,-478\n-617,-959,693\n-841,480,-735\n43,-158,54\n568,809,-661\n\n--- scanner 27 ---\n-688,503,355\n602,-599,627\n633,-605,-905\n638,-650,-906\n666,756,-490\n-8,72,-119\n-707,-336,446\n-789,531,278\n-474,551,-638\n491,-686,601\n461,-640,593\n-400,-616,-904\n-406,-404,-887\n-555,636,-674\n-678,543,-603\n550,631,678\n775,-581,-934\n-697,-364,446\n-855,436,372\n704,677,-438\n705,767,-543\n-191,149,-166\n-474,-522,-992\n538,548,535\n-797,-374,284\n529,726,510\n\n--- scanner 28 ---\n-713,-683,864\n710,829,-871\n569,-596,779\n888,752,850\n561,-775,869\n-637,-474,-537\n-425,637,-643\n-779,-611,823\n-544,681,380\n-474,747,-706\n126,-94,-57\n88,32,118\n525,-912,-725\n480,-912,-684\n824,634,807\n-598,-501,-404\n653,657,-808\n-755,-753,778\n-400,736,-799\n-581,-419,-359\n632,823,-822\n439,-600,869\n593,-809,-732\n834,844,806\n-386,725,470\n-377,716,425\n\n--- scanner 29 ---\n423,-939,368\n496,689,481\n907,-613,-518\n-502,-588,597\n492,-886,258\n-442,-468,-499\n-476,281,-751\n680,570,-569\n561,726,535\n-322,-453,-521\n671,481,-503\n-15,4,-8\n-48,-164,-115\n901,-797,-569\n-445,-665,573\n504,712,682\n-417,456,-807\n-398,384,755\n-320,-554,-541\n896,-715,-471\n-557,396,-782\n-571,416,772\n-454,-643,535\n455,-775,388\n770,451,-485\n-477,321,741\n"
  },
  {
    "path": "advent-of-code/2021/inputs/20",
    "content": "##.##.#..###....##..##.#.##...#..#..##.####..##...###.....##.####.##.##.##...####.######..#.###.#.##..###.#..#####...#.##.#..#.#.#..######..###.##.#..##.#..##..##..#...###.##..####.#..#....#####.#.###..##.....#...#.##.#####.###.###....#.#..###.##.##.#..##.##.#.##..##.##.##..###.#.#....#.##..###.###.#.##......#.##..#..#.#...##.##.....###...#..#...###..##.####..#..##..#.#..###......#.#####....#####..###..####...###.#.####..#.##..#.#####..##...##.#.#.#...##.#...#.##.##..#.#.##....##.####.#.#..#.##.#.#..#..#.#.\n\n.#..###.....###.#..#.#.###.#..##.#.#..#.###.#..##..#.#.#.##.##..###....#..#.#....####.##...##....###\n.#.#.##.#..###...#.#.####..#...##.#.#...#..#...#.###...##..#.#..#.#.##..#.##..#.###.##..##..#...#.##\n##..##.#....#...#....##.#..####..#.#.####....#.##..##.###...#..#..######.####....#..#.#.#.###..#.###\n.##.#.#..#......##......##.#.#.#.###...###.#.##...##..#..#..######.#.##.###.#...#.#.####.#.#.####...\n...#..#####..#....###...#.......#.#..####..#....##..#..####...#...#..#.....#..#...#.#.....##..####.#\n##..##.....###.#.##.#.###.###.#.#####..#.....#...##.#.##.#...##..#####...##.###..###...#...#.##...##\n#.#####..###...#.####.#.#.....##...###.#..##.##...#...##.#..#.###..###.#.##..#.##..##.###.#.#.#...#.\n##...#.#...#..####.#.#..###...#####.#######.##..###..#.#.###.#.#.#..#####.##.#......##.#.#.#..##..#.\n.#.#.#.#..#...##.#.#..###.###.#.#...##..#..##.####.#########.......#.#.#.#.#.#.#..##.#..#..#....##.#\n#######.#.##.##..#......#..#...##..##...#..###.#...#....#.####.##.#.##.....###...##.##..#..##...####\n#.###.#....##.##....#.....####.#.####...###..#..###..#..###.##..###.##.##....#####.##...###.#.##..#.\n...##...##.###.#.#..........##..##.###..#..#....#..#...#.##.#..####.#.#.###..###..#........###.#.##.\n#....#..######....##.######.#.########....#.###.###.#####.#.####.#.....#..#.###.##...........##.###.\n..##.#######.##.#..#.#.#.###..........#.#.#...##...###..####.#.#....#.####.#..#.#####..####.##.#.###\n...###..#...#.###.#.#######..#####.....#.##.##..##....##....#####.#..#.##..##...##...#.#.##...#.##..\n.#...###.#.....#.##.######.#.#..#.....####....#..###.##.........#.###.....#....#.###.....##.#.#.####\n.###.##..###....##...##......###...#....#.##....#...#.#.####.#.......#..#.#.######...###........#..#\n.###..#...#..#..##....##..#.#.#....#..#.#.....#.##.....#.#####..##...#.###..#...#.##..###.####.#.###\n#..#......#####.###.#.##.###...#.#..#....#.##..#..#....#.#..#.##.###...####...##.######.#...#.#..#.#\n.#..#...#####..#.#.#.###.#..##..#.##.#...#..#.##.#..#.##..#..#..####.....#......#.#.#.##...#.##..###\n..#....#..#..##.####.###.#..####...###.#.####.###.#.##....##.....#.##.#.##....##...#....#.##.#####..\n######..#..#...##.#........##.##.#...####...##.....#.##.#.#.#..#.#..##.#...##...#.#.....#.#..#..####\n##...#....#.#.#.....#.#.##.#..#...###..######...###..#.#.#....###.####.#######.##.#.#....#..###..#..\n##.....#....#.#.##.##.#....#.###...##.##.#....##.#####..###.##.#...#..##..#.###.#.#.#...#.########..\n.......###.#.##.....#.##..##..#.#..#.####.#.#...#.##.###.#.##...#..####......#.##.###.#.#...#.....#.\n.##.#.##...#..##.#.#...###..#.#...###.##..#........##.#.##...##.########.......##.#.##.####..####.##\n#.#..###.#...##.....#....#...##..##.#...##.....#..#####...###.##....#####.####.##.#...#...####....#.\n###.####.##....##.#.##.##.....#.##..##.##.##.#.#.##.#..#.###.##..#.##.....#.#...##.##..#.#.##.##.###\n#......##..##.##.#.#####.##..###.....#.##.........##..###.##..#...#..###.#..#.####...#####..#..###.#\n#.##.#.#...##..#..#.#..#.###.#...#..#...#####....###....#..#.###...#.###.#.#####.#..#....##.##..##.#\n..###..###.#..........#.....#...##..##.####.#.##.##.#.#.#..##.#..###..#..#..#...##..#.#..#.#####.#..\n.###..#.###..###..#...#...##.#......####...####..#..###.#.######...#.###..##.......##.##.########.##\n...#...#...#..##....###.#.###..##.#.#...##....#.#...#.#.#....#..####.####.####..#.#######.#.#.....#.\n.#...#....##....#.##...##...##.#..####.....####..##.###..#..##.........##..#...####..##......##.#.#.\n##.####.#...####.#..###..#####.#.#######.#.#...###..###....##..##..##..#......#.#..#.###.###.##.#..#\n...###.##.####.##....##.....#.#...##.#..#.#.#.##..#.#.###..#..#..##.#.##.#..####..####.....#.#.#..##\n#.#.##.##....#.###.##..####.##..#.#..##..#.###.#..###.#....##..#...#...#..#.#.#.#.#....##...##..#.##\n####.####.#####.####.##..#.###.#..#..#.....###......#......#...#.#.#....#....#.##.###..#.#.##.#####.\n.##.#..#.###.#.#.###.....###.######..#..##.###.#.##..#..#.####..#.##.##.#.###..####..#..##.#########\n###..######......#...#..###.##.#...######....#.###....#...###....##.#..##..##.#.##.#....###.###..##.\n#....###..##....###...#.#...##..##...#.......#.####.....######..###....###..##...##.#..###.#.##....#\n.##.##...##..#..##...########.##..##.##.#......##.##..#####.#.#..######.#####....#.#.....##..####...\n#.......##.##.#..#....#.#.###...#.##.##...#..#.#..#..#.#.##.#...##.###.###...#.######......##..###.#\n##.###.######.#..###..##.#.#.#.........##...##.####.#.####............###....#...#..#.#####.#..###.#\n#####...#..##.#.#.#.#.#..####.##.#####.###.###...###.###.#.##..##...##..##..#.#.#...##...#.####..##.\n...##..#...#..#.###..#...#.##...##.##..#.##.#..##.#..#.###....##.#######.###.#.###..#.###..######.##\n.#..####....##.#..#.#.######.#..#...##..#....##.#....##.##.###..#...##.....##.###..#.##.....##..#..#\n....###.####.#..####.....#....#.###...#.....#..##..#.#####.###.####.#.....#####.......###.###.##..#.\n..#...#..#.##..##.###.##......#..#.##..######..####..#.#####..###.######..####...####..#.#####..#...\n####....##...#.##.##.####..#..#.#...#..###.##..###...#......#.#..##..#.##....######.........##..##.#\n..#...#.####.###.#.#..###..#.####..#.#.#.#..#..#..###.#...#...#.##.#.#####.##..#.##.##.......#..##..\n##...#.##...##.#..###########.#.#.#####.#.##.#####.#.#..##.#.#.####.......#....#.#....####.#...###.#\n..#.##...##..##.#.#......###.#...#####.....#...#..####...########.###.#####..##.###...#.#.#..#...###\n#.##..#####.#...#..#.#...####.........##..#..#.#.#..##..#.##...###....#.##..#..#.#.#.#.#..#......#.#\n.#..##..##.###.##..##...##.#.####..##.###.#..#.###.#####..#..#...##..#.#####........#...###.##.#####\n..##..#.###..########.##.#....###.####.#.#..#.#.#...#.#.#..##...##.#..##..##..#.###.##.####...#.....\n###.#.###.#.......#.####.###.....#.####.#.#..#...###....#.####........#...##.##.#..#...####.#######.\n.##...#...#....##.#.##.###.....#..#..##.#..#..#####..#.##.#####.#....#...#.#.....####.#.###.#.#.###.\n######.#.#..#.###.#..#.######.#.#########..##.#.#...##..###.....###...#.###...#.#..###.#.###..####.#\n..#.#.##.#.###.#....#.#.####.#..#.##.##.#..###...###...##.#.#.##.##.#.###.#.#...#.#.#..#.##.#####...\n###.#...#.#..##...#.....##.#..##.#.###.#..#.##...#......###..##.###.....##.##....#.##.#..#####.#...#\n#..#..########...#.#####.###.#...#####....##.#...##...#.#.######.##....###.#.######..#..##.##.#.#.##\n..#.#.#....#.#.#.#.#.#..##..#....#...####.##..###.#...#.#.####.##.#....###.#...###.###..#.##.....#.#\n#####.####..#.#....#.#......##....##..#######....###.#.#.#.#.#.##.#..##.#..####.###.#...#.###..#.###\n#.###..#...###..#...##.#####.###...#.#.#....#######.##.##.###..##..#....##...#.##.#.#...#####.#.#...\n.##..##..##..###..#.#..#..#.#.#.#.#..##..###..####.#..###.#.#....########..###.#.#.##.########..##..\n.....##..#..####.#.#..#...#..#..#..#...#.#.#####.....#..#.###...######..###...#...#.##.##..##.##..##\n.###..####..###...#.####....##..#...#.#.#.....##.#.######....##..###..###.####.##...#......#..##.#..\n#...###..#..#.#.#..#..###.###...#..#........#.#.#.##...#.####..#.#.#...####..#.##.#..#....#...#.#..#\n#.######..####.######..##.##.#.####.....##..#.#.###.####..#...#..##..#..##.#####.#.#########...##..#\n.#.#...#.#..###....###..#....####.#....##..######.....#.####.###.#...##.#..#..#...#.#.#..#..####..##\n##..#.#..##..#####..#.###.....##.#.#...##.##..#.##.#......#.#..###.......#####...########..#...#..#.\n#..##.###.##.#..##.#..#...####.#.#...#.##..#.###.#.#..#####.###...#.###.####...##...##.#...###.###.#\n.#.#....#.##.##.####.##.#.##..###.###.....#..##.#####.....###............#.#.##.#.#..#.#..##.#......\n#..##..##.###.#..#.#.###.#####....#..#.#####.##.#.####.#####.#...#..######...#.###..#......##..#..#.\n..##.##.#...#.#..###....#.#...#.#.#####..###.###.#..#####.....##..#..#.#.#.#.###.##..##..####.#....#\n##...#..##.#.##..###.#..#..##.##...##....#..##..##.#####.###..#.#.##...##.#####.#.##.##....#......#.\n#.#..#.#.####......#.##....##.#....###...##.#####....###.#.##.######..###...#..###..####...#####.###\n.##.##...###.#.##.##........##..###..#.#####....##.#...#..#####.###.#...##...######.##...###.#..#...\n#...#...##.#....#.###.##.##.#####.###..##..#..##.##...##.#.#####...##..##..##........###..#...##.##.\n..##..##..##.#..#.#.###..###..##.#.#.#.#.#.......#.##.##.#.##.#####......##....#..#......#.####..##.\n.#.#.#....#..#...#..#.##.#.....####.#.###..##.#..#.....###....##.###...##..#.###..###...#.#.#..#...#\n..######.##.#####.##.######.##....###....####.....#..##..#.#####.#.#.#.##...###.#####.#......####...\n.##..#.#######..#...###..##.#.#.#...#...#####.#.#.##.#.....###..#.##..#.#.#.####.###..#####....###..\n..#...##..####....####..#.##...#.....####..#......#.##.###.#....#..#..##.####....###.#..#.###..###..\n.##..##..######.##....#.##.#..##.#.#.#...##...#.##.#.##.###..#..###..##.##..#...###..#.#.#..##.###.#\n####.#..##.#.###..##.##..#..###..#.#.....#.#.#.##..##..###.#.....#.##.#.#.##.###.###...####.#.##.#.#\n.##..#####.###.#...#######.#...#.#.####.####.#..#...#.#..#######..#...##..###.#..#####.##..#.#.##..#\n####..####.##....##.#.#.##.#..##...#.##.#.####...#.#####.#.##...#.#.##.##.#..#.###.#.##...###..###.#\n.#..##....##..#.##...##..####....###..#....####.#.###...###.#.#..#.#.##.##..###..##.#..###.##.#####.\n#.#....######....#....##.#.#.###.#..####...##.###...###..#.###.#..##.##....#...####.#.##....#...#.##\n...#..#.###.##.##....####.#.#.######.###....##.######.#..##.#..##...##...###..#######....#.##..#..##\n#....#.##.###.##......#....###.##.#..########.#####.##.#######.###.##.###..#.#.#.#...#########..#.##\n###.#..#...##.#....##..###.....#.#.#.##..#####.##.###.#.#...#.####.#..####.#....#####..##.#.#.......\n##...##...###...#.#.##....##.......#...#........####....#..#.###....#.#.####........##.#...##..#####\n.....#...#....#.#####.#..#.#.###.#..###..........#...########.#......#.######..#.#..#.##.#.#..##....\n..#.###.#..#.##.##..#.#...####.##.#.##.###...##.#..#..##.#.##...##.....#...##.###......#..#.######..\n.##...#..##.##..#.###.#.#..##.#..##..###.##..#.##.....#.#.#######..###.###.##.###..#.#...##..#.#..##\n#.#.#.##.##..###.##.#.##.##...#.##.#####.#.#.....###.##..#####.......#.####.#..#.###.###.##.#.#...##\n#..#..#.#...#..##..###.##..##.#.###.##...#....#..#...##.#####.##..##.#...###.#..##.###..####.##.##.#\n"
  },
  {
    "path": "advent-of-code/2021/inputs/21",
    "content": "Player 1 starting position: 1\nPlayer 2 starting position: 2\n"
  },
  {
    "path": "advent-of-code/2021/inputs/22",
    "content": "on x=-38..7,y=-5..47,z=-4..41\non x=-16..35,y=-21..25,z=-48..5\non x=-43..4,y=-32..21,z=-18..27\non x=-16..38,y=-37..9,z=-10..40\non x=-3..43,y=-40..13,z=-48..-4\non x=-6..43,y=-4..41,z=-6..47\non x=-29..15,y=-9..43,z=-39..5\non x=-37..9,y=-16..37,z=-1..45\non x=-28..21,y=-7..46,z=-10..36\non x=-26..27,y=-6..40,z=-18..34\noff x=13..30,y=32..41,z=-10..1\non x=-43..6,y=-7..46,z=-15..31\noff x=19..30,y=-43..-27,z=-36..-26\non x=-15..34,y=-41..10,z=-45..0\noff x=15..31,y=27..36,z=20..33\non x=-8..42,y=-44..6,z=-22..25\noff x=-37..-20,y=22..40,z=35..44\non x=2..46,y=-43..3,z=-17..36\noff x=23..34,y=5..16,z=-5..6\non x=-9..36,y=-47..7,z=-47..5\non x=-160..27861,y=57453..76567,z=10007..35491\non x=-34240..-12876,y=-87116..-51990,z=33628..53802\non x=-23262..4944,y=62820..88113,z=-7149..-1858\non x=-48127..-16845,y=59088..86535,z=-5102..744\non x=-54674..-32293,y=21567..47184,z=55761..72099\non x=-69807..-50439,y=-53937..-38431,z=14338..28485\non x=13123..34571,y=-74162..-53699,z=5810..32903\non x=-36751..-16860,y=49545..75658,z=-34660..-21694\non x=-68435..-62588,y=-40370..-6437,z=-39677..-23920\non x=-82974..-59309,y=18720..41775,z=-39850..-17189\non x=-72347..-41708,y=9850..18229,z=-53512..-34975\non x=-30894..4418,y=65635..84979,z=19530..39249\non x=15288..25235,y=-29448..1499,z=71472..85280\non x=-54686..-44312,y=36734..56590,z=-60370..-40555\non x=-5266..21740,y=-63065..-47319,z=-53244..-34997\non x=30363..46391,y=65963..73471,z=-16696..-1815\non x=8243..24278,y=-94018..-69081,z=4245..29009\non x=-37020..-23168,y=-72025..-55051,z=-35968..-10146\non x=-47068..-26645,y=-20779..13147,z=56626..75638\non x=-38276..-11929,y=-75280..-63708,z=19483..24673\non x=3913..16625,y=66848..92341,z=9711..32412\non x=-33513..-7553,y=-44460..-19203,z=53802..84399\non x=-46017..-22850,y=-46589..-32578,z=-70024..-47623\non x=48573..58330,y=2974..29593,z=34454..60055\non x=-10056..10090,y=8646..37530,z=-95368..-64816\non x=-40314..-23851,y=49027..75546,z=33133..59153\non x=9529..39846,y=-43216..-6720,z=66362..84337\non x=-45474..-33807,y=15249..40850,z=-72058..-42686\non x=51316..72889,y=-20375..8377,z=32410..56709\non x=-2105..32624,y=-78827..-73957,z=-36836..-9360\non x=28703..45480,y=7042..25778,z=-82005..-55614\non x=6954..42651,y=4674..37873,z=57207..93287\non x=29735..50615,y=17210..29568,z=64317..74832\non x=-71817..-57182,y=-52937..-34602,z=-16791..8172\non x=62789..73440,y=-8262..6641,z=-47239..-39833\non x=22253..33377,y=-66419..-35421,z=-76817..-56664\non x=-81664..-74289,y=-19781..2191,z=-47797..-9331\non x=-15501..3487,y=57147..69359,z=30481..53449\non x=65898..70034,y=-42224..-28303,z=-36101..-5313\non x=43494..54307,y=42390..54768,z=-48993..-31471\non x=-78098..-51348,y=-31792..-29005,z=-59011..-31680\non x=1733..29690,y=-76915..-65890,z=-51511..-21684\non x=15663..36026,y=-43573..-32068,z=54160..67763\non x=-15046..8020,y=73251..81288,z=-6407..6193\non x=-27828..-7924,y=-81275..-66773,z=-6446..19063\non x=53718..81429,y=8690..21113,z=-46849..-30403\non x=-36511..1151,y=59425..77413,z=7092..45917\non x=1629..15400,y=11693..34093,z=68313..91797\non x=-26483..210,y=1338..31754,z=-84816..-58477\non x=-83237..-62066,y=4539..25394,z=-51906..-28397\non x=-9149..923,y=-81989..-60157,z=-26789..-5365\non x=17517..37608,y=26598..46873,z=57508..64782\non x=-7119..11105,y=62942..83529,z=9625..26513\non x=-51514..-30945,y=20145..42149,z=-62845..-43704\non x=5756..29641,y=-22431..5811,z=63100..78564\non x=2390..19403,y=-20570..2836,z=62003..85329\non x=-30076..-15623,y=55291..75814,z=15603..36585\non x=31384..53207,y=-52113..-34713,z=-53230..-48671\non x=-22679..10340,y=13595..27259,z=74909..82901\non x=67880..82348,y=8971..27422,z=-2124..15487\non x=-18895..10483,y=-85666..-59455,z=34047..51125\non x=55861..76270,y=-63315..-43630,z=-14734..14650\non x=574..29499,y=-45563..-10582,z=-90533..-55006\non x=-69275..-42476,y=-59658..-25077,z=-52699..-28481\non x=-56824..-33936,y=-25868..8029,z=-82735..-53242\non x=-90068..-61105,y=25564..34118,z=-8753..8383\non x=-16748..-8507,y=-60001..-44220,z=39386..65527\non x=47454..61550,y=30183..42751,z=-48341..-40487\non x=-75242..-56708,y=-18345..7252,z=27135..42009\non x=-58608..-41635,y=-77670..-51210,z=-19528..-1735\non x=-52353..-35577,y=65342..71094,z=-34292..-10437\non x=-13904..390,y=-85050..-62408,z=-40671..-16675\non x=-70826..-61780,y=-28261..-8503,z=-43838..-22314\non x=23456..34852,y=-75129..-39146,z=-59367..-27639\non x=-21289..-10174,y=-4853..32679,z=-90593..-71383\non x=-37590..-9368,y=-75394..-60296,z=-44762..-24730\non x=-60024..-32249,y=59509..67462,z=-2182..22377\non x=-8113..11767,y=-35418..-18956,z=64722..86638\non x=46854..82238,y=40215..59083,z=-11037..11812\non x=49339..85055,y=28346..47525,z=5491..39152\non x=-50591..-22806,y=-33668..-17243,z=58370..72406\non x=54558..69946,y=-56413..-35097,z=-27088..7730\non x=-64262..-47635,y=-74110..-35937,z=13887..37783\non x=-51771..-28374,y=-60611..-46568,z=23665..55950\non x=-81107..-54757,y=-26037..7731,z=-40004..-22397\non x=-41417..-19367,y=54161..90953,z=12299..44226\non x=-89805..-55266,y=-31643..-22791,z=-15805..-3577\non x=-78290..-54183,y=8949..18096,z=-47920..-37582\non x=-44972..-27636,y=-56757..-33114,z=43862..61796\non x=34720..58327,y=40641..60954,z=5688..14788\non x=-56983..-26271,y=-69520..-43968,z=5457..30306\non x=52234..80932,y=-28451..-12788,z=25327..31570\non x=-20283..-10624,y=55145..77699,z=-55377..-51731\non x=-8918..23862,y=-26789..-7902,z=78219..83878\non x=-81127..-49088,y=-33284..-13921,z=-50207..-32847\non x=3968..12957,y=62162..90459,z=-32604..-13525\non x=50536..63270,y=47029..71173,z=25852..40402\non x=-19947..3085,y=69295..98557,z=-7457..15697\non x=56416..88951,y=-49125..-23678,z=13033..31254\non x=-45415..-13431,y=-70617..-33184,z=-67667..-43697\non x=-25226..-16517,y=11281..39430,z=65912..87788\non x=32863..54130,y=33778..71445,z=42050..55059\non x=-61047..-29947,y=59749..68086,z=-42477..-13948\non x=-18251..9292,y=-89783..-58004,z=-41787..-15274\non x=5759..16739,y=31155..46337,z=-75036..-53352\non x=31554..54658,y=53243..73463,z=-26575..5972\non x=-33007..-6786,y=-62474..-41434,z=50315..75779\non x=27458..32973,y=22810..54163,z=-75563..-58647\non x=8075..18075,y=-50635..-24172,z=62978..85992\non x=-76736..-47443,y=-4014..19377,z=45970..58134\non x=-60157..-52753,y=-43338..-22023,z=-51719..-41956\non x=-3216..22631,y=49983..61450,z=-77551..-54695\non x=-46004..-40643,y=51830..62022,z=18230..48510\non x=42330..66450,y=-40592..-14557,z=-58845..-29636\non x=-32729..-9787,y=-91565..-69806,z=18117..35690\non x=-32002..-10885,y=-1443..14786,z=-90524..-68253\non x=50978..75653,y=7140..18805,z=-63220..-43305\non x=-64568..-49330,y=15278..36078,z=28629..42531\non x=19040..44557,y=-75487..-59006,z=-37514..-20407\non x=-2797..6071,y=-87782..-64015,z=-23722..-9160\non x=30427..40250,y=-51346..-20826,z=-76885..-46217\non x=-9837..5654,y=49778..66163,z=42263..63916\non x=-21072..11872,y=28390..51048,z=-77577..-49183\non x=31541..48623,y=37624..58494,z=-42361..-30931\non x=-56299..-27988,y=47361..70101,z=1213..10546\non x=-23456..-16890,y=-79546..-59160,z=-6743..10289\non x=14204..41142,y=56511..74601,z=5095..33434\non x=-36005..-14701,y=-68016..-39674,z=36553..63480\non x=60545..74232,y=15015..42503,z=-43149..-34200\non x=41594..65337,y=50002..72588,z=12856..37989\non x=-90432..-62701,y=-37837..-4386,z=-32554..-13392\non x=70315..83165,y=-40717..-23351,z=-28440..-1511\non x=-24120..5947,y=34921..55704,z=-69582..-46555\non x=-32209..-8756,y=-77077..-58552,z=-48224..-14837\non x=-43510..-17400,y=64412..85528,z=6143..27595\non x=36053..55013,y=53314..68720,z=-22332..-5189\non x=-29743..-3821,y=65395..78815,z=-9292..23641\non x=-69714..-38553,y=-44109..-30469,z=29793..51760\non x=62579..74277,y=11751..29748,z=23050..34754\non x=-2338..12874,y=75847..79442,z=10731..41551\non x=-47619..-35145,y=-52665..-37628,z=39702..49423\non x=-18665..-6319,y=-71514..-63562,z=42460..45818\non x=-30044..-12170,y=53793..59153,z=-63499..-40230\non x=-12567..16134,y=-90016..-66446,z=-35676..-19472\non x=-85062..-55201,y=4912..28423,z=-41593..-11980\non x=56423..80218,y=-37562..-16517,z=36700..48100\non x=-79818..-55704,y=11491..34326,z=8367..40952\non x=-26293..-12220,y=41552..57647,z=51547..73246\non x=-92036..-71546,y=10557..30361,z=-37285..-11767\non x=36855..65165,y=-77057..-59070,z=4400..24300\non x=-50136..-35853,y=35165..54382,z=37467..66189\non x=16047..55776,y=-39553..-11227,z=58349..80407\non x=27458..35035,y=-32489..-4540,z=-78886..-68473\non x=46937..76452,y=12250..27089,z=-55190..-45467\non x=-60706..-29052,y=-43190..-26027,z=48544..56051\non x=33102..61073,y=27580..41152,z=41873..64266\non x=-83817..-62138,y=-874..20403,z=-57292..-40933\non x=54691..83982,y=-26668..-1254,z=25108..50265\non x=-64405..-32749,y=44513..79090,z=-13114..-3445\non x=4627..28855,y=-38014..-18427,z=-78981..-56867\non x=39450..53446,y=42289..75373,z=-33901..-6131\non x=63899..90602,y=26653..55063,z=-10988..9550\non x=14634..44509,y=-78079..-56702,z=28926..52784\non x=38612..58844,y=41733..50901,z=-69067..-31286\non x=-76929..-61757,y=-65663..-31719,z=-735..7695\non x=28516..47164,y=-29956..-15347,z=-75568..-61002\non x=-50167..-42193,y=-40926..-30244,z=-60920..-47646\non x=-55502..-47750,y=54875..64454,z=-29489..-3798\non x=14430..36601,y=26459..39911,z=-79289..-57027\non x=25075..27283,y=52962..87505,z=18854..33830\non x=-58860..-43502,y=58845..85498,z=-18144..7960\non x=-53792..-49597,y=-62122..-48441,z=-6272..16303\non x=-1823..9424,y=-44705..-17073,z=70120..80148\non x=63692..82216,y=-19361..8359,z=33210..45303\non x=-11840..-2979,y=24389..52039,z=60315..71939\non x=-73992..-63729,y=-45246..-14461,z=-46112..-19286\non x=44923..62221,y=-54960..-42011,z=-38137..-20135\non x=14722..33976,y=-61145..-30720,z=-75360..-54000\non x=245..27732,y=58258..82234,z=30097..48740\non x=6991..26059,y=17174..25794,z=71284..89533\non x=35195..56084,y=51212..74918,z=-32483..-9615\non x=33703..66981,y=-60122..-54236,z=-53453..-17926\non x=-61940..-36371,y=-16581..-4570,z=-60706..-40703\non x=60760..77773,y=-33429..-9006,z=14598..31427\non x=18431..39521,y=-7515..9629,z=60150..89625\non x=54831..71507,y=20590..53690,z=18166..24092\non x=-25927..-4852,y=56797..80031,z=24590..44494\non x=58156..74392,y=-54667..-25937,z=-34893..-13568\non x=-46251..-30782,y=70616..92727,z=-10301..13242\non x=-54435..-31583,y=18809..57238,z=52002..64018\non x=-87191..-65448,y=21016..30554,z=-7539..18577\non x=-27162..-8066,y=-76175..-58675,z=-45390..-18705\non x=-28095..-21402,y=-70382..-55725,z=38509..56620\non x=49521..65654,y=31848..57013,z=29190..51381\non x=-75558..-48003,y=15704..38247,z=17226..43613\non x=23884..58026,y=50160..65808,z=6785..27572\non x=58063..93764,y=-22911..-4938,z=-11895..2739\non x=43350..68759,y=-71427..-46464,z=-6078..15892\non x=-33140..-3203,y=-20673..-10382,z=-75944..-67085\non x=-21259..-17037,y=67489..78783,z=-8541..11664\non x=36779..59339,y=24261..52940,z=-53125..-35093\non x=-30493..793,y=44829..70216,z=-52950..-47982\non x=45292..72628,y=-55273..-48706,z=-1598..9919\non x=29403..34110,y=-54445..-36095,z=43199..56783\non x=-59861..-33784,y=-53249..-37265,z=34591..65790\noff x=41754..57148,y=-80200..-55875,z=3599..22722\non x=-10075..4386,y=27944..45112,z=-79226..-60131\noff x=-15187..248,y=-83279..-72364,z=5037..32511\non x=54933..58881,y=12281..29091,z=-69028..-54121\non x=8090..25240,y=70064..81196,z=-16223..-13021\noff x=-60400..-26105,y=-62607..-40191,z=47851..67422\noff x=24451..46164,y=-75961..-52303,z=-49916..-25476\non x=-44857..-7989,y=-38916..-18382,z=-70680..-58913\noff x=-72200..-43203,y=24727..57702,z=-44696..-7928\non x=26323..57990,y=-14888..994,z=-79264..-65525\non x=-48909..-40386,y=-73244..-64696,z=-323..16342\non x=35358..52991,y=10687..27904,z=-70944..-57912\noff x=-23236..-4162,y=-29712..-17951,z=59106..79389\noff x=53581..72320,y=6800..13298,z=-45872..-42480\non x=-43571..-35441,y=41386..68207,z=-44478..-35187\non x=29214..36514,y=2338..22755,z=54949..83144\non x=-84002..-51122,y=41833..51908,z=9476..15499\noff x=7540..23221,y=-12461..-7794,z=-95431..-66096\non x=76564..93348,y=-9452..16724,z=-13630..7535\non x=24899..35662,y=-61799..-36371,z=50395..73121\noff x=-23379..-14671,y=-61654..-26944,z=-66602..-52265\non x=-75965..-53958,y=-25180..-13183,z=24409..52392\non x=-10197..4622,y=-15474..1783,z=-92565..-76011\noff x=45082..71453,y=9055..32401,z=53858..58811\non x=-76326..-55011,y=-39530..-20949,z=21859..44714\noff x=32466..57949,y=29661..50902,z=38020..60279\noff x=-48739..-19365,y=36215..74060,z=-61189..-33437\noff x=-13146..-2771,y=9021..18827,z=60320..97125\non x=-224..15138,y=31517..57835,z=-83757..-53030\non x=48425..68878,y=14971..40195,z=-64239..-33895\non x=-3608..5152,y=-30571..-5399,z=75733..96504\non x=62972..67090,y=-52211..-34797,z=-11592..8052\non x=6468..27085,y=-75658..-53084,z=24332..51031\non x=-9175..29042,y=-47119..-33884,z=-82475..-62552\noff x=-15847..4062,y=60344..89283,z=-30211..-17239\non x=25768..49899,y=62273..71708,z=349..10734\noff x=42707..63210,y=13025..46778,z=36022..55110\non x=46293..67516,y=-7202..26002,z=-66272..-31228\noff x=-62283..-34594,y=-38660..-16958,z=38044..60467\noff x=-70095..-49102,y=31813..56709,z=8713..28863\non x=13788..17456,y=-12132..6791,z=61871..77520\non x=-43439..-29707,y=-56265..-39662,z=-72104..-38103\noff x=13592..44088,y=-74894..-45793,z=37968..66601\noff x=46700..52734,y=-40463..-19848,z=-69191..-42886\non x=20538..39375,y=61182..85768,z=15326..29409\non x=54417..76403,y=-19878..-1308,z=-42875..-26138\non x=-86317..-61464,y=-18403..3486,z=-18507..6337\non x=2786..19873,y=-20405..9939,z=59315..81073\noff x=-59877..-54443,y=34487..69275,z=3488..18241\noff x=-39007..-20035,y=4078..30312,z=-82731..-51587\non x=32588..56936,y=-76500..-67396,z=-21385..-397\noff x=25080..41990,y=-28846..-19737,z=69970..78086\non x=23152..34879,y=52174..69560,z=27953..49114\non x=60684..71642,y=-30692..-3159,z=31270..54443\noff x=-45205..-29098,y=58510..89307,z=-17925..2596\noff x=19582..24130,y=-83134..-57590,z=35254..46862\non x=-11911..23624,y=-67005..-30930,z=-81907..-60918\noff x=4727..24751,y=-39077..-37491,z=-71684..-61996\noff x=-9593..7610,y=-9049..14670,z=62634..98129\non x=-66988..-43094,y=-62996..-35119,z=11118..43202\non x=-35998..-5275,y=-37152..-15041,z=-87055..-60774\noff x=-14073..-1453,y=48138..72420,z=-55577..-47324\non x=53303..57735,y=-50475..-39459,z=28711..49776\non x=50327..79524,y=-20647..-7189,z=32930..64357\noff x=-21585..-2673,y=67475..97316,z=-16225..10334\non x=12761..42162,y=-75198..-45687,z=27773..56590\noff x=10780..29984,y=30806..53252,z=45151..82121\non x=46365..68175,y=-3920..2578,z=-68115..-55420\noff x=26455..49250,y=-55979..-42110,z=-63322..-50217\noff x=-62311..-44896,y=-70433..-49939,z=-6372..6167\noff x=-68448..-49911,y=12490..21799,z=-66820..-50662\non x=11680..41135,y=42991..76600,z=38991..56525\noff x=60371..92603,y=19664..34168,z=-32784..-13415\noff x=-72850..-41597,y=-58644..-37918,z=-37165..-19623\noff x=53858..74510,y=34819..52123,z=16497..43908\non x=48488..52121,y=-45360..-24737,z=-66885..-37749\non x=20448..57476,y=27537..48980,z=46019..57068\non x=-27248..-19724,y=41351..47693,z=-77216..-44436\non x=-52950..-33175,y=41728..62787,z=-16516..-11981\noff x=-51177..-31463,y=-63233..-45533,z=32418..61549\noff x=-37057..-12370,y=18117..43449,z=-74085..-60338\noff x=-12503..2846,y=-42876..-30104,z=63819..75029\non x=60667..70952,y=-46497..-30751,z=16478..34217\non x=10069..26074,y=50365..61240,z=-68598..-56464\noff x=17685..45785,y=44978..64857,z=53362..71129\noff x=-73990..-42336,y=-72284..-40294,z=8863..26728\noff x=68782..80879,y=22420..46148,z=-2329..26525\non x=59344..83826,y=-40162..-30633,z=2097..16442\non x=-27562..-10414,y=27820..58187,z=-65865..-46977\non x=36887..65981,y=-73709..-52311,z=-42786..-24070\noff x=-20682..-3178,y=64806..78374,z=10659..34470\noff x=-8804..15550,y=-8444..-2404,z=-96231..-65363\noff x=-66648..-53156,y=-56554..-29056,z=-33726..-17793\non x=-203..26059,y=68129..80958,z=-43219..-27404\non x=47218..72444,y=35342..44493,z=-36229..-12760\non x=46904..60309,y=-54993..-32818,z=-50008..-30454\noff x=-21694..-6209,y=-88469..-65433,z=-11873..12245\noff x=-62399..-24805,y=28232..34853,z=51230..60419\non x=-79596..-57362,y=-48983..-34721,z=-13420..10701\non x=-6768..1790,y=-19645..-5406,z=-92627..-74287\non x=-33652..-18284,y=-23439..-8382,z=67655..90006\noff x=16524..39458,y=29152..49162,z=55749..83384\non x=-54254..-34002,y=-88855..-70903,z=-22296..3410\non x=-20779..8521,y=-89181..-73450,z=-7812..26787\non x=1615..21625,y=-6080..17570,z=71668..83316\noff x=-9715..12709,y=-50780..-22669,z=-74774..-69626\non x=9867..24037,y=12358..42384,z=72370..82642\non x=3224..30208,y=28864..51571,z=61883..84706\noff x=-945..19284,y=66805..89823,z=25957..49425\noff x=-25280..-6091,y=-97225..-62630,z=-19807..-7788\noff x=-2250..13009,y=50093..83251,z=-51760..-30168\noff x=-54440..-34334,y=26817..48120,z=48074..60160\non x=23262..49261,y=40455..52393,z=-60959..-43615\non x=-23294..-2268,y=-52310..-24691,z=-87802..-57989\noff x=-26612..7840,y=72808..79999,z=-29713..-3816\non x=54391..88234,y=-51754..-15468,z=1945..19324\noff x=17508..32841,y=-73524..-65420,z=-35218..-11372\noff x=31152..49478,y=-70736..-54693,z=-43913..-40242\non x=53480..64046,y=-62586..-42748,z=34500..47779\noff x=34058..63228,y=-61928..-58936,z=-31573..-3659\noff x=-58697..-39679,y=-81148..-49181,z=13624..23687\noff x=-27245..-8270,y=35092..58039,z=40192..57884\noff x=32739..63309,y=-40682..-17682,z=47869..70035\non x=52219..64202,y=-67303..-51407,z=4800..23668\non x=-54654..-29433,y=-86817..-62196,z=-5556..23658\noff x=-75279..-49504,y=-7178..9542,z=44327..53956\non x=-7810..8890,y=-30024..-89,z=66319..97476\non x=8400..36435,y=12009..44304,z=-80097..-67512\noff x=22016..38709,y=71634..74972,z=-3129..1171\noff x=48394..68796,y=44368..57057,z=-40373..-16910\noff x=-56815..-38268,y=36694..67658,z=-47750..-32089\noff x=-57877..-35052,y=46097..56601,z=33355..49073\non x=23011..37434,y=-53974..-23058,z=-61883..-45402\noff x=11872..42043,y=19031..22704,z=-83665..-55245\noff x=-73243..-46798,y=-4329..17893,z=-57779..-44793\non x=67456..73394,y=-22388..-14950,z=-37499..-28618\noff x=30365..66533,y=-70682..-46579,z=-16208..-5031\non x=21360..45088,y=-76539..-50147,z=21845..41905\non x=-18419..-11559,y=76149..84053,z=-11328..-2185\noff x=33020..55476,y=-15536..2658,z=64275..79458\non x=-48063..-26857,y=-20734..10735,z=-85808..-52673\noff x=43790..66834,y=-56342..-29394,z=31254..58327\noff x=67314..83024,y=-13230..17187,z=-23371..-4720\noff x=-40007..-14810,y=-73067..-57103,z=-66195..-38082\noff x=25841..57188,y=-26024..897,z=-87581..-52851\noff x=45794..76267,y=-52081..-18959,z=-40107..-15901\noff x=-40509..-4365,y=56716..81562,z=-22853..6830\noff x=-77503..-45958,y=-63620..-34287,z=-19880..-7413\noff x=-19264..12115,y=-19022..8117,z=-93523..-72932\noff x=39766..60651,y=-59973..-42774,z=-28355..-7554\non x=-5185..26343,y=42329..68147,z=56719..69801\noff x=-1117..14361,y=41023..50863,z=-73482..-62392\noff x=14618..41995,y=-57249..-23838,z=-82100..-56433\non x=-73588..-51361,y=3468..30508,z=-52360..-20267\non x=12744..37529,y=-54963..-50978,z=-53987..-45070\noff x=-72308..-43455,y=-38389..-24377,z=-50714..-45259\noff x=-78117..-42852,y=-13721..13148,z=-55905..-37080\noff x=-4467..22317,y=-12170..5957,z=71290..88500\non x=-95981..-66408,y=7590..8037,z=-2404..26148\noff x=12232..45401,y=12849..45079,z=-78972..-62278\non x=-46581..-20385,y=43824..70561,z=32388..58000\noff x=14142..24293,y=-26356..7327,z=-82833..-56772\non x=-62185..-54635,y=-62453..-44051,z=-17689..-15452\noff x=7493..30003,y=51943..75363,z=19045..35329\non x=10852..22754,y=-21936..-12574,z=58047..81390\non x=-85885..-60870,y=-5186..26456,z=-18838..-15144\noff x=573..10699,y=-12795..12158,z=62024..82285\non x=-53647..-41451,y=6744..19177,z=-65585..-52437\non x=-1937..13101,y=16787..44245,z=-89301..-69691\noff x=11648..28117,y=65897..81495,z=-51744..-31456\non x=-34510..-23114,y=64316..84122,z=11745..26248\non x=46597..67036,y=-49078..-18339,z=-55106..-43379\non x=-1630..16917,y=44609..68512,z=50592..75476\noff x=-21971..1123,y=24005..48686,z=60732..80668\noff x=42871..68726,y=-60814..-42185,z=27184..53921\noff x=38826..47043,y=-40691..-34285,z=-57815..-35188\non x=44616..56936,y=-18905..4924,z=53303..63015\non x=22934..47063,y=21220..45110,z=48969..72456\noff x=31507..57059,y=41717..67987,z=-48794..-42062\non x=63949..80604,y=11054..40766,z=17043..53534\non x=28112..49371,y=-69150..-55767,z=-37760..-7539\noff x=-39198..-18198,y=-10040..11413,z=-84459..-58961\non x=-21052..258,y=-11980..13528,z=-92447..-67079\noff x=-72190..-65264,y=-11322..11452,z=20127..52589\non x=9456..34476,y=75111..90133,z=-3087..22015\noff x=-48678..-16972,y=-41882..-11490,z=63832..72591\non x=711..33910,y=-92450..-65393,z=-19051..4525\noff x=62421..84065,y=26556..40786,z=14281..29967\non x=-67588..-56095,y=28175..65003,z=22332..47033\non x=-70974..-36736,y=9539..20776,z=49351..68205\noff x=-25177..13122,y=-61323..-41425,z=46642..75842\non x=-52446..-40486,y=-62884..-38244,z=20759..52144\non x=-42548..-33936,y=-53496..-46698,z=-50788..-30250\noff x=33339..50697,y=-75051..-48370,z=36655..54219\noff x=43213..72026,y=-22655..-11856,z=37238..51298\n"
  },
  {
    "path": "advent-of-code/2021/inputs/23",
    "content": "#############\n#...........#\n###B#B#D#D###\n  #C#A#A#C#\n  #########\n"
  },
  {
    "path": "advent-of-code/2021/inputs/24",
    "content": "inp w\nmul x 0\nadd x z\nmod x 26\ndiv z 1\nadd x 10\neql x w\neql x 0\nmul y 0\nadd y 25\nmul y x\nadd y 1\nmul z y\nmul y 0\nadd y w\nadd y 0\nmul y x\nadd z y\ninp w\nmul x 0\nadd x z\nmod x 26\ndiv z 1\nadd x 12\neql x w\neql x 0\nmul y 0\nadd y 25\nmul y x\nadd y 1\nmul z y\nmul y 0\nadd y w\nadd y 6\nmul y x\nadd z y\ninp w\nmul x 0\nadd x z\nmod x 26\ndiv z 1\nadd x 13\neql x w\neql x 0\nmul y 0\nadd y 25\nmul y x\nadd y 1\nmul z y\nmul y 0\nadd y w\nadd y 4\nmul y x\nadd z y\ninp w\nmul x 0\nadd x z\nmod x 26\ndiv z 1\nadd x 13\neql x w\neql x 0\nmul y 0\nadd y 25\nmul y x\nadd y 1\nmul z y\nmul y 0\nadd y w\nadd y 2\nmul y x\nadd z y\ninp w\nmul x 0\nadd x z\nmod x 26\ndiv z 1\nadd x 14\neql x w\neql x 0\nmul y 0\nadd y 25\nmul y x\nadd y 1\nmul z y\nmul y 0\nadd y w\nadd y 9\nmul y x\nadd z y\ninp w\nmul x 0\nadd x z\nmod x 26\ndiv z 26\nadd x -2\neql x w\neql x 0\nmul y 0\nadd y 25\nmul y x\nadd y 1\nmul z y\nmul y 0\nadd y w\nadd y 1\nmul y x\nadd z y\ninp w\nmul x 0\nadd x z\nmod x 26\ndiv z 1\nadd x 11\neql x w\neql x 0\nmul y 0\nadd y 25\nmul y x\nadd y 1\nmul z y\nmul y 0\nadd y w\nadd y 10\nmul y x\nadd z y\ninp w\nmul x 0\nadd x z\nmod x 26\ndiv z 26\nadd x -15\neql x w\neql x 0\nmul y 0\nadd y 25\nmul y x\nadd y 1\nmul z y\nmul y 0\nadd y w\nadd y 6\nmul y x\nadd z y\ninp w\nmul x 0\nadd x z\nmod x 26\ndiv z 26\nadd x -10\neql x w\neql x 0\nmul y 0\nadd y 25\nmul y x\nadd y 1\nmul z y\nmul y 0\nadd y w\nadd y 4\nmul y x\nadd z y\ninp w\nmul x 0\nadd x z\nmod x 26\ndiv z 1\nadd x 10\neql x w\neql x 0\nmul y 0\nadd y 25\nmul y x\nadd y 1\nmul z y\nmul y 0\nadd y w\nadd y 6\nmul y x\nadd z y\ninp w\nmul x 0\nadd x z\nmod x 26\ndiv z 26\nadd x -10\neql x w\neql x 0\nmul y 0\nadd y 25\nmul y x\nadd y 1\nmul z y\nmul y 0\nadd y w\nadd y 3\nmul y x\nadd z y\ninp w\nmul x 0\nadd x z\nmod x 26\ndiv z 26\nadd x -4\neql x w\neql x 0\nmul y 0\nadd y 25\nmul y x\nadd y 1\nmul z y\nmul y 0\nadd y w\nadd y 9\nmul y x\nadd z y\ninp w\nmul x 0\nadd x z\nmod x 26\ndiv z 26\nadd x -1\neql x w\neql x 0\nmul y 0\nadd y 25\nmul y x\nadd y 1\nmul z y\nmul y 0\nadd y w\nadd y 15\nmul y x\nadd z y\ninp w\nmul x 0\nadd x z\nmod x 26\ndiv z 26\nadd x -1\neql x w\neql x 0\nmul y 0\nadd y 25\nmul y x\nadd y 1\nmul z y\nmul y 0\nadd y w\nadd y 5\nmul y x\nadd z y\n"
  },
  {
    "path": "advent-of-code/2021/inputs/25",
    "content": "..vv.v>vv.>..>..>.>...v>vv..>.vv>..v>.v...v>vv.>.>....v>..v>.>.vvv>...>>vvvvv..v.v.>>..v>v.v>..>..>>v>>..v>.>v..>>>>>v.....v..>v.>v..>.....\n.>....>..v.>v>>>.>.v>....>.v.vv>v.>...>....>v..v...v..v>.>.>v.....>.v.v>.>v....v.>..>.v>>>>v.v>vvv>>.>.>v.>..v.v...v.>....>>v..v....v>>>vv>\n>v>>.vvv......>vv.>>>..vv>.v....>>.v..>>..v......v>..>>.>..v..>..>>v.v>v.v.v>v>.>>...vv..v.v>v>.>v.>vv..>>v.>.v.>>>v>>..v.>>...>...>v.>v>.v\n>.>..>>.v...>v.>v..vv....>..v>.>v.v.v>vv.>v..>.>v.vv.>..v.v.v..v>>..v....v>v>>.>v>...v>.>v>>vv>..v..>>>v>...>.>>>v.v.>.>vvvvv...v>v>v..v...\nv>.>>v..v>v>v>>v>v>....v....>>vv>........>.>>v.v>...>.>..v>..v.v>.>.>>v..v.>v>v....>>...v.>v>>>vv....>v>.v.>>>>>.....>vv.>v>.....>.vv.>.vvv\n...>>...v..>..v>.>.v..vvv.v>vvv.>.>..v>>.>..v>v..v...>.>.v.v..v>.v.>..v..>vvvv>v>.>...v.v..>....v.>..>.v>.vv.v>..>.v.>.....>.>...v.>..>v.>v\n>.v.>>..>.vv.>..v>>v..v.>v..vv>v.vv.>vv.>..vv>.v...>v.>vv.>>..v....>.v...v.>......>v..v>...>>..>>v...v.>...>>v.v...>.>>v...v..>>..v.>>v..>.\nv.v.>>v...v....>..>..>.v....vvv.>..>.>...>>v>.>.>v>.>..>>.vv>.vv..v..>v.v.>.v......>..>..>v>v>>..>v>.>.vv.vvv>.v..>v.>>....v>>.v..>.>>>>.>v\n.v>.>.v.v>>v>.......>>>v>.>...>vv>>...v....>v>>.v>>v>v..>v.vv.>v>...v.>.vvv>..v.>v....v.v.>.>.v>.v>vv>.>...v..v..>v.>....vv>.>..>.v....v...\nvv....>>v.>.v...v......>.>>>.vv>v..v.>.v.>...v.>v>.>.v...>>.>>>.>..vv.v>.>...vv>v.v>vv......>vv..v.v>v.>.>>>v.>.>>.>v>...v>v>...v>v..>v..>v\n>.v.>>.v..>>.>v>.>v.v...>.>....vvvv....v..v>v.>.....v>v.v.v>...v>v..>..>>>>v.>.v.>.>v...v.v.>v..>.>.vv>.v.v>>vv>v.>...>v..>..>vv>>.....v...\nv>.>..v.>>.......>...>vv..v.v>.>>.v.>>..>>.>>>....>..>...>.>vv>..v>.>...v.>...v..>...>vvv.v.>.v>v..v...v.vvv>v.v.>.>.v.>...v.v.....>v.>.v.v\nv.>vv....>...>.>v>.....>......v.vv..>....v>.>>......vvv..v..v.......>....>..v...>.vvv.vv>.....>.v>v..v...v>>....v..>v..>..>>>>.>.vv.>..v>>v\n>v.v>>..v..v>.v..v>.v.>>.>.>>>v...>>...vv.v....>v>...vv>>v..>...>.v.>.v>vv>....v.vv..>v>.....>v>vv......>>>>v..>v>>.....>v.v.v>>>..v......>\nv>>>>v.>>.>..>.>>.>.>>>...vv.v...vv>...>.v>>>>>v..>..v.>.>....vv..>>v..v..>..>.v>..vvvv...v..>>>>>v.v..vv.>.v>.>vvv...vv.>..v..>v.v.>....v.\nv>.v.vvv>.vv>>>.>.v>..>...v....v>v>.v...v.>.v.>v.>.v.>v.v...v>..>vv..>..>>.......v..v>>>>.v....>>.>>...>....v>.v>..vvv..>vv>.>v>>....v...>.\n.>...v>...v.>v.....vv.>>>.>.v..vv.vv.vv>.>>v>..v....v.v>v>v>..v>.>v.v>....v...>v.>.v......v...>.>vv>v.v...>.v.>vv>vv.......v..>v.v.vv.>.v>>\n.>.>.>>..>..v....>.vvvv>.>.v>.>v.>.v>.v...>...>..>>.>>.>....vv.>>...>v>>v.>v......>.>>vv.v...>v.>.>v.>>..>>.>.....v.vv.......v.>>.>>v>.>v..\n>...v.>..v>..vv>vv..v>vv>...v...>..>v>.>v....vv.>v>v.v..>>v>.v.>...>.v.>.vv>>.v.vv.v>>>v..v.vv.vv....>>.v..>vv......v.v>..vv>v.vv>.>vv.>...\n>.>v.vv>>>.>v..v>...>.>..>>.......v.vv.>>>>.>v>>..v.v.>v>....v>v.>.>v..v>.v>>...v>.v.v...vv..v>>vv.vv>...v.vv.v..>v>.>..>>...>>>>>v..>vvv>>\n>.vvvv..v>..v....>v.>>>vv>.v..v>....>v>v...vv....>>>v..>v....v...>vv.>>>>.v.>.>v>>vv.>>vv...>>v>v...>>..>>.>>....>.v..v..vvvv>.>>>v.>vv..>>\n...v....>.....>.v.v>.>...v>v..v.>.vv..>.....v.v>v..v>>>.v.v.>.>..>>>v...v.>.>..v.v...>.v>v.>..v...>v>.v>v.v..v...vvvv...>.>>.v.>>>..>.vv>.v\n....>...v.vv>>..>.>.>v....v.vv.v.v.>>..>..v.>>..>v..vv..v.>.vvv...v..>.vv.v>..v.>>v...v.v.>v>.v.>v>>vv.>.>..v.v>...>.>v..>>v>....v..v.>vv..\n....>>v.vv>vv......vv>..vv>..>......vvv.>v.v...v.>.....>..>>....>..>vv>..v..v>.>v..v...v>v..>....v..v.v.....v>>v.>v...v>.v...>.vv>>..v.>..v\n.vv>>v.v..>.>>vv.v...>.v.>.>v.vvv.>.v.>..>...>.>..v.v>.v.v>..vv>>vvv.v.v>>>.>.v..v>.>.>.v.v.v>>...>v..>..>.>>v.v.....v...>...>.vv..>v..vv..\n>v.v.vv....v..v>.v.vvv..v.v.>>>.vv.>..>>.v......>..vv>>.>...v>...v.v>.vv..v>v>.>>..>.>.>>>>>....>..v...>>v>v>...v...v>v..>..v.>>>.......vvv\n..vv.v.>vv.>.>vv..v>>>>>.vv.v>>..>......>v.>.v.>...v>vv.>.>.v.>..v..vvv>..>.v..>.>.>....v>>v>v>....>....>>v>>.v....vv>>>..>.>>>vv....v.vv>>\n...v.>.vv.v.>>v.v..>v>vv........>..>>.......>>.>v.>v>v.>...>>...>.....v..v>..v>>..v...v...>.v..>>..v>>.>>....v..>..>..v.>v....>.....v>.v>..\n.>.>vv.vvv.>v..v.v.v..v..>.>>..vvv>v>>>..v.v.>v....vvv.v......>>...vv>...v>v>..v.>v>>..v>.>.v....v....vvv.>>.v>..v>>>v>..v...v...>>>.vv.>v.\n...vv>.>>>>.v..v.>.v.v.>>>..v.>vvvvvv.v>........>.>.>.vvv>v>v..v>>>>v...v.v>.>..vvv..>..vvv.vvv.v>>>>.v..v.>....v..>>.vv..vv.>..>>.>v....v>\n>v>>v>.>..>>.vv>v.vv..vvv.v.v..>.v.>.>v>.>....v.>>..vv>......>>v>v.v.v..>.vv.>..>>.v>....>vv.>v.....>.v>>.>.v...>>....v.>v.>....>.v>..v>...\n.v.v.vv.>....>>v....v......>>>>.>.>.>....v>..>>....>.>vv.v>>.>.v.>v..>>>.v.>.>..v>>.....vv.vv.v..v>v>>..>>.>v>...v>>>..>vv>....>...vv.v...>\n>..>.vvv..>vv>>..>.>...>..v.>>.....v.v>v.>v.v>.v....v.......>v...vv.vv..>>.v..v>.v.>>v.v..v..v......v>>>>>.....vv.vv..>.v>>>vv.>>>.>.>....>\n..v.v>>vv..v>>>...v....>..v.v.>vv.v>>>.....vv..>.>.v.>.vv..>>.>..>>vv....>v.v.....>vv>.v....>.v..>.>v>..v.>v.>>>v.>...>>.>v..>>v.v..>....vv\n.>v..vv..>.>>..v>>vv>....>..v..v>>>.....v.v>.>>....vv..>vv...>..>>.vvvv.>>>.....v..>v>>>>.>.>vv>....>...>v.>...vv>......v>vv.>vvvvvv.>>>>.v\n>>....>>v>..>.>v.>....v.vv.v>>.>.>.vv...v>.>........v>.>v>v>.....>.vvvv>..vv....v..v..>v.v..>v>....>>.vvv.v.v..v.>.v>vvv>.>>>.>.>.vv.vvv>.>\n.>>.>..vv>>>..v>.>vv..>>.vvv>...>...vv>....>.v..>v.>>.v..>.v.v..>.v.v.v>.>...v>.>>v..v>.>>v..vv..>v.>.......v.>..>v.vv.v>..>..vvv.>v>>.>.>>\n.>>..>.>.v>v..vv..>>>.vv...v.>.>v..>.v.v...v..>....>.....v..>v.>.v.>..v>..vv..>.>.v>v....>>v..>>.....vv.......vvv>>>>v...>>.v....>.v>..v.v.\n.v.v...>.>.>..v>>.>>>v....>v...v.>>.>>>.......>....>....v..v.vvvv>...v..>v...v....>.>v>v.v.v.>>vvv...>...>v.>>vv..v.....v>>>v.>vv>.>>.vv>.v\n.>.>v...>.v..>..>.vvv..>...>v.v.>....>>v>..>.v>...>v.>.v.vv..v..v.>v>vvv>>v>.v>vvvv.>>.v>>.>..>>.v>>v>.v...>..vv>v.vv...>v..v.....v>...>v>>\n>.v.vv.....>>v.>v..v......v.........vv.v.....v>>.vv>.>v..>.v>.v.>..>..v>.>..v.v.>..>....v.>v...v...>......v>.>.>.....>.vv.v>...>.>>>..>v..v\nv>..v..>v>>>>.v....>v>vv>vv......v>>.>>.>vv....>vv>vv.>>...v>>v>v..>>....v>>.v.>..>v>v.>.vv..v..>.v.v.....v.v.>>.v>.....>.....>..>.v>>..v.v\n.>.vv>v>.>v>>>v.......v...>v.v>.v>vvv>>v>>v>>.v.>v.v.>v.>v..v....v..v...vv..v>.>.v>..>..v>..v>v>.....>vv..v>.>v>.v>v>...v>>..v.....v>v....v\n.>>.>.>>..>....>>v....v...vv>.....v.>vv>v.v.>..v>v.>.v.>>.>..v.v.>v.>..>v..>>..vvv>>>vv>..>.>v>>vv..v....vv>v..vv.>.>v....v.>v>v..>>>>>.>>.\n>..v.v.>..>.vv..>>.v....v>..>.v>>...>.>v.v..>>.v>.vv>v..v.>>>...v.>..v..v...>...v.v>>.>.v>>v.v.>.>.v.>.v>.......>.vv.v>>.>>v>.>>v...>>..vv.\nv>..v>.....v....>>>.vv..v..>v...v.>>....>>>...>.>.....v>>.>....>..>>>>>...vv.>.>.v.v>.v>......v..v.>>..v........v.v>..>...>....>....>vv.v>>\n.>>>..vvv.>v>vvvv.v>...vv.vv>v..vvv>v...>v....v.vv>.v.v...>.......>v>..vv>...>...vv>>>....vvv.>v.v.v.v>>.vvv..>..>.v>.>v.>.v..v>.v..v>v.v.v\n..>...v.>v.>>.>v.vv.v...>v>.>..v..v.vv.vvv..>...v>v>v..>>>v>..>>>v>.>.v..>.....>>vvv..v>...>>>>vv.v.>.>......vv>>>vvvv>..v.>vvvvv.>v>v..v>.\n>>....v..v.>.>>.v...vv......v....vv...>>..v>>>.v...>>.>..v.v..>....>>v.>vv>vv..v...>.v..vv...>.>v..>..>.v.v....>v.v.>vv.>..v>>v....>..v>v.v\nvvv..>>v...>.v.v...>.>v.v....>...v.>.......>.>..>>v..vv.v>....vvv>.vv.>vv.v.vvv..>..v....v.v...>>vvvv.>.>>.v..>v.>.>>>..>>>...v...v...>>...\n.>.v>..>..>.....vvv>v..>v..vv.>........v.v>..>..v.v.>v.>v>v.....v.>>>..vvv>>.v..>v>v...>>>>.>v..v..v.>..v>....>..>>v..v.v.>>..>>..vvv>.>v>.\n>........v>..>>>..>v..>.v.>....>v.v>v..>.>>v...v>.v>v>.>>vv....>..>..>.>vvv.v>.>vv.v..v.>>>>....v..v.....>>.>v>>v>v..>>>.>..v..>.>...>...v>\n>>>.>>>vv>.>>.vv.v.>v>.v>...v.v..>.>vvv>vv>v.>>..>>..>.>vv.>..>...vvvv>..v.>v.v>>......>.vv.v..>....>>.v..v>>.>>v....v.vvv...v>>v.v.>v...v.\n>>>>>>..v..v...>vv.>v..>.v..>.>v.>..v.>v.>..v>...>>.>.>.>.>v...v>.v..>>.>>>.v.v>v..v.>>..>...>..v.vv.>....v.>.>>.v..>.>....>.v.v..v>.>v>v.v\nv.....>.>..vv...>v..v.>.>vv>.....>vv....>>vvvv.v..>.>.v...>..v>...>..>>vv..v..v>....>v..>.vv...>vvv.>>..v.v>>.v..vv>..v.v>.....>v.v..vv..v>\n..v..v.v>..>.vvv>..v..vv>v...>.vv..>>>...vv.>.vv..v.v>.>.v.v>v>....>>v...>.>..>>>.>...>v.>.v>>vv.>.>..>..vvv..>.v>.>vv..>..v.vvv>..>vv.>...\n>v.>.>v>>..v>>>v>.>..>>v>v>>...>..v...>.......v..>.>>.v.>>..v...vv..>>.>.>>>v..v...>v...v.v>..v.v...vv>v..>vv>v>..>..v..>..vv.>>v..>....>.v\nv..>v..v>vv..>v...>..v.v>vv....>...v>>v>.....>>.v.vv.v>..>...vv>vvv..>vvv.v...>...v.v>.vv.>.>.v..vvvv.>...>vv.v>v.v....>.v...vv.>vv>.vv....\n.>v..v..v>vvv...v.>..v>vvvvv>>....>>.vv...v.>.>v>...v..>.v.v..vv.vvv>>...v.>..v......>v>.>>v>.v...v.>..>.v..>v.>>..>.vv.>>>...>>>>>v>>>....\nv.....>v.>..>...>vvv..>>>>v.vvvvv..>v.>.>.>....v>..>v.v>...>...>..v.v.vvvvv.v>>>...>.>>>..v..>v.v....>..v...v.>..>..v>..>>......v...>>>.>>>\n.>.v>>v.vvvvv.v..v.vv.>>v.....>>v>..>.v.v>>>>>vvvv...>>>v..>>...vv.v...>vv....>>.>.v..v.v.>>v.>.......>.v>v.vv....>vv.>.>v.vv......>.>vv.v>\n>.....v.>....v.>>vvv.vv.>.vv.>>v..>.v.>vv.>.>v.v.>>..>..>v.v.>>.>>.......vvv>v>>>.>>v>v.vv>..v>v>>>v...>vvvv>.v.....v>...v.>v..vv>v>.v.v>..\nv..v>.>.>......v.v>v...>.>>.>>vv>>>vv.>.v>v>.>v.>>v.v.v..>v.>v..v>>v>>........>.>v..v>...>.v...v..>.v..>....>>.vvv..>>v.v>v..>...v........>\nv.v..>>...>>.v.>v>.v.....v..v>>v>v..v.>.>vv..>v>.>.....>..>...>.v..>.>.v>...>>....>.>>v.v.>v..>>>.>..>v>v.>.>..v>....v...vvv..v.v>.>.v...vv\nv..v..v.....vv..>v>..v>v.>v.>>.>.>..v>....>v>v.....v..vv..>..>.v>v>v..>>v.>..>>>.>...v.>......vv>..>v>v.vv>>v..>.>>v>.v..v...v....v..>..vv.\n...>.>.v.....>>>v.......vvvvv.v>>>v.>>.v>v..v.v..vv>.....>>.>>>v>..v>>>>>..v..>>>.vv....v>v....vv..vv.vvv..>.>.>>>>.vvv....v.>>.>..>>...>..\n.>>.v.vv.v>.>>.v..>..>.v>>..v...>.>>.vv..v>.>>..v..>..>>.>.vv...>v>>>>..>.>>v...v..v.>>v>>....>..>>.v>vv..vvv.>.v..>v..v..v>..vvv.v>..>>.vv\n.>..vv>.v>.....v>.>.>....vv>vv.v.>..vv>..v.vv..>vv...v>>>>..>..>.v..v.v>>v.>..v..>>..v>.>v.v...v....vvvv>v..>>>.>.>v..v.>.v>v..>>.>.>>.vv>v\n.v...vv..>>v>>.>..v..vv>>>>v..v>>.v.>>.v.>>v>>>..v...>>.v.v>>..vv>....v>..v.>.>.vv.v>..>>...>....>v.v>..v>vv..v..vv.>v..v..vv..>...>.v.....\n....>..v>>v.v..vv...v>..v.>>v.........>>..v>.>>>vvv>..>.v..>v>.>.v>..>..v..>vv.v.v>v..vv>.>....>..>....v>>v.>.v..v>>.v.>>....>..v>.v..v>>v.\n......>>>..v.>...v>>vvvv...v>v...>v>>>v.>.>...v...>.vvv.>....>.v.v...>.>>..v..v..>....>v>...>.v>v.v...v>.>.v..v.>>.>.>v..>.>.v....>v.>>>vvv\n.v.v...vv...v>..v>vv.v..>.v>>...>.vv..v.>v.>.vvv>...>v>>>>.>..v>>>v.>v..v..v>....>.>vv>>.>.v.>..>v.....v..v...>v...>..v......v.v.vv..v>.>>.\n..>.v.>>>>...>....>v.>..v...>v.>.v>..>v>.>vv.v......v>v.>.>>......vv..>v...v..vv..v..v.>.....vvv>.>>vv..v.....>v.v.vv>v..>.vvv>..>..>vv>.v>\nvv.>v...v>..>>....>.>...vv..vv>.vv>..vv>>.>v...vvv.>..v.v...v...>vv>.>..>.vv>......>.>vv.vv..v>>>vv>>.v>vvvv>vv>>>..>......>.v>>>v.v>.>.vv>\n>>>v.>..vv..>v..>>vvv.>...v>.v.>v..v>>v.v..v...>>>>.vvv.v>v.v..v>vv..>.vvv>.v...v.....v>>v....v.>>vv>v..>v>....v.>.>>.....v>>>.v>..v.>v.v>.\n.v.vv>>v.>...v>.>v.>.>.>>vv.>..v.vv...>>vv>..>v.>>>.v....v.>>vv.>.vvvv......v.....>>v>...>...>vvv..v.v.v>.>.v..>>v>v.v.vv>v......v>>v.>v>..\nv>..>...>vv..>.v.>.v..vv>v>>>...vvv>..v.>.vvvvv....>..vvv>.>.....vv>v.>>.>v....>>..>.>..vv.>>.....v..>...v...v.>..>>.v>vv>..v..v>.>.vv.>..>\nv>....vv>.v>.>>..>.>.>v..v.>>vv..v...>v...>>.v.vv..v>v.>..v.v.v>.>.>>..vvv>.v>......v....>>>>>v>.v...>.v.v..>v.v..>v....>.v.....>..>...v>.v\n.....vv>...>.vv..v>.>.v.>.vv.vv>v..>>.v.....vv.>>>>.>.v....vv.v.>..>...vvv....v>v.>vv.>..>....>.>.v>.>>>..>..v>...vv.v>>.>>.v..>>>.>v...>..\n...v>v.v.....vvv..vv>.>.>v.....>>.>vv.>.v.v.......v>vvv.....vv...>>..v.>>.>..>.v...>>>..>..v>.v.vv....>>.>>...>v>v.>>.>v..v..>....>....>v.>\n.v>.>.v.v..v>v..v>...v..>>v.>v>vv.v.....v>>..>.......v>.v.>>>>>v>....>>>vv>v.....vv...v.vvv.>...v>v...v>..>.v.v.>..vv....v.vv.....v.>..v>..\n>vv....>.v>>..v..v>vv.>>vv..>.vv...vv.>.........>v.>>..v.>>..>.v>vv.vv.v.>v.v>>.v.v..>>v.v.v..v.>.>..>..vv.vv..vv.v.v..>...>.vv.v.v>..>>>>v\n>..v.v>v.>.v>v..>.v..v>vv.>v..v>v....vv>>v..>...v.>>..v....v>....v......v..>..v....>.>.>.vv...>v.v>vv>..>..v.v..>>.v.v..>..>.vv.>...v..>>vv\n.>..v..v.v>.vv>.vv>..>.vv>.>.v..>v...v...>.v..v...v..>...v..v>.v.v..>>...v.>v..>..vv...>.>..v..>......v.v..>....>v...>.>v...v>.>>>vvv>.v.>v\nv.>>.>..v.>.vv.>..>>>.......v>.v.>....>..vv>v>>v...>>v.>>vvv..>vv>..>v.>>.>>..v..vv...>..vv..vv>.v....>v.>.>.>....v...>>...>>..>..>.>...v>v\n...v...>.v>..>..vv..vv.v>>....v..v.v>.v..>.>v>v.v.v>.v.>>v>>v>.v..>....v.vvv.v.>.>>..>>..>.>.....>>.v.>.v..>>>vvvv>.>....>vvvv>>>.vv.......\nv.v...>>..>.>>>>.>...>..>.vv..v..>>>...>v>..>>>....>..v..v.>....>v>v..v>v.>>..>vv>vv>...>>..v.v.vv>>..v..>.....v..vv>>.v>>>>v>>>.>.vv>...>>\n>.v>v..>.>v..v.v.....>....vv>.v>>..>v.>>v>.>..>....vv.vv..>vv..>..>>.v.v.>.>>......v.v>.>>....v>v..vv>>>v>..v.>..>v..v.vv.v>v>>v>.>>.>v.>.v\n...>>v..>....>......vvv.>v..>>vv....>v..>v>>v>.v..>.>>...v>>vv.>>.>...v>>v...>.v..vvv..>....vv....vvv..>v>..v.v>v.v.>vv>..>..>..v.v.>.>>vv.\nv.v..vv.>>v>v.v>.vv..>v>v.>...>.>.v..>v.>>>>..>..vv.v>..v.v.>.>vv>v.>..>....v...>..>>.>>v....v...>.vv..>vv.>>>..>....>>v>v...vvv.v.>..>....\nv>...v...v...v>.v...>>.v>v...>......>v...>..v..>>..vv.vv.....>.>vv....v.v.v>vvv>..v..v...v...v>vvv>>v>..>.v>.>......>v....v.>v>>>....>vv.v>\n.v>.v...v.v.>>.>vv>...v>>..>.vvv.....>..vv.....v.>v.v>.....>.>....v>...>v.v.v.v>>.>>.>........>.vvvvv>.>.>vvv..>..v..>>v.v.vv>>>.v>.v...v.v\n.vv.>.v....>.>>>.>.>.v>.>>>v..vvv....>v.>.v.>.>>vv>.vv.>v.....v.>>.v>v....vv.......v>.>.>v>....v..>.>.>vv>>..vv.v..>..vvv>v..>..>>>v..v..v.\n.>>.>.>v.vv....>..>v>....v..>.v.>..v....>...>..>v>>>>vv....vvvvv.>v....v>.>>.v..>..>..>.....>.vvv>>.v.v>.v....>>>>..v...v>vv>.....v..>.v.vv\n.vvv>v...>....vv>.>>..>v.v.....v.v.....v>.>>.>v>>.v>v.v.v>vv.vvv>.>....v..v>>v.v.v.>>..v.>v.>.>........v.vv.>.v..v...v>.v.v.v.v>....>>vv.v.\nvv.>>>...>..>>.....>...>....>..>.>>.>>>.v.v...vvv.....v>..vv..>...v.>.>v....>v.vvv....>...vv.>v...>>>..>>.v...>..>.>..>..vv...vv..>>.v.v>v.\n.v.>..vv..v.v.>>....>>..vv>...v.vv..v.vv.>vvv...>vv...v..v.>...v....>>.....v>.v..>.>>>...vv>.v..vv>>.v>>>.>v>....vvvv>>.v.vv>....>v..vv.v>>\n>>>>>...v.......>.vv>>..>.v.>.vv>.v>vv>v.....vv....>>.>.>......>.>.>>>.v.....>.v>v..v.....vv.>.....v...vvvv>..v.v>.v>.v..>>vv.......>vvv...\n>..vv>..v...v...>>.>v>>vv.>...>>>..vv.>v......v.vv>>>>>.vvvv.........vvv>.>.....vv.v...v......vv......v..v.....>v.....v>..vv.>..>vv.>>v>v>.\nv>v..>v.v.v....>vv>>>>v..vvv.vvv.v.....vv.v>..vv..v>v..v>..vvv>>.>..v.vv>.>v.>v...vv..>v>.vv..v..>>v.v..vv>>.>>>vvvvv>.vv>.>.vv..>...>.v>.>\n.v......>v.......v...v...v..v>>vv.>v.vv.vv.>v.v...>v.>v.>vv>..>v>v.>.v.>.>>..vv.vv>.>>v...>v..>v.v>v>>..v.v.v>..>.>>........>>vv......vv>v>\n>..v..>v.>>....>v>.>...>......>.>...v.>.>.>.v..>.v>.>>...>..v.v...v..v...>.vv>v...v>>.>..v....>>...>>>.>..v>v.v>v....v>>.....v>..>>>...>v>.\nv.>vv>.>.v>v>v.v..>>>v>.v>.....v.....v>..vvv.>>v>..v..>.>.>..>.v>...>>>>...>>vv>...>......>..>..>vv.>v>>>...>>.>..v>>>...vv>...vv..>v.v..v>\n.....>v.v>v.v>>>.v..>>..>>>....>..vvv..v..vvvv....vvv.....>>v.>>>....vvv..>v....>v...>v..>.>v>v.vv...>v.vvv.....>v.v.>.v.v.v...v......>v..>\n>v...>.vv>v>...v.>.v.>v>v.v>..v>v>v.>v..>vvv.>...>>>.>..v.>.....>v>.v.vv>.v.>v>>..>>v.>...v...>>>.....>...vv>vv>.v>>....>>...v>vv...v......\n.>..>vv.>.>>.v>.>v..v>v.....>>....vv.>..>>>.v.v..vv>.>>.....v..>>v...>vv..>.v>>>.....>>.>..>.....>..v.>>v.v>.v....>.v......v>..vvv>>>>v>v>.\nvvv.>v...>..>.v...>.v>v....>>...>>.>..>>...>v.v..v.v..>..>..>.>.v.>..>.v...>..>v...>v.vv..v....>..>...v>>v>vv.>>.>>v.v..vv...>>>v>.v.>v...v\n.>.v..v.>>...vv>>.>>v>.vv.vv......>..v.v.>....v.v.>v..v.v...v....v.v..>.>v...>v>.>..>>>v>>v>v.>v>>.v....v...>v..vv.v....>>.>>v>>.....>.>>..\n.>.>....v>.>>......vv...>.>.>..>.vv.>....>.v>>>.v.vv..>.vv.....v>.vv>>>..>>.>v.vv..>v>..v>.>....>>..>.v..>v>.>v..v.....>.>>.v.>.>..v.vv....\n..>.>v......>.vv>....v..vv.v.v.v...>>.>vv..v..>v.>.>.v.v.....>>>.v.>.vv.v......>vv>..v>>.v..>.v...v..>.....v..>>..>....>.......v.>..>.v...v\n.>.v>>v.v...>.v>>..v...vv.>>.>v..v..v.>>vv>.v>vv..>....vv>.v.>v>vv>.vvvv>vvv..>.>.>vv..vv>v>>.v.vv.>>...>vv....vvv>v.>.>>>>.v..vvv.>....v.>\n...v.>..>..>.>.>..vv....>>v.v..vv.>.v>..>v..vv...>>>v.>>.>.v>v>v..v>v....v.>vv.....v>v...........>v...>.>vv>..v>>v>vv.v>v..>>vv...>v.>..>..\n...v...v..>..>.v.>.v.v>..v....v..vv>.>..v..>...>v>>>..>.>...v..v>>>>>vv..v>...v>v.....vv.>.v......>.....>.v>........vvv>v>.v..v......v.>vv.\n..>v>.>.v.v.v..vv....>>v..>......>.vvv>>.v...v>.....v>>v.v>>..vv....vvv>>.>vv....v.>....v....v..vvvv..v..v>..>>.......v.v.>..v.>vv.....v...\n..>vv........>...vvv..v.>...v...v....>>>.v.>.>v..v.>v........v..v>...>>..>...>v.v..>..v>...>>>...>v.>>>v>.>.>....v...v.v...v......>.v..v>.v\nv>>v>..vv.v>.>..>..>>v...>>..vv.vv........>>.>..v.v....vvv>.v..v.>....>>>..vv>.>v..>.>.v.v.>.>v.....>....>.>>.v.v>..>vv.>.>vv......v.>.v>v>\nv>v>>v>...v>.>.......v.v.vv.vvv....vv..vv.v.v>>...v.v>.v...>vv>.>.>.>..>..>v....vvv.v.......>>..>>.v...>.>.v.v.vv.>vv...v.v.vv...>...>>..>v\n>.>...>..v>v.v.>.>.v>>v>>>..>>>..>..>.>>......>.v.>.v>>>>>.v>.v.vv>v>.v>.v....>.....vv.>vv>v.v>.v>....vv.....vv>>>...vvvv......v>>.......v>\nv>.v.>>..vv..>........>>vvv..>>.v>>>>..>>v>.v.v.vvvv>..v>>.>v.>....>vv.v....>.vv.>.vv..v>>..>.>.>..v.>.v>vvv..>>>..vvv.>v....>......>.v...>\n..>>.v...vv>....>.v.>v>v>...>.........v.>vv.>.>v.>>.v....>>.>...v>v>>v>vv>.v>....vv..v......vv>.v.>>vv.vvv>..>....>.>v.>>..>v..v>.>....>.v.\n.>>v..>..>.v..v...>v.>v.>>....vv..>v>vv>>v>v....v...>v...>.v.>>>...v.v....>v..>..v.v....>.>>..>>>..v.vv.v.>..>......>.>v.vvv..v......v>.v..\n..>>v>vvvvv.vv..v..v>v.>..>v>..>..>.vvv>.v>.vv.>.>v>v.>.....vvv.vv.v..v.v...>>>v.vv>..>v.>>.v.vvv.v.>vv......>.v.v..v>.>>vv..>....vv...v..>\n.>.>.>.v..v.>...>.>..v..>v.>>v.>..>..v>.>.>..>v>......v.>..>...>....>.>.v>>>.>v.v>..>v>>..>>>..>.vv>.>v...v.>..>..>.>>.v.v>>.......>.vv>vv.\n....>>.>..>.>.>..vv>.v>v.>vv....>....v...vvv.>v.>..>....>...vvv>v..>v.....vv..v.>vv>.>>..>..>>.v..>.v>>v>.vv>.>vv..v...>..>vv>v>>>>v.>.v.v>\nvv....>.....>.v...v>.........>.>.>.v>>vv>v..vv>v.v>v.vv>..>....>>.>v..v...>.v.>..vv>.>.v...>vv>.vv>vv>>>.v......>..>.>.v>..v..>.v...>.>.v..\nv>.>...v.vv..v..>vv>>v..v.vv.vv...v.>.vv...v>.>.v>>..v...>...>...>v.>....vv>.v>..vv>..vv.>.vvv.>>v..v...vv.v.v>.v>....>..>vv..>.v..>>...>..\n.>.>v>v>..v>>...>.>.>v......v>.>.v..v.>v.vv.>v..>v>v.v>>v..v.vv..>>>>>...vv......>v.>>>.>>...v.v>.v.>>.>vvv>>..>>vv.>.>vvv.>.>v>v.....>.>..\n..>>...v.>.>>>v.vvvvvv>vv......v.>>.v>vv>.>.>.>.v...>vv.>>>>.....vv.>..>.>>>..v>>>.>v..>.>.>...>>.>.>v..>.vv>>.v..>.v>v..vvv>...>...v..v>..\n..v..>vv..v...v...v.>.>..>v..v..v.>.>>v>.v....vv>>.....>>>v.>.v.>v..>.>v>v.v.v.v...vv.v..vvvv.>.>>.>..>>.v..v...v>..>v..>.>>..vvv..>.>>.>..\n>v.>.vvv.>>.>.>..v>.>.>>...v>..>>v>..v>>.....vv>.v.v....>>...>.v.>.v.....v...>.>..v.>v..>...>.v..v..v..>>v...>>>..v.>.vv..>.>vv..>..v.....>\n>.v..v.>.v.v.>.v.vv.>vv>.v>.vvv>...v>.v..>>v>>..>.>>>>>....v>vv..v.v..>>v...v....vv.....>vv...>..v.v....v..v>>.>>.v.>v>vv>>......v...>.vv.v\nvv..vv.....v.>v......vv.>v...>.>.v>....v.v.....>v>..vv...>.>..v>>.>..v.v.>>..>>..v.v.vvv.v.vv.v>vv.>v>....>>v>>>>.....>v.....>vv..>.>..>v>v\nvv>...v>....>..v>vv..v>.v..>....>v>.v.v>>v..>v.>.....>vv.>>.v>.>v...v..>v>vvv...>....v.v.>v.>..v>v>>.>v..v..>vvv>..>.vv>...>>..>..v.>.>>v..\n...vvv.v.>>.>vv..>..>v..>>.>.......vv.>.v...vvv>.v.>..v..>....vv.vv.>>>..>>>.v.>v>.>>.........>.>>v.>v>>>....>>.>.>.>v...v.vvv.v.>.v.>>>>v>\n>.v..>....>.v.>...>v>v.v>>>..v.v>..v.>v.v.>>v>...v>>..>>vv>>.>.>>>>vv.v>...>..v..>.....v.>..v...vv.v...>v..>>v>.....>..v.>.v.>v>v.v.v>.v>..\n>>v>......>>>.>v>..>v...>>v>v>..v>....>.>.>.>v>...v.vv>v>.>>..>.v.v....>>......v.>.v..vvv>...>.v.>v....v>..>>v>....>..>v>..v.>>v..>...>.>>>\n.v>..>.>.v..v..v...v.>v...v>.v>v.vv.vv....>>vv..>vv.....>>v.vv>.vv...v..v.v.>.......v...>.........>v.v>....>>vv>.>..>v.>.>>.>>>.v...>..>v>.\n"
  },
  {
    "path": "advent-of-code/2022/.gitignore",
    "content": "day*/day[0-9][0-9]\nday*/sample\n"
  },
  {
    "path": "advent-of-code/2022/day01/day01.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day01\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day01/src/day01.nim",
    "content": "import strutils, sequtils, strformat, algorithm\n\nlet data = readFile(\"../inputs/01\")\n\nproc calories(): seq[int] =\n  for chunk in data.split(\"\\n\\n\"):\n    var chunk = chunk\n    chunk.removeSuffix\n    result.add(chunk.split(\"\\n\").map(parseInt).foldl(a + b))\n\n  result.sort(Descending)\n\nlet part1 = calories()[0]\nlet part2 = calories()[0..2].foldl(a + b)\n\necho fmt\"Part 1: {part1}\"\necho fmt\"Part 2: {part2}\"\n"
  },
  {
    "path": "advent-of-code/2022/day02/day02.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day02\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day02/src/day02.nim",
    "content": "import strformat\n\nvar partOne = 0\nvar partTwo = 0\n\nfor line in lines(\"../inputs/02\"):\n  let first = int(line[0]) - int('A')\n  let second = int(line[2]) - int('X')\n\n  partOne += ((second - first + 4) mod 3) * 3 + second + 1\n  partTwo += second * 3 + (first + second + 2) mod 3 + 1\n\necho &\"Part 1: {partOne}\"\necho &\"Part 2: {partTwo}\"\n"
  },
  {
    "path": "advent-of-code/2022/day03/day03.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day03\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day03/src/day03.nim",
    "content": "import sugar, sets, sequtils, strutils, math, strformat\n\nproc score(groups: seq[seq[string]]): int =\n  groups\n    .map(group => group.mapIt(it.toHashSet).foldl(a * b).toSeq[0])\n    .map(item => item.ord - (if item >= 'a': 'a'.ord else: 'A'.ord - 26) + 1)\n    .sum\n\nlet lines = lines(\"../inputs/03\").toSeq\n\nlet partOne = lines.map(it => it.toSeq.distribute(2).mapIt(it.join)).score\nlet partTwo = countup(0, lines.len - 1, 3).toSeq.mapIt(lines[it..it+2]).score\n\necho &\"Part 1: {partOne}\"\necho &\"Part 2: {partTwo}\"\n"
  },
  {
    "path": "advent-of-code/2022/day04/day04.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day04\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day04/src/day04.nim",
    "content": "import sequtils, strutils, strformat\n\nlet inputs = lines(\"../inputs/04\")\n  .toSeq\n  .mapIt(it.split({',', '-'}).map(parseInt))\n  .mapIt(((it[0], it[1]), (it[2], it[3])))\n\nvar partOne = 0\nvar partTwo = 0\n\nfor (a, b) in inputs:\n  let overlap = (max(a[0], b[0]), min(a[1], b[1]))\n\n  if overlap == a or overlap == b: partOne += 1\n  if a[0] <= b[1] and b[0] <= a[1]: partTwo += 1\n\necho &\"Part 1: {partOne}\"\necho &\"Part 2: {partTwo}\"\n"
  },
  {
    "path": "advent-of-code/2022/day05/day05.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day05\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day05/src/day05.nim",
    "content": "import strutils, sequtils, algorithm, sugar\n\ntype\n  Input = object\n    stacks: seq[seq[char]]\n    instructions: seq[tuple[count, source, target: int]]\n\nproc readInput(): Input =\n  let parts = readFile(\"../inputs/05\").split(\"\\n\\n\")\n\n  let stackLines = parts[0].split(\"\\n\").reversed[1..^1]\n  let numStacks = stackLines[0].len div 4 + 1\n\n  result.stacks = repeat(newSeq[char](), numStacks)\n\n  for i in 0..stackLines.len-1:\n    for j in 0..<numStacks:\n      let item = stackLines[i][j*4 + 1]\n      if item != ' ': result.stacks[j].add(item)\n\n  result.instructions = collect:\n    for line in parts[1].split(\"\\n\")[0..^2]:\n      let words = line.split(\" \")\n      (words[1].parseInt, words[3].parseInt - 1, words[5].parseInt - 1)\n\nproc solve(input: Input, transform: seq[char] -> seq[char]): string =\n  var stacks = input.stacks\n\n  for (count, source, target) in input.instructions:\n    let start = max(stacks[source].len - count, 0)\n    stacks[target].add stacks[source][start..^1].transform\n    stacks[source] = stacks[source][0..<start]\n\n  stacks.mapIt(it[^1]).join\n\necho \"Part 1: \", readInput().solve(x => x.reversed)\necho \"Part 2: \", readInput().solve(x => x)\n"
  },
  {
    "path": "advent-of-code/2022/day06/day06.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day06\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day06/src/day06.nim",
    "content": "import sets\n\nproc solve(size: int): int =\n  let chars = readFile(\"../inputs/06\")\n  for i in 0 ..< chars.len - size:\n    if chars[i..<i+size].toHashSet.len == size:\n      return i + size\n\necho \"Part 1: \", solve(4)\necho \"Part 2: \", solve(14)\n"
  },
  {
    "path": "advent-of-code/2022/day07/day07.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day07\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day07/src/day07.nim",
    "content": "import strutils, tables, sugar, sequtils, math, strformat\n\nvar cwd: seq[string] = @[\"\"]\nvar sizes = {\"/\": 0}.toTable\n\nfor line in lines(\"../inputs/07\"):\n  let words = line.split(\" \")\n  let path = cwd.join(\"/\")\n\n  if line == \"$ cd /\":\n    cwd = @[\"\"]\n  elif line == \"$ cd ..\":\n    cwd = cwd[0..^2]\n  elif line.startsWith(\"$ cd\"):\n    cwd.add words[2]\n  elif line.startsWith(\"dir\"):\n    sizes[&\"{path}/{words[1]}/\"] = 0\n  elif line == \"$ ls\":\n    discard\n  else:\n    sizes[&\"{path}/{words[1]}\"] = words[0].parseInt\n\nvar dirs = initCountTable[string]()\n\nfor dir in sizes.keys.toSeq.filter(d => d.endsWith(\"/\")):\n  for (file, size) in sizes.pairs:\n    if file.startsWith(dir):\n      dirs.inc dir, size\n\nlet delta = dirs[\"/\"] - 40000000\necho \"Part 1: \", dirs.values.toSeq.filter(x => x <= 100000).sum\necho \"Part 2: \", dirs.values.toSeq.filter(x => x >= delta).min\n"
  },
  {
    "path": "advent-of-code/2022/day08/day08.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day08\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day08/src/day08.nim",
    "content": "import algorithm, sequtils, strformat, sugar\n\nlet grid = lines(\"../inputs/08\").toSeq.map(line => line.toSeq.mapIt(it.int - '0'.int))\n\nvar visible = 0\nvar optimal = 0\n\nfor x in 0..<grid.len:\n  for y in 0..<grid[0].len:\n    let height = grid[x][y]\n\n    let lines = [\n      grid[x][0..<y],\n      grid[x][y+1..^1].reversed,\n      (0..<x).mapIt(grid[it][y]),\n      (x+1..<grid.len).mapIt(grid[it][y]).reversed,\n    ]\n\n    if lines.any(line => line.allIt(it < height)):\n      inc visible\n\n    proc reach(line: seq[int]): int =\n      for tree in line:\n        inc result\n        if tree >= height: break\n\n    optimal = lines.mapIt(reach(it.reversed)).foldl(a * b).max(optimal)\n\necho &\"Part 1: {visible}\"\necho &\"Part 2: {optimal}\"\n"
  },
  {
    "path": "advent-of-code/2022/day09/day09.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day09\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day09/src/day09.nim",
    "content": "import strutils, math, sets, strformat\n\ntype\n  Point = tuple[x, y: int]\n\nproc `+`(a, b: Point): Point = (a.x + b.x, a.y + b.y)\nproc `-`(a, b: Point): Point = (a.x - b.x, a.y - b.y)\nproc sgn(a: Point): Point = (sgn(a.x), sgn(a.y))\n\niterator directions(): string =\n  for line in lines(\"../inputs/09\"):\n    let parts = line.split(\" \")\n\n    for _ in 0..<parts[1].parseInt:\n      yield parts[0]\n\nvar rope: array[10, Point]\nvar one = initHashSet[Point]()\nvar two = initHashSet[Point]()\n\nfor direction in directions():\n  case direction:\n    of \"L\": rope[0].y -= 1\n    of \"R\": rope[0].y += 1\n    of \"U\": rope[0].x -= 1\n    of \"D\": rope[0].x += 1\n    else: raise\n\n  for i in 1..9:\n    let delta = rope[i - 1] - rope[i]\n    if delta.x.abs > 1 or delta.y.abs > 1:\n      rope[i] = rope[i] + delta.sgn\n\n  one.incl(rope[1])\n  two.incl(rope[^1])\n\necho &\"Part 1: {one.len}\"\necho &\"Part 2: {two.len}\"\n"
  },
  {
    "path": "advent-of-code/2022/day10/day10.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day10\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day10/src/day10.nim",
    "content": "import strutils, sequtils\n\niterator changes(): int =\n  for line in lines(\"../inputs/10\"):\n    yield 0\n    if line != \"noop\":\n      yield line.split(\" \")[1].parseInt\n\nvar cycle = 0\nvar register = 1\nvar sum = 0\n\nvar display = newSeq[array[40, bool]](6)\n\nfor n in changes():\n  if (register - (cycle mod 40)).abs <= 1:\n    display[cycle div 40][cycle mod 40] = true\n\n  cycle += 1\n\n  if cycle mod 40 == 20:\n    sum += register * cycle\n\n  register += n\n\necho sum\n\nfor row in display:\n  echo row.mapIt(if it: \"#\" else: \" \").join\n"
  },
  {
    "path": "advent-of-code/2022/day11/day11.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day11\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day11/src/day11.nim",
    "content": "import strscans, strutils, sequtils, parseutils, sugar, algorithm\n\ntype\n  Monkey = object\n    index: int\n    things: seq[int]\n    operation: Operation\n    divisor: int\n    success: int\n    failure: int\n    inspections: int\n  OperandKind = enum Self, Number\n  Operator = enum Multiply, Add\n  Operation = ref object\n    operator: Operator\n    case kind: OperandKind\n    of Self: discard\n    of Number: operand: int\n\nproc parseInput(): seq[Monkey] =\n  proc operation(input: string, output: var Operation, start: int): int =\n    if input[start + 2..start + 4] == \"old\":\n      output = Operation(kind: Self)\n      result = 5\n    else:\n      output = Operation(kind: Number)\n      result = parseutils.parseInt(input[start + 2..^1], output.operand) + 2\n\n    case input[start]\n    of '*': output.operator = Multiply\n    of '+': output.operator = Add\n    else: raise\n\n  proc numbers(input: string, output: var seq[int], start: int): int =\n    var parts: string\n    result = parseWhile(input[start..^1], parts, Digits + {',', ' '})\n    output = input[start..<start+result].split(\", \").map(parseInt)\n\n  const format = \"\"\"\nMonkey $i:\n  Starting items: ${numbers}\n  Operation: new = old ${operation}\n  Test: divisible by $i\n    If true: throw to monkey $i\n    If false: throw to monkey $i\n\"\"\"\n\n  collect:\n    for chunk in readFile(\"../inputs/11\").split(\"\\n\\n\"):\n      var monkey: Monkey\n      discard scanf(chunk, format, monkey.index, monkey.things, monkey.operation, monkey.divisor, monkey.success, monkey.failure)\n      monkey\n\nproc apply(op: Operation, number: int): int =\n  case op.kind\n    of Self: result = number\n    of Number: result = op.operand\n\n  case op.operator\n    of Multiply: result *= number\n    of Add: result += number\n\nproc solve(turns: int, fn: (int) -> int): int =\n  var monkeys = parseInput()\n\n  for _ in 1..turns:\n    for monkey in monkeys.mitems:\n      for item in monkey.things:\n        let item = monkey.operation.apply(item).fn\n\n        if (item mod monkey.divisor) == 0:\n          monkeys[monkey.success].things.add(item)\n        else:\n          monkeys[monkey.failure].things.add(item)\n\n        inc monkey.inspections\n\n      monkey.things.setLen(0)\n\n  return monkeys.mapIt(-it.inspections).sorted[0..1].foldl(a * b)\n\nlet m = parseInput().mapIt(it.divisor).foldl(a * b)\n\necho solve(20, x => x div 3)\necho solve(10000, x => x mod m)\n"
  },
  {
    "path": "advent-of-code/2022/day12/day12.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day12\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day12/src/day12.nim",
    "content": "import sequtils, strutils, deques\n\nvar map: seq[seq[char]]\nvar start: (int, int)\nvar target: (int, int)\nvar distance: seq[seq[int]]\n\nvar x = 0\nfor line in lines(\"../inputs/12\"):\n  distance.add repeat(-1, line.len)\n\n  if line.contains('S'):\n    start = (x, line.find('S'))\n\n  if line.contains('E'):\n    target = (x, line.find('E'))\n\n  map.add(cast[seq[char]](line.replace(\"E\", \"z\").replace(\"S\", \"a\")))\n  inc x\n\nlet height = map.len\nlet width = map[0].len\n\nvar left = [(target, 0)].toDeque\n\nwhile left.len > 0:\n  let (point, steps) = left.popFirst\n  let (x, y) = point\n\n  if distance[x][y] != -1 and distance[x][y] <= steps:\n    continue\n\n  distance[x][y] = steps\n\n  for (dx, dy) in [(0, 1), (0, -1), (1, 0), (-1, 0)]:\n    let (nx, ny) = (x + dx, y + dy)\n    if 0 <= nx and nx < height and 0 <= ny and ny < width and map[nx][ny].ord + 1 >= map[x][y].ord:\n      left.addLast(((nx, ny), steps + 1))\n\nlet first = distance[start[0]][start[1]]\nvar second = first\n\nfor x in 0..<height:\n  for y in 0..<width:\n    if map[x][y] == 'a' and distance[x][y] != -1:\n      second = min(second, distance[x][y])\n\necho \"Part 1: \", first\necho \"Part 2: \", second\n"
  },
  {
    "path": "advent-of-code/2022/day13/day13.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day13\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day13/src/day13.nim",
    "content": "import json, math, strutils, algorithm, sequtils\n\nproc wrap(node: JsonNode): JsonNode =\n  if node.kind == JInt:\n    result = newJArray()\n    result.add(node)\n  else:\n    result = node\n\nproc cmp(a, b: JsonNode): int =\n  if a.kind == JInt and b.kind == JInt:\n    return (a.getInt() - b.getInt()).sgn\n  elif a.kind == JArray and b.kind == JArray:\n    let first = a.getElems\n    let second = b.getElems\n\n    for i in 0..<min(first.len, second.len):\n      let res = cmp(first[i], second[i])\n      if res != 0:\n        return res\n    return (first.len - second.len).sgn\n  else:\n    return cmp(wrap(a), wrap(b))\n\nvar i = 1\nvar sum = 0\n\nfor line in readFile(\"../inputs/13\").split(\"\\n\\n\"):\n  let parts = line.split(\"\\n\")\n\n  if cmp(parseJson(parts[0]), parseJson(parts[1])) <= 0:\n    sum += i\n\n  inc i\n\necho \"Part 1: \", sum\n\nlet separators = [parseJson(\"[[2]]\"), parseJson(\"[[6]]\")]\n\nvar items = separators.toSeq\n\nfor line in lines(\"../inputs/13\"):\n  if line == \"\": continue\n  items.add(parseJson(line))\n\nitems.sort(cmp)\n\necho \"Part 2: \", separators.mapIt(items.find(it) + 1).foldl(a * b)\n"
  },
  {
    "path": "advent-of-code/2022/day14/day14.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day14\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day14/src/day14.nim",
    "content": "import strutils, sequtils, sets, math\n\ntype\n  Point = tuple[x, y: int]\n\nproc `-`(a, b: Point): Point = (a.x - b.x, a.y - b.y)\nproc `+`(a, b: Point): Point = (a.x + b.x, a.y + b.y)\nproc sgn(a: Point): Point = (a.x.sgn, a.y.sgn)\n\nproc parsePoint(s: string): Point =\n  let parts = s.split(',')\n  (parts[0].parseInt, parts[1].parseInt)\n\nproc parseInput(): HashSet[Point] =\n  for line in lines(\"../inputs/14\"):\n    let points = line.split(\" -> \").map(parsePoint)\n\n    var point = points[0]\n    for waypoint in points:\n      result.incl waypoint\n      while point != waypoint:\n        result.incl point\n        point = point + (waypoint - point).sgn\n\niterator flow(map: var HashSet[Point], point: Point, limit: int): Point {.closure.} =\n  if not (point in map) and (point.y < limit + 2):\n    for delta in [(0, 1), (-1, 1), (1, 1)]:\n      let recur = flow\n      for another in recur(map, point + delta, limit):\n        yield another\n\n    map.incl point\n    yield point\n\nvar input = parseInput()\nlet limit = input.mapIt(it.y).max\nvar count = 0\nvar found = false\n\nfor point in flow(input, (500, 0), limit):\n  if not found and point.y > limit:\n    echo \"Part 1: \", count\n    found = true\n  inc count\n\necho \"Part 2: \", count\n"
  },
  {
    "path": "advent-of-code/2022/day15/day15.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day15\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day15/src/day15.nim",
    "content": "import re, strutils, sequtils, algorithm, options, math, sugar\n\nconst LIMIT = 4_000_000\n\ntype\n  Point = tuple[x, y: int]\n  Sensor = tuple[location: Point, distance: int]\n  Span = tuple[a, b: int]\n\nproc manhattan(p1, p2: Point): int = abs(p1.x - p2.x) + abs(p1.y - p2.y)\n\nproc `&`(x, y: Span): bool = x.a <= y.b and y.a <= x.b\nproc `in`(x: int, span: Span): bool = span.a <= x and x <= span.b\nproc len(span: Span): int = span.b - span.a + 1\n\nproc parseInput(): tuple[sensors: seq[Sensor], beacons: seq[Point]] =\n  for line in lines(\"../inputs/15\"):\n    let numbers = line.findAll(re\"-?\\d+\").map(parseInt)\n    let location = (x: numbers[0], y: numbers[1])\n    let beacon = (x: numbers[2], y: numbers[3])\n\n    result.sensors.add (location: location, distance: manhattan(location, beacon))\n    result.beacons.add beacon\n\nproc project(sensor: Sensor, y: int): Option[Span] =\n  let point = (x: sensor.location.x, y: y)\n  let distance = manhattan(point, sensor.location)\n\n  if distance > sensor.distance:\n    return none(Span)\n\n  let delta = sensor.distance - distance\n\n  return some((a: point.x - delta, b: point.x + delta))\n\nproc compact(spans: openarray[Span]): seq[Span] =\n  var left = spans.toSeq\n\n  while left.len > 0:\n    var span = left.pop\n    var i = 0\n\n    while i < left.len:\n      if span & left[i]:\n        span = (min(span.a, left[i].a), max(span.b, left[i].b))\n        left.delete(i)\n        i = 0\n      else:\n        inc i\n\n    result.add span\n\nproc nonBeacons(sensors: seq[Sensor], beacons: openarray[Point], y: int): int =\n  let spans = sensors.mapIt(project(it, y)).filterIt(it.isSome).mapIt(it.get).compact\n  let overlapped = beacons.filter(b => b.y == y and spans.anyIt(b.x in it)).deduplicate\n\n  return spans.mapIt(it.len).sum - overlapped.len\n\nproc tuningFrequency(sensors: openarray[Sensor], limit: int): int =\n  var sorted = sensors.sortedByIt((it.location.x, it.distance))\n\n  for y in 0..LIMIT:\n    var x = 0\n\n    for sensor in sorted:\n      if manhattan((x: x, y: y), sensor.location) <= sensor.distance:\n        x = sensor.location.x + sensor.distance - abs(sensor.location.y - y) + 1\n\n    if x <= LIMIT:\n      return x * 4_000_000 + y\n\nlet (sensors, beacons) = parseInput()\n\necho \"Part 1: \", nonBeacons(sensors, beacons, LIMIT div 2)\necho \"Part 2: \", tuningFrequency(sensors, LIMIT)\n"
  },
  {
    "path": "advent-of-code/2022/day16/day16.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day16\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day16/src/day16.nim",
    "content": "import re, tables, strutils, sequtils\n\ntype\n  Index = range[0..63]\n\nvar indices: Table[string, Index]\nvar rates: array[low(Index)..high(Index), int]\nvar paths: array[low(Index)..high(Index), seq[Index]]\n\nvar index: Index = 0\nvar pathNames: Table[string, seq[string]]\n\nfor line in lines(\"../inputs/16\"):\n  let name = line[6..7]\n  let rate = line.findAll(re\"\\d+\")[0].parseInt\n  let rooms = line.split(re\"valves? \")[1].split(\", \")\n\n  rates[index] = rate\n  pathNames[name] = rooms\n  indices[name] = index\n\n  inc index\n\nfor (name, rooms) in pathNames.pairs:\n  paths[indices[name]] = rooms.mapIt(indices[it])\n\nproc flow(open: set[Index]): int =\n  for i in open:\n    inc result, rates[i]\n\ntype Memo = tuple[a, b: Index, time: int]\n\niterator possible(position: Index, open: set[Index], valid: bool): (Index, set[Index]) =\n  if valid:\n    if not(position in open) and rates[position] > 0:\n      yield (position, open + {position})\n\n    for next in paths[position]:\n      yield (next, open)\n  else:\n    yield (position, open)\n\nproc solve(steps: int, moveElephant: bool): int =\n  var best = 0\n  var seen: Table[Memo, int]\n\n  proc go(time: int, one: Index, two: Index, score: int, open: set[Index]) =\n    if time == 1:\n      best = best.max(score)\n      return\n\n    if seen.hasKey((one, two, time)) and seen[(one, two, time)] >= score:\n      return\n\n    seen[(one, two, time)] = score\n\n    for (one, open) in possible(one, open, moveElephant):\n      for (two, open) in possible(two, open, true):\n        go time - 1, one, two, score + flow(open), open\n\n  go steps, indices[\"AA\"], indices[\"AA\"], 0, {}\n\n  return best\n\necho \"Part 1: \", solve(30, false)\necho \"Part 2: \", solve(26, true)\n"
  },
  {
    "path": "advent-of-code/2022/day17/day17.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day17\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day17/src/day17.nim",
    "content": "import std/enumerate, sets, sequtils, tables\n\ntype\n  Point = tuple[x: int, y: int]\n\nlet shapes = [\n  @[(0, 0), (1, 0), (2, 0), (3, 0)],\n  @[(1, 0), (0, 1), (1, 1), (2, 1), (1, 2)],\n  @[(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)],\n  @[(0, 0), (0, 1), (0, 2), (0, 3)],\n  @[(0, 0), (1, 0), (0, 1), (1, 1)],\n]\n\nproc `+`(a, b: Point): Point = (a.x + b.x, a.y + b.y)\n\n\nproc fingerprint(cave: HashSet[Point], top: int): string =\n  for y in countdown(top, top - 30):\n    for x in 0 .. 6:\n      result.add(if (x, y) in cave: '#' else: '.')\n\nvar wind: seq[Point]\n\nfor c in readFile(\"../inputs/17\"):\n  case c:\n    of '<': wind.add((-1, 0))\n    of '>': wind.add((1, 0))\n    of '\\n': discard\n    else: raise newException(ValueError, \"Invalid character: \" & $c)\n\nvar rock: seq[Point] = shapes[0].mapIt(it + (2, 4))\nvar cave: HashSet[Point]\nvar fallen = 1\nvar foundPhase = false\nvar gain: int64 = 0\nvar left = 0\nvar seen: Table[(int, int, string), (int, int)]\n\nproc move(point: seq[Point], delta: Point): seq[Point] =\n  let moved = point.mapIt(it + delta)\n\n  if moved.allIt(it notin cave and 0 <= it.x and it.x <= 6 and 0 <= it.y):\n    return moved\n  else:\n    return point\n\nblock solution:\n  while true:\n    for (beat, delta) in enumerate(wind):\n      rock = rock.move((0, -1))\n      rock = rock.move(delta)\n\n      if rock.move((0, -1)) != rock:\n        continue\n\n      for pebble in rock:\n        cave.incl pebble\n\n      let height = cave.mapIt(it.y).max + 1\n      let memo = (fallen mod shapes.len, beat, fingerprint(cave, height))\n\n      if fallen == 2022:\n        echo \"Part 1: \", height\n\n      if foundPhase:\n        dec left\n        if left == 0: echo \"Part 2: \", height + gain\n      elif seen.hasKey(memo):\n        let (a, b) = seen[memo]\n        let phase = fallen - a\n        let remaining = 1_000_000_000_000 - fallen\n        let ha = (remaining div phase).int\n\n        left = int(remaining mod phase)\n        gain = ha * (height - b)\n        foundPhase = true\n      else:\n        seen[memo] = (fallen, height)\n\n      rock = shapes[fallen mod shapes.len].mapIt(it + (2, height + 4))\n      inc fallen\n\n      if left < 0 and fallen > 2022:\n        break solution\n"
  },
  {
    "path": "advent-of-code/2022/day18/day18.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day18\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day18/src/day18.nim",
    "content": "import strutils, sequtils, sets, sequtils, sugar, math\n\ntype\n  Point = tuple[x, y, z: int]\n\nproc within(p: Point, lower: int, higher: int): bool =\n  lower <= p.x and p.x <= higher and\n    lower <= p.y and p.y <= higher and\n    lower <= p.z and p.z <= higher\n\nproc sides(p: Point): seq[Point] =\n  @[\n    (p.x - 1, p.y, p.z),\n    (p.x + 1, p.y, p.z),\n    (p.x, p.y - 1, p.z),\n    (p.x, p.y + 1, p.z),\n    (p.x, p.y, p.z - 1),\n    (p.x, p.y, p.z + 1),\n  ]\n\nvar cubes: HashSet[Point]\n\nfor line in lines(\"../inputs/18\"):\n  let parts = line.split(',').mapIt(it.parseInt)\n  cubes.incl (x: parts[0], y: parts[1], z: parts[2])\n\nlet lower = cubes.mapIt([it.x, it.y, it.z].min).min - 1\nlet higher = cubes.mapIt([it.x, it.y, it.z].max).max + 1\n\nvar left: seq[Point] = @[(x: lower, y: lower, z: lower)]\nvar seen: HashSet[Point]\nvar count = 0\n\nwhile left.len > 0:\n  let point = left.pop\n\n  if point in seen:\n    continue\n\n  seen.incl point\n\n  for side in sides(point):\n    if side in cubes:\n      inc count\n    elif side notin seen and within(side, lower, higher):\n      left.add side\n\n\necho \"Part 1: \", cubes.toSeq.map(cube => cube.sides.countIt(it notin cubes)).sum\necho \"Part 2: \", count\n"
  },
  {
    "path": "advent-of-code/2022/day19/day19.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day19\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day19/src/day19.nim",
    "content": "import strutils, sequtils, sets, math\n\ntype\n  Blueprint = seq[int]\n  State = array[9, int]\n\nvar blueprints = newSeq[Blueprint]()\nfor line in lines(\"../inputs/19\"):\n  blueprints.add line.replace(\":\", \"\").split(' ').filterIt(it.all(isDigit)).map(parseInt)\n\nproc `+`(a, b: State): State =\n  for i in 0..8:\n    result[i] = a[i] + b[i]\n\nproc solve(blueprint: Blueprint, steps: int): int =\n  var best = 0\n\n  let\n    a = blueprint[1]\n    b = blueprint[2]\n    c = blueprint[3]\n    d = blueprint[4]\n    e = blueprint[5]\n    f = blueprint[6]\n\n  var seen: HashSet[State]\n\n  let max1 = max([a, b, c, e])\n  let max2 = d\n  let max3 = f\n\n  proc dfs(state: State) =\n    let t = state[0]\n\n    if t == 0:\n      best = max(best, state[8])\n      return\n\n    var state = state\n\n    state[1] = min(state[1], max1)\n    state[2] = min(state[2], max2)\n    state[3] = min(state[3], max3)\n\n    state[5] = min(state[5], t * max1 - state[1] * (t - 1))\n    state[6] = min(state[6], t * max2 - state[2] * (t - 1))\n    state[7] = min(state[7], t * max3 - state[3] * (t - 1))\n\n    if state in seen:\n      return\n\n    seen.incl state\n\n    let next = state + [-1, 0, 0, 0, 0, state[1], state[2], state[3], state[4]]\n\n    dfs next\n\n    if state[5] >= a: dfs next + [0, 1, 0, 0, 0, -a, 0, 0, 0]\n    if state[5] >= b: dfs next + [0, 0, 1, 0, 0, -b, 0, 0, 0]\n    if state[5] >= c and state[6] >= d: dfs next + [0, 0, 0, 1, 0, -c, -d, 0, 0]\n    if state[5] >= e and state[7] >= f: dfs next + [0, 0, 0, 0, 1, -e, 0, -f, 0]\n\n  dfs [steps, 1, 0, 0, 0, 0, 0, 0, 0]\n\n  return best\n\necho blueprints.mapIt(solve(it, 24) * it[0]).sum\necho blueprints[0..2].mapIt(solve(it, 32)).foldl(a * b)\n"
  },
  {
    "path": "advent-of-code/2022/day20/day20.nimble",
    "content": "srcDir        = \"src\"\nbin           = @[\"day20\"]\n\nrequires \"nim >= 1.6.10\"\n"
  },
  {
    "path": "advent-of-code/2022/day20/src/day20.nim",
    "content": "import strutils, lists\n\nproc properMod(a, b: int): int = (a mod b + b) mod b\n\nproc advance(node: var DoublyLinkedNode[int], count: int) =\n  for _ in 0..<count:\n    node = node.next\n\nproc solve2(mixes: int, key: int): int =\n  var ring = initDoublyLinkedRing[int]()\n  var nodes = newSeq[DoublyLinkedNode[int]]()\n\n  for line in lines(\"../inputs/20\"):\n    let number = parseInt(line) * key\n    var node = newDoublyLinkedNode(number)\n    ring.add node\n    nodes.add node\n\n  for _ in 1..mixes:\n    for node in nodes.mitems:\n      var previous = node.prev\n      ring.remove node\n\n      previous.advance properMod(node.value, nodes.len - 1)\n\n      previous.next.prev = node\n      node.prev = previous\n      node.next = previous.next\n      previous.next = node\n\n  var node = ring.find(0)\n\n  for _ in 1..3:\n    node.advance 1000\n    result += node.value\n\necho solve2(1, 1)\necho solve2(10, 811589153)\n"
  },
  {
    "path": "advent-of-code/2022/inputs/01",
    "content": "3864\n5112\n3233\n3008\n5052\n3291\n4002\n5402\n2907\n2398\n3014\n3923\n1475\n1997\n2519\n\n9130\n9712\n12437\n3457\n11610\n4598\n\n1698\n1551\n6798\n7440\n3574\n12107\n3697\n\n9019\n12113\n6266\n11838\n7562\n6444\n\n10364\n1437\n10513\n2988\n10836\n13749\n\n3011\n9552\n11575\n12646\n9861\n6347\n\n15883\n15888\n6725\n7353\n4998\n\n3165\n7637\n6348\n3250\n13535\n12802\n\n6683\n13364\n15858\n5489\n5315\n\n12294\n13732\n9734\n6165\n\n6023\n2374\n5773\n5578\n6419\n4301\n6861\n4560\n6021\n2960\n1349\n\n1847\n2687\n4164\n3599\n4361\n7463\n3010\n4351\n6738\n7941\n3855\n\n1848\n6606\n1662\n4276\n2488\n3635\n1954\n2375\n2020\n6327\n4907\n4523\n1756\n\n25495\n6242\n\n20001\n19849\n1924\n\n14631\n12374\n3017\n16388\n\n4779\n3772\n5719\n3491\n5698\n4909\n5656\n3250\n3805\n4068\n1689\n5141\n5754\n5097\n1951\n\n1824\n1235\n5428\n4808\n5453\n6331\n8706\n2132\n2107\n4675\n\n8668\n11626\n8358\n8178\n3039\n\n6897\n2675\n5347\n6427\n7065\n1305\n5852\n4200\n4995\n5786\n7447\n6742\n\n3863\n5824\n1725\n3534\n5440\n5958\n5225\n1794\n3812\n5589\n3028\n1252\n1746\n1196\n5477\n\n3938\n2800\n8859\n7153\n4821\n3198\n2694\n4947\n\n6697\n3509\n4723\n3891\n6796\n1662\n1369\n3632\n3649\n6928\n2270\n5340\n\n20974\n30984\n\n7699\n5994\n4189\n4527\n11298\n3529\n2212\n\n2603\n2414\n8646\n3184\n4391\n5234\n7213\n7920\n2147\n1809\n\n5039\n7539\n4470\n2247\n9676\n12772\n\n1630\n8375\n9097\n9007\n7498\n5776\n8173\n8946\n\n1130\n3475\n5415\n4784\n5293\n5724\n1730\n2220\n4327\n4915\n4210\n2089\n2161\n\n54387\n\n5235\n6486\n6332\n6169\n4904\n3117\n4987\n5488\n3506\n6267\n3229\n2268\n2058\n2575\n\n10343\n7175\n7614\n1014\n8145\n7014\n8807\n7703\n\n2942\n2045\n9735\n6097\n9103\n3805\n10274\n4901\n\n5227\n6127\n6923\n3691\n2423\n4298\n4130\n5149\n6163\n3855\n2709\n4583\n5465\n\n6713\n7303\n2326\n1054\n2108\n6795\n1399\n5164\n8389\n1413\n\n11210\n2885\n2768\n4565\n7853\n8590\n4953\n\n3359\n5464\n6359\n9578\n3986\n3114\n2449\n5502\n8884\n\n4380\n6795\n6388\n3666\n6385\n5336\n4891\n2633\n6116\n4340\n6410\n2381\n5618\n\n6611\n8713\n3262\n2084\n5305\n6025\n6210\n4838\n6432\n1770\n\n7316\n7253\n1999\n2136\n9789\n6351\n9843\n6965\n\n13110\n10487\n2738\n11418\n5886\n4257\n\n5279\n3005\n5787\n4700\n4579\n5366\n4134\n3856\n4433\n4225\n1119\n3261\n1206\n\n7528\n6795\n3581\n7530\n4287\n3004\n4899\n1682\n6540\n8041\n1163\n\n5271\n9504\n4466\n5030\n9039\n6302\n9526\n5770\n7822\n\n3927\n1053\n7169\n8745\n6919\n8249\n1402\n5462\n2763\n7113\n\n4657\n20694\n21592\n\n4904\n6515\n9389\n9141\n5209\n1682\n7319\n9383\n4057\n\n13752\n9584\n8823\n\n2085\n8569\n6909\n6769\n7842\n1740\n8757\n2428\n1151\n\n1240\n6410\n5661\n1817\n4367\n6749\n3837\n3287\n2126\n\n48984\n\n5064\n2260\n7884\n6506\n1312\n2949\n\n2501\n3041\n5435\n4134\n4921\n9071\n1539\n8718\n4927\n\n13457\n13830\n14262\n16094\n6856\n\n4134\n5955\n2100\n3580\n1618\n6258\n2037\n3407\n6043\n5882\n5180\n5852\n1142\n\n6315\n3132\n4804\n7315\n1145\n6572\n4295\n1818\n6889\n3224\n2124\n4383\n\n49471\n\n16847\n14810\n10031\n15268\n\n9925\n13290\n11355\n12632\n7822\n\n2393\n2849\n1713\n6708\n2818\n7002\n4987\n2814\n1650\n5845\n6962\n3250\n\n3022\n4101\n6484\n6655\n5900\n3114\n2479\n7243\n3711\n3322\n3543\n6403\n\n3922\n6921\n2825\n3470\n6452\n1334\n7415\n4350\n1250\n6732\n6071\n\n13203\n10169\n14375\n9425\n6521\n\n14621\n8430\n19479\n10045\n\n5082\n1198\n1420\n2902\n2764\n3099\n6677\n5280\n1059\n2165\n6836\n\n1275\n7294\n5909\n4850\n3642\n4437\n7639\n2001\n8353\n7923\n\n65166\n\n8180\n2720\n5919\n1586\n7115\n2500\n1213\n8595\n6904\n1338\n\n3154\n6288\n8212\n7799\n4547\n5465\n4819\n4080\n7698\n\n4718\n2231\n3672\n4929\n3608\n1125\n1283\n3307\n5198\n6605\n5178\n5314\n1539\n\n5772\n5108\n5245\n3701\n2893\n5852\n2399\n4988\n4363\n4949\n5894\n6708\n\n7223\n3143\n8012\n1442\n5661\n8021\n6281\n5132\n3742\n3028\n5716\n\n1439\n9221\n8094\n7476\n1144\n1889\n4245\n6198\n9020\n\n6934\n5060\n2312\n1886\n1988\n4895\n7235\n1647\n2814\n3147\n5432\n7285\n\n39249\n\n18283\n24247\n1734\n\n7175\n\n7790\n7393\n12909\n14444\n4285\n\n4692\n7363\n6394\n7058\n4988\n5041\n1886\n2515\n1490\n2791\n5734\n2365\n\n1468\n8324\n23095\n\n4178\n5102\n5153\n3115\n4749\n1387\n5849\n2752\n1318\n5515\n6390\n3345\n5912\n5829\n\n4765\n4421\n1225\n3593\n8691\n6986\n7451\n8529\n5251\n4784\n\n2862\n3838\n7199\n7330\n2514\n8670\n8281\n3576\n4912\n2260\n\n1962\n5598\n4649\n5922\n4135\n4373\n6511\n5068\n3156\n2439\n6200\n1464\n4222\n\n5741\n10630\n3768\n3343\n8548\n3202\n2871\n\n6916\n17569\n24608\n\n7823\n7460\n6920\n3049\n8003\n3858\n3611\n4790\n3392\n\n27393\n\n4616\n8220\n1239\n7295\n6397\n1372\n\n17576\n18361\n10204\n13704\n\n15826\n3578\n14185\n2385\n1221\n\n5127\n3905\n4206\n1073\n5846\n2267\n1482\n1450\n1451\n2768\n2849\n2850\n3312\n1479\n5513\n\n10345\n4158\n12513\n5591\n16153\n\n6027\n1377\n1804\n3795\n5796\n2626\n6336\n3746\n6146\n6311\n6113\n4062\n3067\n\n2448\n1058\n4229\n3204\n6020\n2882\n5419\n2084\n3590\n5993\n3840\n1156\n2502\n1817\n6055\n\n32707\n1241\n\n3045\n1309\n3599\n3823\n2307\n1547\n1612\n6550\n3459\n5435\n1056\n4990\n4650\n\n4354\n6100\n2169\n2654\n6645\n4525\n2880\n2747\n6052\n6365\n5701\n\n1503\n1293\n2530\n9166\n8656\n9926\n9255\n7066\n\n9305\n7085\n6824\n9498\n9025\n7904\n3118\n3142\n\n10108\n2329\n4742\n8494\n1708\n1343\n3350\n6716\n\n6532\n2895\n4189\n1971\n7834\n1107\n1027\n6415\n1211\n3023\n1636\n\n4973\n5464\n3843\n6092\n2053\n1745\n6005\n5862\n4142\n1415\n4875\n1617\n5642\n1920\n4706\n\n7408\n17800\n11194\n13159\n\n5566\n1756\n2450\n5854\n1639\n3928\n2742\n6385\n6120\n5802\n1599\n1249\n3625\n\n1670\n4618\n5316\n3653\n5167\n3252\n4995\n1200\n3446\n4433\n6113\n1342\n4176\n5753\n\n4597\n9620\n3712\n1774\n5338\n4078\n7296\n3434\n9310\n\n8976\n12080\n8938\n6131\n10273\n10621\n4234\n\n6447\n13533\n10763\n11732\n5190\n9129\n\n5281\n3655\n5424\n5314\n3908\n5582\n3114\n1744\n5385\n3111\n4497\n2897\n4401\n1298\n\n12623\n8559\n12761\n1280\n12850\n11620\n\n1809\n2403\n2257\n4586\n4585\n5761\n3264\n4621\n1045\n2354\n1954\n\n5074\n7245\n5125\n6481\n6424\n5650\n6906\n1789\n5924\n1086\n1690\n2558\n\n3471\n1419\n10640\n2304\n11881\n11729\n12014\n\n17503\n19515\n15606\n1866\n\n4486\n3617\n9287\n4473\n7289\n1852\n9402\n3964\n3602\n\n7989\n2612\n1003\n7634\n4889\n1978\n5232\n1146\n\n5487\n7770\n8115\n2268\n3609\n3100\n\n6205\n6444\n8414\n2959\n7972\n8829\n6256\n1156\n\n4737\n1069\n3768\n2510\n3527\n5221\n1666\n4470\n3563\n1654\n5734\n3075\n5575\n\n15504\n12559\n8976\n9824\n8990\n\n7934\n3476\n6965\n3686\n3923\n2709\n8648\n7699\n\n6772\n3077\n2503\n4261\n2890\n3068\n3921\n4858\n4882\n2770\n5354\n6859\n3445\n\n52484\n\n11901\n15405\n13990\n17226\n\n5850\n4678\n5707\n5673\n1485\n3913\n3480\n5013\n2565\n2062\n2406\n6342\n5828\n\n4758\n3972\n5428\n7975\n1407\n5563\n4808\n7919\n4359\n5078\n3682\n\n18959\n4053\n1937\n6684\n\n6150\n2908\n4347\n1341\n6863\n6723\n2992\n4434\n6267\n4876\n\n4458\n12449\n10626\n4621\n3687\n9892\n\n13207\n1659\n18006\n12201\n\n6923\n2813\n2898\n1837\n5875\n4333\n5434\n1703\n1930\n3207\n4145\n6236\n5833\n\n8993\n6150\n10505\n2085\n9550\n9271\n11322\n\n3046\n2665\n1049\n2145\n1082\n2523\n3809\n3976\n1052\n3415\n3224\n3522\n3740\n4872\n2536\n\n23303\n24203\n6904\n\n5562\n1246\n3109\n4849\n3079\n4853\n2026\n5356\n4397\n2953\n6317\n6009\n4248\n2557\n\n14594\n25779\n16865\n\n1229\n5756\n3663\n5951\n7077\n1950\n3508\n\n3758\n4208\n8189\n10315\n3057\n2813\n4001\n\n7597\n1192\n8466\n10400\n4446\n7610\n6265\n3735\n\n7012\n2301\n12432\n4820\n1329\n\n12293\n4034\n\n4964\n3467\n2701\n5807\n3710\n4313\n3761\n3127\n4525\n2948\n4560\n1989\n3900\n4193\n4177\n\n11249\n36854\n\n1034\n4105\n2297\n5906\n3525\n2047\n6844\n2436\n6523\n3394\n2502\n4028\n2509\n\n4336\n3094\n2833\n4452\n6331\n6115\n2301\n3217\n5287\n7749\n7323\n\n4148\n1984\n4102\n6569\n3790\n6576\n3567\n3802\n2742\n6539\n2247\n5713\n6088\n\n4975\n1430\n2970\n3669\n1025\n1244\n3788\n1979\n5738\n3292\n3556\n3730\n6105\n3277\n4346\n\n15738\n9547\n16697\n\n66474\n\n4263\n6015\n3324\n3812\n5843\n2654\n1389\n6766\n6319\n1516\n5893\n4485\n2272\n\n12631\n3624\n7153\n16205\n13771\n\n10426\n12897\n17028\n\n9876\n6551\n9756\n1740\n7096\n8600\n7217\n4773\n\n7909\n7798\n9063\n8985\n4679\n1808\n7964\n1699\n4306\n\n4503\n6328\n7241\n2595\n4247\n7351\n4336\n4402\n4159\n\n31634\n\n8118\n1323\n4680\n1149\n4085\n10126\n4137\n3525\n\n8530\n3662\n3779\n8656\n5607\n8840\n7246\n4802\n2720\n\n2839\n5366\n5585\n1265\n6497\n1123\n2588\n3881\n5866\n3361\n5737\n5557\n3432\n3415\n\n1155\n6948\n1379\n3529\n2804\n6611\n2950\n1813\n6580\n6723\n5971\n5549\n\n2561\n2538\n1721\n2674\n2618\n3598\n1152\n5254\n6073\n3352\n1016\n2452\n5835\n5319\n2337\n\n4682\n8460\n8055\n1318\n8906\n7333\n7422\n1762\n3159\n\n4290\n4947\n3993\n1717\n7989\n6175\n3558\n1492\n6565\n7338\n\n1687\n6502\n5542\n6358\n2954\n5758\n5980\n6825\n5866\n1280\n4830\n3345\n\n5162\n3923\n1385\n4797\n3288\n1723\n2312\n5272\n5749\n5538\n4432\n3931\n4573\n2554\n\n7658\n4023\n7144\n6541\n3310\n5114\n4847\n8803\n5657\n1784\n\n4370\n3305\n6516\n5828\n9182\n4402\n9934\n\n6053\n\n8494\n\n6095\n11294\n8547\n10083\n8434\n11764\n2951\n\n2952\n3177\n7103\n4875\n1817\n10323\n1381\n\n13123\n9521\n23873\n\n5787\n12655\n12756\n20017\n\n1849\n4191\n6295\n6289\n2796\n4640\n4409\n1030\n2279\n1813\n1948\n2271\n6518\n\n9749\n1518\n3621\n9996\n9173\n1741\n\n8417\n2916\n6781\n9461\n7940\n8660\n10204\n8902\n\n36117\n\n4928\n11184\n6168\n12046\n3466\n6830\n\n4507\n1340\n5878\n3276\n3793\n6844\n4796\n1096\n5405\n3905\n1762\n5264\n1384\n\n3121\n5572\n5864\n6716\n9604\n1966\n10685\n4693\n\n5684\n5699\n2937\n2273\n1618\n4506\n3601\n5460\n6154\n4258\n6404\n4984\n3264\n1155\n\n4268\n7380\n7893\n3865\n6244\n5745\n7877\n3322\n3627\n\n5996\n4074\n5569\n3507\n6114\n3961\n6042\n5272\n2995\n4667\n2161\n5336\n3922\n5647\n2187\n\n4228\n4393\n5050\n1155\n2427\n4201\n1233\n6100\n5369\n4142\n3524\n3058\n6176\n2121\n\n7869\n8100\n6906\n2028\n3868\n8614\n5236\n1366\n9400\n\n23443\n9993\n8524\n\n1473\n4354\n2258\n5343\n2574\n6151\n4949\n4792\n5509\n5791\n6246\n3977\n5126\n4920\n\n2080\n3619\n2138\n2745\n\n2001\n9394\n7088\n5665\n9985\n8964\n2620\n\n3346\n4344\n15757\n4227\n9296\n\n4465\n5869\n4651\n2306\n3055\n5572\n4963\n3055\n1328\n4879\n6011\n4266\n5300\n1046\n5571\n\n6086\n5882\n21009\n\n4163\n9276\n11926\n2012\n11726\n9290\n\n23241\n20013\n6592\n\n4638\n8473\n2576\n3643\n8712\n5578\n4112\n3300\n4531\n6702\n\n1360\n2866\n5521\n4452\n1437\n6475\n4393\n6121\n4211\n3168\n6841\n3096\n2048\n\n11379\n\n3821\n6927\n1607\n3907\n8928\n4193\n2371\n3760\n7531\n\n3976\n1570\n8665\n8603\n2337\n3396\n3583\n5928\n6876\n6429\n\n9263\n5094\n11647\n3988\n7631\n3263\n\n5716\n8255\n5940\n10735\n7349\n6548\n4650\n5816\n\n1229\n2098\n6221\n5073\n4343\n6126\n3950\n1293\n2848\n4351\n6438\n5156\n2619\n3244\n\n6788\n5274\n2215\n3979\n2788\n7081\n2119\n6235\n1359\n7141\n1497\n3362\n\n6956\n2914\n3014\n5001\n7681\n7144\n2914\n4128\n3004\n6170\n1417\n\n13926\n18761\n6405\n\n2805\n2134\n5990\n1899\n3919\n3040\n2357\n2352\n2295\n3900\n1039\n4151\n\n21789\n17570\n24738\n\n3241\n9968\n5793\n8790\n10130\n6838\n2229\n9715\n\n7270\n6954\n10077\n10701\n10903\n4370\n\n7931\n3629\n14710\n2728\n5862\n\n2262\n2517\n3677\n4296\n1177\n5268\n3759\n4892\n2275\n6369\n4674\n4536\n1970\n\n8547\n4623\n1624\n7643\n9658\n6489\n1199\n7866\n9443\n\n6363\n6567\n2584\n9352\n8291\n10254\n3179\n4177\n\n1358\n4057\n5758\n1719\n5758\n5143\n5942\n3502\n1033\n3488\n4825\n2379\n5280\n4139\n2928\n\n16444\n23345\n\n1933\n3294\n5717\n7357\n2773\n7946\n3876\n7471\n5962\n4976\n6369\n\n14677\n9136\n24025\n\n14151\n18024\n4880\n10196\n\n1152\n5591\n5800\n2475\n5481\n7792\n6041\n1224\n1138\n5768\n3158\n\n2689\n3417\n4316\n1811\n1853\n4110\n1860\n2250\n6493\n3285\n6372\n2214\n4907\n5587\n\n3713\n4494\n3322\n5279\n2203\n5933\n4894\n1353\n4219\n1011\n\n4117\n2122\n4192\n3719\n1855\n1842\n3312\n2056\n3121\n1974\n5752\n3417\n4830\n3341\n3080\n\n5172\n5003\n2775\n4138\n5964\n4643\n5584\n5634\n3776\n5664\n3815\n1702\n5195\n6368\n\n8665\n\n41002\n\n4531\n5677\n2926\n2964\n3287\n2916\n2527\n1677\n1535\n3773\n6299\n5507\n3247\n\n6025\n8452\n9375\n8793\n4184\n6122\n11183\n\n21084\n\n2635\n7467\n1635\n2903\n2572\n4592\n7070\n4212\n8780\n\n4910\n7018\n6084\n3618\n1922\n2781\n2283\n1541\n1971\n1445\n1528\n6543\n\n6867\n5700\n4220\n8066\n3951\n1890\n7064\n2486\n3213\n1323\n\n49337\n\n2188\n7181\n6604\n5420\n4804\n5447\n2652\n1824\n5731\n3217\n2954\n7297\n\n4106\n3442\n6464\n6654\n3723\n1293\n6951\n3407\n3993\n3524\n\n2163\n5961\n6245\n1510\n4674\n6248\n2035\n1510\n1105\n4586\n5132\n5687\n5381\n2342\n\n15330\n22553\n25696\n\n6825\n3520\n3181\n2552\n1875\n2522\n4232\n1897\n6190\n1155\n4446\n2414\n5686\n\n6164\n5650\n4649\n6471\n2415\n1229\n6458\n6585\n6982\n2279\n4215\n3518\n\n5048\n5614\n2542\n5841\n1986\n10453\n8196\n9669\n\n8040\n4567\n7515\n2496\n5786\n1226\n8596\n2383\n7726\n1760\n"
  },
  {
    "path": "advent-of-code/2022/inputs/02",
    "content": "B Y\nA Z\nA Z\nC Z\nB Y\nB Y\nB X\nB Z\nC Z\nB X\nB Y\nA Z\nB Y\nB Z\nB Y\nC Z\nB Z\nB Y\nB Z\nC Y\nB Y\nA Z\nB Y\nB Y\nB Y\nC Y\nA Z\nB Y\nB X\nA Z\nB X\nA Z\nA Z\nB Y\nB Y\nB X\nA Z\nB Y\nB Z\nC X\nC X\nB Y\nB Y\nB X\nB X\nC X\nB X\nA Z\nB Y\nB Y\nC X\nA Z\nB Y\nB Z\nB X\nB X\nA Z\nA X\nB Y\nB Y\nB Z\nC Z\nB Z\nB Z\nB Z\nA Z\nA Z\nB X\nB X\nB Y\nB X\nB X\nC Z\nC Z\nA Z\nA Y\nA Z\nB Z\nA Z\nB Y\nC X\nB X\nC X\nB Z\nB Z\nC Z\nB Z\nB X\nC X\nA Z\nC X\nB Z\nA Y\nC Z\nB Y\nC Y\nB X\nA X\nB Y\nB X\nB X\nB Z\nB Y\nA Z\nB Z\nB Y\nB Y\nA X\nA Z\nB X\nB X\nB X\nB X\nB Z\nB Z\nB Y\nC X\nA Z\nA Z\nB Y\nB Z\nB Y\nA Z\nB Z\nA Z\nA Z\nC X\nB Z\nA Z\nA Z\nB Y\nB Z\nA Z\nB Y\nB Y\nA Z\nB Y\nC X\nB Z\nB Y\nB X\nC X\nB X\nB X\nB X\nA Z\nA Z\nC Y\nA Z\nB Y\nA Z\nC X\nB Z\nB Z\nC X\nB Y\nC X\nB X\nB X\nC X\nA Z\nB Y\nC X\nB X\nB Y\nA Z\nB Y\nB Y\nC X\nB Y\nC X\nA Z\nA Z\nA Z\nB Y\nB Y\nA X\nA Z\nA Z\nB Y\nC X\nC Y\nB Y\nC X\nA Z\nB X\nA Z\nA Z\nC X\nB Y\nA Z\nB Y\nC X\nA Z\nB X\nB Y\nA Z\nB Y\nB X\nB X\nC X\nB Y\nC Y\nA Z\nB Y\nB Y\nC Y\nB Y\nC Y\nC X\nA Y\nA Y\nB Z\nB Y\nA Z\nB Z\nB X\nB X\nB Y\nA Z\nB Y\nB X\nB Y\nB Y\nC Z\nB Y\nB Y\nA Z\nA Z\nB Z\nA Y\nC X\nB Y\nB Y\nB Z\nB Z\nB Y\nC X\nB Y\nB X\nB Z\nB Y\nB X\nB Y\nC Z\nB Y\nB X\nA Z\nB Z\nB Z\nA Z\nC X\nB Y\nC Z\nA Z\nB Y\nC Z\nB Y\nB X\nB Y\nB X\nC Z\nB Z\nA Z\nA Z\nA Z\nA X\nB Z\nB Y\nB X\nB Y\nA Z\nB Z\nC Z\nB X\nB Z\nB Z\nA Z\nB Y\nB X\nA Z\nA Z\nB Y\nB X\nA Z\nA Z\nC Z\nA Z\nC Z\nB Y\nB Y\nB Z\nC X\nA Z\nB X\nB Y\nB X\nB Y\nB Y\nB X\nB Z\nB X\nC Z\nC X\nC X\nA Z\nA Z\nB X\nB X\nA Y\nC X\nB Y\nA Y\nB Z\nB X\nA Z\nB X\nB Y\nB Y\nB Y\nB Y\nA Z\nA Z\nB Y\nB X\nC Z\nB Z\nC X\nB Z\nB Y\nC X\nA Z\nB Y\nA Z\nA Z\nB Z\nB Y\nB X\nA Z\nB X\nB Y\nA Z\nB Z\nB X\nB X\nA Z\nC Y\nB X\nA Z\nB X\nB Y\nC X\nB Y\nC Z\nC X\nB Y\nB Y\nB Y\nB X\nB Y\nB X\nA Y\nA Z\nB Z\nB Y\nB X\nB Z\nB Y\nC Z\nB Y\nA Z\nB X\nA Z\nC X\nA X\nB Z\nB Z\nC X\nA Z\nB X\nA Z\nA Z\nB Z\nA Z\nB Y\nB Z\nC Z\nA Y\nA Z\nA Z\nA Z\nC X\nB Z\nB Z\nB Y\nB X\nB Y\nB Y\nB Y\nB Z\nB Y\nB Y\nA Z\nB Z\nA Z\nC X\nB Y\nB X\nB Y\nB X\nB Y\nB Y\nC X\nB Y\nB Y\nB Z\nB Y\nC X\nB Y\nB X\nB Y\nC X\nA X\nA Z\nC Z\nB Y\nC Z\nB X\nC Z\nC X\nC Z\nB Y\nB Y\nC X\nC X\nB Y\nC X\nA Y\nB Y\nB X\nB X\nB Z\nB Y\nC Y\nC X\nB X\nB Y\nB Z\nB X\nB Z\nB Z\nC X\nB X\nB Y\nB Z\nB X\nC Z\nA Y\nB Y\nB Y\nB Y\nA Y\nC Y\nB Y\nB Z\nB Z\nB Y\nB Y\nB Z\nB X\nB X\nB Y\nA Z\nC Y\nC Z\nB Y\nB X\nB Y\nB Y\nC X\nB Y\nC X\nA Z\nB X\nC X\nC Z\nA Z\nA Z\nB Y\nC X\nA Z\nA Z\nB Y\nA Y\nB Y\nA Z\nA Z\nB X\nC X\nA Z\nB X\nB Z\nA Z\nA Z\nB X\nB Y\nB X\nB Z\nB Y\nB Y\nB Z\nC X\nC X\nB Y\nA Z\nB X\nB X\nB Y\nB Z\nB Y\nB X\nB Z\nB X\nB Y\nC X\nB Y\nB Y\nC Y\nA Z\nB Y\nB X\nB Y\nA Z\nC X\nA Z\nA X\nB Z\nB X\nA Z\nB Y\nB X\nB X\nA Z\nB Y\nA Z\nB Z\nB Y\nA Z\nB Y\nB Y\nA Z\nB Z\nC Z\nB Y\nB Y\nC Y\nA Z\nB Y\nB Y\nB Y\nB Y\nB Z\nB Y\nB Y\nB Y\nC X\nB Z\nB X\nA Z\nB Z\nC X\nB Y\nB Y\nA Z\nB Y\nB X\nA Z\nA Z\nC Z\nB X\nB X\nB Y\nB Z\nB Z\nB Z\nB Y\nB Y\nB Y\nB Y\nB Z\nB Y\nA Z\nA Y\nA Z\nB Y\nB Y\nA Z\nB X\nB Y\nA Z\nC Z\nB Z\nB Z\nB Y\nA Z\nA Z\nB Y\nB X\nB Z\nB X\nB Y\nB Y\nB X\nC X\nB Z\nB X\nA Z\nB Y\nC Z\nB X\nA Z\nC Z\nC Z\nA Z\nB Y\nB Y\nA Y\nB Y\nC Z\nB X\nC X\nB Y\nB X\nB Z\nB Y\nB Z\nB Y\nB Y\nA Z\nB X\nB X\nA Y\nB Z\nB X\nB Z\nA Y\nB Z\nC X\nB X\nB X\nB Z\nB X\nC Y\nB Y\nC X\nC X\nB Z\nB X\nC Z\nB Z\nA Z\nC Y\nB Y\nB Y\nB X\nB Z\nB Y\nB Y\nB X\nC X\nB Y\nB Y\nC Y\nB Z\nC X\nA Z\nB X\nB X\nB Z\nB X\nB Y\nA Z\nB Z\nB X\nA Z\nB Y\nC X\nA Y\nA Z\nC X\nB X\nB Z\nB X\nC X\nA Z\nB X\nB Y\nB Y\nA Z\nB Z\nC X\nA Z\nB Z\nC X\nB X\nA Z\nC X\nC Z\nB Y\nB Z\nB Y\nB X\nC Z\nB Z\nB Z\nB Y\nA Z\nC Z\nA Y\nB Y\nC X\nB Y\nB Z\nA Z\nB Z\nA Z\nB X\nC X\nB Y\nA Z\nB Y\nB X\nC Z\nB Z\nC X\nB Y\nB X\nC Y\nB Y\nC X\nB Y\nB Y\nB Y\nB Z\nB Y\nB X\nB Y\nB Y\nA Z\nA Z\nC X\nB Z\nB Y\nA Z\nB X\nC X\nB Y\nB X\nA Z\nC Z\nA Z\nB Z\nB Y\nB X\nB Z\nB Y\nA Z\nC X\nC Z\nA Y\nA Z\nC X\nC Y\nC Z\nB Y\nB X\nB Z\nB Y\nB X\nB Y\nA Z\nB Y\nC X\nB X\nB Y\nC Z\nB Y\nB Y\nB Y\nB X\nB Y\nC Z\nB X\nB Y\nB Y\nB Z\nB X\nB X\nB Z\nB Z\nA Z\nA Z\nC X\nB Y\nB Y\nC X\nB Y\nB X\nA Y\nC Z\nB Y\nB Z\nB Y\nB Y\nA Z\nB Y\nB Z\nB Y\nB Z\nB X\nB Z\nB Y\nA Z\nB X\nB Z\nB Y\nB Y\nB Z\nB Y\nA Z\nB X\nB Y\nB Z\nB X\nB Y\nB X\nB X\nB Y\nB X\nC Y\nB Z\nB Y\nB Z\nC Y\nA Z\nB Y\nA Z\nB X\nA Z\nA Z\nC Z\nB X\nC Y\nA Z\nB Z\nB Z\nB X\nB Z\nB Y\nA Z\nB Z\nC Z\nA Z\nC Y\nA Z\nB Y\nA Z\nB Y\nA Z\nB X\nA Z\nB Z\nC X\nB Y\nB Y\nB Y\nC X\nB Z\nC X\nA Z\nA Z\nC X\nB Y\nB Z\nB X\nB Y\nB X\nA Z\nB Y\nB Y\nA Z\nB Y\nB Z\nB Z\nB X\nB Z\nB Y\nB X\nB Y\nB Y\nC X\nC Z\nB Y\nB Y\nB Y\nB Z\nB Y\nB Y\nB Y\nA Z\nB Y\nB X\nB Y\nB X\nB Z\nB Y\nB X\nB X\nA Y\nB Y\nB X\nB Y\nB Y\nB Y\nB Z\nB X\nA Z\nB Y\nB Y\nB Y\nA Z\nB X\nB X\nC Z\nB Y\nB Y\nA Z\nB Y\nB Z\nB X\nC X\nB Y\nB Y\nC X\nC Z\nB X\nA Z\nB Y\nB Y\nB X\nB X\nB X\nB Y\nB Y\nA Z\nA Z\nB Y\nB Y\nA Z\nB Z\nA Z\nC X\nC X\nB Y\nB Y\nA Z\nA Z\nC Z\nB Z\nB X\nA Z\nB X\nB Y\nB Y\nB X\nB Y\nB Y\nC Z\nB Y\nB X\nC Z\nC Z\nB X\nB Y\nB Y\nB Z\nA Z\nB Y\nB Y\nB Y\nB X\nB X\nA Z\nA Z\nB X\nB Y\nB Z\nB Y\nB Z\nB Y\nB Z\nC X\nB Y\nC X\nB Y\nB Y\nC Y\nA Z\nB X\nC Z\nB Y\nB Z\nB Y\nB Y\nB Y\nC X\nB X\nB Y\nA Z\nC Y\nB Y\nA Z\nB Y\nB Z\nB Z\nB Y\nB Y\nB Y\nC X\nB Y\nA Y\nC Y\nB X\nB X\nB X\nB X\nB Z\nB X\nB Z\nB Y\nB Y\nA Z\nB X\nB X\nA Z\nA Y\nB Y\nB Z\nB Y\nC X\nB Y\nB X\nB Z\nC X\nB Z\nB Y\nB X\nB X\nA Z\nB Y\nB Y\nB Y\nC X\nA X\nB X\nC X\nB X\nC X\nB X\nA X\nB Y\nB Y\nB Y\nB Y\nB Z\nC Y\nC X\nA Z\nB Z\nB Z\nB Y\nB Z\nB Y\nB Y\nB X\nB Z\nA Z\nA Z\nB Z\nB X\nB Z\nA Z\nB Y\nB Y\nB Y\nB Z\nA Y\nB X\nB Z\nB Y\nB Y\nB Y\nB Y\nC X\nB Z\nC X\nA Z\nA Z\nB Z\nA Y\nC X\nB X\nB X\nC X\nA Z\nA Z\nA Z\nB Y\nB Z\nA X\nA X\nB Y\nC X\nA Z\nB Z\nA Z\nB Y\nB Y\nB X\nB X\nB Y\nC X\nB Z\nB Y\nB X\nB X\nB Y\nB Z\nB Y\nB Y\nB X\nB X\nB X\nB Y\nC X\nB Y\nB Y\nB X\nB Y\nB Y\nB X\nB X\nA Z\nC X\nB X\nA Z\nB Y\nB Y\nB Z\nB Y\nB X\nA Z\nC Y\nB X\nB Z\nB Y\nC X\nA Z\nB X\nA Z\nA Z\nB Y\nB Z\nB Y\nA Z\nB Y\nB Z\nA Z\nC Z\nB Y\nB Y\nB X\nB Z\nB Y\nB X\nB X\nB Y\nB Z\nB X\nB Y\nC Z\nA X\nB Y\nC X\nA X\nB X\nB X\nB Z\nA X\nB X\nB Y\nB X\nA Z\nB Z\nC Z\nB X\nB X\nA Z\nB X\nB X\nB Z\nB Y\nB Y\nA Z\nB Y\nB Y\nB X\nB X\nB X\nB Y\nA Y\nC X\nB X\nA Z\nB X\nB Y\nC Z\nB Y\nB Y\nA Z\nB Y\nA Z\nB Y\nA Z\nB Y\nB Y\nA Z\nB X\nB X\nB Y\nB Y\nB Y\nA Z\nB Y\nB Y\nA Z\nB X\nA X\nA Z\nB Y\nB X\nB Z\nB Z\nB Y\nB Y\nC Y\nB Y\nB Y\nB X\nB Y\nA Z\nC X\nB Z\nB X\nB Z\nA Z\nB Y\nB Z\nB X\nA Z\nA Z\nC X\nB X\nA Y\nC X\nB Z\nB Z\nC Z\nB Z\nB Z\nC Y\nA Z\nC Z\nA Z\nC Z\nB Z\nB Y\nC X\nB Y\nB X\nA Z\nC Y\nB X\nB Y\nB Y\nB X\nB Y\nA Z\nA Z\nB Y\nB Z\nB Y\nC X\nB X\nB Y\nB X\nA Z\nC X\nB Y\nB Y\nB Y\nB Y\nC Z\nB Y\nC Z\nA X\nC Z\nB X\nB Y\nB Y\nB X\nB Y\nC X\nC X\nA Z\nB Y\nB Y\nC X\nB Z\nC Y\nB Z\nB Z\nB Z\nB X\nB X\nB X\nB Z\nB X\nC X\nB Y\nC X\nB X\nC Z\nB Y\nB X\nB Z\nB Y\nB Y\nB Y\nB Y\nB Y\nB X\nB X\nA Z\nB Y\nB X\nB Y\nB Y\nA Y\nB Y\nB Y\nA Z\nA Z\nC Z\nB X\nB Y\nB Y\nB Z\nC Z\nC X\nA Z\nC X\nA X\nB X\nB Z\nB Y\nA Z\nC Z\nB Y\nC Z\nB X\nA Z\nB X\nA Z\nB Y\nA Y\nB Y\nB Y\nA Z\nC X\nB X\nB Y\nA Z\nB Z\nB Y\nB X\nB X\nC Y\nB X\nA Z\nB Z\nA Z\nC X\nC Y\nB Z\nB Z\nA Z\nB X\nB Y\nB X\nC X\nB Y\nB Y\nB X\nC X\nB X\nB Y\nB X\nB Y\nB Z\nB Y\nB X\nB X\nA Z\nB Y\nB Y\nC X\nC Y\nC X\nA Z\nA Z\nB X\nB X\nB Z\nA Z\nA Z\nC Z\nB Z\nA X\nB X\nB Y\nB Y\nA Z\nB Y\nB X\nB X\nB X\nB Y\nB X\nB Y\nB Y\nB Y\nB Y\nB Y\nB Y\nB Z\nA Z\nB Y\nB X\nC X\nA Y\nB Y\nB Y\nB Z\nC Z\nB X\nC X\nB Z\nB Y\nB Y\nB X\nB X\nB X\nA Z\nB X\nA Y\nB Y\nB Y\nC X\nA Z\nB Y\nC X\nB Y\nB X\nB X\nB X\nC Z\nB X\nA Z\nB Y\nB Y\nB Y\nA Z\nA Z\nB X\nA Y\nB Y\nB Y\nB Y\nB X\nB X\nB Z\nB X\nB Z\nB X\nB Y\nA Y\nA Z\nC Y\nB Z\nC X\nB Z\nB Y\nB X\nA Y\nB Y\nB X\nB Y\nB X\nC Z\nB X\nC Z\nB Y\nB X\nB Z\nA Y\nA Y\nC Z\nB X\nB X\nB Y\nA Z\nB Y\nB Z\nA Z\nB X\nB X\nB X\nB X\nB X\nB Z\nA Z\nA Z\nC Y\nC X\nA Z\nA Z\nC X\nB X\nB X\nB Z\nB X\nA Z\nB Y\nB X\nB Y\nC X\nA Z\nB Z\nC X\nB Y\nB Y\nA Z\nB Y\nB Y\nB X\nB Y\nC Y\nB X\nB Z\nB Y\nA Z\nB Z\nA Y\nB Y\nA Z\nB X\nB Y\nA Z\nB Y\nC Z\nB Z\nB Y\nC X\nC X\nB X\nB Z\nB Y\nB Z\nB Z\nB Z\nB Z\nA Z\nB Y\nB X\nB Z\nB Y\nB X\nA Z\nA Z\nA Z\nB Y\nC Y\nC Z\nB Z\nB X\nB Y\nB Z\nB Y\nA Z\nA Z\nC Z\nB X\nB Y\nB Z\nB X\nA Y\nA Y\nB Y\nA Y\nB Z\nB Y\nA Z\nB Y\nB Y\nB Y\nC Z\nB X\nB Z\nB X\nB Y\nB Y\nB Y\nC X\nB X\nB Y\nB Z\nB X\nB Y\nB Y\nB Y\nB X\nB X\nB X\nA Z\nB Y\nB Y\nC X\nC X\nC X\nC X\nB Z\nA Z\nA Z\nB Z\nB Y\nB X\nA Z\nC Z\nB Y\nB X\nC Z\nC X\nB X\nB Y\nB Y\nB X\nB X\nB Y\nA Z\nB X\nB X\nB X\nB Y\nA Y\nB X\nA Z\nB Y\nB Y\nB Y\nC Y\nB Z\nB X\nB Z\nC X\nB Y\nB Z\nC X\nB X\nB X\nB Y\nB Y\nB Y\nA Z\nA Z\nA Z\nB Y\nB X\nC Z\nB Z\nB Y\nB Y\nB Y\nB Y\nB Z\nC X\nA Z\nC Z\nB Z\nB X\nB X\nA Z\nB X\nB Z\nA Z\nB Y\nB Y\nA Z\nB Y\nB Y\nC Y\nC Z\nB X\nA Z\nB Z\nB Y\nC Z\nC X\nB X\nA Z\nB Y\nB Z\nB X\nA Z\nA Z\nA Z\nB Y\nB X\nC X\nB Z\nB Z\nB X\nB X\nB Y\nA Z\nB X\nB X\nB Z\nA Z\nC X\nB X\nB Y\nB Z\nA Z\nB Y\nB Y\nB Y\nC X\nB Z\nA Y\nA Z\nB Z\nC X\nA Z\nA Z\nB Y\nC X\nB Y\nB Z\nC X\nB Y\nB Y\nA Z\nB Z\nA Z\nC Z\nA Z\nB X\nB Z\nA Z\nB X\nB Y\nC Z\nA Y\nB Y\nB Y\nB Y\nA Z\nB Z\nA Y\nA Z\nB Z\nB Y\nB Y\nA Y\nB Y\nC X\nB Z\nB Z\nA Z\nB X\nB X\nA Z\nB Z\nC Y\nA Z\nA Z\nB Y\nB Z\nB X\nC Y\nB Y\nB Y\nB Z\nB Y\nB Z\nB X\nB X\nB Y\nB Y\nC X\nC X\nB X\nB X\nC X\nA Z\nB Y\nC Z\nA Z\nB X\nB Y\nB Z\nA Z\nC Y\nA Z\nB Z\nA Z\nC X\nC X\nB X\nB X\nB Y\nB Y\nB Y\nB Y\nB Z\nB X\nB Z\nC Y\nB Y\nA Z\nB Y\nB X\nA Y\nB Y\nB Z\nC X\nB X\nA Z\nA Z\nB Y\nB Y\nA Z\nC X\nB X\nB Y\nB Y\nB Z\nA Z\nA Z\nC Z\nA Z\nB Y\nB Y\nB Y\nA Z\nB Z\nB Y\nA Z\nA Y\nB Y\nB Y\nB Z\nA X\nA Z\nB Z\nB X\nA Z\nB Z\nB Y\nB Y\nB X\nA Y\nC Y\nB Y\nB Y\nB X\nB Z\nA Z\nB X\nB X\nB Y\nB Y\nA Z\nB X\nC X\nB X\nB X\nA Z\nB Y\nC X\nA Z\nB X\nC Z\nA Z\nB Y\nB Y\nB X\nB X\nA Z\nC Z\nB X\nB X\nB Y\nA Z\nB Y\nB Y\nB X\nB Y\nB X\nA Z\nB Y\nB Z\nB X\nA Z\nB Y\nC Z\nC X\nA Z\nA Y\nB X\nB Z\nB Y\nB Y\nB Y\nB Z\nB Z\nA Y\nC X\nB X\nC X\nB Y\nB Y\nB Z\nB Y\nC Y\nC X\nB Z\nC X\nB Y\nB X\nB Y\nB Y\nA Z\nB Y\nA Z\nA Z\nA Z\nA Z\nB Y\nA Z\nB X\nB X\nB X\nC Z\nB Z\nC Y\nB Y\nA Z\nB Z\nB Y\nB Y\nB Y\nA Z\nB Z\nC Y\nC X\nB Y\nB Y\nB Y\nB X\nB Y\nB Z\nA Z\nB Y\nB Y\nC Y\nB Z\nB X\nB Y\nB X\nB Z\nB Y\nC Y\nC Y\nA Z\nB X\nB X\nA Y\nB Z\nA Z\nB Y\nB X\nB X\nB Z\nB X\nA Z\nB Y\nC X\nC X\nB Z\nA Z\nB Y\nB Y\nB Y\nB Y\nB Y\nB X\nB Y\nB Y\nB Z\nB Z\nA X\nA Z\nA Z\nA Z\nA Y\nC X\nB Y\nB Z\nB X\nA Z\nB Y\nB Y\nB X\nB Y\nB Y\nC Y\nC Y\nB X\nA Z\nB Y\nC X\nB Y\nA Y\nB X\nB X\nB Y\nC X\nA Z\nB Y\nB X\nC X\nC Z\nB Y\nB Y\nB Y\nA Z\nB X\nA Z\nC Z\nB Z\nB Y\nB Y\nB X\nB Y\nB Y\nB X\nA Z\nC X\nC Z\nB X\nB Y\nC Y\nB X\nA Z\nB Y\nA Z\nB Y\nA Y\nA Z\nA Z\nB Y\nB Y\nB Z\nC Z\nC X\nB Y\nB Z\nB Y\nA Z\nB Y\nB Z\nB Y\nB X\nB Y\nB Z\nB Y\nB Z\nC X\nB Y\nB Y\nC Z\nA Z\nB Y\nC X\nB X\nA Y\nB Y\nA Z\nB Y\nB X\nB Y\nB Y\nB X\nB X\nB X\nB Y\nB Y\nC Z\nB Z\nC X\nC Z\nB Y\nC X\nB X\nA Z\nB Y\nC Z\nA Y\nB Y\nB Y\nB Y\nC X\nB X\nB Y\nB Y\nB Z\nC X\nB X\nB Z\nA Z\nB X\nB Z\nB X\nA Z\nB Y\nB Z\nC X\nB X\nC X\nB X\nB Y\nB Z\nB Z\nB Z\nA Z\nB Y\nB X\nB Y\nB Y\nB X\nB Z\nB Y\nC X\nA Z\nB Z\nB X\nA Z\nB Y\nB Y\nB Y\nA Z\nA Z\nC X\nB X\nA Y\nB Y\nB Y\nB Y\nA Z\nA Z\nA Z\nC Y\nB Z\nA Y\nB Y\nB X\nB X\nB Y\nC X\nB Y\nC Z\nB Y\nA X\nB Y\nB X\nB Y\nB X\nC Z\nB Y\nB Z\nB X\nB Z\nA Z\nB Y\nB X\nB Y\nA Z\nB X\nC Y\nB X\nB Y\nB Y\nB Y\nC X\nB Y\nB Y\nB Y\nA Z\nB Z\nC X\nA Z\nB Y\nC Y\nB X\nA Z\nC Z\nB X\nB Y\nB X\nC Z\nB X\nB Z\nC Y\nB X\nB Y\nB X\nB Z\nB X\nB Z\nB Y\nB Z\nB X\nA Z\nB X\nA X\nB X\nB Y\nB Y\nB Y\nA Z\nB Y\nB Y\nB Z\nC X\nB Y\nB Y\nB Y\nB X\nB X\nB X\nC Z\nB Z\nB X\nA Z\nB Y\nB Z\nB Y\nB Y\nB Y\nB Y\nC X\nA Z\nB Z\nB Y\nB Y\nB Z\nA Z\nB Y\nB Z\nB Y\nB Y\nC Y\nA Z\nB Z\nC X\nB X\nC Z\nB X\nB X\nB Y\nB Y\nA X\nB Y\nC Z\nA Z\nB X\nC Z\nC Z\nB X\nA Z\nB X\nC Z\nB Z\nB Y\nB Y\nC X\nA Z\nB X\nB Y\nB X\nB X\nB X\nB Y\nC X\nB Z\nB Y\nB Y\nB Y\nB X\nA Z\nA Z\nB Y\nB Z\nB Y\nA Z\nB Y\nB X\nA Z\nB Z\nB Y\nB X\nB Y\nA Y\nB Y\nB Y\nB Y\nB Z\nB X\nB Y\nC Z\nC X\nB Y\nC Y\nB Z\nA Z\nA Z\nB Y\nB Y\nA Z\nB Z\nB Y\nB X\nA Z\nA Z\nC X\nA Z\nC X\nA Z\nB Y\nC X\nB X\nB X\nB Y\nA Y\nB Y\nB Z\nB X\nB Y\nB Y\nA Z\nB X\nB Y\nA Z\nA Y\nA Z\nC X\nA Z\nC X\nA X\nB Y\nB Y\nA Z\nB X\nB Z\nB Y\nB Y\nB Z\nB Y\nB Y\nB X\nB Y\nC X\nC X\nB Y\nB Y\nB X\nC Z\nC Z\nC Z\nC X\nB Y\nC Z\nA Z\nC Z\nB Y\nA Z\nB Z\nB X\nA Y\nB Y\nB Y\nB X\nB Y\nB Y\nC X\nB Y\nA Z\nB Y\nA Z\nC Z\nA Z\nB Y\nB Z\nA Z\nB X\nB X\nB Z\nB X\nB Y\nA Z\nB Y\nC X\nA Z\nC Z\nB X\nA Z\nB Y\nB Y\nC Z\nB Z\nA Z\nB Y\nB X\nB Y\nB Z\nC Z\nA Y\nA Z\nB X\nB X\nA Z\nC Y\nB Y\nA X\nA Z\nB X\nB Y\nB X\nA Z\nC X\nB Y\nB Y\nC X\nA X\nB Y\nA Z\nA Z\nB Y\nB Z\nB Y\nB Y\nB Y\nB X\nB Y\nB X\nB X\nB X\nB Y\nA Z\nC X\nA Z\nA Z\nA X\nA Z\nB X\nB Z\nB Y\nA Z\n"
  },
  {
    "path": "advent-of-code/2022/inputs/03",
    "content": "PnJJfVPBcfVnnPnBFFcggttrtgCrjDtSjzSS\nllWlLbmmdLLwLbqGdmTmbZfCQtzrMQfrjSzrtSrMqgMt\nsHlZTsWZwGGlZmGTmdlZbhJNRPphVfRvVnRBsRsJJV\nfsHtVbjtqstBghhwwPBw\nSDQzzSzQrQMmmQlmlcNcJLZPgLrVZTdCddhgdPwwCw\nJmSWSVGGlJJbRsbpWHfbRj\ntJndRtwtddPvllvfrldrfPpHWDgglFDWWmMmHWmHpZlS\nBBJTTjCsJWZCmSHSZD\nLhqLcVzshTNjhqhcjLLTLjbTnGndfdwrfPRVRrdnwftQwJRv\nwHlPJZwbbZfqbFwqFZfrrcrJrtMWSMMVtVcJht\nNzzzNBjNfLzvGfDNjMhVhrrMShLchsRVLs\nDDdmmgBGDNdgfgZggnZbZHln\njqNjZJqsGsRqJJqnlJJGzMzffcffTCfQcFmvcWfvTNfcvv\nPdhVdrwphhVtDdSPLmFCWTLFWWTfFQQr\ndSPwbbVdbpQllZMQbMjM\nQQdfflqvjTvfZqLMWfNDGhwsCNGGGM\nrzRRRTVTPTNhsDWDRhGC\ngHSTpTnppvjQgJjcql\nnzNvsFBBBFsNrnNBrvndfThwDbhVPzVVwhZZChpZPCbZ\nGMQQStmcHHmlfMtPwbZVVVVhhPhbVc\nGmSmMGlmWWgqQMHgQHtSvTNTTrgBBvNvFsfTfLvd\nVNVBgRRBRzWRRbRTrTBgbzpZvMvMJlQJZJpJvlTMdJlp\nmfdfdfdHfQplZJJh\nttnPmsLHmqsPGgWjjWRbBdbbGj\nmMMzwFFpnwgMggSzhQSbSJbhWzbr\nNPRlHHPbPRdPHCdRNGWWhWQhJVVGhZrCCJ\nLlNbRllLLdHnpLgMTgTsDT\nmWhvwmthrzJrLhvftwPrtNHlbcHgbDzNDHcGgzllHl\nTCjdSCFMQCCCjMspCMQBMqpFHNGblPPnGNNbpnpccZGccclc\njVBPsqdFMFsTVMsdMmfwhwvVwLrvWhVtJR\nTdhJJttgmdgctBBhBwBqBCLWqC\nfjNGPblpPlRDfsfGbfcWqBqwWvnHVvBLVHss\nlpRNDGjbrGfPZbmZZMFdTzTgcFdS\nWPLMvWLMqLcSvrrBmDPFfRzmDPRfZDHP\ndCggNCCdNCbHTHTfFnNHzM\nGlJVQjdCCwjMGbGpjGdCpqrtctqcttchsrLLcthlhc\njgPHPgjGCwrqjqrvzBfFfCTTCdFpDD\nQhQLtcrQQLWshQttdzzvzBnhvvBhvFTv\nRJRssrQSWQSqjqqVSSGP\nsPszmnmnQPQbjSRVVjbRjVVB\ncdvZqMfNchMMMqCBlBZlmSmWCHBj\ndFFDqJNNJvTJTqvvwmGQsGwJztgrwsts\ndJGPMNStSclWJSPScMNMzqqDfzqVzwwjGfzjqfQz\nhppFbrhFrrhgCpFlFhvFTgrsDfsjVzvLDfqwVzzwQDsVwL\nRrgnZbphTpbgrnZgmpbhFcMlnWdMBNWJdtNJBMMSMc\nHqtfLZCLmLtrSqZStzFtwpPQWlNQBpplpQWmBpNp\njMJcnRFcJjvjvcGvdJpBppBwQBpwQWPW\nDcvDgbhjMMsjGvcjRRvjvgbGtsTZFHCCHSCHZHLfsSsCSrZH\nwvFPFqvjlgTwjvjZbMSzHTSScMBBbN\nVVmpVsmmptfDsdSZbMzZzMZBtB\nLVhfGJVhQsWhVJhfmGJMwljFvqWrlPvCqrqjFFvj\ncdNbtwrtwrRNLzhQhHfCzbGzQH\nDMlMgFDBMSBjMTqMFWMFDQHdGZHvQdTHHvHzHChJJv\nMBVWDngVqVWlqqBgBjjcsPnwnNdNsPNPpRcLws\npQqHsBmmrQHrrmsmmpwMdfdPbfWPMVbMdWbPwG\nZSvZDlvghgSDZCSzJZzgZNNPFRFMVRVfMdbFPddfMzGRWR\nvWgJhSntvglSgDCHsjHBBpnTrTmjmB\nhDgmmgnwDCdddRCqCPzz\nsSslHbctbHsNrhpZqdqprc\nWbsHSBQHQBLHTWJSlmjnVwFDvWhnvjmfgv\nphwdhVLRddWJLVglLWRlWWgwhCjCrrrHZmCjZNHtjvvZrHTN\nzzFzPQqFDcFsHsFPHSsGSCCNmftjjNDjCfCCCNfvrr\nBSQsqFQMcPqHbcGzFMWgLlgwpLlpJLLpBwnp\nGTrsHGGHfGMvsrGsvnGcHsvTwhghwhpVpJhQpwhQghhmmm\nbFPFPPtSdPtSZPZWjSdZSNFdmhDJQgRQbQgmhJgJmRwVQMRh\njPdjldqlSNBdFBjtFZsfsGMqsHCMcqcfvnrf\ncrZHHZcZZsSrVrSCrBNTTpppBpJBCbwbBn\nDzhRggfhhlRghmBNBpLJwDpDDTNp\nqvwqwPRfvfzPPRvQlfPvPlRjZSHZrcScWrtVQscjjtZHMS\nGRGBgsgghbvRvgsBTsgRjjznCCtSVCZtCFZtzFtwnSdj\ncmqpPNnWWPrqWHplHDDcpCddFfZdFtdrwzrfdVFFdt\nlPNPNPcqpcHWmPLllDDGhbRbnMgLgRbvRsbhhg\nZRBBNFWWBWPDZZprnwVvDD\nbSzzhHdttMtCCzCThMTShStcvrqNNjwnrcvqvvVVpprvnnpN\nCStdTMLztMmTSSMTSSSfBQNWlsFRJRPfmlNRNB\npMLptvGHTSGSHtLLwNWvcqsJmWWzmPFFms\nnrQPrjrddgQlDPZjdlBcFFzFsFWhqWgshszhNW\nCZDCQjjBBjrnCfQCrZrbSbHLRwGftbfPbHRMfp\nsqQHBqsHbwDtmbSB\nGjVGrlsMsPjbPbPmTtSwDb\nlzFFGznLGGrLrnrVzMzsqvpqvWQcnNZWvCpnqpHc\nnZWZjdWRwhRdBRhhdNZMtHtpPrGCCGsrTGsG\nDzFFbblvbzFvVJzzzlVmvlpTpMpMrMCgGMtprJgCMrPM\nzVmFzFvfzSmDzmCmzmmVQwNRqdRhcWBqShjqNndWWj\nQQTdgLQlhGhQdPbwJJgwRVmtNRBV\nvCSnjzFqSDDFMDjvrqvjvnVBRsNJRpJwtNJNpNrtbtbt\nDfnCCjDMzcnqvHZGlcTcZThBlG\nlWtmssWNcBjTjhlLpn\nfwJbgfQfVfqPwmdgJjppHTjCphppBHCnhV\nbgvfmvmbqdfDqJvqgbPJNDNSMscNDtccDzzcNtRt\nttBHSflTlqwGGQJBQq\njvdPdPLsDvCzvVqVQQGw\nZDdZnPrrPLPLZMZlfWSqmmTWmtTMtF\nShhwCZSwlPwZPSplwlRGGVmttWVVQcJVnJtSJVLcjc\nqmzDmgNqNfgtJWWqtQLJqL\nrsFgvrmFdfRhPBRvRRPZ\nRQQRGJRpfJzlTQmbfbsGlsTMSHMPgcMFpgqPHHpHqqPpcP\nWmLZDBBLZLNVdjWqDCFHCMccSPgSgg\nthrNBVVBrWZNBWNrRGQbRtJGzlRRbmlf\nNfdjBfsnDfNjfBddNBnBwsQShzQDhSDhvZSRDpFRSVFQ\nlHrbTgtLmrblPzShhRpvRPZPVz\ntWbqHlHmWHgWHtqrLJJsvBwnBfjswjwnNMwf\nqQfdCVqZSqZmQmgVqCqCWTMcNFTwWwTccgpcWcpw\nnSLrjrJnLcTwLNcz\nsjRjSnJnRsBlPtnqCqCGfCbmQGHfCl\ntqSmNPNcVrNNmPtHfMZbCWMCZbHwfdzW\nRwgGvFwFdsssgjdb\nLnLhhnFDStLJSrtw\nHHGCHgfjgjgzNSTgJTDJ\nWdMbDBdQLLZPWZVZZmLdzqqNbvzswSzrqqsJwSNw\nQQmQBmWQZBmRPGfRjRcHccplpD\nzFpjDvzDzWWvWBqDqvQcjsfbHPjHsVjcPGffGc\nTttwldmlTPSCCZmhlNggwffhHsshRsGssRsfGHRhHf\ntwmMMmltZdNNlZLLMrPWzrrprpDr\nChCnpqhzCdndsDCnVpVJBgLTpTtgVggL\nswHPGmwHbjPjvjQsGLSgVMtgSLLTVBHSrg\nmRPPwvbvbvQjljvbPvPlfwWhsnhZDzFnWhDFdWcdhZWl\nndnSZSfNgmmSZlbllglVVsBCfqFBfttpPFtsqV\nDJwcMzJDwLcMHMDRMRrtVWFWtCBqBWpWCzzP\nwvcHhRcTJJvTRLRvRhwTQTHdQjqqGdgnbGQgSbqSbgNSdl\nMHtvCFtCFvMvBDcVfjhhQf\nWJZWSgZbdlwZZsbTbwDhcBVQhmTTTcfRjmjD\nWwwrBwZsSJWwFttnLrMCpntn\nBJgWJVSPVzNJNPZPVHBJHBfdhbjDnbQndnBnBQfndQ\nMwMsNmNpmsrrwLssvsvpRpvQnCqbCCQfCfhhbDnqCfqLqn\nMFvtrmGMFwRmFvcvMFmsWSVHWVHNzgZWTtWSTPSZ\nwWNsHswfsWnVvNZvMLDRRpcLMBDnBlpR\nQFdhqzFbzmgbhzQhFSLRrpBBBRcRBcLldpWc\nSbmhzChGhqgQFFzqGJhwvtvNWCtVjVfwwZjHjT\nWHGDHBRQHDBBQpGzBzQlDVjPmmVtbqbLmtPtzvmZbb\nnchMhdMgCMJcwvLZvVcffjZfmq\nndhghggCwSnhCnnTNSdBpFWQFNLFlpHQpDLRGl\nFZdjbqjjZTFbRHfVwgttfBZrBpBB\nLJQFJWhPPnQJJQCPQpzwphczchrgtrfBrf\nFFWvnlLGDGRMDHjm\njCsCNZTTfjcQMLWTtvHQvG\nmgwdznllpRgBgpBDdnDDzBDmdrMHMLjtvvHJtLrWrHQWvQtv\nlgjDpVSppmqsqssVPZPf\nNcNwtChhScfPtwVRgmvWvWvNllVg\nnZGJMJLnqqGzLzrGQvlmmgrTmWWlcVvR\nLLdMzdssLZnMMbbZBJGsqLcjwjwPffpdtjFpFhPdFwjFFD\nwQvZHfbLjrMZSVWMZSdZ\nwwqhwtTRRpCCMmsnVlWGMpWM\nqBDcqBTBtJCBDqctRDCBCzDFLfbfLwvfbQcFHNvLvvfQjQ\nQDFwwvLJFjWQvWgGNnfNftCJPggP\nlpqdpqqrqBBpTTBsprpsTsbrNGPfCPzftfPMMGztfzNgNflM\nsqdpHrcbmTTHTdcspZNbZmDSQLQjhhSSWwvWWFHQvLLh\ngjQHjfqgVSqjqMSnCRMDMvCGZDvCNCNJ\nFnLswmdphJchhcZd\nbslwFmLTTbWWmlmbBLwlpBHPPBjqHjBSgPSSSfrVnzqQ\nJddrdBgJpChGfDLDDpcm\nWnSFqRhnjjWSSlSFWqTFVSLGbDLcbLDDvDLztbftVzcv\nnRWjsRjQFnQRshgwJCZwJrhw\nrnbZwrcZQdpsLpHDVWBBBgDv\nNNTSFCqJFMMMSJqTFFPttmNPlwgLvWvgWBffWlClLfvlVCVv\nTMTTJSJFRNwmjZsnGsrhnZZR\nCMZhZstZqlClJScfBrfHHHFWFFHh\nRwGdpjdGVGdmNHcfczpJWWpf\ndDJnQbdnwQdbggSPgPsnlqSn\nhnczBfznJFmzhnzJLLMwLjmQrppgCjqC\nHRRlrPRZSDtQjjPQNMPpPw\nttlZHDRGRlRtGltTtGvcbnFrbvWJhvWhndcFWF\nhRsCqfRdqdqfqdtqmMmmZpStMTZZSTnp\nVjDDjWbzPFFwPRPFDjzLSnTMnZSGZMnWpLLmpL\nPVHFNBzDRbDwzjNNzHdvdHvlhhcHgvCglf\ncRLLzhRBhLhVLLLMnnRVVhtJgNgPJmPgPvDPJgvzvvNJJP\nlpFffHHWHbbMNPQgsgJJmW\nlpdplSpHSHlCCTbSpSFwdnLqMwcdBRRRLdRnth\ncsZWwFFZbtbztcZttbnRbGlbJhqfnhlpnn\nmmTjjBLdSMQdBggQHNgTmjgJJRqRhCJphRHRRClGnhlWJJ\nMNMMNTmBLDmTLDSQmFDvvzwPWzsvDZFFcD\nfmflRfGcCtGDDbRCRlhCmmBJQsvBBWWvtWBnBJvLLvLn\nGFjdMMFGzVQvWWVWJQVJ\nwjTZzjrFTHgZjTFjMwGRcfRcqlbhcccrcmmlqC\nPvnvjHPnjRPPqvvnPqZNNWHTSdVDHwTLSDWDlTTTLl\nMJswhgppwspJpJsGbhchbcMlLLDQdVSgVldtSlSlSTdTld\nFwzwJzpfzzJRPZmPBvvmBF\nZrJhslhhclDJhrDZllcGGrZnFCCWNMCHfsFbPddwdwWwCCfP\nBTjgvtBBSLqqBSLVzgTpBVMFHNPHwFbSwMPbMwbHMCPf\nfRtTppTjRJmrmJDR\nhJzcQcwMQhcQwZHVNmSmPCQZSm\ntpfvgWFFGGfRWFBqtPrHCmSwPPVPwgVgPC\nfpWBRqWqqGRpWWRpFWssMnLczJnnwcjscsJnLhbz\nHggzqvvrgtlrrHlQtvlJqFdfBLFJBbnfbBBdfBBfFd\nSVVmpZVsRLZGGZwRGZSTDWBbmBFBdFBnnFCnWnBfhB\nwpjVppVpZLRTGZQrrjjHNzcgvjrg\nGsMgMCFGMsbwbbSwwglS\nmJDMqRJzTRVdPWttPffZppBBfS\ndzcdqQcmQMGnHCsQ\nHlPgHwlHVwsVPPFVsNwzwLnmRmCCMcJcMRRLqGtRjCjJ\ndWhrWdDnmrrRMRct\nBZDvBpfTDDfBddWTZhDddWDQgwsFsHVvVHgHHznFQFznlQ\nFjmqFqJJGsBGGhsZdRDDRZZjTvdMdt\nNnHPngrPbPpbPfVvfCrnwccTwrRwTZdcdTZLwRTD\nlbbPvHWlHCNNnJzGJlQsJlsBBq\nmLNRpRDcDDCmCpzTcCPcNTTDrrnrPrPvjqtqhnhhhqQQjrhF\ndVMlVGgVSlGgWgsWSZlwtrHvqMjhnrhQjnBBqHqvhv\nWJfsVwZfJGfdLNmcmCcCtztf\nbBTtWQDMpDSjjznztCLd\nJhfZfrNPPwNJrhqRcJjfCCCzLSGLbGGjGznj\nRsPRZhwNbgbrgbBpBWWsQFvDMTDF\nrqLzTmqqMmmwrqwrJJwPTplhbRDphhdhDvnnhnRDnP\nggfctFfSRNgZFBRVfFfWfZNSvjjvjCChpDhhDCCjdvlDDD\nNQfFRFgtffcGfcgZcfBqJrGLJJqLTwwmmHJrqz\nWVGJCltslWJsbbtNJbDJPMrPLBNLrpNjfqQQMMNr\nnTFnTmdRnTmmmdHZZnPQpLMfMZPMPqLZDqLf\nHRvRFRTvvvRmnvFcFRndcwVVJWWGbsJGwgttlCzJlGDg\nrfwdfLwLwwNdwbLcgCCTtFPvFPzWtWVtzvJF\nMpjqDDQQRmQjDspzTWWthVWRvRVRzn\nZTQQQqlQZsqlrlgwNlgLcSdf\nQqBNgbNNJvcgnbBQQgJjQZSJWppPWsGpDpSGPpWTRDTp\nrrldddlrChLFpWPSSPWvPGCR\nfhFltdLhHwVfvgcZZqjzNNtQgt\nBMCMQZSMvSZSQTQTWvMSvrrTccgGRNljBFglGRgBVgFGRRGc\nffmdmwdLbDJwFVNlGRRVVbRR\ndwJnJLfJwLhnPQSSNMvMqhMP\nRpQDDCHQwMRpwpNMCwpZhgZrPSqQdgrqPqPZqq\nzbtzmzzGbVzJSTScZqrthddT\nLVLJlLBnGnWNHMDRHnCCDh\nwQDcLhScLLBStHhctwVwsBjNTrssTjgNsgGCgssj\nfWblbRqMZWRffldFZpqWRbTCsPrsTNgnCQjgTrMGGgsr\nFZRpqdlWWbZZJJJppWWdHQVmLLDmzwDcLSVcQJLw\nDlllCDRlflQRsRnlCCBhzvLFVhJzJVzh\njHjNNqdHqwNgpgqNcpgZwjZhJJbvdbPVhBbbvVvBvLzbPF\ncpcgSwWqgVnftSSTTf\nQmLZvjwwmDWFLNLqbqfF\nJJSBMBpdpgSBRBHJgdHBNVbsgqVlqfbVFVlqVFqb\npCttfdCRMDCjhPDhmQ\nnDjnzdcDbDtGdcQTvssHssHbbfTq\nlVgRgpWCrMRVgVglRLjJmQFHqHHHsqFvFfTQsHSfMQ\nVrlpmWmgWppllLpPPWPWljPBntcnhdBNPhZBZhGdDd\nfQsRRfBHvRRjjvSgTwCTphdlphqBpn\nWJrDZbrNJZPWJcZmWLrrbPczpCnTddqdshqhDgTTwlwwTqhs\nbrcPbZPcWGWssGtVfVMjFF\nGBZgqHhHGBZcLcGMjVJhrjrbStjbbb\nwTTNFPQpvDQTQLQvntRSbRJjVnrSDtJV\nTTwzQzPPTvmWLTTcdWfdGdZgfZHfZH\nVswNdtMgdsvQDJgdVNgQrrLlhrSCLflqfLrDnzLL\nRbjRbcZGTGpRbzrTqChtflhSnt\nmBjPRWpGcmBZGZpmZjtRbQQVwJgsPsQMsvNJdsVFdN\nTDmDTTThRDbbZtpTSnhRcFJMglldGdrJltgBMtMB\njNjsWLqqqvzWswNqdccrFNBFMBlMrdMr\nLjjqwvsWCwjHwQHHTbDHbbRZmnRd\nqtnncCFCqjwjcDwnFQSGGRSBGBSvFdvrhR\nJPZzpgPJWNJBRhqSvQvBgB\nmZmJmMPWzmWmPLbmqTTJPfDHnHjCjflHjflfDcfMwC\nVfJrplTqzVVlVVlpfTMJfqDtWSLgbHgDjSHLgjHWjrjb\nvhGsRdsNRPRvvRhjSZjJLPDjDJttbZ\nGvGhQmhBnQNmnJGvhdFqBFVqcllqMBCMlVCc\ncnmsmmDCBDmcmvVnsVBtQQWWrrltQlrBfRHB\nhqphjLZFhMMjZQGQWGfftQWf\nJhFqhbjSLjMpqzJFbSLdFSggDwgmgcDVsVzVfvNvDvsm\nmRdspZZggmbJbpDcDJDqPhvvGvrnVqPqpzvVVV\ndSjSjQtwfQlLwjQSPrrqVqvGPGPVPjnP\nfMQtFQLHSfLtHFttHMflfwHWgFJsDbmJRDWdFBRJWmcbsJ\nlMMftpGHMntGtMMGpJnSPQvwzvvHscsdQscQsscQss\nhbfmWWLggVFjVVQdvbQvbcdzwbRR\nqZWFWTgTZhrLhLmWGlGGrSnJSNfGtSll\nQVGdmgVGLdllrGVgnZrdBvNvBSSjSvWtBHBqNNmv\nThRjRFwpfTNBBqSBSSvT\nMFzbzfDjFFCCFJpRpFwbwJRnZndDgsZlgLrQLDgdlglZnD\nPjbDQvQPjbjjvtrQcpHBWnLfqnqGcHngnLdf\nVTwmMzMFnqHBwHBB\nlMTTNCzCZmClVVQjstQpPlprlHSp\nMtMqBtwFFsMRZMMZMjJGZR\nPHbpbPqHmVVCRGGCGRjv\npdrrgdrqPbpzrHQbbqQPLHcQBsNtNnwzNhSFfhtfffFffwDs\ncPjpPcRJJVtSGGtJtffN\nCldrWrmDHnHnmWmTWsNzzfbbFNhtsbbNGGfb\nLCDTldCmnLLVwPVgQt\nNJpFrbpFZhlzhbzzqCtgMCgRbqCRMMtm\ndWcnntHQWcjRHHCVMqCsRg\nvLnQDvnGptrzLPwp\ndwTwTHwvZHqTrTRTlWtfzt\nGbFFbFBPnGQBQcQcLbPjFtCSrtgMMLrMfrrWgRgStr\nPnBnQhsGPQbnJRqwdRDwvJNDwq\nzzjWtnQRntzSBjZccmZmmC\nbdJdbdfJdFCGflfGwBJsmhmSMgmgcsmM\nqDbGDbvrFbbvGdvdffFdTTWQzrTWTLWLNnttLnCH\nWMMssTqCbpGzGSlmzLbG\nFVdwftRRVDZPcdZtZVRcjmvQSzzLrmlrclSGms\nDVfPFZDZRfVFPFHRPFRCphhMpCTHTsNgqHNWgn\nLzBGCRjHCnmnHzdzLLjHwGplflfrfPcgtflgLFLlcrcc\nhqhDMSSqWZsDMVWTVWmTcglglflFVflFrpPtggcv\nsshbJsTsqWMbqNWbhbzzjzGBQjCJQnzwmzBw\nQnpfLpbLfGbvgjHzjgmNRqbz\nSSMBMZDwMwFsqgSPPmHlHj\nBhMFJhMBddDMFcTdMVddrQfvrnCqnCffpqnVCLtC\nlhrTZNJZjCRjSCvRSlTSLlrvFnMHQhVDnqnmqqqmQqPDHmqF\nwcpGdtwtwzcbpzggCFPMqtMQmQqmVqHP\nbBfwgWbfwBdGpppGGGbcBsTRLlZTZsTRTsRNZClJsvZL\nnJLgNcQDNMlQHMvCbv\nzphFpmTszmwhGGFhhtppNfffVlvZvHCCVZzbfzvS\nmTTsmTRGstsFhWwtWjPRdjnJdjJnLjcLNd\nMfBDjllflHLTpDhhppDDbp\nNZBBnGJNnNPWTcTTmVhZCh\nPSzgSgwrnzrSzBGJSJrSLQqfMHQfqgRgfjHLljll\nRgbNmBbqgWHWRNRqHtcMlMwJJjcDtVlD\nSzpFLGPddSGnnSLQZLtJJcclDlVjDQwMhDcc\nLtTZCTttRqqqvqTN\n"
  },
  {
    "path": "advent-of-code/2022/inputs/04",
    "content": "71-89,66-70\n24-70,23-55\n19-85,18-86\n50-90,50-95\n55-55,56-72\n3-65,5-66\n98-99,66-99\n14-67,14-14\n4-79,78-79\n13-98,10-98\n27-78,77-78\n22-28,22-27\n84-99,98-99\n7-96,99-99\n33-54,34-54\n29-45,44-44\n18-48,57-78\n89-95,89-93\n39-53,63-99\n13-95,94-95\n7-43,7-42\n16-16,16-96\n41-68,68-87\n83-83,73-82\n65-95,64-71\n5-98,5-95\n51-54,50-99\n33-39,36-74\n9-73,10-86\n20-31,21-59\n12-27,11-12\n10-96,7-11\n55-71,70-77\n13-97,3-14\n5-99,5-5\n25-98,25-98\n81-94,81-94\n26-42,49-74\n77-98,31-77\n8-77,6-8\n48-61,60-61\n11-14,13-52\n97-97,1-96\n48-83,48-82\n44-76,75-93\n21-89,20-89\n10-68,9-91\n2-79,78-80\n10-97,96-97\n9-11,10-76\n44-45,45-97\n34-57,27-56\n12-88,12-87\n16-77,16-16\n74-84,14-75\n22-36,21-85\n15-70,9-70\n81-97,3-81\n24-97,23-79\n8-54,54-55\n18-73,17-74\n22-79,39-79\n2-3,2-73\n1-90,1-90\n59-96,19-96\n31-71,31-31\n62-63,63-64\n15-92,91-93\n73-74,18-78\n64-96,65-96\n5-7,6-64\n96-98,2-97\n62-81,51-62\n38-40,33-39\n26-96,21-95\n31-86,30-87\n11-94,2-11\n3-53,30-52\n28-77,27-98\n17-48,44-69\n9-89,1-89\n42-97,42-99\n1-3,2-93\n16-17,17-21\n95-99,14-96\n51-99,52-57\n28-35,28-35\n30-90,76-91\n4-97,4-4\n78-92,14-57\n74-97,75-97\n15-94,14-94\n29-68,29-69\n1-95,2-30\n6-84,98-99\n12-72,71-72\n5-6,5-30\n19-63,63-72\n4-99,3-99\n5-61,62-62\n35-55,34-56\n11-58,75-87\n4-98,3-98\n33-34,34-77\n56-94,55-95\n8-78,99-99\n19-20,19-90\n58-90,43-57\n87-94,22-84\n20-50,49-60\n14-15,16-90\n7-93,7-89\n7-97,7-7\n4-88,4-89\n35-49,48-56\n53-85,55-94\n5-66,4-6\n17-78,19-78\n6-28,28-66\n55-88,91-98\n21-22,21-94\n18-42,17-42\n4-98,6-98\n10-96,97-99\n25-89,89-93\n5-98,1-5\n62-77,63-73\n12-37,11-38\n17-29,17-29\n51-62,45-61\n86-87,44-86\n33-88,22-33\n89-89,14-88\n89-89,53-81\n61-63,59-64\n56-75,55-75\n21-93,20-90\n81-82,81-82\n8-86,87-96\n3-99,4-98\n30-30,30-33\n3-59,2-59\n58-72,7-70\n45-67,16-45\n14-37,13-13\n29-47,14-46\n2-85,1-3\n61-98,81-86\n16-35,17-80\n4-92,4-92\n10-38,11-97\n92-93,20-93\n40-53,41-53\n28-84,3-35\n11-96,6-36\n57-81,57-82\n77-86,6-77\n4-67,4-67\n55-57,56-76\n26-27,27-45\n44-47,44-46\n7-98,6-99\n10-51,9-87\n10-41,10-10\n7-37,7-90\n55-97,54-54\n21-97,20-64\n64-85,44-53\n31-47,46-59\n67-78,68-95\n27-95,26-66\n11-82,54-83\n52-75,24-67\n13-84,6-84\n37-48,33-41\n27-28,28-57\n23-95,86-95\n8-8,8-28\n27-74,26-28\n56-82,42-56\n9-59,14-59\n26-62,61-94\n1-2,1-88\n83-92,97-98\n13-91,13-30\n42-96,95-96\n43-97,34-97\n45-82,15-69\n90-90,65-91\n25-89,26-26\n16-36,15-15\n14-80,79-79\n49-72,49-50\n19-47,18-88\n7-46,7-23\n14-24,24-80\n2-2,3-98\n2-99,2-99\n14-44,14-14\n25-27,6-27\n28-96,27-97\n24-75,23-81\n10-74,13-75\n61-62,13-62\n94-95,96-98\n22-24,22-82\n10-10,10-81\n37-77,76-77\n10-32,18-32\n8-79,7-7\n45-46,45-77\n16-21,16-20\n8-45,44-57\n19-61,18-61\n9-67,9-66\n4-86,1-86\n49-63,48-63\n39-83,23-82\n3-67,18-67\n74-84,83-83\n32-77,33-77\n14-55,5-49\n59-73,26-73\n15-55,16-83\n19-19,20-43\n59-60,32-60\n30-58,33-39\n9-76,9-76\n67-81,21-68\n37-37,28-38\n64-75,63-84\n5-91,11-88\n41-95,37-96\n46-76,76-87\n39-82,40-82\n92-95,2-93\n92-93,1-93\n4-97,4-98\n31-75,30-75\n97-98,2-97\n78-78,40-77\n36-36,36-41\n5-93,4-94\n29-92,29-92\n41-88,42-92\n9-50,47-51\n16-87,16-16\n18-63,62-63\n89-92,90-95\n80-81,16-81\n3-34,4-34\n13-97,96-98\n1-93,92-94\n34-88,35-87\n97-98,43-97\n41-76,42-69\n28-33,27-46\n1-35,3-99\n9-95,10-94\n15-99,15-92\n93-94,1-94\n42-92,43-94\n91-98,71-90\n19-50,47-50\n24-91,94-99\n10-98,11-98\n42-87,86-86\n18-92,48-92\n52-52,5-51\n73-80,32-74\n43-46,39-50\n41-45,40-44\n48-86,49-68\n55-67,56-67\n34-94,34-34\n16-72,17-71\n27-75,33-75\n3-34,33-34\n27-70,70-71\n85-97,31-84\n46-46,21-47\n1-98,97-99\n15-90,5-90\n10-63,10-62\n3-4,5-77\n18-41,23-62\n32-80,33-79\n17-17,17-89\n63-83,15-83\n5-82,5-82\n51-60,51-82\n1-82,1-82\n9-14,13-97\n10-99,13-99\n70-89,88-97\n84-89,83-90\n80-86,25-85\n29-88,29-89\n5-68,10-68\n95-96,47-78\n26-95,26-96\n1-2,2-87\n32-57,21-58\n3-99,2-3\n93-93,50-94\n62-96,62-89\n52-82,52-81\n27-82,27-27\n39-79,38-39\n17-97,16-97\n2-90,1-91\n43-48,43-52\n5-25,9-25\n4-95,4-5\n14-59,13-59\n44-81,43-43\n95-96,20-96\n13-14,11-14\n26-91,20-91\n23-64,64-64\n20-95,21-21\n4-85,4-84\n17-60,15-60\n79-80,66-79\n78-95,78-90\n34-38,33-38\n41-49,48-49\n4-44,3-44\n68-68,10-69\n4-83,82-84\n86-88,12-87\n2-37,36-75\n7-57,58-81\n11-13,12-99\n6-93,5-90\n28-84,29-56\n6-93,3-3\n35-63,36-72\n7-7,7-55\n27-44,19-44\n41-86,30-80\n1-82,2-81\n1-3,3-92\n2-10,4-52\n12-98,8-11\n5-10,4-27\n47-79,46-46\n47-96,97-98\n74-82,74-75\n36-95,11-35\n10-18,17-24\n32-34,33-48\n9-83,9-83\n7-92,19-92\n12-92,12-86\n7-81,7-82\n24-74,38-73\n19-26,1-26\n5-11,4-11\n13-82,14-81\n33-98,32-33\n30-97,96-96\n28-79,79-81\n60-91,59-86\n50-94,50-94\n74-98,57-73\n5-85,4-37\n4-90,3-71\n22-76,22-76\n48-51,51-65\n4-56,5-55\n2-72,46-71\n18-99,17-93\n98-99,3-98\n14-66,14-79\n12-73,13-72\n16-19,2-17\n2-98,3-98\n65-97,65-96\n9-38,37-38\n9-55,10-95\n49-65,26-66\n7-85,7-86\n18-20,7-19\n33-73,33-73\n18-89,35-56\n1-81,1-71\n18-65,17-65\n84-97,59-94\n10-73,72-73\n2-90,3-66\n13-41,4-29\n1-99,86-99\n20-96,19-68\n84-85,83-85\n27-92,27-92\n20-70,19-19\n11-96,12-97\n35-86,34-36\n8-9,8-22\n9-72,8-72\n5-89,5-57\n46-58,57-59\n41-41,42-75\n32-84,31-88\n39-91,90-91\n6-39,5-60\n51-69,70-83\n5-78,32-75\n8-92,8-8\n2-3,4-81\n70-95,14-95\n10-15,16-72\n26-64,29-63\n26-83,27-82\n48-93,44-47\n76-90,76-91\n73-99,74-74\n9-71,8-41\n13-13,13-91\n32-81,32-80\n9-95,9-95\n97-99,84-96\n90-91,52-90\n2-96,2-97\n73-99,2-97\n6-33,7-27\n9-67,10-67\n47-48,47-59\n3-87,87-99\n35-53,49-64\n40-98,41-93\n52-86,33-85\n23-55,89-91\n29-90,91-96\n5-69,5-69\n27-29,28-68\n14-33,81-88\n2-79,79-98\n34-92,93-94\n1-66,2-66\n8-96,7-97\n12-96,97-98\n78-92,10-88\n86-86,2-87\n11-65,2-64\n19-42,20-41\n2-34,34-93\n36-42,36-43\n10-86,11-78\n2-22,2-71\n8-20,19-95\n5-99,6-89\n6-18,6-6\n3-6,10-81\n69-71,69-69\n52-62,52-62\n79-98,79-98\n49-93,49-70\n10-97,10-97\n23-32,12-24\n7-8,8-94\n37-98,97-97\n2-80,2-79\n33-82,18-98\n53-65,54-90\n68-95,68-96\n7-8,7-14\n24-92,24-91\n31-36,32-48\n13-83,13-82\n23-54,53-53\n43-52,10-43\n24-66,23-94\n19-51,49-68\n66-72,39-66\n23-67,66-67\n34-80,48-79\n83-96,33-82\n79-90,33-95\n10-96,9-78\n12-97,96-99\n10-44,13-96\n2-94,93-93\n5-94,5-94\n71-95,74-97\n60-95,59-96\n86-95,14-86\n4-99,4-54\n12-47,13-13\n23-34,22-34\n49-96,49-86\n37-59,37-59\n1-4,3-94\n9-91,9-91\n57-99,45-57\n8-13,11-13\n11-85,84-85\n47-92,48-92\n4-89,5-89\n4-30,29-31\n10-65,9-64\n60-63,62-92\n43-78,23-42\n16-46,45-47\n26-95,95-96\n63-63,12-64\n21-47,20-47\n14-97,20-98\n6-90,6-86\n71-83,13-72\n64-91,83-90\n5-8,5-7\n42-84,41-98\n30-59,29-60\n6-92,5-95\n5-39,4-40\n71-85,16-70\n2-92,2-91\n8-91,20-91\n72-99,3-71\n31-82,97-98\n78-89,77-90\n48-89,47-89\n63-64,64-64\n24-74,73-88\n1-97,98-99\n73-82,72-82\n13-29,30-98\n11-41,11-12\n36-53,33-52\n46-90,66-89\n4-7,8-87\n5-45,46-91\n11-39,12-78\n42-93,41-85\n40-91,40-91\n23-27,23-51\n3-20,3-21\n64-91,48-91\n57-62,86-91\n5-21,22-89\n45-86,43-86\n94-97,54-93\n13-61,60-60\n25-98,19-97\n34-37,36-37\n97-98,16-96\n4-96,24-95\n2-55,1-92\n62-65,61-73\n21-52,20-21\n43-85,85-86\n2-95,2-95\n10-92,9-92\n8-99,9-98\n23-76,77-90\n18-18,1-19\n47-59,46-60\n78-84,77-81\n23-98,24-96\n2-61,1-60\n37-57,37-56\n58-74,58-58\n28-68,27-67\n16-84,17-84\n1-36,1-36\n62-63,14-63\n22-99,23-98\n1-86,85-86\n47-98,46-82\n4-72,5-72\n41-82,41-79\n64-95,64-93\n14-98,13-95\n38-83,35-83\n69-70,26-69\n1-99,2-72\n18-20,19-82\n12-34,11-34\n68-94,95-95\n59-89,89-90\n71-73,73-75\n58-78,18-92\n32-73,21-33\n31-91,90-91\n28-90,89-90\n54-56,77-94\n15-15,16-79\n57-88,24-57\n8-96,7-82\n5-50,5-50\n34-53,54-54\n75-75,62-76\n1-99,2-49\n4-4,3-61\n16-51,17-52\n19-99,4-44\n20-75,19-20\n36-57,21-35\n9-99,9-96\n15-61,38-61\n98-98,99-99\n2-94,13-94\n15-52,16-51\n10-98,12-98\n1-44,1-89\n4-97,3-97\n20-36,21-36\n28-29,29-79\n1-76,1-74\n69-69,69-94\n47-47,47-59\n15-22,21-91\n57-57,57-80\n11-11,11-35\n6-59,58-64\n15-70,15-71\n52-79,51-64\n60-65,55-64\n20-55,21-54\n26-75,99-99\n82-82,48-83\n4-81,82-82\n12-45,44-45\n3-80,2-81\n11-98,1-12\n21-41,35-41\n41-93,40-40\n87-99,1-87\n11-82,11-82\n5-86,4-8\n93-93,5-77\n11-94,1-10\n38-58,39-58\n63-64,35-62\n2-98,3-56\n9-75,76-77\n52-85,52-85\n32-36,32-36\n44-87,43-84\n4-85,84-85\n85-96,12-95\n2-66,26-66\n23-33,8-22\n16-92,15-80\n72-86,72-86\n8-42,7-7\n14-53,15-53\n4-78,8-78\n41-98,27-99\n33-40,4-39\n12-78,13-89\n9-93,10-93\n91-98,92-98\n30-90,29-69\n33-50,2-34\n22-89,23-89\n28-93,93-99\n5-45,4-45\n12-85,86-91\n52-99,52-99\n14-81,82-92\n3-98,4-69\n64-92,8-99\n1-90,5-90\n38-77,26-91\n49-65,35-42\n3-94,4-74\n4-58,4-4\n2-96,95-97\n2-99,3-98\n21-94,20-95\n11-76,12-75\n2-96,92-95\n44-76,41-76\n5-93,6-92\n85-90,20-89\n5-13,12-28\n97-97,96-98\n34-87,34-88\n14-27,14-35\n79-80,17-79\n6-23,22-52\n5-78,72-83\n25-80,26-46\n51-79,90-97\n28-80,77-80\n87-90,24-89\n89-90,71-90\n16-96,16-23\n32-86,31-31\n9-83,9-10\n46-53,52-53\n28-93,92-93\n41-50,40-48\n48-64,47-71\n5-23,3-6\n44-85,7-85\n30-57,29-58\n5-95,8-90\n6-95,12-95\n29-95,29-99\n15-44,14-14\n28-94,28-97\n8-8,7-8\n35-35,36-67\n35-88,71-93\n89-90,27-90\n89-91,30-90\n57-82,56-57\n24-74,19-74\n2-95,2-95\n55-91,54-91\n86-89,87-91\n30-81,30-81\n52-77,53-66\n5-91,75-90\n41-77,50-77\n52-73,34-69\n33-37,32-37\n40-71,74-85\n9-34,33-33\n95-95,25-96\n12-50,51-95\n16-65,53-60\n15-75,16-27\n6-33,6-7\n10-30,36-57\n10-60,2-60\n28-58,57-94\n16-62,15-62\n96-98,10-97\n19-28,8-47\n4-94,93-93\n2-96,95-96\n58-60,36-59\n8-62,13-98\n21-96,21-34\n11-50,11-50\n49-93,95-97\n6-76,8-99\n65-99,65-92\n13-66,3-54\n13-95,94-94\n57-96,57-96\n42-85,57-84\n26-81,25-82\n54-98,54-86\n3-84,83-92\n7-72,8-51\n67-83,67-71\n6-34,14-39\n1-47,1-47\n97-97,12-94\n2-89,2-98\n12-16,15-87\n30-59,31-59\n78-82,80-83\n14-69,9-70\n9-97,9-99\n45-68,44-69\n24-51,47-48\n48-48,48-68\n75-77,47-53\n7-73,7-73\n9-72,8-66\n39-70,38-71\n39-69,68-98\n26-94,26-93\n14-63,15-62\n19-61,61-62\n7-15,11-99\n1-73,2-51\n44-90,90-91\n54-97,96-98\n1-93,11-20\n34-70,35-69\n11-11,11-87\n8-73,8-73\n15-23,24-85\n42-57,43-99\n23-29,13-67\n99-99,1-54\n65-66,21-65\n23-38,23-75\n84-94,18-94\n10-63,11-62\n33-35,34-38\n68-70,4-69\n4-8,7-94\n20-95,20-54\n11-99,4-44\n20-97,3-97\n7-85,85-96\n44-85,45-84\n9-17,5-10\n82-97,22-81\n4-98,3-98\n17-80,17-75\n22-49,22-49\n94-99,27-91\n49-91,17-50\n20-30,36-49\n8-84,83-84\n59-91,60-73\n76-93,2-97\n5-48,5-94\n22-67,21-21\n3-4,4-5\n20-95,21-99\n21-86,85-87\n38-44,36-43\n2-90,91-99\n60-67,3-60\n3-58,4-57\n46-84,46-82\n13-13,14-95\n30-74,73-74\n24-34,24-34\n4-98,5-98\n6-7,2-6\n41-98,42-98\n16-58,57-85\n86-90,61-86\n2-85,2-84\n7-90,90-93\n25-65,26-30\n41-69,12-70\n31-88,32-87\n10-87,10-87\n4-29,4-98\n8-40,30-40\n26-82,25-82\n89-90,88-89\n4-13,9-14\n10-65,6-7\n6-13,13-99\n75-79,45-79\n6-98,9-89\n6-55,54-58\n2-78,25-78\n3-98,3-98\n95-95,6-94\n9-78,77-77\n56-57,56-58\n49-87,24-66\n47-47,47-73\n33-35,6-34\n30-80,36-80\n30-30,31-81\n99-99,68-74\n2-99,3-98\n14-92,10-15\n16-31,18-51\n95-97,2-94\n31-31,15-32\n98-99,68-93\n14-71,14-15\n5-39,14-38\n47-54,53-55\n37-64,37-37\n58-78,10-58\n40-88,41-41\n68-99,16-94\n25-25,26-58\n84-87,1-99\n72-87,72-78\n49-81,48-49\n1-99,2-99\n24-91,25-93\n12-81,11-58\n1-16,15-50\n12-26,12-26\n17-80,17-79\n94-96,38-95\n1-84,83-84\n20-82,20-20\n3-86,2-95\n19-98,60-94\n9-45,45-50\n8-57,9-12\n15-18,18-83\n1-1,1-15\n85-96,84-95\n1-40,40-78\n57-58,30-58\n48-90,57-89\n26-51,27-86\n2-86,85-86\n25-78,26-77\n82-99,81-97\n1-14,13-97\n76-96,75-97\n66-94,64-97\n34-60,38-61\n80-95,22-81\n51-80,51-80\n2-78,1-78\n43-46,45-69\n75-85,76-76\n33-65,32-32\n15-96,14-96\n68-86,67-71\n12-26,12-16\n1-51,3-43\n87-88,27-88\n17-99,16-99\n9-36,20-24\n25-32,24-32\n32-32,32-76\n77-92,52-78\n4-79,4-82\n38-61,54-59\n38-99,38-99\n94-98,54-95\n80-96,2-95\n8-97,8-97\n7-28,8-22\n66-82,83-91\n33-48,49-83\n3-3,4-83\n76-90,77-90\n34-62,34-61\n40-87,16-27\n1-98,2-98\n55-96,95-98\n5-99,5-5\n36-97,10-98\n12-94,93-94\n72-78,71-78\n13-18,14-18\n47-76,75-76\n21-96,21-95\n69-96,68-87\n27-64,28-62\n19-40,25-39\n4-59,4-98\n10-66,10-67\n16-82,17-82\n7-99,3-99\n18-30,17-92\n86-99,24-52\n19-77,20-77\n97-97,93-94\n11-33,10-11\n84-96,53-95\n3-85,4-91\n15-52,16-53\n86-90,52-56\n33-76,33-76\n3-98,17-92\n79-79,4-80\n85-85,2-84\n13-94,94-96\n60-84,90-93\n93-97,15-98\n9-54,10-53\n28-59,27-98\n12-85,11-65\n59-67,58-67\n20-50,20-65\n63-65,16-64\n76-96,75-75\n23-91,24-91\n3-99,3-97\n25-48,26-48\n48-48,49-87\n15-96,1-16\n9-79,25-78\n52-61,62-84\n6-85,7-84\n54-77,53-78\n1-99,1-99\n59-96,60-96\n12-45,12-46\n22-87,3-87\n36-98,36-74\n56-56,22-57\n94-95,99-99\n7-92,8-83\n13-94,14-93\n22-90,89-89\n46-94,83-87\n11-76,75-78\n3-94,3-95\n4-14,5-52\n90-92,66-83\n46-61,46-47\n22-23,22-90\n47-47,48-53\n89-91,16-90\n42-93,93-94\n9-61,60-94\n1-1,1-67\n3-38,2-99\n46-98,47-97\n96-97,1-95\n8-54,55-92\n52-72,53-71\n"
  },
  {
    "path": "advent-of-code/2022/inputs/05",
    "content": "    [C]             [L]         [T]\n    [V] [R] [M]     [T]         [B]\n    [F] [G] [H] [Q] [Q]         [H]\n    [W] [L] [P] [V] [M] [V]     [F]\n    [P] [C] [W] [S] [Z] [B] [S] [P]\n[G] [R] [M] [B] [F] [J] [S] [Z] [D]\n[J] [L] [P] [F] [C] [H] [F] [J] [C]\n[Z] [Q] [F] [L] [G] [W] [H] [F] [M]\n 1   2   3   4   5   6   7   8   9 \n\nmove 1 from 5 to 6\nmove 5 from 6 to 7\nmove 10 from 7 to 3\nmove 4 from 8 to 4\nmove 2 from 5 to 4\nmove 4 from 3 to 6\nmove 6 from 2 to 4\nmove 8 from 6 to 9\nmove 5 from 9 to 2\nmove 7 from 2 to 7\nmove 2 from 1 to 4\nmove 3 from 3 to 8\nmove 1 from 5 to 9\nmove 1 from 3 to 8\nmove 1 from 1 to 2\nmove 11 from 4 to 6\nmove 2 from 5 to 6\nmove 10 from 9 to 1\nmove 4 from 8 to 3\nmove 7 from 7 to 1\nmove 9 from 1 to 2\nmove 1 from 6 to 5\nmove 1 from 5 to 9\nmove 5 from 3 to 8\nmove 2 from 9 to 1\nmove 5 from 3 to 9\nmove 3 from 6 to 8\nmove 5 from 9 to 6\nmove 6 from 6 to 3\nmove 3 from 3 to 2\nmove 1 from 9 to 8\nmove 13 from 2 to 3\nmove 3 from 8 to 1\nmove 11 from 1 to 4\nmove 3 from 4 to 1\nmove 2 from 6 to 5\nmove 4 from 6 to 8\nmove 17 from 3 to 9\nmove 1 from 1 to 8\nmove 1 from 6 to 5\nmove 1 from 3 to 7\nmove 1 from 7 to 4\nmove 3 from 4 to 1\nmove 1 from 3 to 8\nmove 4 from 8 to 1\nmove 3 from 5 to 9\nmove 1 from 6 to 4\nmove 4 from 4 to 8\nmove 2 from 8 to 4\nmove 2 from 1 to 6\nmove 4 from 8 to 6\nmove 1 from 8 to 3\nmove 6 from 6 to 3\nmove 6 from 3 to 9\nmove 6 from 1 to 4\nmove 5 from 8 to 4\nmove 1 from 3 to 6\nmove 3 from 1 to 7\nmove 1 from 6 to 7\nmove 4 from 4 to 5\nmove 24 from 9 to 5\nmove 2 from 9 to 1\nmove 27 from 5 to 7\nmove 13 from 7 to 2\nmove 1 from 5 to 9\nmove 7 from 2 to 7\nmove 1 from 9 to 8\nmove 5 from 2 to 8\nmove 1 from 2 to 5\nmove 1 from 5 to 7\nmove 21 from 4 to 1\nmove 1 from 4 to 6\nmove 1 from 6 to 5\nmove 22 from 7 to 5\nmove 2 from 7 to 8\nmove 7 from 5 to 4\nmove 1 from 4 to 5\nmove 2 from 7 to 9\nmove 5 from 5 to 2\nmove 5 from 4 to 2\nmove 3 from 5 to 1\nmove 7 from 8 to 7\nmove 1 from 4 to 1\nmove 23 from 1 to 8\nmove 2 from 9 to 4\nmove 11 from 8 to 3\nmove 3 from 1 to 3\nmove 1 from 4 to 2\nmove 12 from 3 to 2\nmove 7 from 7 to 3\nmove 3 from 2 to 1\nmove 1 from 4 to 9\nmove 1 from 1 to 3\nmove 9 from 8 to 6\nmove 2 from 5 to 4\nmove 3 from 1 to 7\nmove 3 from 2 to 4\nmove 7 from 2 to 3\nmove 9 from 3 to 4\nmove 7 from 5 to 2\nmove 2 from 7 to 2\nmove 1 from 7 to 2\nmove 13 from 4 to 6\nmove 1 from 9 to 8\nmove 2 from 8 to 2\nmove 12 from 2 to 1\nmove 3 from 3 to 1\nmove 1 from 8 to 1\nmove 5 from 3 to 7\nmove 3 from 2 to 8\nmove 7 from 2 to 5\nmove 3 from 8 to 3\nmove 1 from 4 to 8\nmove 22 from 6 to 4\nmove 1 from 3 to 6\nmove 3 from 5 to 8\nmove 4 from 5 to 8\nmove 1 from 3 to 9\nmove 8 from 4 to 2\nmove 8 from 8 to 3\nmove 1 from 6 to 3\nmove 4 from 2 to 6\nmove 1 from 9 to 4\nmove 5 from 3 to 9\nmove 2 from 8 to 1\nmove 3 from 2 to 1\nmove 10 from 4 to 8\nmove 4 from 7 to 6\nmove 10 from 1 to 3\nmove 9 from 8 to 2\nmove 1 from 7 to 1\nmove 15 from 3 to 1\nmove 1 from 8 to 9\nmove 4 from 4 to 1\nmove 17 from 1 to 3\nmove 3 from 2 to 3\nmove 3 from 6 to 8\nmove 5 from 9 to 7\nmove 11 from 1 to 8\nmove 4 from 7 to 8\nmove 6 from 2 to 5\nmove 2 from 1 to 4\nmove 4 from 6 to 8\nmove 16 from 8 to 6\nmove 2 from 6 to 1\nmove 1 from 9 to 5\nmove 1 from 7 to 5\nmove 2 from 5 to 6\nmove 5 from 6 to 3\nmove 2 from 8 to 5\nmove 1 from 2 to 1\nmove 10 from 6 to 3\nmove 6 from 5 to 9\nmove 2 from 1 to 2\nmove 2 from 4 to 2\nmove 1 from 2 to 4\nmove 5 from 9 to 2\nmove 1 from 4 to 3\nmove 1 from 9 to 7\nmove 1 from 6 to 1\nmove 1 from 1 to 7\nmove 2 from 7 to 5\nmove 7 from 2 to 5\nmove 6 from 5 to 1\nmove 1 from 2 to 3\nmove 1 from 4 to 1\nmove 2 from 8 to 9\nmove 8 from 1 to 3\nmove 2 from 5 to 3\nmove 29 from 3 to 9\nmove 5 from 3 to 8\nmove 6 from 8 to 5\nmove 1 from 6 to 5\nmove 6 from 3 to 2\nmove 2 from 2 to 4\nmove 1 from 1 to 7\nmove 18 from 9 to 6\nmove 2 from 2 to 9\nmove 2 from 2 to 8\nmove 13 from 6 to 8\nmove 1 from 7 to 4\nmove 3 from 5 to 6\nmove 1 from 5 to 7\nmove 1 from 7 to 4\nmove 14 from 9 to 3\nmove 3 from 4 to 5\nmove 1 from 9 to 7\nmove 14 from 3 to 2\nmove 1 from 7 to 3\nmove 4 from 2 to 5\nmove 16 from 8 to 6\nmove 11 from 6 to 9\nmove 13 from 6 to 4\nmove 5 from 5 to 2\nmove 12 from 2 to 4\nmove 19 from 4 to 3\nmove 7 from 4 to 5\nmove 14 from 5 to 2\nmove 2 from 3 to 6\nmove 3 from 9 to 5\nmove 2 from 6 to 2\nmove 1 from 5 to 2\nmove 3 from 5 to 4\nmove 3 from 4 to 1\nmove 7 from 9 to 6\nmove 4 from 6 to 1\nmove 1 from 1 to 8\nmove 3 from 6 to 9\nmove 1 from 8 to 7\nmove 1 from 9 to 6\nmove 4 from 1 to 2\nmove 1 from 7 to 2\nmove 2 from 9 to 8\nmove 10 from 2 to 9\nmove 2 from 2 to 9\nmove 11 from 3 to 7\nmove 1 from 8 to 9\nmove 2 from 3 to 7\nmove 1 from 1 to 7\nmove 10 from 2 to 4\nmove 3 from 4 to 1\nmove 4 from 1 to 8\nmove 1 from 6 to 5\nmove 6 from 7 to 9\nmove 3 from 9 to 1\nmove 1 from 5 to 1\nmove 4 from 4 to 2\nmove 5 from 2 to 1\nmove 1 from 2 to 7\nmove 2 from 7 to 6\nmove 1 from 2 to 1\nmove 2 from 9 to 1\nmove 3 from 4 to 7\nmove 1 from 3 to 7\nmove 2 from 8 to 3\nmove 2 from 6 to 5\nmove 2 from 5 to 8\nmove 10 from 7 to 2\nmove 6 from 9 to 1\nmove 1 from 7 to 3\nmove 2 from 8 to 9\nmove 7 from 3 to 7\nmove 7 from 3 to 9\nmove 1 from 8 to 9\nmove 6 from 2 to 8\nmove 13 from 9 to 1\nmove 6 from 9 to 8\nmove 2 from 2 to 7\nmove 3 from 7 to 1\nmove 1 from 8 to 1\nmove 1 from 1 to 6\nmove 16 from 1 to 4\nmove 2 from 7 to 5\nmove 12 from 4 to 9\nmove 4 from 8 to 6\nmove 2 from 5 to 1\nmove 8 from 8 to 4\nmove 2 from 4 to 5\nmove 1 from 8 to 6\nmove 4 from 6 to 8\nmove 19 from 1 to 9\nmove 3 from 8 to 5\nmove 1 from 6 to 9\nmove 2 from 2 to 1\nmove 10 from 4 to 9\nmove 1 from 1 to 2\nmove 2 from 1 to 5\nmove 4 from 7 to 9\nmove 1 from 8 to 2\nmove 1 from 2 to 6\nmove 7 from 5 to 4\nmove 11 from 9 to 8\nmove 1 from 4 to 3\nmove 10 from 8 to 1\nmove 1 from 2 to 3\nmove 29 from 9 to 3\nmove 2 from 6 to 5\nmove 1 from 5 to 3\nmove 5 from 9 to 3\nmove 1 from 8 to 9\nmove 1 from 9 to 3\nmove 6 from 4 to 6\nmove 1 from 5 to 1\nmove 1 from 6 to 3\nmove 2 from 1 to 5\nmove 1 from 9 to 5\nmove 37 from 3 to 2\nmove 3 from 6 to 2\nmove 1 from 6 to 2\nmove 1 from 6 to 4\nmove 3 from 1 to 3\nmove 2 from 1 to 6\nmove 35 from 2 to 1\nmove 1 from 6 to 8\nmove 5 from 1 to 8\nmove 7 from 1 to 6\nmove 5 from 3 to 7\nmove 1 from 8 to 7\nmove 3 from 7 to 5\nmove 4 from 2 to 9\nmove 1 from 2 to 1\nmove 1 from 4 to 3\nmove 3 from 7 to 1\nmove 1 from 3 to 6\nmove 1 from 1 to 9\nmove 5 from 9 to 2\nmove 18 from 1 to 3\nmove 6 from 1 to 8\nmove 6 from 3 to 7\nmove 4 from 8 to 6\nmove 4 from 6 to 7\nmove 9 from 7 to 8\nmove 3 from 2 to 7\nmove 4 from 6 to 1\nmove 3 from 5 to 3\nmove 3 from 2 to 5\nmove 3 from 6 to 1\nmove 4 from 7 to 4\nmove 6 from 5 to 9\nmove 3 from 1 to 9\nmove 1 from 6 to 1\nmove 15 from 8 to 2\nmove 1 from 8 to 5\nmove 3 from 4 to 8\nmove 1 from 5 to 1\nmove 1 from 6 to 5\nmove 11 from 3 to 9\nmove 12 from 2 to 3\nmove 3 from 8 to 1\nmove 15 from 1 to 2\nmove 8 from 9 to 4\nmove 8 from 4 to 9\nmove 4 from 2 to 5\nmove 1 from 4 to 6\nmove 1 from 2 to 8\nmove 1 from 6 to 7\nmove 4 from 3 to 1\nmove 1 from 8 to 5\nmove 5 from 3 to 9\nmove 14 from 9 to 2\nmove 1 from 7 to 4\nmove 4 from 1 to 3\nmove 1 from 4 to 7\nmove 8 from 3 to 7\nmove 8 from 7 to 5\nmove 1 from 7 to 9\nmove 3 from 3 to 2\nmove 7 from 9 to 8\nmove 1 from 9 to 5\nmove 2 from 8 to 5\nmove 7 from 5 to 4\nmove 4 from 9 to 2\nmove 6 from 4 to 3\nmove 18 from 2 to 5\nmove 1 from 4 to 7\nmove 15 from 5 to 4\nmove 1 from 4 to 6\nmove 2 from 2 to 7\nmove 3 from 8 to 5\nmove 1 from 7 to 3\nmove 8 from 2 to 6\nmove 4 from 2 to 3\nmove 1 from 7 to 5\nmove 3 from 4 to 6\nmove 5 from 6 to 9\nmove 8 from 5 to 6\nmove 2 from 4 to 3\nmove 7 from 4 to 2\nmove 2 from 8 to 5\nmove 7 from 5 to 6\nmove 3 from 5 to 8\nmove 1 from 8 to 9\nmove 13 from 3 to 8\nmove 2 from 2 to 7\nmove 9 from 8 to 9\nmove 6 from 8 to 5\nmove 5 from 5 to 2\nmove 2 from 7 to 8\nmove 9 from 2 to 5\nmove 1 from 7 to 5\nmove 1 from 5 to 7\nmove 21 from 6 to 2\nmove 1 from 7 to 8\nmove 3 from 8 to 9\nmove 1 from 4 to 2\nmove 23 from 2 to 7\nmove 8 from 9 to 8\nmove 20 from 7 to 4\nmove 3 from 7 to 2\nmove 1 from 2 to 7\nmove 1 from 6 to 7\nmove 3 from 5 to 4\nmove 8 from 5 to 9\nmove 2 from 7 to 1\nmove 1 from 8 to 7\nmove 4 from 2 to 4\nmove 2 from 8 to 7\nmove 2 from 8 to 2\nmove 1 from 7 to 6\nmove 3 from 9 to 7\nmove 2 from 2 to 7\nmove 5 from 7 to 1\nmove 8 from 9 to 6\nmove 15 from 4 to 3\nmove 4 from 4 to 7\nmove 6 from 1 to 4\nmove 11 from 3 to 4\nmove 8 from 6 to 1\nmove 24 from 4 to 7\nmove 6 from 1 to 8\nmove 27 from 7 to 3\nmove 2 from 7 to 8\nmove 5 from 8 to 3\nmove 4 from 8 to 4\nmove 1 from 8 to 6\nmove 1 from 6 to 9\nmove 1 from 6 to 5\nmove 2 from 4 to 2\nmove 1 from 8 to 1\nmove 1 from 5 to 2\nmove 4 from 1 to 6\nmove 1 from 7 to 5\nmove 1 from 5 to 8\nmove 1 from 8 to 7\nmove 1 from 7 to 8\nmove 1 from 8 to 1\nmove 1 from 2 to 3\nmove 2 from 4 to 8\nmove 7 from 9 to 6\nmove 2 from 8 to 1\nmove 3 from 3 to 8\nmove 3 from 1 to 8\nmove 2 from 2 to 3\nmove 1 from 4 to 1\nmove 1 from 1 to 8\nmove 5 from 8 to 3\nmove 8 from 6 to 2\nmove 1 from 9 to 4\nmove 2 from 4 to 8\nmove 2 from 8 to 3\nmove 2 from 6 to 2\nmove 33 from 3 to 2\nmove 2 from 8 to 7\nmove 1 from 6 to 1\nmove 1 from 1 to 7\nmove 2 from 3 to 8\nmove 2 from 8 to 4\nmove 1 from 4 to 8\nmove 2 from 7 to 2\nmove 2 from 3 to 7\nmove 12 from 2 to 1\nmove 1 from 8 to 4\nmove 1 from 4 to 8\nmove 1 from 4 to 3\nmove 1 from 8 to 2\nmove 3 from 7 to 2\nmove 37 from 2 to 7\nmove 1 from 1 to 7\nmove 12 from 7 to 1\nmove 13 from 1 to 7\nmove 1 from 3 to 4\nmove 35 from 7 to 6\nmove 1 from 4 to 5\nmove 3 from 7 to 4\nmove 1 from 5 to 7\nmove 2 from 3 to 4\nmove 23 from 6 to 9\nmove 3 from 1 to 5\nmove 3 from 3 to 7\nmove 1 from 3 to 6\nmove 2 from 5 to 3\nmove 23 from 9 to 8\nmove 2 from 4 to 9\nmove 16 from 8 to 2\nmove 2 from 7 to 3\nmove 1 from 5 to 8\nmove 3 from 7 to 6\nmove 1 from 9 to 8\nmove 3 from 8 to 1\nmove 1 from 9 to 1\nmove 11 from 6 to 5\nmove 2 from 4 to 1\nmove 4 from 8 to 6\nmove 16 from 2 to 3\nmove 9 from 1 to 9\nmove 1 from 8 to 4\nmove 3 from 9 to 3\nmove 1 from 1 to 4\nmove 1 from 9 to 4\nmove 7 from 5 to 2\nmove 6 from 2 to 5\nmove 1 from 8 to 6\nmove 22 from 3 to 7\nmove 8 from 5 to 8\nmove 4 from 4 to 9\nmove 2 from 1 to 8\nmove 16 from 7 to 2\nmove 1 from 3 to 5\nmove 14 from 2 to 7\nmove 2 from 2 to 4\nmove 6 from 9 to 3\n"
  },
  {
    "path": "advent-of-code/2022/inputs/06",
    "content": "pwjwljjjvqjqjzqjqvvpgvpggmdgdrrzmzfzmzffzbbjnbjnjddsdpsdsgsgvsgvgmmzvvpspvspsdsbsbffhwhlwwzllftfhhrfrsrrnnngqgtglgfgtffnssrspsqppdvdtdwwpfpzffnpnddvsswjswjjhdjdrjrwwfpwfpfjppzwzvzpzrznzgzcgzgpgfpffwggtbbhsslzztpplltdtqtctrrszrzszpsprptrtgrtrzrvzrvzrrsfsbswsvvbdbjjgljjwqwgqwwtmwwnbbzdbdwwsnntztstbssnjssjmmldmmrrnfrfgfbbszzzlrrwzwtwwbrwrlwrwzwmwqmwwtqwwtvvdqdtqqfnfjnjsnslltcllvmmdmttvsszrsrwssdmdttdmdrmrsrvrllrhlltmlmlzmlzzhvhbbflfsslclpcczmmcjmjccpgprrgnrrzqqmgqggfvgffbsfsbfbttrgtrtptgtjtnnfbfmmrrcmcwwbbmwmvvvtppslsvvlsvswwztwztzqqpggdccmlldlplggrgddlrddvwvsswllsffbllsbbslshslswsllnqlqrqqpmqmtmqtmqtmmbwmbbzdbzbttvptvpvgpvggblbsspgppvmvsswfssfdfrdffpbfpprmrssmbbmggszslzlslblsldsldssjjsrjjjdfdjdtdmdnnncddpfddrjdjvjfvjffftmfmqqqqqfjjhssbzbbfjjmmzgzllphlplhlplfpfnpnsppjjqsshpssjdjzzwvvjfvfnfttmtbbgtgbbdpbbjppzcpzzvcvpvvdcvvcfvvfsvsccmhhrwrjjsrjrvrfvfwvvtftzztlztlthlhrhnnlpnllnmnfmffzpffhlhbhqbhqhfhwwlglnndgdwdswwgtwgtgsttpbprpqpnnbsnbsnszzrszsqzqlqggvhghrrvprvvvqnnmmrwrbrrmttwrrlmrrrddmsddbhdhdjhdhrhffppphghvvtztptjjlppcqcscjscstsmsbspsgpgqgmmndmdvvpnpnrrjtrthhtzzjlzzrwzrrfsfflrrmffhlhglhhhhvwwttlcttbqqzzbzzzbhbsscqqjggqpggqffbttrfrjjjqmmpttlvvqlvqqqtgtrtcrcbcnbbhfbfhbhqbhqbqvbvqvrqvvgttqwqpwqwnnpgngpphjppztptnnrssjqqrplzrvmwmbrbgbnggvzpmphqsrjrdhtslpmmwrhgcndwtbsbrfmsplzqswsnmrwdwwhzmpbqcmjfsmnwqnjmvdczhgmtfjwnjfdllfzdwpwgclpbdqtqnqqqvpthltznfzshhgrwwqclpplmdwtpjszrdwwzfbljcjmqmhptfhvcbvgfjfftbsfglwqldphdzzgcmvtsbhlsdncfjcsqrqrtdhttcwzlbqhvgppbrjfzdzwzprwpfflmdspcmqcbdhsvwjswwbzwnqrshbqfnmtdzrsrjgqngntllcgwjnmjqvtgwvttfqrcjlhbpcrszlngfmdgzprcdttgbjpcdzbhtdghpltcbvcddnslhqthfvzjtspqlzhdprhgtrlqqgtsqwwjqthgdwfgdfzhrnrwlrpqmgqltgldpjqgjzvngrphclbfftnwfnfvsvhftthptqfnvlftdpdhcrjdhfwtpwwvsblgntdwcpnsprhnpjtjsprdrdjwlhnmnzmmjmcdfsctzgmlqwwrwztjndqgpqrvdgplcnntqhfjlzjszpdwnvlwdzzgpzvplglgrmsjgjpmsrdsgzlfblgbgszgdtgsggqvhzmnfcnvlnzrfpqphctlcqccqzslmlsbbztnpncqpgscgdmmsgfwqrzpmbqrmfqsnnggswhmgmtmgdmhwthbgbdsrtnsrvdfdhlhhczgdsdqnpsgjzpbnsmgrvsfdjlhgjfjjwqnrnrbzdzcjlstclpqfnrflgnzbdbzvbjcbgqrrrlfcpgptcghhqqfsvsgljvjhdgdgcjtnrqsctmwhzbmbrfrsvndhfrtwlfgvqcbjsvttrctfshrggdvgbhthnwbwqglrvfbsqnbhdwgzhbccjnlhtcbjlpgrvttthnwvvspnzvqhjvmtwshcstdjhfqhqcgvwqwwwwrfdmnjhldsrhgmtjddsghdmdrpczbcjflmbhszctmvdttfrrqqpwslhvqbjlsrjdjrcqjrhwgjlsqmvdpvvvlbzwtthptpsggddcbqbhrvrpdtncvgndclhpngzgfqdqgwwbrjltjtqbpbtbzjmfmnjnlqmtzvdqdwqhbgptplrgdsfpjzfrpdcdsznwffpnzsmpqjfbcpddqjgfqhqbwsfmzgstfdnzhphhvgbzvjrlmqmrznpctftcmbtdpbfbfpfpjtjhbcrrssnlvtrtnzvwtjwplclpqndpfstjmghmzsllhntprtjwlppjnjgjzlvlcbcwjvrjqjhfnnpmwlpngwtvvbcllmjzqfrwvtvsrvbcpfwcdfwmdwvztwtbrgvlvmfjmpzdzmfbcmrsqfwqjfjfrgmnblnzfzcvgwllvmqfmdlqqgvvjrptlrjcwphvchwhmtwhnlnjprqhlrhmdfptvpshjbzrhptvnqfvjfjcnglnbfhbwghqqjbqzdthjwqzznwfsmqmbsqnwrdrrwjgzjdmgtsqswlqcpshdmcfjttpszqmsjhgfsrvgchgwzbqgbdqhmbndmnmwjsnjjvmtpprbtlwzpvfdnbtjnzzvlwndgbhgwbpllvfghwvwjmlpnzfjzjwwmtvbbfndppbqwhjlwgtswmgffddbhnwqljvgcvfnqmzgvfmjwsbcrpgtcpchlblccgpgpmddsjsfwbnvnsfttnsqjshchdztvsbjwsfmszfwpwsmgzvvcfddtczvvmnhgjffrsfqzfmphpfblmwgcbbrjqzdztzzzjhqmjzrgmwgrqdfqdbjsgwfndqgnmdvjlwdtjpjtpcqlhtcfvnmzjswldrbqjpmrlqwhvnqjshbqqvzwwsdjmspgbvrgvpjjnwsvnvnppvlnqbdllfczjjftpnlrjfvcwgwbdmldtcnczqzcptjjrgglnnbgmrdffgmnnwvjzwbgcncnhzmthswrdsrhchprrrrnhjfnzmsgfjltqzmttvhslnsgcjfgqwcsddfstcstspcpdbznvdrnqhwqsfgqtdbtwspfswfjbzgtqjpvzfhfdblszblmgrmmlwvnwwdsdjjvrsfjfjltcsfccplftvpltqshgnpnqlqcglrhvzldptspnbvjcchnnvzvbbqnnnbnggrhpcgqtgnjdqplswtblgtwqzmltjjhpdttgbcvhfrsdcgjzswvtbbhrpnzmrjhgznbdpqgqdhwcnmgflpdtbzdbvzvslbvvwdpcnwjtvjhgncnljfwlrvqgdrjhdcprsqjrmwwlcrrvsjtlmqmjtcbqwcbmgnvfshdgmmfffzvwjphjfspvdzjsqdlgqfdjwwshdcssqvvgdcvvtmwlfjdvtfllrvltmrsgpdtdqsfjpcvjnqszpnbqqlnpdvhtswbgwnpcqpgzqwlgsmlnlngcdmqhchcdgfmrhfwwrgrrdrhcsbbcrhghdjrcsltchqghvmbvbbpqzqbgwmqrgwchhbvdsqbqrfcbzwjrlqtnmghtjbtjdpngcjzswfmjfphjnftbhdgvwjsvqfbsfgqhfbcrgrsppsvbnpwlhsdrffcmmgzpjfsvllcrbtwrwddthfjvjndzfzbcmglhbzpzwwbtzdpdlwrnbzqjbqwpbdlwfddbtzjhqshmcghqfcrzrmrtmqwpqhvqzbfwhbssgjcmzqcpvnntbpfqwhbmtjdtbtrrdhsvzqjltdshtlvwwmlbdzlvjhmtppnbqcjnncpslcggsjbrmzvdgqzclwszgzfqthndnjfjrznlmmtjwwhnzvhnjncccpczrftvhtdhjbzvwvlgqhdnfqdqrhctfffpcnqzdrgqqzcczdjvpzqfgfcpjzqhbwshsqhvqzpsb\n"
  },
  {
    "path": "advent-of-code/2022/inputs/07",
    "content": "$ cd /\n$ ls\ndir bzgf\n199775 dngdnvv.qdf\ndir fhhwv\ndir gzlpvdhd\ndir htczftcn\n23392 lbcgmm\n251030 lsw.jgr\n305227 nflgvsgz\ndir qcqg\ndir qtqpw\ndir qzcdscbp\ndir rfgvg\ndir rzb\n202033 zqzlbvgl\n$ cd bzgf\n$ ls\n80802 htczftcn.bdr\n$ cd ..\n$ cd fhhwv\n$ ls\ndir bjml\n274615 bzmwfgf.wwp\ndir ddpf\ndir jngvpc\n220692 lbcgmm\ndir pffdg\ndir prwpzhb\n21309 qtqpw.mhb\n12989 vbvt\n46352 vhnsp.dhg\n$ cd bjml\n$ ls\n307491 bzmwfgf.wwp\ndir cwghv\n164053 dngdnvv.qdf\n144223 jbc.zgp\n274358 mcqbcttc.mwr\ndir pffdg\n573 spbw.mnt\ndir vdd\ndir zzvs\n$ cd cwghv\n$ ls\n298079 htczftcn\n33689 nflgvsgz\n287144 svfqpfm.bgs\ndir tdgw\n164244 tzrz.hms\n52508 zmm.ndc\n$ cd tdgw\n$ ls\n195017 htczftcn.cnl\n$ cd ..\n$ cd ..\n$ cd pffdg\n$ ls\n64762 bbqh.wzf\ndir bgzdv\n56148 bhrw.jls\ndir hqwmfdj\n28260 htczftcn.lvs\ndir lzhz\ndir nbmsrl\n91675 qtqpw.hsj\n$ cd bgzdv\n$ ls\n205543 srzlfd.hnq\n$ cd ..\n$ cd hqwmfdj\n$ ls\n37910 dzpgcrn.rbj\n290553 mrrngcdr\n175411 nflgvsgz.tsj\n$ cd ..\n$ cd lzhz\n$ ls\n73620 bbtdnpvf\ndir jbc\n$ cd jbc\n$ ls\n125475 tzrz.hms\n$ cd ..\n$ cd ..\n$ cd nbmsrl\n$ ls\n106099 dngdnvv.qdf\n$ cd ..\n$ cd ..\n$ cd vdd\n$ ls\n136746 vlc.vcp\n$ cd ..\n$ cd zzvs\n$ ls\n8406 dngdnvv.qdf\ndir nflgvsgz\n55902 qtqpw.lcc\ndir vmbrt\n269256 whjmbnm.ngd\n$ cd nflgvsgz\n$ ls\ndir mdgzvzbs\ndir nlzc\n$ cd mdgzvzbs\n$ ls\n88913 ggvd\n$ cd ..\n$ cd nlzc\n$ ls\n37916 rww\n$ cd ..\n$ cd ..\n$ cd vmbrt\n$ ls\n194547 dwvbcvw.tmv\n54334 htczftcn.bqh\n299821 jnqgz\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd ddpf\n$ ls\ndir plv\n$ cd plv\n$ ls\n178177 dzsns\n$ cd ..\n$ cd ..\n$ cd jngvpc\n$ ls\n276675 dcgmtcb\n108711 htczftcn.dsr\ndir jbc\n280837 rqprcth.dhp\n84724 tzrz.hms\n$ cd jbc\n$ ls\ndir htczftcn\n74153 tzrz.hms\n$ cd htczftcn\n$ ls\ndir nflgvsgz\n$ cd nflgvsgz\n$ ls\n208092 nnrd.zrj\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd pffdg\n$ ls\n264811 htczftcn\n$ cd ..\n$ cd prwpzhb\n$ ls\n181249 fstwrdqp\ndir jbc\n140710 nflgvsgz\ndir pffdg\n103710 qlqfc.qbm\ndir qtqpw\n15917 sqgmfl\ndir zhcs\n171467 zls.tmj\n$ cd jbc\n$ ls\n12337 tzrz.hms\n$ cd ..\n$ cd pffdg\n$ ls\n302369 cshb.fbd\n251192 htczftcn.vnn\ndir msdtpqqd\ndir sgtqmfgq\n$ cd msdtpqqd\n$ ls\n42614 mptlnbp\n$ cd ..\n$ cd sgtqmfgq\n$ ls\n81125 jbc.szn\n$ cd ..\n$ cd ..\n$ cd qtqpw\n$ ls\n160846 dngdnvv.qdf\n$ cd ..\n$ cd zhcs\n$ ls\n166883 vtz.bvb\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd gzlpvdhd\n$ ls\ndir ffvz\n$ cd ffvz\n$ ls\n74736 jvb.ppb\n$ cd ..\n$ cd ..\n$ cd htczftcn\n$ ls\ndir dqbml\n149343 gqjgvz\n112647 lbcgmm\ndir lbm\n192438 mpdzgzm\ndir nflgvsgz\ndir pffdg\ndir qtqpw\n149952 qtqpw.gdv\ndir rcnwghg\n134076 rvdsldpf.zqc\ndir sglgqlp\ndir wrfmf\n$ cd dqbml\n$ ls\ndir bphwp\n303757 gglsqjbz.ffb\ndir htczftcn\ndir hwm\n56134 pml.pmq\ndir rsv\n108298 tzrz.hms\n201663 wqqdrml.wsl\n$ cd bphwp\n$ ls\n94931 dngdnvv.qdf\n90517 jsgl\n118142 pzl\n7387 tzrz.hms\n$ cd ..\n$ cd htczftcn\n$ ls\n300063 ctfgqld\ndir htczftcn\ndir jhldlsc\ndir nflgvsgz\n125403 pffdg\n25617 pffdg.zdg\ndir qddqn\ndir tpmbzslr\n$ cd htczftcn\n$ ls\ndir zzpnff\n$ cd zzpnff\n$ ls\n79133 ssznrqlz.llw\n$ cd ..\n$ cd ..\n$ cd jhldlsc\n$ ls\ndir swcbqqd\n$ cd swcbqqd\n$ ls\n11202 htczftcn.cjs\n111869 htczftcn.nvb\n$ cd ..\n$ cd ..\n$ cd nflgvsgz\n$ ls\n37140 bffzwn.gqj\ndir glmvgr\n233206 lpclj\n79112 lpqh.ldp\n254611 qtqpw\ndir rmbwlbt\n206666 tgbdwgn\n$ cd glmvgr\n$ ls\n115043 nflgvsgz.jgl\n$ cd ..\n$ cd rmbwlbt\n$ ls\ndir pffdg\n$ cd pffdg\n$ ls\n92779 tzrz.hms\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd qddqn\n$ ls\ndir jbc\n$ cd jbc\n$ ls\n268367 cdcs\n$ cd ..\n$ cd ..\n$ cd tpmbzslr\n$ ls\ndir dbfcp\ndir lgsdbjz\n$ cd dbfcp\n$ ls\n23450 nflgvsgz.nsl\n$ cd ..\n$ cd lgsdbjz\n$ ls\n248980 cqzqzb.nfh\n248463 tzrz.hms\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd hwm\n$ ls\n174410 jbc.rvr\n310669 tzrz.hms\n$ cd ..\n$ cd rsv\n$ ls\ndir rsdnfh\n$ cd rsdnfh\n$ ls\n276060 dngdnvv.qdf\n137576 zsznp.ccq\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd lbm\n$ ls\n201564 pffdg.rpv\n$ cd ..\n$ cd nflgvsgz\n$ ls\ndir jbc\ndir svmmm\ndir zfjdnbs\n$ cd jbc\n$ ls\ndir jbc\ndir mzt\ndir qzth\ndir scwdmwj\n$ cd jbc\n$ ls\n71570 hhdt\ndir ldzjsrm\n27263 qtqpw.tcg\n$ cd ldzjsrm\n$ ls\n217073 mlmwjq\n172121 nflgvsgz\n39275 pzrrlgt\n$ cd ..\n$ cd ..\n$ cd mzt\n$ ls\n130917 tzrz.hms\n$ cd ..\n$ cd qzth\n$ ls\n280896 dngdnvv.qdf\n6736 jbc.mtm\ndir nfsbdfv\n293220 nvzjz\ndir pffdg\n88075 ppmr\n$ cd nfsbdfv\n$ ls\n58157 bzmwfgf.wwp\ndir gmhbnffd\n65369 gmq.zvb\ndir htczftcn\ndir qmc\n278485 tvs.csj\n$ cd gmhbnffd\n$ ls\n195493 lbcgmm\n264234 mvqbqprp\n268782 rtqts.zls\n$ cd ..\n$ cd htczftcn\n$ ls\ndir lnhjgl\n$ cd lnhjgl\n$ ls\n80056 ffsrvl\n$ cd ..\n$ cd ..\n$ cd qmc\n$ ls\n29571 hqftnv.vwn\n$ cd ..\n$ cd ..\n$ cd pffdg\n$ ls\ndir bfdmm\n244334 ppf\ndir rggmf\n$ cd bfdmm\n$ ls\n296551 nflgvsgz.bch\n77180 tzrz.hms\n$ cd ..\n$ cd rggmf\n$ ls\n187569 dngdnvv.qdf\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd scwdmwj\n$ ls\ndir fhwnjp\n191201 gztswt.cvn\ndir jsbdjv\ndir nflgvsgz\ndir pffdg\n55401 qtqpw.hfv\n$ cd fhwnjp\n$ ls\n200583 tqrqsmwt\n$ cd ..\n$ cd jsbdjv\n$ ls\n46882 fgjhsb.szs\n156238 qtqpw.ctw\n$ cd ..\n$ cd nflgvsgz\n$ ls\n216012 nrfchlbs.wlw\n75316 qtqpw\n218733 vzldr\n$ cd ..\n$ cd pffdg\n$ ls\n75020 htczftcn.trw\n6370 snnvrrwb.qmm\n281520 vwstfbzg.jgq\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd svmmm\n$ ls\ndir bgh\n22016 czchmpc\n294397 dngdnvv.qdf\n14175 gdhtprt\ndir nclpsp\ndir pffdg\ndir qtqpw\ndir rwhq\n138882 smqdrdjs\n174171 vqjztp.zlr\n$ cd bgh\n$ ls\n172183 fhsfhhjn\n209572 phpdrzm\n$ cd ..\n$ cd nclpsp\n$ ls\n41222 bzmwfgf.wwp\n134164 dqbqvg\ndir dqtgwjn\ndir htczftcn\n210868 htczftcn.cjp\ndir jbc\n185752 lfrdq.wrm\ndir pwvbnc\ndir qhrtrsvm\n235340 rljlr.lfs\n$ cd dqtgwjn\n$ ls\ndir lbft\n118196 tpl.qgw\n83985 wbjmdmjm\n$ cd lbft\n$ ls\n187172 vrd\n$ cd ..\n$ cd ..\n$ cd htczftcn\n$ ls\n210604 hzlf\n154916 nflgvsgz\n115688 pffdg.ptz\n$ cd ..\n$ cd jbc\n$ ls\n122033 bzmwfgf.wwp\n105912 dngdnvv.qdf\n16049 nflgvsgz\n43497 slmwmtfn\n69357 tcsc.fgf\n$ cd ..\n$ cd pwvbnc\n$ ls\n10200 pfvsnqp.fwr\n$ cd ..\n$ cd qhrtrsvm\n$ ls\n193675 djmhdr.vcc\n108939 qtqpw\n$ cd ..\n$ cd ..\n$ cd pffdg\n$ ls\ndir dbtmdvq\n$ cd dbtmdvq\n$ ls\n127568 vhnqsm.ghq\n$ cd ..\n$ cd ..\n$ cd qtqpw\n$ ls\ndir crpzfdn\n$ cd crpzfdn\n$ ls\n135177 lpzrl.qvj\ndir qtldnjtd\n$ cd qtldnjtd\n$ ls\n88481 rlbzbjt.rrz\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd rwhq\n$ ls\n87944 bzmwfgf.wwp\n70798 dngdnvv.qdf\ndir hgqbmgch\ndir lrvncpvz\ndir nflgvsgz\n$ cd hgqbmgch\n$ ls\n293841 bzmwfgf.wwp\n286937 lwpf\ndir smfbjhw\ndir smqh\n103844 vmpqmzf.dnf\n$ cd smfbjhw\n$ ls\n186167 crgrnf.dns\ndir htczftcn\n$ cd htczftcn\n$ ls\n11324 gssn.rlt\n46905 tzrz.hms\n$ cd ..\n$ cd ..\n$ cd smqh\n$ ls\ndir pffdg\ndir zbg\n$ cd pffdg\n$ ls\n3570 bzmwfgf.wwp\n3335 fvpd.bct\n$ cd ..\n$ cd zbg\n$ ls\n108877 bzmwfgf.wwp\n310302 drhsdtcv.rrw\n152250 wfvvsg\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd lrvncpvz\n$ ls\n206419 nflgvsgz.tvr\n$ cd ..\n$ cd nflgvsgz\n$ ls\n286461 tzrz.hms\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd zfjdnbs\n$ ls\ndir htczftcn\ndir nflgvsgz\ndir scvzpf\n$ cd htczftcn\n$ ls\ndir jznspqtr\ndir tpz\n$ cd jznspqtr\n$ ls\n86738 hqftnv.vwn\n$ cd ..\n$ cd tpz\n$ ls\n126506 nflgvsgz.qnh\n$ cd ..\n$ cd ..\n$ cd nflgvsgz\n$ ls\n248446 gwjgdb.vrr\n$ cd ..\n$ cd scvzpf\n$ ls\ndir fpbbjmjf\n173634 gbpql\n141796 jzncpqb.pgc\n69394 rpvnchs\n65500 tzrz.hms\n$ cd fpbbjmjf\n$ ls\n224020 hhrjc\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd pffdg\n$ ls\n101444 clwdmcz.thc\n58211 dngdnvv.qdf\ndir mnj\ndir ncwh\n153413 nflgvsgz\ndir qtqpw\n141829 rrfs.ffn\n$ cd mnj\n$ ls\n298654 qtqpw\n$ cd ..\n$ cd ncwh\n$ ls\n133042 bmthlszz.mtr\ndir nflgvsgz\ndir nrsqtdz\n201720 wqhnfz\n$ cd nflgvsgz\n$ ls\ndir bqqmlffw\n115991 hsljpqpf\ndir htczftcn\n$ cd bqqmlffw\n$ ls\n49001 wltpcszs.bvj\n$ cd ..\n$ cd htczftcn\n$ ls\n264620 sfdssh.dnj\n260432 vgvzjl\n$ cd ..\n$ cd ..\n$ cd nrsqtdz\n$ ls\n258978 htczftcn\ndir jbc\ndir nsqlmlqp\n28767 pffdg.blw\n172773 tzrz.hms\n$ cd jbc\n$ ls\ndir ztphfs\n$ cd ztphfs\n$ ls\ndir gpps\n$ cd gpps\n$ ls\n74744 bzmwfgf.wwp\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd nsqlmlqp\n$ ls\ndir zvwvdzlv\n$ cd zvwvdzlv\n$ ls\n218727 hsjm.qgm\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd qtqpw\n$ ls\n171370 sdmhwctq.gzr\n$ cd ..\n$ cd ..\n$ cd qtqpw\n$ ls\ndir csqvzqdc\n131580 jbc.ppb\n126635 jbc.sbm\n302398 pbjd\n74429 vnpj\ndir zhmp\n$ cd csqvzqdc\n$ ls\n150923 jbc.grw\ndir lthhrqnn\n240950 pffdg.qbt\ndir rgzqq\n$ cd lthhrqnn\n$ ls\n123194 czl\n17546 pffdg\n$ cd ..\n$ cd rgzqq\n$ ls\n156566 jbc.hpw\n$ cd ..\n$ cd ..\n$ cd zhmp\n$ ls\n291659 dngdnvv.qdf\n309738 nflgvsgz.wmc\n$ cd ..\n$ cd ..\n$ cd rcnwghg\n$ ls\n108285 hvhlggsn\n308801 sgstjfqq.hln\n$ cd ..\n$ cd sglgqlp\n$ ls\ndir gnvnlrz\ndir nchq\ndir nlrbnwp\ndir zpg\n$ cd gnvnlrz\n$ ls\n62071 lgqrm\ndir pvt\ndir srdqwtcs\n$ cd pvt\n$ ls\ndir fpfddfw\ndir jbc\ndir jzrb\n$ cd fpfddfw\n$ ls\n257231 rgccj.dwc\n$ cd ..\n$ cd jbc\n$ ls\n118252 dsvsmgm.hdm\n$ cd ..\n$ cd jzrb\n$ ls\n157243 gcrfg.svt\n86860 pblts.jtd\n$ cd ..\n$ cd ..\n$ cd srdqwtcs\n$ ls\n267482 bzzghfpq.gmh\ndir cbd\ndir gwqzndrt\n288249 hhdmlslr\n286213 lwmhd\ndir rfvmgch\n121131 vbm.rbp\n$ cd cbd\n$ ls\n238535 jpbzwvd.rrw\n246606 wgl.gfg\n$ cd ..\n$ cd gwqzndrt\n$ ls\ndir twtpbh\n262912 vcmv.qcs\n$ cd twtpbh\n$ ls\n245819 dngdnvv.qdf\n295823 ghrnmd\n308384 pffdg.ptr\n231669 sqhnt.grn\n$ cd ..\n$ cd ..\n$ cd rfvmgch\n$ ls\n306719 cwr.jsm\n6449 hqftnv.vwn\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd nchq\n$ ls\n137003 qtqpw\n267253 zrgvq\n146047 zww.nrr\n$ cd ..\n$ cd nlrbnwp\n$ ls\n91151 tzrz.hms\n$ cd ..\n$ cd zpg\n$ ls\n68248 bzmwfgf.wwp\n$ cd ..\n$ cd ..\n$ cd wrfmf\n$ ls\ndir cdlwfjhp\n16673 dsctg\n304187 jbc\ndir lchrdvm\ndir nflgvsgz\ndir qtqpw\ndir rgdc\n306410 tzrz.hms\ndir zqzzg\n$ cd cdlwfjhp\n$ ls\ndir clshzcrc\ndir lplgpg\n$ cd clshzcrc\n$ ls\n191491 tzrz.hms\n$ cd ..\n$ cd lplgpg\n$ ls\n169864 cmhrmh.pjp\n$ cd ..\n$ cd ..\n$ cd lchrdvm\n$ ls\n149068 chwbr.spd\n250029 hqftnv.vwn\n23399 jbc\n69746 nflgvsgz.nmp\ndir pldctfcf\ndir vngv\n251416 zhf.qtz\n$ cd pldctfcf\n$ ls\n297722 bcpwcn\n276738 cspls\ndir gghvnc\n80690 htczftcn\ndir pffdg\n97610 qfjs.gps\ndir tvc\n106070 tzrz.hms\n$ cd gghvnc\n$ ls\n93770 dngdnvv.qdf\n$ cd ..\n$ cd pffdg\n$ ls\n180916 bzmwfgf.wwp\n$ cd ..\n$ cd tvc\n$ ls\n11724 gtgzwsq\n$ cd ..\n$ cd ..\n$ cd vngv\n$ ls\n92840 qtqpw.gcl\n$ cd ..\n$ cd ..\n$ cd nflgvsgz\n$ ls\ndir htczftcn\ndir lcjqzrwm\n54961 lfn.rmz\ndir plvbmb\ndir vdfwfg\n$ cd htczftcn\n$ ls\ndir gflz\ndir mpp\n292374 rzm\n$ cd gflz\n$ ls\ndir qpdn\n$ cd qpdn\n$ ls\n258037 ddqb.jhd\n$ cd ..\n$ cd ..\n$ cd mpp\n$ ls\n248628 pffdg.spt\n$ cd ..\n$ cd ..\n$ cd lcjqzrwm\n$ ls\n249155 mbz.gsq\n291857 nngm.nft\n100136 zwvwlg.hrs\n$ cd ..\n$ cd plvbmb\n$ ls\ndir nnrnwp\n163552 pffdg\n$ cd nnrnwp\n$ ls\n289041 bzmwfgf.wwp\n29165 nvcwzfpr\n$ cd ..\n$ cd ..\n$ cd vdfwfg\n$ ls\n264391 hqftnv.vwn\n309071 htczftcn.mrd\ndir wtqrrvvr\n$ cd wtqrrvvr\n$ ls\n230331 swhpd\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd qtqpw\n$ ls\n292434 hbjlsrw\n$ cd ..\n$ cd rgdc\n$ ls\ndir hqldlpg\n$ cd hqldlpg\n$ ls\n188809 rvjwsmnz.hqt\n$ cd ..\n$ cd ..\n$ cd zqzzg\n$ ls\n250923 qtqpw.zrb\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd qcqg\n$ ls\n309875 tzrz.hms\n$ cd ..\n$ cd qtqpw\n$ ls\ndir rcnp\n$ cd rcnp\n$ ls\n131725 bzmwfgf.wwp\n46663 chwfd\n$ cd ..\n$ cd ..\n$ cd qzcdscbp\n$ ls\ndir mtqt\n$ cd mtqt\n$ ls\n27367 llbt.pth\ndir mcrddwgp\n$ cd mcrddwgp\n$ ls\n77221 bzmwfgf.wwp\n37941 lrwlhz\ndir tcmrv\n85568 tzrz.hms\n$ cd tcmrv\n$ ls\ndir hprvr\n$ cd hprvr\n$ ls\n59831 qbchdjw.gjg\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd rfgvg\n$ ls\ndir qlg\n$ cd qlg\n$ ls\n142825 dngdnvv.qdf\n$ cd ..\n$ cd ..\n$ cd rzb\n$ ls\n250575 dngdnvv.qdf\ndir jbc\ndir lbg\n187509 plblzt.zzz\ndir qwjlvqdp\n237529 rrrqcl.pvt\ndir rsjg\n$ cd jbc\n$ ls\n253304 lpdndfn\n$ cd ..\n$ cd lbg\n$ ls\ndir fml\n$ cd fml\n$ ls\n106624 shm.fgh\n$ cd ..\n$ cd ..\n$ cd qwjlvqdp\n$ ls\ndir htczftcn\n$ cd htczftcn\n$ ls\ndir gnnzlzwd\n272143 jbc.ldg\ndir sztdtpjt\n$ cd gnnzlzwd\n$ ls\n218355 tzrz.hms\n$ cd ..\n$ cd sztdtpjt\n$ ls\n53466 tzrz.hms\n$ cd ..\n$ cd ..\n$ cd ..\n$ cd rsjg\n$ ls\n101889 cct.sfg\n"
  },
  {
    "path": "advent-of-code/2022/inputs/08",
    "content": "101000101302332302213011003243304222032110202245353522155334033122313210221230000001220130100022122\n122210210320302310331324310141124041443541534154545244332222431041103123300231344112333231232020100\n011020221031210311014411033201443431122251335521121521353321531213122340222303023121303012232120211\n000012230303012110404302322434112535321314325133151343154523152113352323222121143131230230300010211\n000101020102331320324033211434345545252433432135545542415124544553222514400213440042311303011013001\n202001312100200021421012223142431211335331532444233515224153311522222555314232210423334003210102220\n011131032221232202214203134355134325534535155321321531342523311414524444121034331120010122133121002\n012103011013234340220133253444344345551421425245564632231421413155444352235322124240443423130033133\n023022222331211330242121333322511343331564456422534434233336641233441411225132333403444004323031130\n122001122320002403311244123154323212364525225546632523326222646644534552432225114212121041202201101\n201302222421043202412532245351442246452432423633626243642533322462435241134121531144434002132010000\n122213111044103234351235511134413234563453322444242566263522522644342234232253155254301234110300021\n113313344244423401511525531451323665263352262243423362556353564226362361322533445233424434111012012\n323302332240441412134135252445553645636653465334245666253662345645324254224333254123311012030133130\n332120111102141423234341243443234252334456556562545633354222256464632536622143552122541234130423323\n122224242212403144121523166423356623443663733433635436675735253523644354643342421314522214442040123\n130344143331342212242115255554543656334463733356637544676553543434653253623265551525411402131040421\n111003030342123123511252646254623535534357466353375646547564673536553255646533231452351410404020013\n332124444335243313522222325635244436373363367347547657365464656355466356464545443334344153423341012\n232342033111333231112656656265266357433564755537367665764637367764355253532366254114254324201100404\n101233233343414344126532556226436647555645667376455456566557763767647635362565344622322534502310312\n234111202233233215562262624436676643737337566473664453776457667475754435533226344322323423442342100\n402232031433442312344526624557553755447353367466446577646665446357633777326623652432513252124004232\n212231104214255124434243353647647447747775775475564685467674776466656644576645454532511251542330044\n330321113544342342426252636573364357677754446645866464745647666457667355744545264522332325451130321\n222411133521223236526546377433545377875565668665875675445864767573357464763354424234622534554143223\n142220224123433353553534675777475684577445474444865557477778878786435663546733536644336533253210444\n234303342221216325225647673565373587477777868464685648447578886544463547554576225446223235252550331\n400113133345165253462253446365744855777875886776767567754874477477474565777333744664664551142214124\n412132413313346333333555557454655547587847767896975957685547645564677763453677666366442342332232122\n334033315545442636426445433765664666566478697675657685577868857488675767536433674224636523553151431\n324335552413266326423347463568467745578777576776975669795799554567464666367654473542325262221441101\n131511125256525526575766676354478786689579886969969766585778679485865565765376657344353536125153151\n244524422253656346455634754665787648778667596778789965999786796565866745454753567443526323341424544\n211132342564425664553757656668566547577957579778997556765667698865476847475563663373462554343345314\n113141312266236453646536658484648878886895867677578576855575899996648686874734543472262346612411225\n431125132236423453574474786578758875686695678776896989668789687975947747448445663477565546314151414\n402551145566253546577566556767555768898865976676679779987865977786756486586544653544344365623144521\n351214235565362646577336454557746895975887896697996767766878996959979558677463654563456353553235351\n122455323664634254446376786844865576755676688896987688886888786957558784675485475744734434541123152\n112255425232642335473748564488859768857777688879799876677866659587557857757676576435634662452134342\n455522444545426534753674548867768687755997866776777898776877795885986544844677753434655623564212345\n412155113623434466447774757776859997987899767989667679699996798679877666567544533665746223252315114\n453332352265242676763377447478765586959766867978979778796767886576986584766747353364676266364245535\n151313336624645447656645455475896896867678697897788997767687866859866655578744537376442664636152223\n455243453435463635337684757445755596698989687799788989986786699797775556586655575653353265554241131\n251415166645666563375376748859997866687967868797978889987998679758798569865756775546344344554312124\n331433134422534365636487656449699586969998668879897987878866676876786989484485864476366325223244142\n132213365423424647776468664875878887697667999777799999878688966768769697755484845766657556635534231\n442522446624224775544665486745678975989677887777989879987899876967997869745484464775476226634414441\n414243454243325747553386586456565559666796897787798878877798976968696887568644467363665645654234342\n215142336343427766345557875578557579699966878799879877798979788987865568455575637643634465625633514\n444521352456524367445584475449688677868789867989777898788779999778897868868864555755544265525241213\n343543163545642554464368767749999765868779787787777877798686666796668788574458637363772366342655525\n341551255466346443643474885467855956677968987898897998798799766789865977556474773777434225343324211\n251123114442354577537368486476558966978789689879787987987678869955568989544465534546734456625112225\n142232534343445746343588765654798855667798978799977888869787696878585778876688643366444565625121131\n311521132563323444745365788677775659598666966787888977889678977759678568746674466335353644435243313\n345412452526465744655568445844688575598969989969889868677699797895799996847586645734753242322441323\n445215142456262354554345445558465597557969867789867867976887979786657576884756676435763335635533122\n444513115342463476355578485576766696688698976689876999966667668996957648447678733463742632553444325\n435555323544423276337437788874665776967796769769676979786987556678595545788564435557456444325233523\n222113511456444244557563476655458686865689666797979989867989658855669574474554336653455456354211121\n315144115556526323767633347588465755769768687968988689996565855887665755648467656776264455322421211\n111332432346444643653743668478845495996777588978799876866697958688946447765557735447666544224153424\n111222244546622353567456366475487446866576799967576859876798989699857548685447663535243336355221325\n223141152542346522576653337565445575768888879786785875899988865987686846876447635576334244515325230\n443322255116456436444377473448654875565887887677885788577796795848468644487447457355523453315211414\n130352124432526245245373467387668847788589695578599869797998978476788754675633774542534423122125242\n334433234534245442367347557564758856564657667677775865656999947474888685776636767445356541551214420\n123124441342636465633633636643567578564865665876975796565965478645468583743436454544523645441113323\n242225422212252456342556737767366667445574888895855965667456845645567874653456675652263612411321330\n110323431333344346242375635633757857778767677445467568468478768776548455535745634226323614531252123\n241142353413552266662225545476534578655856577486484854456447575686474664464757236365246132521542433\n421424323241433233253346776474445566747875748674565775684785456758576776345732334353455412441153141\n010122052414252642656355634756334733656886485474774657557568886554553636454662236335251454214322311\n231112232134413163642365663666654774637684654564855676688477585537434654355636322624345154324544044\n104341445335335525545465224746557546355577764777687567587584763455643366572233664462225221454324214\n202233445441355333555534254446354373543735737858476867667436544435455347623553643353521112454200434\n201321322145223422364346626365663554776746563367656544365357436765366345255436466663141522354332340\n114131034015542352554665526643636655756663737333333655547647533374366345355445546241521354443321244\n304010331133454511122264453343667667753744575554547377645777633436537233566662356531144312112302002\n331022344323342414454432543663463456557657355357556654673444477465425323556623461442221334243421322\n221111410243535512112125336342542555757357463734577556766753754335344364256433325151425553440311021\n303102431041251352533313622645444353263444446445673366655667756625524226323632231111132511122414221\n000231442030315552522221354356554426543653573343647777477652663343536536344454334544555431204210013\n303332131303211152155545523665255343623566653552575333542362645333624335354422123323113100410430232\n012313114410102214155512513453365254625625263323426343526365646353444535342225342142222201204212111\n123112140043004303153112233343562466536223225466423264666465544336564361241322454534403213222132320\n002123324244424104214133514125254522563336645445243436453622555362253154331412543153043133210311001\n111322131223421221241354554411542266265635332643365333232652434365645345323233444421034211131232130\n101202110344332102242331441251235443162522453233265235364246362222155155145313352043204304432021120\n201201023022424401040425555531112132215522664564236643322224622422131412223244514224042220223102112\n123333110113212031214024411121114232312333521434626453641234214533431514242423433431313213223000201\n220130301112144042132412415353433515153111224124321423445525211134534555335010210434111012300120121\n001030102113333002130222433032352335142323423512223143325222125433324311332130022212443221220222322\n000201122000001012423133100004411541433323341344154214212435543542121422002123313144202022122100012\n012111322300213034030131330142125211254543321454454243442412331255315002103332314442011003113122000\n001202021022233123031004403230031341512221513345352553531452554321113401010231031311031210320110120\n"
  },
  {
    "path": "advent-of-code/2022/inputs/09",
    "content": "R 1\nU 1\nD 1\nU 1\nR 2\nD 2\nR 2\nD 2\nR 1\nU 1\nL 1\nU 2\nD 2\nR 1\nD 1\nR 2\nU 2\nR 2\nL 2\nD 2\nL 2\nU 2\nD 2\nL 2\nR 2\nD 1\nU 2\nD 2\nU 1\nL 2\nD 2\nR 1\nU 2\nD 2\nL 1\nD 2\nL 2\nR 2\nU 2\nD 2\nU 1\nR 1\nU 1\nD 1\nR 2\nL 2\nD 1\nU 1\nR 1\nL 1\nU 1\nD 1\nL 1\nU 1\nD 1\nU 2\nD 2\nU 1\nD 1\nU 1\nL 1\nR 2\nL 1\nD 1\nU 1\nR 1\nL 2\nU 2\nL 2\nU 2\nD 1\nR 2\nD 2\nL 2\nR 1\nU 2\nR 1\nD 2\nL 1\nD 1\nL 1\nD 2\nR 1\nU 1\nL 1\nU 2\nD 2\nL 1\nU 2\nD 2\nR 1\nU 1\nR 1\nL 2\nD 1\nL 2\nU 2\nL 2\nD 2\nL 2\nD 2\nU 1\nL 1\nU 2\nR 1\nD 1\nR 1\nD 1\nR 1\nD 2\nU 1\nR 1\nU 1\nR 1\nD 1\nU 3\nL 2\nR 2\nL 3\nR 1\nL 1\nU 2\nL 1\nU 3\nD 3\nL 3\nD 2\nL 3\nU 1\nL 1\nR 2\nD 3\nL 1\nR 1\nU 2\nL 2\nD 3\nU 2\nD 3\nR 3\nU 1\nD 3\nL 3\nR 2\nU 3\nD 1\nU 1\nR 1\nL 2\nR 1\nL 2\nD 3\nL 1\nD 3\nR 2\nU 1\nD 1\nR 3\nD 1\nL 1\nU 2\nD 1\nL 3\nU 3\nR 1\nD 1\nU 3\nD 2\nL 3\nR 2\nL 1\nD 2\nU 1\nR 2\nL 1\nU 2\nR 2\nL 2\nU 2\nL 2\nU 2\nR 1\nU 2\nD 3\nU 1\nD 1\nL 2\nU 1\nL 2\nR 3\nL 2\nR 3\nL 1\nR 2\nL 2\nR 1\nD 3\nL 3\nD 2\nR 1\nD 1\nU 1\nD 2\nR 3\nU 3\nD 3\nR 3\nL 1\nU 1\nR 3\nU 2\nL 1\nR 1\nL 3\nD 3\nR 2\nU 1\nL 2\nD 2\nR 1\nU 3\nD 2\nR 1\nL 4\nD 3\nR 3\nL 1\nD 1\nR 3\nU 3\nL 2\nD 4\nU 3\nD 2\nL 4\nD 2\nR 1\nD 3\nR 3\nD 1\nU 4\nR 1\nU 4\nD 2\nU 4\nL 1\nR 1\nL 2\nR 1\nD 1\nL 4\nU 1\nR 4\nD 3\nR 1\nU 3\nR 3\nU 2\nL 3\nU 2\nL 2\nR 4\nU 2\nD 3\nR 4\nD 1\nU 4\nD 3\nR 2\nD 3\nR 1\nD 1\nU 1\nR 3\nL 1\nU 3\nL 1\nD 3\nL 3\nD 3\nR 3\nD 3\nU 1\nR 4\nD 2\nR 2\nU 1\nR 1\nD 1\nL 4\nD 2\nL 1\nU 4\nD 1\nL 2\nU 4\nD 3\nU 3\nL 2\nR 2\nD 1\nL 4\nD 2\nR 3\nD 4\nR 4\nU 1\nD 1\nL 2\nR 1\nD 4\nR 2\nL 1\nD 4\nL 3\nR 3\nU 4\nR 3\nD 3\nL 2\nR 1\nD 3\nL 2\nR 3\nD 1\nL 2\nU 3\nR 4\nD 4\nU 3\nR 2\nD 3\nR 3\nD 1\nR 4\nU 3\nR 5\nU 1\nD 2\nR 5\nU 1\nR 3\nL 1\nU 1\nL 1\nD 1\nR 5\nU 2\nD 3\nR 4\nL 5\nR 2\nD 1\nL 2\nU 2\nD 3\nR 5\nD 2\nR 5\nD 5\nU 5\nD 1\nL 5\nU 3\nD 2\nR 1\nD 5\nR 2\nD 2\nR 5\nU 3\nL 2\nU 1\nL 4\nR 5\nL 3\nR 2\nU 2\nD 3\nL 1\nU 3\nL 4\nR 5\nL 1\nU 4\nL 1\nD 5\nR 3\nU 5\nR 3\nL 2\nU 4\nD 2\nU 4\nL 1\nU 1\nL 1\nR 4\nD 4\nU 4\nR 5\nD 2\nU 2\nL 3\nU 4\nD 3\nL 2\nR 4\nU 1\nL 3\nR 3\nD 1\nL 2\nR 5\nU 2\nL 2\nR 2\nL 4\nD 4\nL 2\nU 4\nR 2\nL 3\nU 4\nL 5\nD 5\nL 5\nU 3\nL 5\nR 2\nD 4\nL 5\nU 3\nD 2\nL 2\nD 2\nU 2\nD 4\nR 5\nU 5\nL 3\nR 5\nD 3\nL 1\nD 1\nL 1\nD 5\nR 2\nL 1\nU 2\nL 3\nU 2\nR 2\nL 5\nR 3\nU 2\nR 1\nL 4\nD 4\nU 3\nR 2\nL 2\nD 3\nL 2\nR 4\nL 1\nU 6\nR 2\nD 5\nL 4\nU 3\nR 6\nD 6\nL 4\nD 3\nR 2\nD 2\nL 2\nR 2\nD 4\nL 6\nD 3\nL 5\nR 4\nL 5\nU 3\nL 6\nU 5\nL 3\nR 2\nU 3\nL 1\nD 1\nL 3\nU 4\nL 5\nD 3\nL 2\nU 5\nD 4\nL 3\nR 1\nU 3\nD 4\nU 3\nD 3\nU 6\nD 4\nR 3\nU 6\nR 1\nU 3\nR 3\nU 3\nR 5\nU 6\nL 1\nR 2\nD 5\nU 3\nD 4\nU 4\nD 4\nL 1\nU 4\nD 3\nL 1\nU 5\nR 3\nU 3\nR 1\nU 1\nL 3\nR 3\nU 4\nR 1\nL 3\nU 2\nL 2\nD 2\nL 4\nU 4\nL 3\nU 4\nR 2\nU 1\nD 2\nU 2\nD 5\nL 5\nR 1\nD 3\nL 4\nR 3\nD 6\nU 7\nD 5\nL 7\nD 5\nU 3\nD 1\nL 2\nR 2\nD 7\nU 7\nD 3\nL 2\nU 1\nL 6\nD 5\nR 4\nU 3\nR 5\nU 6\nL 6\nU 6\nL 1\nR 5\nU 7\nR 5\nU 5\nR 4\nU 5\nD 6\nR 4\nD 7\nL 7\nU 5\nR 2\nU 7\nR 3\nD 5\nR 5\nD 4\nU 1\nL 6\nR 4\nD 6\nL 6\nR 2\nU 7\nL 3\nD 5\nL 4\nR 3\nL 1\nU 3\nD 3\nR 5\nU 1\nL 6\nU 7\nR 7\nD 4\nL 4\nU 6\nR 7\nU 4\nR 1\nL 1\nR 4\nU 7\nD 1\nU 5\nD 3\nR 7\nL 1\nD 4\nU 6\nD 2\nL 3\nU 1\nD 6\nL 1\nD 5\nR 3\nU 3\nL 6\nD 5\nR 4\nU 5\nL 4\nR 4\nU 7\nR 1\nL 7\nU 2\nR 4\nL 1\nD 5\nU 4\nL 6\nD 2\nR 3\nL 2\nD 5\nR 5\nU 7\nR 4\nD 7\nU 6\nR 6\nL 6\nR 6\nU 1\nD 1\nR 3\nD 2\nU 3\nR 3\nD 8\nU 1\nR 5\nL 8\nD 8\nL 7\nD 3\nU 6\nR 6\nU 8\nD 3\nU 2\nR 2\nD 7\nU 8\nD 5\nL 2\nR 8\nU 3\nL 2\nR 5\nU 3\nR 6\nL 8\nU 8\nR 8\nL 2\nU 1\nD 1\nU 4\nL 1\nU 2\nL 4\nD 2\nU 4\nD 3\nL 8\nD 3\nR 3\nL 2\nD 7\nL 5\nR 5\nL 3\nR 4\nL 7\nD 6\nU 3\nL 3\nD 4\nR 4\nL 3\nD 5\nU 2\nR 4\nU 6\nL 7\nD 2\nR 6\nL 3\nD 8\nL 8\nR 2\nU 7\nD 7\nU 3\nR 7\nU 8\nL 5\nD 6\nR 6\nU 8\nR 1\nU 3\nR 5\nL 4\nD 7\nU 6\nR 8\nL 2\nR 6\nU 1\nL 4\nD 1\nL 2\nU 4\nR 2\nU 4\nR 5\nL 3\nR 1\nL 4\nR 7\nD 7\nR 1\nU 5\nL 6\nD 4\nR 4\nD 5\nU 8\nL 3\nD 8\nL 6\nU 5\nD 1\nR 7\nL 2\nD 1\nR 7\nL 5\nD 8\nU 6\nD 1\nL 8\nU 8\nL 1\nR 1\nU 2\nD 9\nL 5\nD 9\nL 4\nU 8\nD 3\nR 6\nL 1\nR 8\nD 7\nL 6\nU 7\nR 6\nU 2\nL 3\nD 6\nL 5\nU 3\nR 1\nU 6\nD 1\nU 2\nL 9\nR 2\nL 2\nR 9\nD 1\nR 2\nU 7\nD 7\nU 5\nR 4\nU 9\nL 5\nU 9\nD 5\nL 1\nR 3\nL 1\nU 1\nD 7\nL 8\nD 2\nL 7\nD 1\nL 6\nR 2\nD 1\nU 9\nD 4\nU 8\nL 8\nU 1\nL 8\nD 6\nU 1\nR 2\nU 3\nR 4\nD 4\nU 4\nL 9\nD 5\nL 2\nU 6\nD 8\nU 6\nR 1\nL 6\nD 5\nR 3\nL 4\nR 6\nL 5\nR 4\nL 6\nD 5\nR 8\nD 6\nL 1\nU 8\nR 8\nU 8\nR 3\nU 2\nD 9\nL 9\nU 3\nD 5\nL 2\nD 2\nR 3\nL 2\nD 8\nR 6\nD 9\nR 5\nL 9\nR 2\nL 9\nU 5\nR 9\nD 3\nR 1\nU 1\nL 6\nR 7\nD 7\nU 3\nR 2\nL 5\nD 2\nL 8\nU 8\nR 9\nU 5\nR 1\nU 9\nD 8\nR 10\nU 9\nD 5\nR 4\nD 8\nU 4\nL 7\nU 10\nL 8\nR 10\nL 9\nD 9\nL 4\nR 7\nU 4\nD 3\nU 10\nR 6\nD 9\nL 5\nR 3\nD 7\nR 9\nD 4\nL 9\nD 3\nR 7\nU 6\nL 6\nR 6\nL 7\nD 8\nL 7\nU 5\nD 8\nL 8\nU 9\nL 5\nD 9\nU 9\nR 3\nD 1\nU 9\nL 9\nU 6\nR 4\nU 6\nD 10\nU 4\nR 9\nD 9\nR 2\nD 10\nL 9\nU 8\nL 2\nD 7\nL 10\nR 2\nL 9\nR 9\nL 10\nU 6\nD 7\nR 1\nD 9\nR 5\nL 7\nD 4\nU 7\nL 3\nD 3\nR 4\nL 8\nU 1\nL 1\nD 10\nU 2\nD 9\nL 2\nD 8\nU 2\nD 3\nR 6\nU 3\nR 5\nU 4\nL 6\nR 10\nL 1\nD 2\nL 3\nU 11\nR 5\nU 11\nD 11\nU 10\nD 2\nL 10\nU 8\nR 4\nD 11\nU 11\nR 11\nU 5\nD 3\nR 7\nD 9\nU 9\nR 5\nU 8\nD 7\nU 9\nD 2\nU 11\nL 7\nD 1\nR 9\nD 2\nR 5\nU 4\nR 11\nD 1\nL 2\nR 1\nU 5\nD 4\nL 10\nR 11\nU 6\nL 3\nU 11\nR 1\nD 1\nL 2\nU 5\nR 6\nU 9\nR 11\nD 9\nL 11\nU 6\nR 5\nL 7\nD 6\nU 9\nD 5\nU 6\nR 10\nD 11\nR 4\nU 7\nL 5\nU 7\nL 2\nR 6\nL 10\nD 3\nR 6\nL 9\nD 8\nL 1\nR 1\nL 1\nR 3\nD 8\nL 10\nD 2\nU 1\nD 1\nL 3\nR 10\nL 3\nU 1\nD 2\nU 2\nD 3\nU 1\nR 8\nU 8\nD 10\nU 6\nL 5\nU 6\nD 4\nR 9\nD 9\nR 9\nD 11\nL 3\nD 7\nR 9\nL 7\nU 7\nD 7\nR 4\nL 3\nR 5\nU 3\nL 9\nD 10\nL 1\nR 9\nL 6\nD 5\nL 6\nD 4\nU 7\nL 8\nR 7\nL 5\nU 9\nR 1\nL 1\nD 12\nR 5\nU 1\nL 8\nD 11\nU 5\nD 5\nR 4\nD 10\nR 2\nU 6\nD 2\nL 12\nD 1\nR 10\nU 4\nD 8\nL 7\nD 9\nR 7\nD 1\nR 10\nD 5\nU 7\nD 12\nR 9\nU 2\nD 3\nU 5\nD 2\nU 6\nD 3\nU 7\nD 4\nR 11\nD 2\nL 3\nR 9\nL 2\nR 12\nL 3\nD 5\nU 7\nD 6\nR 9\nD 12\nR 11\nD 5\nU 5\nD 2\nR 1\nU 6\nR 6\nD 5\nL 9\nU 10\nD 4\nU 1\nR 3\nD 10\nU 1\nR 9\nD 8\nL 1\nD 12\nU 11\nD 12\nL 2\nR 9\nU 12\nD 6\nL 1\nR 4\nL 8\nD 8\nL 6\nR 10\nL 8\nD 4\nU 11\nL 1\nR 5\nL 6\nR 10\nD 12\nR 3\nL 9\nD 10\nU 6\nD 9\nR 7\nU 9\nR 10\nU 10\nL 10\nU 1\nL 3\nD 7\nL 12\nU 4\nR 3\nU 1\nL 8\nR 5\nU 4\nL 4\nD 5\nR 4\nD 11\nL 9\nD 5\nL 7\nU 6\nR 8\nU 7\nD 3\nU 1\nL 6\nU 8\nD 2\nR 7\nD 2\nU 1\nL 9\nU 8\nL 10\nU 4\nD 12\nL 12\nD 5\nR 3\nU 1\nD 1\nR 11\nL 10\nR 11\nL 6\nR 3\nL 13\nR 6\nL 4\nR 10\nD 9\nR 13\nU 8\nL 7\nR 7\nL 10\nR 9\nU 4\nL 1\nD 1\nL 12\nD 6\nL 3\nR 4\nU 6\nL 12\nD 2\nU 5\nR 11\nL 2\nU 8\nR 10\nD 2\nU 6\nL 4\nD 2\nU 9\nL 7\nD 5\nL 6\nU 9\nR 6\nL 9\nR 1\nU 3\nL 6\nR 6\nU 8\nD 1\nR 5\nU 12\nD 9\nU 10\nD 13\nL 10\nR 4\nL 13\nR 9\nL 9\nD 6\nU 8\nD 6\nU 8\nD 10\nR 3\nL 11\nR 8\nD 4\nR 2\nU 10\nD 9\nU 8\nR 5\nD 10\nL 11\nR 7\nD 9\nU 7\nL 6\nU 3\nL 5\nU 6\nD 1\nU 3\nR 8\nL 5\nU 3\nR 13\nL 8\nD 1\nU 8\nL 6\nD 11\nU 4\nD 1\nR 9\nD 11\nR 1\nD 2\nR 10\nU 2\nD 12\nU 6\nR 13\nU 6\nD 4\nR 11\nU 6\nR 9\nU 10\nD 3\nR 2\nL 13\nU 14\nD 14\nR 6\nD 9\nU 5\nD 2\nL 5\nR 10\nL 3\nR 8\nD 9\nU 10\nR 11\nU 8\nL 8\nR 12\nD 13\nU 7\nR 14\nD 9\nL 12\nR 13\nL 10\nD 11\nL 7\nU 6\nD 14\nL 14\nD 13\nU 11\nR 11\nU 9\nL 8\nD 2\nL 9\nR 12\nU 5\nD 9\nU 10\nR 1\nL 2\nD 8\nL 8\nR 4\nU 2\nL 13\nR 9\nL 12\nD 7\nL 14\nD 13\nR 12\nD 10\nL 5\nU 12\nR 6\nL 3\nU 14\nR 8\nU 10\nR 5\nU 3\nD 1\nR 6\nU 9\nR 4\nL 9\nU 7\nR 6\nU 8\nR 10\nU 9\nR 9\nU 12\nL 14\nR 2\nU 11\nL 12\nD 5\nR 15\nL 10\nU 8\nR 6\nU 8\nR 6\nD 2\nU 9\nL 15\nD 13\nL 14\nU 1\nD 9\nU 6\nR 8\nL 6\nD 3\nL 13\nR 7\nU 1\nL 8\nU 7\nD 8\nR 1\nD 6\nL 8\nR 14\nD 14\nU 9\nL 14\nR 15\nU 11\nL 14\nD 14\nL 1\nU 5\nL 3\nR 4\nL 13\nR 5\nD 14\nR 4\nU 7\nD 9\nR 4\nU 6\nD 11\nR 12\nD 13\nU 15\nD 10\nR 1\nD 1\nU 10\nL 14\nR 13\nU 6\nD 10\nU 15\nD 3\nU 8\nD 2\nU 15\nR 6\nU 12\nL 9\nR 2\nD 6\nR 15\nD 13\nR 2\nD 5\nR 8\nU 3\nR 10\nD 6\nL 7\nD 6\nR 11\nU 13\nD 1\nL 7\nU 7\nL 4\nU 10\nD 4\nR 10\nU 2\nL 2\nU 4\nR 7\nD 15\nR 15\nD 7\nR 14\nU 3\nD 8\nL 2\nU 11\nD 11\nU 9\nR 5\nL 3\nD 9\nR 12\nL 2\nR 10\nD 6\nR 6\nU 15\nR 10\nD 16\nR 5\nU 14\nR 16\nU 5\nL 10\nR 14\nL 15\nR 13\nL 15\nR 12\nL 9\nD 16\nU 13\nD 16\nR 2\nU 1\nD 15\nL 7\nD 5\nR 9\nU 8\nR 12\nU 3\nD 16\nR 11\nD 1\nU 3\nD 4\nU 10\nL 8\nR 4\nL 8\nR 8\nU 8\nL 9\nD 16\nU 7\nD 6\nR 1\nD 3\nL 15\nU 9\nD 9\nU 1\nL 9\nD 7\nU 14\nR 1\nD 11\nL 16\nU 13\nL 3\nR 12\nL 9\nR 9\nL 9\nU 5\nR 10\nD 14\nL 8\nR 7\nL 12\nR 13\nD 5\nU 10\nR 12\nU 11\nL 7\nR 9\nD 7\nL 11\nD 1\nR 8\nD 7\nU 6\nD 10\nR 13\nL 16\nU 10\nL 5\nR 12\nL 16\nU 6\nD 10\nU 3\nD 7\nU 7\nD 15\nL 2\nR 9\nU 8\nD 11\nL 15\nU 10\nD 10\nL 6\nD 14\nL 5\nU 3\nD 9\nU 2\nD 16\nU 6\nD 3\nR 15\nD 12\nR 9\nL 16\nR 4\nU 9\nL 8\nR 11\nL 14\nD 6\nU 11\nL 6\nR 7\nU 8\nR 7\nU 8\nD 7\nU 6\nL 15\nU 3\nD 6\nU 3\nR 6\nD 3\nL 10\nR 14\nL 17\nD 12\nL 15\nD 5\nR 6\nD 4\nR 6\nD 5\nU 8\nD 10\nR 13\nD 6\nU 3\nL 5\nU 3\nR 11\nD 11\nU 8\nL 5\nU 11\nL 7\nR 16\nL 11\nD 3\nL 16\nD 14\nR 1\nU 10\nL 7\nU 4\nD 11\nL 9\nR 3\nD 1\nL 7\nR 17\nD 17\nR 11\nU 4\nR 15\nL 10\nR 13\nU 17\nD 16\nL 16\nU 14\nD 11\nU 10\nD 12\nL 11\nR 5\nD 17\nU 1\nR 5\nL 14\nD 14\nR 5\nL 6\nR 11\nU 13\nR 10\nU 15\nL 2\nR 8\nD 3\nR 11\nL 8\nR 11\nU 5\nL 12\nU 2\nL 16\nD 5\nL 17\nR 10\nD 15\nL 16\nU 1\nD 10\nR 13\nL 6\nD 5\nR 13\nU 2\nD 16\nL 9\nU 11\nD 13\nU 16\nL 6\nR 15\nD 10\nU 17\nL 15\nD 7\nR 6\nD 15\nR 11\nL 14\nU 12\nD 18\nR 6\nU 16\nL 1\nU 10\nR 15\nU 3\nL 12\nD 9\nL 11\nD 18\nR 11\nL 12\nU 5\nL 13\nD 2\nR 11\nD 10\nL 15\nR 5\nD 17\nR 6\nL 16\nR 11\nD 1\nR 5\nU 13\nR 11\nD 13\nL 12\nU 10\nD 9\nR 1\nD 15\nR 1\nD 17\nR 10\nU 11\nR 14\nL 17\nR 2\nL 1\nD 12\nR 6\nU 18\nR 3\nL 8\nR 11\nL 15\nU 8\nL 7\nD 2\nL 9\nD 9\nL 11\nU 5\nD 8\nU 16\nR 13\nL 7\nD 6\nU 16\nL 9\nU 3\nR 4\nL 12\nU 18\nD 7\nL 10\nR 16\nD 1\nR 4\nU 4\nR 13\nD 6\nL 5\nR 3\nD 10\nU 4\nL 17\nD 9\nR 8\nL 1\nD 8\nL 16\nD 3\nU 3\nR 1\nU 9\nR 13\nD 3\nL 4\nR 6\nD 10\nU 16\nL 9\nU 5\nL 14\nU 8\nD 17\nL 18\nD 5\nU 10\nR 14\nL 8\nU 6\nR 5\nU 19\nL 9\nU 2\nD 7\nU 14\nR 17\nL 16\nD 15\nU 11\nD 4\nL 16\nU 14\nD 6\nL 3\nR 18\nL 17\nD 6\nL 10\nU 7\nD 11\nL 15\nU 12\nL 6\nD 6\nL 14\nU 17\nL 7\nD 2\nL 7\nU 12\nL 17\nR 16\nU 19\nL 12\nU 10\nL 6\nU 3\nD 16\nL 5\nD 15\nL 7\nR 6\nD 2\nR 19\nL 4\nD 18\nR 19\nD 9\nR 11\nL 17\nR 1\nU 15\nR 3\nD 18\nL 13\nU 7\nD 7\nR 15\nU 4\nD 16\nR 6\nU 4\nR 10\nU 10\nR 1\nD 19\nR 13\nU 7\nL 13\nD 15\nU 2\nL 18\nD 5\nU 5\nD 10\nL 8\nD 13\nU 8\nL 15\nD 12\nU 11\nD 17\nL 14\nR 4\nD 19\nL 6\nD 5\nL 13\nD 16\nU 1\nR 14\nU 15\nL 18\nD 7\nL 14\nD 11\nL 7\nD 18\nU 16\nL 1\nR 18\nL 1\nU 19\nR 3\nD 1\n"
  },
  {
    "path": "advent-of-code/2022/inputs/10",
    "content": "noop\naddx 24\naddx -19\nnoop\nnoop\nnoop\naddx 5\nnoop\naddx 1\naddx 5\naddx -1\naddx 5\naddx 1\naddx 14\naddx -9\naddx -1\naddx 5\nnoop\naddx 2\naddx -20\naddx 24\naddx -36\naddx -2\nnoop\naddx 3\naddx 2\naddx 5\naddx 21\naddx -16\nnoop\naddx 2\naddx 15\naddx -14\naddx 2\naddx 5\naddx 2\naddx -4\naddx 5\naddx -8\naddx 15\naddx 2\naddx 3\naddx -2\naddx -38\nnoop\naddx 3\naddx 4\nnoop\naddx 7\nnoop\nnoop\naddx -2\naddx 5\naddx -16\naddx 21\nnoop\naddx -10\naddx 11\naddx 2\naddx 5\naddx 4\nnoop\nnoop\naddx -6\naddx 7\nnoop\naddx 3\naddx -36\nnoop\naddx 5\nnoop\naddx 20\naddx -19\naddx 5\naddx 4\nnoop\naddx -2\naddx 3\nnoop\naddx 4\nnoop\naddx -1\naddx 5\naddx 3\naddx -28\naddx 30\nnoop\naddx 6\nnoop\nnoop\naddx 1\naddx -38\naddx 40\naddx -33\naddx 20\naddx -19\naddx 2\nnoop\naddx 28\naddx -23\naddx 5\naddx 2\naddx 2\naddx 3\naddx -2\naddx 5\naddx 2\naddx -7\naddx 12\naddx -2\nnoop\naddx 3\naddx -38\nnoop\naddx 24\naddx -17\nnoop\naddx 5\nnoop\nnoop\naddx 1\naddx -8\naddx 13\nnoop\nnoop\naddx 2\naddx 5\naddx 2\naddx 6\naddx -5\naddx 4\nnoop\naddx 1\naddx 2\nnoop\naddx 3\nnoop\nnoop\n"
  },
  {
    "path": "advent-of-code/2022/inputs/11",
    "content": "Monkey 0:\n  Starting items: 50, 70, 89, 75, 66, 66\n  Operation: new = old * 5\n  Test: divisible by 2\n    If true: throw to monkey 2\n    If false: throw to monkey 1\n\nMonkey 1:\n  Starting items: 85\n  Operation: new = old * old\n  Test: divisible by 7\n    If true: throw to monkey 3\n    If false: throw to monkey 6\n\nMonkey 2:\n  Starting items: 66, 51, 71, 76, 58, 55, 58, 60\n  Operation: new = old + 1\n  Test: divisible by 13\n    If true: throw to monkey 1\n    If false: throw to monkey 3\n\nMonkey 3:\n  Starting items: 79, 52, 55, 51\n  Operation: new = old + 6\n  Test: divisible by 3\n    If true: throw to monkey 6\n    If false: throw to monkey 4\n\nMonkey 4:\n  Starting items: 69, 92\n  Operation: new = old * 17\n  Test: divisible by 19\n    If true: throw to monkey 7\n    If false: throw to monkey 5\n\nMonkey 5:\n  Starting items: 71, 76, 73, 98, 67, 79, 99\n  Operation: new = old + 8\n  Test: divisible by 5\n    If true: throw to monkey 0\n    If false: throw to monkey 2\n\nMonkey 6:\n  Starting items: 82, 76, 69, 69, 57\n  Operation: new = old + 7\n  Test: divisible by 11\n    If true: throw to monkey 7\n    If false: throw to monkey 4\n\nMonkey 7:\n  Starting items: 65, 79, 86\n  Operation: new = old + 5\n  Test: divisible by 17\n    If true: throw to monkey 5\n    If false: throw to monkey 0\n"
  },
  {
    "path": "advent-of-code/2022/inputs/12",
    "content": "abaccccccccccccccaaaccccaaaaaaaaaaaaaccccccaacccccccccccccccccccccccccccccaaaaaa\nabaaccaacccccccccaaaaaccccaaaaaaaaaaaaaccccaaacccccccccccccccccccccccccccccaaaaa\nabaaccaaacccccccaaaaaacccaaaaaaaaaaaaaacaaaaaaaaccccccccaacccccccccccccccccccaaa\nabcaaaaaaaacccccaaaaaacccaaaaaaaaaaaaaacaaaaaaaacccccccaaaacccccccccccccccccaaaa\nabcaaaaaaaaccccccaaaaaccaaaaaaaaccaaaaaccaaaaaaccccccccaaaaccaaaccccccccccccaaac\nabccaaaaaacccccccaaaaccaaaaaaaaaacaaaacccaaaaaacccccccccakkaaaaaacccccccccccaacc\nabccaaaaaacccccccccccccaaaaaaaaaaccccccccaaaaaaccccccckkkkkkkaaacccccccccccccccc\nabccaaaaaaccccccccccccccccaaaaaaaaaccccccaacaaacccccckkkkkkkkkaccccccaccaaaccccc\nabccaacaaacccccaaccccccccaaacacaaaacaaccccccccccccccakkkoppkkkkicccccaaaaaaccccc\nabccccccccccccaaaccccccccaacccccaaaaaaccccccccccccccjkkooppppkiicccccccaaaaccccc\nabccccccccccaaaaaaaaccccccccccaaaaaaaccccccccccccccjjjooopppppiiiicccccccaaacccc\nabaaacccccccaaaaaaaacccccccaacaaaaaaccccccccccccccjjjjooouuppppiiiiiicccccaacccc\nabaaaccccccccaaaaaaccccccccaaaccaaaaacccccccccccjjjjjooouuuupppiiiiiiiiccccacccc\nabaaaaaacccccaaaaaacccccaaaaaaaaaacaaaccccccccjjjjjjooouuuuuupppppiiiiiicccccccc\nabaaaaaacccccaaaaaacccccaaaaaaaaaacccccccccccjjjjjooooouuxxuupppppqqqijjjccccccc\nabaaaacccccaaaaccaaccccccaaaaaaccccccccccccciijjnooooouuuxxxuuupqqqqqqjjjdddcccc\nabaaaaaccaaaaaaccacccccccaaaaaaccccccccccaaiiiinnootttuuxxxxuuvvvvvqqqjjjdddcccc\nabaaaaaccaaaaaacaaaccaaccaaaaaaccccccccccaaiiinnnntttttuxxxxxvvvvvvqqqjjjdddcccc\nabaaccacccaaaaacaaaaaaaccaaccaaccccccccccaaiiinnnttttxxxxxxxyyyyyvvqqqjjjdddcccc\nabcccccccaaaaacccaaaaaaccccccaaaaacccccccaaiiinnntttxxxxxxxyyyyyvvvqqqjjjddccccc\nSbcccccccaaaaacaaaaaaaaccccccaaaaaccccccccciiinnntttxxxEzzzzyyyyvvqqqjjjdddccccc\nabcccccccccccccaaaaaaaaaccccaaaaaaccccccccciiinnnntttxxxxyyyyyvvvvqqjjjdddcccccc\nabcccccccccccccaaaaaaaaaacccaaaaaacccccccccciiinnnttttxxxyyyyyvvvqqqjjjdddcccccc\nabccccccccccccccccaaaaaaacccaaaaaaccccccccccciiinnnntttwyyywyyyvvrrrkkjdddcccccc\nabcccccccccccccccaaaaaaaaccccaaaccccccccccccciiihnnnttwwwywwyyywvrrrkkkeeccccccc\nabcccccccccccccccaaaaaaaaccccccccccccccccccccchhhmmmsswwwwwwwwwwwvrrkkkeeccccccc\nabcccccccaacccccccacaaacccccccccccccccccccaacchhhhmmsswwwwwswwwwwrrrkkkeeccccccc\nabcccccccaaaccacccccaaacccccccccccccccaaccaaccchhhmmssswwwssrrwwwrrrkkkeeccccccc\nabcccccccaaaaaaacccccccccccaaaccccccccaaaaaaccchhhmmssssssssrrrrrrrrkkkeeaaacccc\nabcccccaaaaaaaaccccccccccccaaaaccccccccaaaaaaachhhmmmssssssllrrrrrrkkkeeeaaacccc\nabccccaaaaaaaaaccccccccccccaaaacccccccccaaaaacchhhmmmmsssllllllllkkkkkeeeaaacccc\nabccccaaaaaaaaaccccccccccccaaacccccccccaaaaacccchhhmmmmmlllllllllkkkkeeeeaaccccc\nabcccccccaaaaaaccccccccccaacccccccaaccaaacaacccchhhmmmmmlllgfflllkkffeeeaaaacccc\nabccccccaaaaaaaccccccccccaaaaaaaaaaaaaccccaacccchhhggmmmggggffffffffffeaaaaacccc\nabccaacccaacccaaaaccaccccaaaaaaaaaaaaacccccccccccgggggggggggffffffffffaacccccccc\nabaaaaccaaaccccaaaaaaccccaaaaaacaaaaaaccccccccccccgggggggggaaaaccffccccccccccccc\nabaaaacccccccccaaaaaaccaaaaaaaaaaaaaacccccccccccccccgggaaaaaaaacccccccccccccccca\nabaaaaacccccccaaaaaaaccaaaaaaaaaaaaaacccccccccccccccccaaacccaaaaccccccccccccccaa\nabaaaaacaaaaccaaaaaaaacaaaaaaaaaaaccccccccccccccccccccaaaccccaaaccccccccccaaacaa\nabaaaaacaaaaccaaaaaaaaaaaaaaaaaaacccccccccccccccccccccccccccccccccccccccccaaaaaa\nabaaacccaaaaccccaaaccccaaaaaaaaaaacccccccccccccccccccccccccccccccccccccccccaaaaa\n"
  },
  {
    "path": "advent-of-code/2022/inputs/13",
    "content": "[[1,4,7,4,8],[],[8,0,7,[],[]]]\n[[10,[5,[0,2,5,3,3],[9,7,9],6],7,9,[2,9,[],4,0]],[8]]\n\n[[7],[7],[[[3,4,6],1,[1,2,4],[7,5,3,5,2]],[[1,3,2,7],10,[9,9,0,2]],[9],[1,[10,4,7],[5,2,1],[10,9,4,3]],[7,[8,9,9,4],[]]],[],[]]\n[[8,[[]],[7,3],4],[[[2,3]],10,[[4],[3,9,4],[0,6,5],1,3]],[],[]]\n\n[[5],[[[],[8,0,4],1],[],2,6,10]]\n[[[[3,0],[7,10,9]],[9,4,3]]]\n\n[[2,10,[1,[],5],[[1],[3,0,9,7,2],[6]],[[],[7,0,2]]],[[[0,10]]]]\n[[3,[[],[5,0,2],2],7,[[0,2,9],2,[4]]],[3,[[4,5]],[[10,2,5,1],[1],9,[3,3,7,7,10],9]],[]]\n\n[[[[],9,7,[2,8,2,1],[6,3,7,6]],8]]\n[[[[9,8,2],[10],[9,0,3],0,[3,5,0]]],[]]\n\n[[[9,10,[1,0,6],[1,2]],[[],[9,5,3],[7,3,10,1],0,0],5,10,[]],[]]\n[[5,6,1,6],[8,6,5,[7,0,5,[0,4,3,6,6],[8,7,8,5]]],[[[1,2],9,1],10,4,3,[5,[5,10,9,9],7,0,[2,3]]],[[[1,5],[0],0],3,[[]]]]\n\n[[0,[[4,6,4,8]],3,[10]],[],[6,8,6],[8,[3,[7,7,10,6,5]],[0,8,[7],[],5]],[1,[3,[4,4,8,3,8],3,[1,9,8,3,10],[0,5,8]]]]\n[[0,[],10]]\n\n[[[[2,4],[5],10,1],[3,6,3],8,0,9],[9,1,9],[[[1],[2,0,7],[10,2],6,[10,9]],[[10],[1,0,3],5,[1,7],[]],3]]\n[[9,6,3],[[6,[8,10,3],2,[6,1],10],1],[]]\n\n[[8,[],[10]],[]]\n[[[[8,5,6,6,5],1,[10]],[]],[],[],[7],[2,2]]\n\n[[9,3]]\n[[0,[1],6,[10,0,6],7],[7,[1,[4,3,10],[],[6,6]],5,[9],7],[7,[[6,2,7,2,5],9,8,7,[9]]],[5]]\n\n[[9,9,[[10]],[8,[7]]],[8,5,7,[[6,1,8],[9,5],[],10,8],[8,[10],[],[5,3,2]]]]\n[[[9,9,6],1,0,9,[[0],[8],2,0]],[[9,5],[[],[9]],3,[[0],9,3,0,8],10],[[[4],[8,2],[2,0,3]],3,6,[[3,8]],4]]\n\n[[4,3,[[10,8,3,1,10],[9]]]]\n[[[6,[0],[3,4],[0]],[],[6,2,[],1],[[],1,[1,4,3,7],9,4]],[0,[[0],[9,2]],1]]\n\n[[[[8,4],[7,8,6,10,1],[]],[[2,8,10,4,5],[0,8],7,[1,5],4],8,[1]],[],[]]\n[[3,[4,[3,3,4]]],[[],1,9,[0]],[[],[[6,9,1],[10,2,3,2,8],3],3,5]]\n\n[[[[0,3,7],3,[4,0],[6,2,0],4],1,[[3,4,7],8,[1]],2]]\n[[0,6,[[6,9,6],9,[0],[2,10]],4]]\n\n[[2,[],6,[[8,10],7,7]],[[[1,2,3,8,3]]],[]]\n[[[],9,9],[9],[[2,4,8,[7]],[1],1,9]]\n\n[[1],[[[],[6,7,6,8],0,[2,3]]]]\n[[[[9,7,2]],3,[8],7,[[3,6,10]]],[[],10]]\n\n[[3,6,[5]],[5]]\n[[],[0,[[6,2],[]],3,4,[[6,1,6,10],8,[5,8],5]],[1,4],[[[8]]],[4,3,[[7,2],9,[],3,3],[5,0,[9,0],10],[[7,8,2],3,3,3]]]\n\n[[[7,[]],[]]]\n[[[[0,1,2],[3,7,6,5,9],8],[7]],[[[8,6,3,6,2],[7,0,2,5,3],[1,2,1],8]],[7,[2,[0,0,4],[4,1,8],5,[7]],4,2,5]]\n\n[[9,1,10,[[5],[],[2,1,4],5,0]],[10,[2,9,1],[10,[0,4],9,4],9],[[4,3,6,[0,3,10,6]],[4,[2]],9],[],[]]\n[[6,[4,[2]],[],10],[[[1,1,5],[5,6,6],7],[2],[[10],[],10],[[3,3],1,5,[1,1,9,4,3]],0],[8,[],[[]],10,1],[1,[],[[7,4,2],1,0,9],2],[[0,9],[[2],9,[9,1,8]],1,[4,1,9,[3]],3]]\n\n[[[3,[],[9,7]],[[3,0,2,6],2,[0,9,1],[6],[7,4,0,7]],[3,[],[10,1,6,2],0],5,3],[3,[]],[],[2,[[],10,4],[6,[5]]],[]]\n[[],[],[[7,[1,1],4,7,[6]],[4],[7,3,6,[4,9,8,3],7],[4,8]]]\n\n[[4,3,8,2,6],[[[8,1]]],[[6,3],[3],[8,[7,7,4,2]]],[8,[6,[10,10,3],0,8],[],7,[10]],[8,0,7,4]]\n[[5,10],[],[6],[]]\n\n[[2,6]]\n[[1,7]]\n\n[[4,0,[[],[2,6,3],10]],[[],[1]]]\n[[3,10,2],[[10,[7],[7],5],[[0,4],[9,1,8,8]],1,[9],1]]\n\n[[3],[[[2,1,5,0]],8,7,[[5,7]],[[],2,8]],[[9,[3,5,2,8]],[[4,7,9],[8,7,4]],[3,10],3,7],[[]]]\n[[5,[],3],[8,[[2,8,10],[],9,[7,9,7],[3,10,4,1,10]],6],[]]\n\n[7,7,4,8,0]\n[7,7,4,8]\n\n[[],[5],[4,0,[[1]],[[],[0,1,0],[8]],[[9,8],6,[],[8,8,6,1,4]]]]\n[[],[0,[]]]\n\n[[[],10],[[[2,7,7,0],[5,5,1,8],0,[]]],[[[5,6,4],0,3,[10,3,2,10,2]],7,9,4,6],[[[],[6],[3,7,4,6,3],4,7]],[4,[]]]\n[[8]]\n\n[[],[],[[10,[0,7],9,[3,6],[]]],[5,[1,2,[1],[9,2,3,4]],[[6,7,7,1,10],7],[8],[[10,8],[2,3,5,2,5],[9,9,9,10,7],[8,2]]]]\n[[7],[],[[[1],9,10,[9,1,1,4],6]],[[[7,4],0,[10,1],9],0,[[],[1,6,6],[]]],[]]\n\n[[],[10,3,1],[[[9,5,10,10,5],[4,1],5,6,10],0]]\n[[4,[[8,9,0],0,[0,10,2,4],7,5],[8,2,3,5],0],[],[3,[[0,1,2,10]]],[6,[],[[],0,3,[4,4,4,3,4]],0],[[[5],5,3],[[],[3],4,0,[3,3,6]],4,[0,6,[]],[5,5,7]]]\n\n[[[],4,[1,0,0,7],10],[],[],[7,[8,[4,0,10]],[[4,5,4,7],6,8,1,[7,10]]],[[[3,6,0],1,8,2],[],10,0,1]]\n[[4,7,5],[6,[[0,9],[1]],[[2],[8,1,2]],8,[9,[7],7,1,[7,0,6,4]]]]\n\n[[6,[[6,10,4,3,8],5]],[],[[[8,9,6],[5,9,8,4,4],[3,10,3]],10,9],[[8,3,[6,2,5,1],[1,7,1]],[5,[3,8,3],[2,3,7,5],8],[[7,5,2],[5],[4,1,10],9]],[5,1,7]]\n[[],[5,[6,[4,0,8,10,0],[9,6]]],[[],6,[[3]]],[]]\n\n[[2,[]]]\n[[[]]]\n\n[[[8,[3,9,1,0,2],[],[1,10,9,10],[1,10,3,2,7]],6,[[8,9,0],[8,1],4]],[[5,[],[3,2,3,2,2]],[],[0,[10],7,3],5],[[10]]]\n[[0,10,[3,3,7,[1,1,5],5],1],[[1,5,5,7,6],[],[],7],[],[1,[9,8,[4],2]],[[],[0,0,[3],[1]],[5,[9,10,1,1],8,1]]]\n\n[[10,0,3],[2],[1],[[[9,9,3,10]],[],2]]\n[[[0,3,[9,1,1,5],6,[]],[8,10,5,1,[8,2,4,0,8]],[[4,9,7,7,4],[7,7,7,5,5],7],[[],[2,10,4,6,2],[6],[6,4,2,2]],2]]\n\n[[[[9,1,2,6,9],[8,4,5]],0]]\n[[9,[[6],[],2,7,0],1,[[8,0,9],[5,1,1],10,8]],[3,[[10,3,7,0,1]]],[1,[[],2,3,[5,5],0],[[8,6,1,9,2],10,[],4]],[]]\n\n[[0,3,6,4]]\n[[7,3,[5,[5,7],[9,3,7],0],[[7,7,10,2,3]],[10,[0,9,0,5]]],[],[]]\n\n[[1,1,[2,[1]],[[8,2,7]]],[7],[[3],8],[[[7,1,7],[1,6,5,0,2],7,[4,3],4],1,8,2,[[8,9]]]]\n[[[10,[],5]],[[3],[6,5,5,[1,2]],8,3]]\n\n[[6,0,8,6],[2,5,[[10,8,6,0],6,[3,10,7]],[4,[3,9],[4,6,3]],9],[]]\n[[10,[],[[10,5,6,1,10],5,[9,1,1,8]],[[2,8,8,6,5],10,4,[5,0,2,6,1],5]]]\n\n[[[[2,8,9,4],[8,9],[7,0],[10]],4,9],[[0,[3,2,4,0]],2,[[0,0],[10,9,1],6,[5,6,3,8]]]]\n[[[6,10],[9,9],[1],[4,9,6,[3,6],[]]],[6,2,6,[[7,1,4],1,7,[4]],5],[[[10,4,6]],[4]],[5,[[5]],[[7,1,7,0,1],3,2,7,[4,5,7,8]],[10,8]],[[4,[]]]]\n\n[[10]]\n[[[7,[]],[10,[0,1,4,6,3],0]]]\n\n[[5],[8]]\n[[[3],10,[[7,1,1,5,6],0,4,2],8,[[6,3],[10,2,9],[3,10,3,3],1]]]\n\n[[],[]]\n[[2,1]]\n\n[[],[5,8,2],[[[1,0]],4,[[2,5],8,[6,0],10]],[[[3,8,10,7],8,8,1],1,9]]\n[[0,4,[[7],0,[],[5,8,7,8,4]],[2,0],4],[2,5,5,[]],[],[0,[[3,3],0,[10,1,0],5]],[]]\n\n[[[[4,2,8],10],[7],0],[7,[10]],[[6,[],[1,5,8],[2,1,1],8]],[[]],[[[5,5,7]],[[]],[[],[],8],7]]\n[[],[[[6,7,6,1,2],4,9,[7]],7,10,4],[[],4,1]]\n\n[[6],[],[8],[[[6],2,9],[[],1,1,[],[2,5,3]],5,8,[[8,3],7,[],[2,10,7,0],9]]]\n[[8,[[9,9,1,8],6,[6,8],1,7]],[[0,[5,7,8],6,8,6],0,2,4,[[10,6,10,6,8],[8,3,7,5],[0],2,[0]]],[],[[10],[[],[8,9,3,8,2],[6,3,2,1],[7,10,8,7,1]],[7]],[2]]\n\n[[10,[[4,6],[9,10,8,6,6],[10,6,0],1,0]],[[3],10,[]],[[1],2],[1,[1,[3,1,2],1,10],[[9,1],[2,4,0,10,4]],[0,8,[5,1,9,9,7],3],5],[[[10,4,3,3]],[[3,6,1],1],[[4,2,10,7,3],8,[2,6,0],[6]]]]\n[[8],[[[9,6,0]],[],[],10],[[[],6,[7],[2,2,9,6]],0,10,1,1],[[[1,7,0],6,10,6,2],3,[]],[2,6,6,[]]]\n\n[[3,[[2,10,3,2,4],7],2,[[],7]],[],[],[[[1,4,9,3],[],7,[0,7]],0,1,3,4]]\n[[4,3,[4,1,[]],[[6,5,1],10,4]]]\n\n[[7],[0,[3,[0,9],10],[[9,5],9,7],1,[0,[0,8,9,3,7],2]],[2],[4],[[[8],4,[7,4],8],9,7,[2,5,8]]]\n[[10,[[0,3],[9]]]]\n\n[[[[],9,[8,8,9,10,9]],[],10,10],[10,[],0]]\n[[0,[],6,3,[[],[]]],[7,[8]],[[[4,3,3,2,9],10,4,[]],5],[]]\n\n[[3]]\n[[[3],[],[6,[7,9],[1,7,3],[8]],2,0]]\n\n[[[[5,8],[5],[7,5,7,6,4]],[[],1,[0,10,3,0,1]]],[]]\n[[[[6,10],[1,4],[7]]]]\n\n[[[[6],[9,8,5]],4,[[7,6,3,2],[7,3,6,3],9,[6,4,0,5]],4],[5,[],9,[[],[6,0,9,9],4]],[[],1]]\n[[[[],6,3],3,[]],[0,1,[8,[1,9,10]],0],[9,[[3,0,6,0,3],0,0],[2,[8,9,3,10]],7,[[6,3,8,9,4],[2]]],[[],0],[6,[6,[4,3]],[],4,[10,9,[2,7,9,8,3],8,[]]]]\n\n[[5,8,[[1,8],4,[8],[10],0],8],[],[[9,9,10,1],2,[1,8,[4,7,4,1,0],[8],6]],[[],[7,0,[4,2,7,5]],10,[]]]\n[[0,[5,6],10],[[[2,9,5,1],4,[5,7,6,3,10]],8,[4,[2,4,3],9],5],[],[[9,[4],[9,5]]]]\n\n[[[],7,[[3],8,5,[8,7]]],[[5,4,3,8,[]],7,[[]],[],[4,[6,7],7,3]]]\n[[7,2,4,[8,[0,3],1,6,[]]],[],[9,6,[8,9,3,0],[]]]\n\n[[[],7],[0,10,[0,[9,9],8,7,[8,3,0]]]]\n[[],[[[1,5],[10,4]],[[2,1,4,1],[3,2],4,[7,9,10,5,4]],7,[]]]\n\n[[10,4]]\n[[[[8,3,10]]],[1,[[1,8,9,9,6],[6,5,2,6,3],5],8],[6,8],[10,1,[[4,4,8],7]]]\n\n[[[[]]],[],[9,8]]\n[[0,1,8],[1,[5,1,[10,2,4,2,5],8,8],6,2],[4,[4,[3],3,[2,0,3],7],6,[]],[[[8,5,3],10,[1,2,6,6]],4]]\n\n[[7,[2]],[]]\n[[[[1,5,10,0,2],1,[8,2,8,2],[5,10,8,2]],4,2,[2],2],[[6,[],[],[]],[[]],9],[9,3],[8,2]]\n\n[[],[1],[2,[[0],8,9],5,[[10,0,3,5,2],7,2,[9,2,2],[9]],[[7],[]]]]\n[[6],[[[5,4],[],[4,0]],[[5,3,0],7,[8,2,10,7],[0,8,5],5],[],[0,5],5],[[10,7],4,5,9]]\n\n[[7,10,3,2],[1]]\n[[10,[[7,7,9,4,9]],2,[3,8,[],[],10]],[7,[[2,4],7,0,[9]],4,[[10]]]]\n\n[[4,[2,[],[1],10],4],[[[7],[4,6],[9,1,10,0,4],3,[2]],[[7,4]]],[[4,4,5,0]],[5,1,[[3,0,8,10]]],[3,[[2],[3,8],[],[2,6]],3,[10,[7,3],9],3]]\n[[[[2,0],[2,4,10,10,9],2],7,10,[],8]]\n\n[[[[6,4,5,2,9]],1,[3],[6,[10,1],9,[10,10],[3,1,6,10]],5],[[]],[],[8,10,2,10,[[10,8,6],2,[],[10,9,1,10],1]]]\n[[[],2],[[[7,2,2,9,7],7,2,4],[[2],3,5]]]\n\n[[[],[[8,5,7],[0,0,10,7]],10],[[0,10]],[[8,6],4,[4],[[],[1,0,4],[5,2,0,3,8],[9,2,5,8]]]]\n[[0,[[7,7]],0,[],4]]\n\n[[5,0],[3,[],6,[3,10,0]]]\n[[[],[4,[10,3,10],[9,4,5,0]],[],[[10,7,6,6,0],1],[10,10,7,[],[1,0,4,0,7]]],[[1],[],[],[4]],[8,[],8,[[2,6,8],2,[2]],10],[[[8,3,3,5,4],[5,8,2,8,9]],4,6],[3,2]]\n\n[[1]]\n[[9,1,2,6,3]]\n\n[[8],[9,[[]],9,[[0,5,8,1],7,0,3,[0,4,1,6]],[[3,8,9,6,3],[],[8,7,4,6,10],[8,7,0]]],[[[5],[9,7,6],[8,3,2],1],8,6,[10,[6,6]],9],[[],10,[7,[6,4,3],[],6,4]],[[3],[[6]],[6,[],[],[9],[10]],9,6]]\n[[[],2,[0,[3,5],4,9],3,[]]]\n\n[[[[1],7],[[],4,[4,8,8],[10,7,3,2],[]],[]],[7,1,6,0,[3,0,[1,0,2,6,5],[2,2,9,6,2],[6,9,6,7,10]]]]\n[[[[3,2,8,9,3],[6,2,4,7],[2,7],[7,2,9,2],[3,4]],[]],[[3,2],[1,2,[9,10,3],[7],[8,8,7,3]],[0],[[4],10,5,3],[6,[],[0],[]]]]\n\n[[[5,[],[],5],[0,[1,0,5,1,3],10]],[8,[4,10,3,[]],5,1]]\n[[2,[[8,7],5],5,0],[],[[],5],[[],2,[[9],5,[7,2,1,0],[6,2,8]],[[2,4,2],8,[9,7,8,0,7]],10]]\n\n[[4,7,[2,3,9],3]]\n[[[[0],[0,1],7],[1,[]],4],[],[[[5,8,5,8],8,[10,6,8,4,8],[10,3,7,5],10],[]],[[[1,8,6],[5],[9,2,6,3,2]],[1,[9,10,3,2,7],[2,10],10,4],7]]\n\n[[[],[10],[4,[2],6,[8,1],7],8],[[9,[9,8,9,10,10],7,[8,0,9,7,4],[]],[[7,2],[5,5,9,1,3],[4,8,6],[2,10],5],3,[4,[5,6],8,[]]],[8,[7,[9,1],[1,8,6,2,7]]],[8,[],[],[[0,1],8,2],0]]\n[[8,[[1,6,3],1,[6,7,0],10],10],[9,[[7,6],9,[7,6,10],9],6],[10,[[6,7],9,4,5],7,0,1],[[3],[6,1,[3,4],[0,0,5],[]]],[[[0]],10,5,[[7],[],7,[7,7,3]]]]\n\n[[[],7,5,1],[4],[4,[[3],0,6,[9,0,3,3,0],6],9,[[9,9,2,5]]]]\n[[[[10,0,7],8],[[6,9,1],3,[2,1,1,0],10],4,10]]\n\n[[[[10,9,4,1,9],[1,4],0],3,[9,[2,5,0,9],9,8]],[7,[8,[1],3,[6,1,7,1,5],4],[[10,2],[9,4,7,4],[10,2]]],[10,6,0],[[[10],[],[2,3,8,6,8],2,6],[[5,3,2]],9,8,1],[[4],[[2,5,3,4],1],[2,7,4,6,[4,6]]]]\n[[10,[[4,0,7,7,2],[7],[6,8]],9,7],[6]]\n\n[[1,4,6],[],[[0,[7,6,10],[8]],[9],[[3,4],10,[9,6,5],3],[[3]]],[8,[],1,9]]\n[[[5]],[[2],[[1,3,6]],0,6,10],[4,1,[10,4,10,3],2],[6,6]]\n\n[[],[6,1,[[5,8]],2]]\n[[7,[9,[],[5]],[6,[8,1],3],8,[6,[10,0,1],3,[6],[]]],[8,1,3,[4,[5,3,5],[],[3,10],8],0]]\n\n[[[3],3],[3,[10,[2,6,4,7],[10,4,4,6]],[3,10],[0,8,6,2,[10,10,5,9,8]]],[[4,2,5,[],2],[[],[9,0,8],[2,4,5,0]],[[6,10,6],9],[4,4,9,4],10],[[]],[[[7]],7,[6,[6],8],8,[[8,8]]]]\n[[0,[7,[3,10,4],2]],[0,1,[[1,1],[6,0,10],2,4,[10,3]],5,4],[[[3,3,2,4],[3],3,[0,2,8,5,3]]]]\n\n[[[],10,[4,2]],[]]\n[[[4,[10,6,3,1],[0,2,10,2,3]],9,[4,1,7,9,8]],[[[5],2,2,[8,8]],7],[[],[[],[8,4,3,7],[],[2,9,4,4],[]],[[7,10,10,9,8],3,2,6],2],[3,[[4,8,8],[10,5],1,3,8]],[[[0,7,2,4,3],[],[2,10],4,4],[],1]]\n\n[[3,9,10],[[[4,7,4],[10,2,4,7,7],[8]],[[3,1,5,4,4]]]]\n[[5,7,5,[[7,9,1]],[[9,7,1,4,2],1]],[10,10,5,[[0,0,7,8],3]],[[3],[],[1,[1,2]],[]],[[],0,6]]\n\n[[[[0,6,9],[9,9],7],2,3],[[[8,9,7,7],8,5,[6]],4,5]]\n[[1],[10,[[]],8,[[0,2],[2,10,4],[3],[]]],[],[[1,5,[4,1,0]],[],[5,[8,2]],[5]],[0,9,[],6,7]]\n\n[[9,4,[9,4]]]\n[[[[2],8,8,[10,1],[6]]],[[[],[8,9],6],[]],[[1,[8],5,2,10],7]]\n\n[[[[3,1,2,2],0,[7,1]],[],2,9,2],[[6,[4,0,0],[4,4,6,3,2],[1,10,5,10,8],5],[4,[3,8,5,3],3,[2,6,0,4,0]],[[8,5,4,6]],3],[[[10,1,5],[],[2,3,9],[4,8]],3,[3,[],8,1]],[[[7,5,2,8,7],[4,8],[10,10],3,0],[[3],[6,9,9,5,9],4],6,5,[[2,10],[10,4],1,[10,8]]]]\n[[],[9,8,[0,[9]],8,[4,[3,5]]],[]]\n\n[[[2,1]],[],[[],2],[[[1,7,2,9,7],3,6,[5,0,7]],6],[]]\n[[2,[6,[5,4,8,0],8,6],[[8,7,5,3],[5,1,3,6],[1],2,[0,1]]],[[[9]],[[],[],2],5,6,7]]\n\n[[[0],[9,[]]]]\n[[],[1,[7,[10],[10,6],7,[7,8,9,3]],[[8],[0],[],[9]]],[[5],[6,8]],[[8,[0,4,0],5,[2,1,10,6],[]],6,6,[[],3]],[[[2,2,7,3,3]],3,3]]\n\n[[9,4,[[5,10],[],[],[9,8,10,0,8],[1,6,8]],8,6],[[[0,1,9],2,[9,8,2,7]],0],[]]\n[[10,5,2],[[7,[8,4]],7,4],[],[6],[4]]\n\n[[[6,[8],[1,9,6,9],[10,1],6],[[7,3,3],2,7,[1,0,3,2,4],[7]],4],[9,[[7,5,10,4],6,4],[[4,2,9],[7,2],[0]],2]]\n[[[]],[3,[[0],[9],[],[],10]],[3,10],[7,10,[],[0,7,2,8],[3,[8,6]]]]\n\n[[6],[],[5,[6]]]\n[[],[[9,[1,1]]],[3,0,[],2,[]]]\n\n[[[6,10,[]],[1,[7,4],2],6,4,[[2,8,5],5,6,[1,6,9],[9,3,4,10]]],[]]\n[[],[7,[5,[9,1,5,6],[1,4,10],[2,4,10,9,3]]]]\n\n[[],[10,0,7,0],[2]]\n[[10,[[6,2,8]]],[[1,9,[]],3,4],[1,[5],1,1]]\n\n[[[5,7,4,1,[9,8,7,7]],[10]],[4,7,[[4,9,9],1,6,[10,4],7],[7,10,7,5],9]]\n[[],[8,0],[2,[8,3,8,1]],[[[6,8,6]],[2,7,7],[[8],5,9]],[[1,[5,8,5,7]],[9],[0,8,4,7,[]],[9,5]]]\n\n[[[6,6],1,10,9,10]]\n[[6,6,7,[[8,7,6],3,[4],10],[8,6,[0,3,9,3,0],[5,9,10]]],[8,4,[5,[9,5,2,2],[8],4,10],2,[[10,6,6,0],[6,6,7,3],6,0,[1,6,6]]],[[],[],4],[4,[1,[2,3,1,7],3],8]]\n\n[]\n[[1,[[4,2,6,0,1],[8,6]],[6,[4,5,9,3],10,[0,7]],8],[6,3,7,[[10,7,10,4,7],[3,0,5,10,10],10]],[[]]]\n\n[[5,5,[[],0,[3,10],[6,3]],[9,[10,0,6,8,8]]],[[[1,3,1],8]],[],[]]\n[[6,5,[8,0,9],9,2],[10,[3]]]\n\n[[[],8]]\n[[8,0],[[6],[4,8,[9,2,2,0],[5],[]],2],[[4,3,[9,3,5,4,5]],[[1,6,0,8],5]],[4,10,[[9,8,5,10,5],2,[4,9,9,1],[10,8,9,2],[4,10,5]],[9,1]]]\n\n[[[[5],[3,7],9]],[[7,10,[7,6,0],[1,0,5,6],[3,5,2,4,0]],[[2,0,7,1,7],1,[7,0,4,10],6],0,[9]],[3,[3,5,[10,8],[5,9,9]],2],[6,[],1,3]]\n[[[[5,4]],[[1,9,0,5,8],4,[2,6,2,0],9]],[9,[0,7,[2,8,10,6]],[[10],[4,2,4,3,4],0],4],[],[2]]\n\n[[[2,[2,10,4,4,6],10,6,[3,8,3,0,2]],[[3,0,2,0],[7,1],[1,0]]]]\n[[[8,1,1,[9,2]],[[9,7,2],[],7,4,3],[1,[3],[2,3],3,4],[[1],[6,7,3,2]],7],[6],[[[2,5,4,4],[],4,9,4],[[10,8,4,0],8,[1,1,6,2,6],[6,8,5,10,0],7]]]\n\n[[],[3],[[2,5,9],2,9,[[5,9],[2,3]]],[[3,1,[3,10,4,3,9],[2,0,6]],[[6,3],6,[9,7,9,7,10],[8,7,8,0,6]],7,[],[7]]]\n[[[6,8,4,[4]]]]\n\n[[2,7,[],[6,[1]]],[[[8,0],[4,8],[]],[0,[2,2,1,3],[8,0,3,7,4],[7,7,4,5,3],2],1,[7,[3,9],[5,6,8,8,5],[7,2,9]]],[[0,9,4,4],[9,4]]]\n[[[10,[7],5,[]],10,10,4],[1,[[],0,[10,10,7],[7,10,1,4],10],4,[0,[8,9,1,8,8],3]],[]]\n\n[[[3],0],[[5,1,[4,10,4],9]],[6,5,[[7,1,8],2,8,[0],5]],[[[5]],[5,[7,10],[1,9],2,[9]],2],[]]\n[[[[10,5,0,1]],8,[]],[[1],[7]]]\n\n[[3,6,4,[7,[6,9,4,9,9],8],[10]],[0,9,3,[[],8,[10,7,1,8],7,[1,2,5,7,7]]],[4],[[4],[],7],[[[2,9,1,5,6]],8,3]]\n[[[5,[7,1,4,8,9]],[[2,8,8,2,10],7,[8,9],9],10,[[3,1,0,3,3],[3,7,10,0,8]],[5,2,[3],[2,3]]],[],[5,8]]\n\n[[[],6,10,0]]\n[[[[8],9,4,[],[]],[5,10,1,[1,4,10,9,0]],2,9,1]]\n\n[[]]\n[[[3,4]],[[8,0,[1,9,6,7]],[9,[10,2,6,3],2,[3,6,7,8,6]],[]]]\n\n[[[[10],0,6,3,[4,4,3,5,10]],[2,[6,4,7]]],[]]\n[[5,8,[0,[0,5],[0,8],6,[]],[8]],[[[5],[7,5,8,9],[2],[]]],[6],[[8,[9,8]],[[0,10,10],[7,6,6,2,10],[10],[]],[[2]],[4,[],[2,1],[7],4],[0,7]]]\n\n[[0],[],[5],[4,7]]\n[[3],[6,6],[5,0],[4]]\n\n[[[]],[9,[[1,7,8]]]]\n[[[4],7,8],[[10,3]],[10,[[7,6,10,10],7,7],[7,9,1],3,2]]\n\n[[],[[[],[2,5,7,6,1],8,7,9],[4,[7,5],[10]],[[7,3,1,1,3],0,1]],[10,10,[4]],[],[8,[[9,4]],[8,[3,2],[7,4],0],5,8]]\n[[4,[],2],[],[],[0,4]]\n\n[[[4,1,9,[8,6],8],[6]],[2],[2],[[[2,3],[8,7,8,1,5],4,0,2],[[3],[1,9,10,6],3,[1,1,4,1]],[[9,5,6],[10,4,10,4],1],4],[7]]\n[[[1],8,[[8]],[[6,10,5],7,7,9],[3]],[5],[[8,9],[[10,1,2],[4,8],5,6],4],[[4],8,[5],[[4,9,3,2,5],8,[],[0,4,9,4],0],9]]\n\n[[[],[[],7,[]],8,1],[[[0,9,5,10,0],7,9,[1,5]],7,2],[[6,[4,2,0,0,1],6,2,[1,8]]],[[0,[]],5],[0,[],[[],[8,0,6],[9],2,10]]]\n[[5,[[3,3,9],[3,1],[]],[9,[1,8,7,9],0,2,4]]]\n\n[[0],[4,9,[[],8,[2]]],[[6,4,1,[],2],8,[[9,1,2],3,7,[1,1,2]],4,[2,[10,7,7,9,0],2,10]]]\n[[10,[[0,2,5,10],8,[10],1,[8]]],[[[7],[4,8],[7],[9,10],9],0],[[[0,6],[8,3,3],[5,10,1,1,1],7],[4],[10],8,6]]\n\n[[0,4],[4],[5,[3,[3,7,3]],[[4,1,0,7]],9],[4,[[5,6],[7],0,6,[7,6,7,0,5]]]]\n[[],[1],[5,[[2,1,6]],1,[7,[8,7,6,1,4],2,[4,5]],1],[],[[9]]]\n\n[[1,8],[6],[[[9],[9],[2,10,8],[2,3,1,0],[6,7]],0,2,[1]],[]]\n[[[1,3,8],[[4,5,4],2,[8,8,7,9],[6,8]],9],[[1,8,[4,9,9,8,8]]],[6,[1,[5,8,3,1,4],[],[9],[6,5,2]]]]\n\n[[],[[],[[9]]],[]]\n[[5,[4,4,[1,3,8,5],10,0],0,[],7],[]]\n\n[[5]]\n[[[],5,3,10,3],[[1],[5,[0],[],10,8],[[10,6,3,2,6],[5,10,1,7],2,[7]]],[8,[[2,3,9,2,9]],10,10]]\n\n[[[2,1,9],0,[10,5,6],[0]],[[4],9,[5,3]]]\n[[7,2,0,9],[[1,3],4,3,7],[9],[],[5,[[8,3],7,[2,0,1,2]],9]]\n\n[[[5,3],5],[],[8,[1,10,[10,1]],[6,0],[[1,2,0,2],4,0],[]],[[10,6,7,1],3,[8],[[3,10,9,0],7,[5,1],3,8]],[[7,6],10]]\n[[2,8],[7,3],[[1,[6,2],7],5],[[6,[1,10,4],[0,5],[4,5]],10,10],[]]\n\n[[2],[[[],[],[0,8,6,2,1],6,[5]],[[1,4,5,5,7],1,2],1]]\n[[],[[[8,5,9,8,7],5,[7,7,10]]],[8]]\n\n[[[],7],[[[9,10,6,6],[6,10,1,9,4]],[1,9,0,[0,4,10],10],4],[[[5,7],6,3,6],[[9],[2,3,5],0],2],[[[10,10]],[0,[8],[6,6],5],[[8,8],5,7],[8],2],[9,9,[[]]]]\n[[[8],[[9,0,6,6,5],8],[4,[7],[4,6,6],[3,3],10],8,[]],[[[8,2]]],[9,4,[[4]],[[1,5],[0],[1,6,1],[]],0],[0,3,9,[6,7,1,0,[]]]]\n\n[[3,[],[[1],[4],7,[1,2,0,6,5],[5]],6],[4,9,1,1],[5,[[4,2]],[]],[2],[8,2]]\n[[[8,[7,9,8,0,4],[2,3,3],[],[9,5,6]],3,[2,[2,1,3,10,10],9,[4,9,2,2],8],2],[3,0,0,5,[4,[2,1],6,[2,3,9,1,8]]],[9,0,7],[8,5,1,[],9]]\n\n[[],[[[2],[0,4],6],4,[[1,8],8]],[[],10]]\n[[[],[5],10,[[10,5,0,7],[],1,[],7]],[3,[]],[],[2,[[8],9],[3,0,1],[[3,5],[9,2]]],[]]\n\n[[5,[[10],6,[3]],7],[3,10,[1]],[[[7,6,8,8,10],[5,5,2],[7,1,2],[]]],[3,9,[0,3]],[7]]\n[[2,[[6]],10,[9,[8],[],[1,10,4,4,9],[5]],[8]],[10],[],[3,[10,3],2,[[4,10,5,6,7],[5,7,7],6]],[10,7]]\n\n[[[[],[5,2,9],10]],[[6,[],[2,0]],[[0,9,0],7,[]],[[9,3]],[]]]\n[[10,[[1,1,8],7,3],[[8,6,10],4,0],9,6],[],[7,[],[3,[9,1,5],[10,4,1,8,1],0],[[3,2,1],4],[[8,10]]]]\n\n[[],[],[[[10,3,7,10]],0,0,6,[[6,3,4,8]]],[9,[[],[2,10]]],[[8,[],[3,10,5,8,10],6,[9,6]],6]]\n[[[],[9,3,[10,7],[6],7],[[6,10,10],[3],[10,7,0,5,0],7],6],[[[7,9,4,9,4],3,7,[7,1,7,4]],8,[9,7,[6,2,3,9,1]]],[4,[],3]]\n\n[[5,5,9],[[5,[8,9,7,2],[5,7],[5,1,4,3,4],4],[0,[],3],1,3,3],[5,5],[[2,[2,9,4],[1,3,4],[5,6,9],[1,2]],9]]\n[[[[8,6,9,9]],[[8,3,7,9],[10,1,0,3],8,[0,3,10,7]],[4,5,[3,4,3,2,6]],[[10]],9],[[[]],2],[8,10]]\n\n[[[0,1,[7]],8,[[3],4,0],[[]]],[[0,1],[[5],10,1,[4,6,0,10,0],[5,6,10,10]],4,[1,[1,8],[4,9,9,10,5]],[8,3,1,[],9]],[6],[[],[[2],9,[7,1,6,5],[9],[10,9]]],[[[0],[9,3]],[2,5,[8,1,7],[]],[],[],5]]\n[[2,[[4,3,5,5,2],4,[9,6],2,9],9,[3,2]],[[]],[[[10,9],[2],10,4,4],3,[[3,7,3],[0,2,1,9,0]],[9,6,5]]]\n\n[[],[[[8,7,10],6,[3,8],5],[2,1,[1,5,4,3]],9,[[],[],[8,3],6,[10]],2],[2,0,[[],3,2,5,[0,7,8]]],[[[5,5,6],[1,9],[6],[10],7],8,[[8,7,3],0]]]\n[[8,[],5,0],[],[10,[[],9,4,[7]],[]],[9],[4,10,0]]\n\n[[5,9],[[[10,8,5,6],5,9,7,[]],[],[0]],[[1,4]],[[[5,9,4,1],[10,7,5,9],[6],0,7],[4,8],4,10,4],[6,9,[8],1]]\n[[],[9,6,[6],7,0],[6]]\n\n[[3,1,3,5,[]]]\n[[3,[[0,8,2,10,3],[5,1,3,4,0],10,9],0,6,1],[6],[0,3,8,[2,7]],[10,2,5,[7,10],[2,3,[],[2]]]]\n\n[[3,8,5,[7,[5,2],4],[3]],[[1,[1,0,5,1],7],4],[[8],[[1,5,9,0,9],2,[]],7,[[4],[7],[0,10,2,5,5],8],[10,[1]]],[[10],[7,[5],5,[4,3,9],[]]]]\n[[],[[6],[2]],[[2,[1,9],[8,3],1],10,0],[[10,1,[5],7,2],[4,3],[[6,4,9,1,4]]],[[5,[2,6,9],[4,7,9,6,3],[1,6,0,6,0]]]]\n\n[[[[0],7,[0]],[],[10,3,[5,9],6,[2,7,10]]],[],[[[5,7,3,3],[3]],0,[7,9],[7,4,[9],8,8],[7]],[10,7,10,0,5]]\n[[[],[],[[],8,0,[8]],0,[]],[6,3,9,5,9],[],[[],7,7,[4],[[0],[6,3,6,0,9],9]]]\n\n[[5,2,[[8,0,0],8,8]]]\n[[6],[[4,[9,4],[3,1]],[6,2,0,[3]],0,7]]\n\n[[],[[],[]],[],[10,[],[[7,4,1,3,5],9,0],[],7],[]]\n[[[8,7]],[1,[0,[9],2,[]],9],[[[10,3,9,5,8],[],[]],7,[9,[3,0,3,8,9]],[[2,1],[7,2,0,2,9]]],[]]\n\n[[[],[[7,7],[4]],6,[[],7],[]],[[[3,0,0,1],[1,9,10,4,10]],2,[10,[],[5,0],3],1,[[7,6,2],5,10,0,[7,8]]],[]]\n[[[1,[2,0,9,0,8]],[[],1,0],6,[5]],[[],10,[8,[1,2]],[]]]\n\n[[2,7,[[3,4,4,2],1,[9],5,3],[[2],8,[3,7,5],9]],[7],[[3,4,[],[]]],[4,[],5,[10,5,[4,4,5,0],1]]]\n[[[0],2,7],[]]\n\n[[2],[[2,7],5,[[9],10,0],[[1,5,2,7],3,10,6,[6]],[[2,0,9,4],6]],[[[10,8,7,4,9],[10],[5,1,4],9],[[10,3,10],[],[5,9,9],[10,3,2,5,9]],[[0,7,3,10],8,3,[9,7],[3,4,9,8]],7],[[1,10,6,0],5,6]]\n[[[]],[[0,2,[4,1,9]],[],5,[[10,4,5,4,2],[10,3,0,1,3]]],[3,0]]\n\n[[8,4,4,[[],[7,9,2,8],8,6],8],[[[9],[10]],[[5,7,5],[],[4,6,0,5,5]]]]\n[[2,[[6,6,0,2,5],6,[7,1,7,9],7],[[9,3],5,[9,2,7],[9,8,3],0],2],[[[3,8,3],[3,1,5],[0,0,0,6],[5,5,4,1],[3]],[0],6,[0,[]]]]\n\n[[2,[3],[]],[2,[[10,4,6,10,5],3,4,8]],[[[],5,1,10],[9,[8,0,2,5],9,8,[6,10,5,9,1]],[3]]]\n[[4,[[7,10],9],[7,1]],[[[8],1,9,[1,10,5]],[[9]],[[4,1,3]],10,[4,2,[9],[7,8,2,1,1],5]],[[[],0,6,2],[2,[],1,[2,9,0,8,7]],[[8]],4],[[[6,3],[],5,8,[10,3,5]],6,0,6],[[[1,1,0],0,[10]]]]\n\n[[3,[[1,1,9],9,[6],8,4],[]]]\n[[],[6,[7,1],[6,10,[0,2,1,3],[],[8,4]],10,2],[[[6,10]],8,6,[10,[0,2,3],1]],[0,5,4,6,[]]]\n\n[[9,[[1,8,3,2],[3],[8,2,9,3],[6,8,7]]]]\n[[],[6,[[10,1,9]]],[10],[6,[[4]],[[2,8,10],[5,10],[2,8,3]],0],[7,5,1,[[7,10,3,1,9]],[[0,1,0,0,3],[]]]]\n\n[[1,7],[0,[],2]]\n[[[[2,0,0,5,1],3,[5,6]]]]\n\n[[8,[[0,8],2,3],10,[[6,5,0,1,6],10,8,[10,4,5]],5],[1,4,2,6,[[9,7,10,7,9],2,5]],[5,[[6,0,4,8]],7,[[2,3,2,7]]],[[4,[],7,7,5],[[],10,[],8],[[1,6,5],2,0,8,[]],[[0,9,7,1,3],9,[7,2,9,8]],[[],[1,7],2,2]],[1,8]]\n[[10,[]],[9,[]],[[4,[4],3],7,[[4,2,4],10]],[[5,[5,5,4,3],4,6,[6]],9,[[5,8,7,4,6],[],10,2,[1]]],[]]\n\n[[6,9],[0,2,[[9],0,[8,10,9,7]],7,[4,4,2,[]]],[[9],[7,[8,4],[8,2],0],[[4,2],[5],[4,6],[0,6]],[5]],[[[9,2],8,[0],9,[1,9,4]],[[7,0,2,5,5],1,[6,8,2],6,7]],[[10],9,3,5,[]]]\n[[[[4],0],[],[5,9,[9,3,4,9,7],8],3,9],[7,8,2,3,0],[4,[5,[7,2,3,9],6,[0,4,0,3],8]]]\n\n[[[[2,4,0,1],[2,10,7,6,1],7,[7,1,10],7],[],[[8],1,[9,6,5,2],4,[4]]],[[4,1,[5,9,7],[4],6],4,3,[[8,2,8,8,9],[7,0,10]]],[[]],[[],[[0,0,1,3],5],9],[1]]\n[[[[]],[9],[[6,5,0,0],[8,8,9,2],[10,10,10,8,2],[7,2,4,0,0]]],[8,[3,[6,1,5,7,4],5,0,4],3]]\n\n[[4,[]],[9,2,[0],[3,2,[2,6,7,5,6]]],[[[3],[],[4,5,9,0,2],[5,3,0,1],[2,7,7]],10,9,3,[[3,4,6,8,10],3,1,2]],[]]\n[[[8,[3,2,2],10,10,[8,7,8]],[[7,2,2],[1,8,2,7],[0,2,1,2,7]],[8],7],[10,0]]\n\n[[[[6,6,3,4,0],5],[6,7,9],5,[[4,9,1],[9,2],0,6],[7]],[7]]\n[[[0]]]\n\n[[[],8,[]],[1],[]]\n[[6,[]],[3,4],[[7,[9],3,4,7],[10,[3,10],0,3,[1,9]],[0,5,[6,3,6,7],2,9]]]\n\n[7,6,8,6]\n[7,6,8,6,4]\n\n[[[5,[10],[6,2,2],3],7,[],[],7],[[2,[7,5,3],1,7,10],6,[[],4,9],[6,[4,8]],1],[],[[[2,4,3,6,3],[0,10,8],[2,2,7]],6,[[5,7],2,5,10],[9,[0,8,0,9,7]]]]\n[[10],[3,[[3,5,5],[5,2,10],[2,9,10],[1,3,3,0,7],1],[[7,2,4,3],1,[0,8]]],[5,0,[[3],5,8],[[],9,[4,10,1],7]]]\n\n[[9,[[],1,1,4],[10,4,[5,3,1,6],10,[]],0,0],[8,7,4],[6,[3,[9,9,6,3,3],[10,0]],[[],4,[10,0,9],1]],[[4,[6,3],[0,10,8,5,5],1,7],[[]],2,3,1]]\n[[[3,[3,8],[4,9,3,8,1]]],[],[[3,[],[4,3,9],8],4,1,2,2],[],[[[5,3,8,7]]]]\n\n[[[[8,9,3,6,4],[9,10,3],[],6],[4,1,[0,2,3]],4,[[9,6],10,9,0]],[[[9,8,1,0],[8,9,5,4,6]]],[[]],[[3],6,[2,6,8,[2,1,3,3,6],[4,7,5,1]]],[2]]\n[[],[10],[[4],10,[8]]]\n\n[[3,[[9,9],[4,4,5,8,3],0,4],9,[[1,9,0],4,1,0,8]]]\n[[2,2,[6,4],[],7],[0],[10,8]]\n\n[[[[]],6,[[3,8,6,3,9]],9,6],[5,[[0,9,8,7],1,8],9,7],[4,[2,[4,8,3,6]],5,[0,8,[3,9,6,3,10]],7]]\n[[0,[],8]]\n\n[[[[6,8],[10,1,5,1,5]],[[]],[[4,0,10,6],4,[10,5,1],9],[10],[10,[],[10,2],[10,4,3,7],[3]]],[10,2,[10,[],8],[8,[1,5,0,7,5],[],[4,9,10]],9]]\n[[[],10,[],8,10],[[[],7,0,[10,0,1,10,4]],5],[8,[4,3],[[10,10,9,1],[3,0,6]],4],[[]],[]]\n"
  },
  {
    "path": "advent-of-code/2022/inputs/14",
    "content": "515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n502,32 -> 507,32\n522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47\n516,32 -> 521,32\n501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161\n512,30 -> 517,30\n522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n520,130 -> 520,133 -> 515,133 -> 515,138 -> 533,138 -> 533,133 -> 525,133 -> 525,130\n506,34 -> 511,34\n529,112 -> 529,116 -> 526,116 -> 526,122 -> 541,122 -> 541,116 -> 535,116 -> 535,112\n498,13 -> 498,15 -> 492,15 -> 492,23 -> 506,23 -> 506,15 -> 501,15 -> 501,13\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n523,63 -> 523,66 -> 515,66 -> 515,71 -> 529,71 -> 529,66 -> 528,66 -> 528,63\n501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161\n512,173 -> 517,173\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n498,13 -> 498,15 -> 492,15 -> 492,23 -> 506,23 -> 506,15 -> 501,15 -> 501,13\n545,94 -> 550,94\n539,100 -> 544,100\n522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47\n529,112 -> 529,116 -> 526,116 -> 526,122 -> 541,122 -> 541,116 -> 535,116 -> 535,112\n553,100 -> 558,100\n501,170 -> 506,170\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n498,13 -> 498,15 -> 492,15 -> 492,23 -> 506,23 -> 506,15 -> 501,15 -> 501,13\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n498,13 -> 498,15 -> 492,15 -> 492,23 -> 506,23 -> 506,15 -> 501,15 -> 501,13\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n546,100 -> 551,100\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n542,97 -> 547,97\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n535,97 -> 540,97\n533,108 -> 533,109 -> 538,109 -> 538,108\n522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47\n509,32 -> 514,32\n513,34 -> 518,34\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n520,130 -> 520,133 -> 515,133 -> 515,138 -> 533,138 -> 533,133 -> 525,133 -> 525,130\n507,164 -> 512,164\n501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161\n501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161\n557,103 -> 562,103\n538,94 -> 543,94\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n520,130 -> 520,133 -> 515,133 -> 515,138 -> 533,138 -> 533,133 -> 525,133 -> 525,130\n520,130 -> 520,133 -> 515,133 -> 515,138 -> 533,138 -> 533,133 -> 525,133 -> 525,130\n498,13 -> 498,15 -> 492,15 -> 492,23 -> 506,23 -> 506,15 -> 501,15 -> 501,13\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n523,63 -> 523,66 -> 515,66 -> 515,71 -> 529,71 -> 529,66 -> 528,66 -> 528,63\n501,28 -> 506,28\n505,173 -> 510,173\n531,87 -> 531,88 -> 543,88\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n520,130 -> 520,133 -> 515,133 -> 515,138 -> 533,138 -> 533,133 -> 525,133 -> 525,130\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n524,126 -> 524,127 -> 528,127 -> 528,126\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161\n523,63 -> 523,66 -> 515,66 -> 515,71 -> 529,71 -> 529,66 -> 528,66 -> 528,63\n508,28 -> 513,28\n501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161\n523,63 -> 523,66 -> 515,66 -> 515,71 -> 529,71 -> 529,66 -> 528,66 -> 528,63\n511,167 -> 516,167\n549,97 -> 554,97\n541,91 -> 546,91\n522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47\n522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47\n520,34 -> 525,34\n522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161\n522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47\n501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161\n505,30 -> 510,30\n543,103 -> 548,103\n510,146 -> 515,146\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n498,173 -> 503,173\n498,13 -> 498,15 -> 492,15 -> 492,23 -> 506,23 -> 506,15 -> 501,15 -> 501,13\n501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161\n523,63 -> 523,66 -> 515,66 -> 515,71 -> 529,71 -> 529,66 -> 528,66 -> 528,63\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47\n498,13 -> 498,15 -> 492,15 -> 492,23 -> 506,23 -> 506,15 -> 501,15 -> 501,13\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n533,108 -> 533,109 -> 538,109 -> 538,108\n517,146 -> 522,146\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161\n513,144 -> 518,144\n515,170 -> 520,170\n501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161\n520,130 -> 520,133 -> 515,133 -> 515,138 -> 533,138 -> 533,133 -> 525,133 -> 525,130\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n523,63 -> 523,66 -> 515,66 -> 515,71 -> 529,71 -> 529,66 -> 528,66 -> 528,63\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n519,173 -> 524,173\n532,100 -> 537,100\n524,126 -> 524,127 -> 528,127 -> 528,126\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n529,112 -> 529,116 -> 526,116 -> 526,122 -> 541,122 -> 541,116 -> 535,116 -> 535,112\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n521,148 -> 526,148\n504,167 -> 509,167\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n529,112 -> 529,116 -> 526,116 -> 526,122 -> 541,122 -> 541,116 -> 535,116 -> 535,112\n520,130 -> 520,133 -> 515,133 -> 515,138 -> 533,138 -> 533,133 -> 525,133 -> 525,130\n514,148 -> 519,148\n510,141 -> 515,141\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n533,108 -> 533,109 -> 538,109 -> 538,108\n524,126 -> 524,127 -> 528,127 -> 528,126\n550,103 -> 555,103\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161\n529,103 -> 534,103\n504,26 -> 509,26\n529,112 -> 529,116 -> 526,116 -> 526,122 -> 541,122 -> 541,116 -> 535,116 -> 535,112\n508,170 -> 513,170\n523,63 -> 523,66 -> 515,66 -> 515,71 -> 529,71 -> 529,66 -> 528,66 -> 528,63\n499,34 -> 504,34\n522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47\n529,112 -> 529,116 -> 526,116 -> 526,122 -> 541,122 -> 541,116 -> 535,116 -> 535,112\n495,32 -> 500,32\n507,148 -> 512,148\n515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60\n501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161\n531,87 -> 531,88 -> 543,88\n536,103 -> 541,103\n501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161\n522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84\n522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47\n498,30 -> 503,30\n492,34 -> 497,34\n529,112 -> 529,116 -> 526,116 -> 526,122 -> 541,122 -> 541,116 -> 535,116 -> 535,112\n"
  },
  {
    "path": "advent-of-code/2022/inputs/15",
    "content": "Sensor at x=3482210, y=422224: closest beacon is at x=2273934, y=-202439\nSensor at x=3679395, y=2737332: closest beacon is at x=4104213, y=2980736\nSensor at x=3173475, y=3948494: closest beacon is at x=3494250, y=3554521\nSensor at x=27235, y=3642190: closest beacon is at x=-190885, y=3635525\nSensor at x=3851721, y=1754784: closest beacon is at x=3145586, y=2167751\nSensor at x=327074, y=3250656: closest beacon is at x=-190885, y=3635525\nSensor at x=3499970, y=3186179: closest beacon is at x=3494250, y=3554521\nSensor at x=150736, y=2522778: closest beacon is at x=-85806, y=2000000\nSensor at x=3000768, y=3333983: closest beacon is at x=2564067, y=3163630\nSensor at x=1751302, y=1660540: closest beacon is at x=3145586, y=2167751\nSensor at x=2591068, y=2923079: closest beacon is at x=2564067, y=3163630\nSensor at x=48946, y=3999178: closest beacon is at x=-190885, y=3635525\nSensor at x=3695475, y=3863101: closest beacon is at x=3494250, y=3554521\nSensor at x=1504031, y=2760: closest beacon is at x=2273934, y=-202439\nSensor at x=3021186, y=2667125: closest beacon is at x=3145586, y=2167751\nSensor at x=1514629, y=3771171: closest beacon is at x=2564067, y=3163630\nSensor at x=234064, y=616106: closest beacon is at x=-85806, y=2000000\nSensor at x=3990843, y=3393575: closest beacon is at x=4104213, y=2980736\nSensor at x=768875, y=2665271: closest beacon is at x=-85806, y=2000000\n"
  },
  {
    "path": "advent-of-code/2022/inputs/16",
    "content": "Valve VN has flow rate=0; tunnels lead to valves LW, TK\nValve FQ has flow rate=0; tunnels lead to valves AJ, YC\nValve DO has flow rate=0; tunnels lead to valves RV, HJ\nValve MW has flow rate=0; tunnels lead to valves TE, HJ\nValve LT has flow rate=5; tunnels lead to valves KO, SG, KH, HZ, RV\nValve UJ has flow rate=0; tunnels lead to valves FW, DE\nValve IZ has flow rate=0; tunnels lead to valves LU, SX\nValve FE has flow rate=17; tunnels lead to valves WG, WI, LC\nValve KS has flow rate=25; tunnels lead to valves QA, BT\nValve HJ has flow rate=11; tunnels lead to valves MW, CZ, ZE, DO\nValve WI has flow rate=0; tunnels lead to valves WX, FE\nValve EK has flow rate=0; tunnels lead to valves KE, BS\nValve HD has flow rate=0; tunnels lead to valves KH, FW\nValve HZ has flow rate=0; tunnels lead to valves XY, LT\nValve CD has flow rate=0; tunnels lead to valves XD, LU\nValve OZ has flow rate=0; tunnels lead to valves GX, LW\nValve AA has flow rate=0; tunnels lead to valves EP, FU, DV, OU, HC\nValve OU has flow rate=0; tunnels lead to valves VX, AA\nValve XD has flow rate=10; tunnels lead to valves VX, VW, BS, XY, CD\nValve AI has flow rate=0; tunnels lead to valves KE, FW\nValve GX has flow rate=0; tunnels lead to valves OZ, WX\nValve FW has flow rate=8; tunnels lead to valves AI, FU, UJ, TK, HD\nValve KO has flow rate=0; tunnels lead to valves DV, LT\nValve DV has flow rate=0; tunnels lead to valves KO, AA\nValve CZ has flow rate=0; tunnels lead to valves LU, HJ\nValve WG has flow rate=0; tunnels lead to valves KE, FE\nValve WX has flow rate=15; tunnels lead to valves WI, GX\nValve AJ has flow rate=0; tunnels lead to valves FQ, LU\nValve LC has flow rate=0; tunnels lead to valves LW, FE\nValve XX has flow rate=0; tunnels lead to valves LA, VW\nValve RK has flow rate=0; tunnels lead to valves BX, LW\nValve YC has flow rate=22; tunnels lead to valves FQ, QA\nValve KH has flow rate=0; tunnels lead to valves HD, LT\nValve ZE has flow rate=0; tunnels lead to valves HJ, SX\nValve BX has flow rate=0; tunnels lead to valves KE, RK\nValve VS has flow rate=24; tunnel leads to valve UP\nValve SX has flow rate=16; tunnels lead to valves IZ, ZE, LV\nValve RV has flow rate=0; tunnels lead to valves LT, DO\nValve UP has flow rate=0; tunnels lead to valves VS, LW\nValve EP has flow rate=0; tunnels lead to valves AA, AU\nValve VO has flow rate=0; tunnels lead to valves KE, HC\nValve HC has flow rate=0; tunnels lead to valves AA, VO\nValve TE has flow rate=0; tunnels lead to valves LA, MW\nValve LW has flow rate=19; tunnels lead to valves UP, OZ, LC, VN, RK\nValve SG has flow rate=0; tunnels lead to valves OY, LT\nValve BT has flow rate=0; tunnels lead to valves KS, LU\nValve DE has flow rate=0; tunnels lead to valves LA, UJ\nValve BS has flow rate=0; tunnels lead to valves EK, XD\nValve VX has flow rate=0; tunnels lead to valves OU, XD\nValve TK has flow rate=0; tunnels lead to valves VN, FW\nValve HQ has flow rate=14; tunnel leads to valve LV\nValve LU has flow rate=20; tunnels lead to valves CZ, IZ, AJ, BT, CD\nValve LA has flow rate=7; tunnels lead to valves OY, XX, TE, DE, AU\nValve VW has flow rate=0; tunnels lead to valves XD, XX\nValve LV has flow rate=0; tunnels lead to valves SX, HQ\nValve XY has flow rate=0; tunnels lead to valves XD, HZ\nValve OY has flow rate=0; tunnels lead to valves SG, LA\nValve KE has flow rate=12; tunnels lead to valves VO, EK, WG, AI, BX\nValve AU has flow rate=0; tunnels lead to valves LA, EP\nValve QA has flow rate=0; tunnels lead to valves YC, KS\nValve FU has flow rate=0; tunnels lead to valves AA, FW\n"
  },
  {
    "path": "advent-of-code/2022/inputs/17",
    "content": "><<<<>>><<<><<<<>>><<<>>><<<><<<<><<>>><<<>><<<<>>>><<<><<>>><>><<<<>>><><<><<>><<<>>><<<>>>><<>><>>>><>>><<<<>>>><<<<>>><<<>>>><>>><<<>><>><<><<<>>>><>>><<>><<<><<<><<<>>><>>><<<>><<<><><<>>>><<>>><>>>><<<>>><<<><<<<>>><<<><<<<><<>><>>><<>><<<<>>>><<<>><>>><<>><<>>>><<<<><<<<><<<><<>>><>>><<><<>><<>><<>>><<>>><>>>><<<><><<>>><<<<><<>>>><>>>><<<><>><<>>><<<<>>><<<<>>>><>><>><<>>>><<<<>><<<<>>><<<<><<<<><<<<>>>><<<<>>><<>>><<>>>><>>><<<>>>><<<>><<<>>>><<><<<<>><<>>><<<<><<<>>>><<><<>>><<<<><<><><<<<>><<<>>>><>>>><<<>>>><<<<>><><<<<>><<<<><><<<<>>>><<<>>>><>><<<>><<<<>>><>>><<<><<>>>><<>><>>>><>>><<<<>><><<<>>>><<><<<<><<<>><<<<>>><<>>><<<<><>>>><<><<<>><<<><>><<>>><<<><>>><<<<><<<>>><<<<>>><<>>><<<<>><<<<><<>>><<<>>><>>>><<<>><>>>><<>>>><<<>><<>>>><><<><<<<>>>><<<>><<<><<<>>><<>>>><<>><<><<<>><><<<<><<>>>><<<<>>>><<><>><<<><<>>>><<<><<<<>>>><<<><<>>><<>>>><>><>>>><<>>>><<<>>>><<<>>>><>>><<<<>>>><<<<>><<>><>>><<>>><<><<<>>>><<<<>>>><<><<<>><<>>><>>><<><<<<><<>><<<>>>><<<>>><<<><>>><<<<>>>><<>>><>>><<<<>>><>>>><<<<>><<<<>>>><<<<>><>>><<<<>>>><<><<<<>>><<>><<>>><<<>>><><<><<<>>>><>><>><<>>><<>>>><<<<>>>><<<<>><<<<>><>>><<>>><<<<>>><<<<><>>><<<><<<<><<<>><>>><<<>><<<<>><<<<><<><<<><<<<>>><<>><<<>><<<>>><<<<><<<>>><<><>>>><<<<><<<>><<<>>>><<<<><<<>>><<><<<<>>>><<<<>>>><<>>>><<<>>>><<><>>><>>><<<<>>><<>>>><<<<>>>><<<<>>>><<<>>><><<<><><<<><><><>>><><<<<><<>>><>>>><<>>>><<<<>><<<>>><<<><><<>><<<<><<<><<>>><>>>><<<<>><<>><<>><<<<>>>><<<>>>><<<>>><>><<>><>>><<>>>><<<<>>>><<<<>>><<<><>>>><>><<<<>>>><>>>><<><<<<>>>><<<>><<<>>><<>>><<>>><><<<<><<>>>><<>>>><<<>><<>><<>>>><><<<>><<>>>><<<>><<<>>><<>>><>><<<<>>>><>>>><<<<>>>><<>>>><<>>><>>><<<>>><<>><<<<><<<<><<>>>><<>>>><<<><<<<><<<><>><>><<<><><>><>><><<<>><<<<>>><>>><<<>><<<>>><<<>>>><>>>><<<>>>><<<<>>>><<<><>>>><<<>>>><<<><<<<>>><>>>><<<>><<<<><<<>>><<<<>><><<<<>>>><<<>>><>>>><>>>><><<>><<><<<>><>>><><><<>>><><<<>>>><<><>>><<<<>><<>><><>><<<>>>><<<>>>><<><<<>>><<<<><<>>><<><<>><<>><<<<>>>><<><<<>>>><<><>>>><<><<<>><<<<>>>><<<<>><<><<<<><<<<><<>>><<<<>>><<>>>><<<<>>>><>>>><>>><<>><<<<><<<>><<>><<<>>><<<>><<<><<<<>>>><>>>><<><<>><<<>>><<<<>><<<>>>><<>>>><<<><<<>>>><<<><<<<>><<<<>>>><<><<>><<<>>><<<><<<>>>><<<<>><<><<><<<<>>>><<>><>>>><<>>>><>>>><<><<>><<<>>><>>><<<<>><>>>><<<<>>>><>><<<>>>><<<<>><<<<>>><<<>><<<<>><<<>><<<<>><<<<>>>><<<><>><<<<>>><<<<>>>><<>><<<><<<<>>><<<>><<<>>><<>><>>><<>><<<<>>><<<><>>><>>><>>><<<<>>><<<<>><<<<>>><>>><>><<<<>><<<<>>>><<><<<>>><<<<>>><>><<>>><<>><<<>><>>>><<>><<<><<<>>><<<>>><><<><<<><<>>><<>>><<>><<>>><<>>>><<<><>><>>><<<<>>><<<>>>><<>><<><<<<>><<<>>><<<><<>><>><>>><<<>>><<>><<<<>>>><<<<>>>><<>><<<><<<<>><<<>>><><<>>>><<<<>><>><<<>><<<>>>><<<<><<<>>>><<<><<<<><>>><<>><>>>><<>>><>>>><<<>><<<<><<><<>>>><<><<<<><<>><<<<>>><<<<>>>><>>><<<><>>>><<>>>><<<>><<<>>>><<>><<<<>><><<<<>>><<>>>><<<<><<>>><<<>><>>>><<<><<<<><<<><><>>><<><<<>><<>>><<<<><<>>><><<<>>><>><<>>>><<>><<>>><<>>><<>>><>><><<<><<<>>>><>>>><<><<<<>>>><<<>>><<<<>>><<<><<<>>>><<<><<<><<<<>>>><<<<><<><<<>>>><>>><<<><>><<>><<<<>>>><>><<>><<<<>>><<<<>>><>>><>>><>><<<<><<<><<<><<<<>><>>><<<><<>>><<<>><>><><><><>>><<><<<<>><<<>>>><<><<<<>>>><<<>>><><<<<>>>><>>>><<<<><<>><>><>>><>>>><<><>><<<<>><<<<>><<><<<>>>><<<<>>>><<<<>>><<><<<<>><<<<>><<<>>><<<>>><>><<<<>>><<<>><<<><<<<><<<<><<<>>><<>>><<><<>>><><<>>><<<<>><<<>>><>>>><<>><>>>><<>><<<<>>>><<><<<>>><<<>>>><>>><<>><>><<<>><>>>><<<>><<<<>>>><<>>><>><<>>>><<<<><<<<><<<>><<<>><><<<<>>>><<<>>><<<<>><><>>><<><>>>><>><<<<>>><>>><<<><>>><>><>>>><<>>><<<><><<<<>><>>>><>>>><<<>>><<<<>>><<<<>><<<<>><<<>>>><<<><<<<>><<<>>><<<><<<>>><<><<>>><<<>>><<>><<<<>>><<<>>><>><<<<><<<<><>><><<<<>><<<>><<>>>><<<>><<>><<<<>>>><<>>><<<<><<<<><<>>>><<>>><<<>><>>>><<<<><<><<>>>><<>>>><<<>><>>><>>><<<<>>><<<<>>><<>><<>>><>>><<<>>>><<>>><<<>>><<>><<<<>>><>><<<>>>><><<<<><<>>><<<<>>><<<<>>>><<<<>><>>>><>>><<><<>>><<>><<<>>><><<<<>>>><<<<><<<>>>><<<>>><<>>><>><<><<>>>><>><<<><<<<>><<<<>><<<><>><<>><<><<<<><<<><<<>><<>>>><<>>><<<<><<<>><<>>>><<<<><<>>><<>><<<<><<><<<<>>>><<>>><<<<>><<<<>>><<<<>>><<<<>><<<<><<>>>><>>>><<<>>>><>>><<<>><<>><><<<><>>>><<<<>>><<<>>>><<><<<<>>>><><>>>><<<>>>><<><<<<>><<><<<<>>><<<<><>>>><>>><<><<<>><>>>><<<>>>><<>>><<>>><<<><<>>><<<>><<>>><<<>>>><>>><<>>>><>>><>><><<>>>><>>><<>>>><>>>><>><><<<<><<<>>>><<<<>>>><<<<>>><<>>><>>>><>><<<><<<<>>><<<<>>>><<>>>><<>>>><<>><<><>><<<<>>><<<>>>><<<<>>><><<<<>><<<><><><<<><<>>>><<>>>><>>><<>><<><<<<><><>>>><<<<>>>><<<<>><>><<<>><<><<>>>><<<<>>>><<<>><>><<<>><>>><<>>>><<>><<>>>><<>><<>>>><<<><>>>><<<<>>><<>><<<><<<<><<>><<<<>><<<>>>><<>>>><<<<>>>><<>>><>>><<><<<<><<>>><<<>>>><<><<>>>><<<>>>><<<<><<><<>>><<<<>><<<>>><>><<<<>>>><<>>><<<<>>>><>><<<><<><<<>>>><<<<><<>>><>>>><<>>>><<<<>>><>>>><<<<>>><<>>><<>>><<>>>><<>><<<>>><<<><<>>><<>>><<>>><>>><<<>>>><<<<>><<<<>>>><><<>>>><<>>>><<><<<>>>><<<>>>><<<><<>>><<<>>>><<><<<>>><<>><<<>>>><<><<>>><>>><>>><<>>>><><<<<><>>><>>>><<<<>>>><<>>>><>>><<<>>>><<>>>><<><<<<>>><<<<>><><<>>>><<<>>><<<<>>><<>>>><<<<>><>>>><<<<><<<<>>>><<<<>><<<<>><<<<><<><<<><<><<><<<<><<>>><<<<>><><<<>>>><<>><>><<<<>>>><><<><<<<>><<<<>><<<>>><>><<<<>>>><<>>><>>><<<>>>><<<>>>><<<>><<>><<<><>>>><<<<>>>><>>>><<<<>>><<>>>><<<>>><<<<>><>>>><<<><<<<>>><>>><<<<>><<<>><<<>><<<>>>><>>>><<>><<<>><><>>>><<<<><<>><<>>><<<>>><>>>><<<><<<<>><<>>><<<<>>>><<>>>><<<>><<<<>>><<<><<>><>>>><<<<><<<<>>><<>><<<>>><<>><<<>>><<<>>><>>><<<<><<>>><<<<>><<<<>>>><>>><<<<>>>><>>><<<<>>>><<<<>><<><<>><<<<>><<<<>>><<>>><<<><<>><>><<<><<<<>>>><<>><<>><<<<>>><<>><<>>>><<>><><<>>>><<<<>>><<><<<>>><<<>>><>>><<<<>>>><<<>><<>>>><<<<>><>><>>><<>><<<>>>><<<><<<<>>><><<<<>>><<<>>>><<<<>>>><<<>><<><<>><<<<>>><<><<<<><>>><>>>><><<>>>><<<><<<<><><<>>><<>>><<<<>>><<<>>>><>><<<<>><<<<>>><<<<>>><<<<>><<<>>><<<>>>><<<><<>>>><<<><<<<>><<<<><<<<>><<<<>>>><<>>>><<<<>>><><<<>>>><<<><>>><<><<<<>>>><<>>><<<<>>><<<>><<<>>><<<<>>>><<<><<<>>>><<<>>><<>>>><>><<>>><<<>>><<<>>>><>>><<<>>><<><><><<<<>><<<<>><<<<>>><<<>>>><<><>><>><<><<<<>>>><>><><<<<>><<<<><>>>><<<>>>><><><<<<><>>><<<>><<<>>>><<<<>>><<<>><<<<><<>><>><>>><<><<>>>><<<<>>><>>><><><<<<>>><<<<>>><><>><<><<<>><>>>><<<<><<<>>>><>>><<<>>>><<>><>>><<<<>><<<><<<>>>><>>><<<>><>>>><<<>>><<<><<<><<<>>>><<><<<>>>><<>>><<<<>>>><>><<>><<<>><<<<>>><<<>><<>><<<>>>><<<>>>><<<<>>><<<<>><<<<>>><<<<><<>>>><<>>><<<><><>><<>><<<>><>>>><<<>><<<<>>>><<<<><<<><<<><<>><<>>><<<<>>><>><>>>><<<<>>>><>>><<>>><>>>><>>>><<<>><<<<>>>><<<><>>>><<<<><<>><<<<>>>><<>><>><<>>><<>><<>>>><<<<>><<<>>><<><<<<>><<<<>>><<<><>><<><<>><<<<>><<<>>><<<<>>><<<>>><>><>><<<<>><<<>>>><<<<>>><<>>><<<<>>><<<>>>><<<<>><<>>>><><<><<<>>>><<<<>>>><><><>>>><<<<><<<>>>><>><>><<<>>>><<<>>>><>><><<>><<<><>><<>>><><>>><<>><<>><<>><<><<<>><<>><<<<><<<<>>>><<<<>><<<<>><<<>><<<<>><<<<>><>><>>><<<>>><<<><<>>>><<>><<<><<<>>><<<>>><<<<><<<>>><<>>><>><<<>>>><<<>><>>>><><<>>>><<<<><<>>><<<<><>>><<><>>><<<<>><<<>>><>><<<>>>><<<>><<><<<><<<>><<<>>>><<<>>>><>>>><<><>>>><<>>>><<>>>><<<<>><<>>>><<><>><<<<>><<<<><<<<><><><<>>>><><>>><<>>>><>><<<<>>><>>>><><<<<>>>><>><<<><<<><<<<>>>><<<>>>><<<>>><<<<>><<<><<<>>>><<<<>>><>>>><<>><<>>>><<<>>><<><<<<>>><><<><<<<>>><><<<>>>><<<>><<<><><<<<>><>><<<><<<>><>>><<<<>>><<<>>><<<>>>><<>><<<>>>><>>>><<>><<<>>>><<<<>>>><<<>>>><<<>>>><>><>>>><<<>><<>>><<><<<<>>><<<<><<>><<>><<<>><<<>>><<<><<<<>>><<<<>><>><<<>><<<<><>>><<<>>><<>>>><<<>><>><>>><<>>>><<<<><<<<>>><<<>>><<<>>>><<<>><<<<>>><<<<>>>><>>><<<>>>><<<>><<<>>><<<>>>><<<<>>>><<>>><><<<<><<>>><<><>>><<>>><<>>>><<<<>><<>>>><<<><><<<>><><<<>>>><<>>><>>>><<>><<>>><<>>>><<<<>>>><<>>>><<<><<><<<><<>><<>>><>><<>>>><<<>>>><>><<<>><>><<<<>><>><<<><<><><<><<<<>>><<><<><<<><<>>><<<>><<<>>>><<>>><>><><<><<<<><>><<<>><<>>>><>>><<<>>><>>>><<<<>>><>><<>>>><<<>>><<><<<<>>><<<>>>><<<<>>>><<<<>>>><>>>><<<<>><><><>>>><<<>><<<<>>>><<<>>><<>><<><<<>>><<<><<<><>>>><<<<>><<<<>>><<<>>><<<>>><<>><<><><<<>>><<<>>><<<><><<>><<>>><>>><<<>>><<<<>>>><<<<><<>>>><>>>><<><<>>><>>><<>>>><><<>>>><<>><<<<>>><><<>><<>><<>>><>><>>>><<<<>>><<>><<<><<<<>>><<<<>>><<><<<<>><>>><<><<<>>><<<<>>><<>>><><>>><<<<>>>><>><<<>><<<><<><<<>>><<<<>>><<>><<>>><<><<<>><<<<>>>><>>>><<<<>>><<>>>><><<<<>>><>><<>><<<>><<<<><<<>><<<<>>><<<>>><<><>><<<<><>><<<<>><<<><<<<>>><<<>><<<>><<<<><<<><<>>>><<>><<<>>>><><<<<>>>><<<<>><<<<><<>>>><><>>>><<<>>><>>><<<>><<<<>>><<<<>>>><<<<>>><<><>><<<<>><>>>><<<<>>>><>><<>><<<>><<<>><<>><<<>>><<<<>>><<<<>><<<<>>>><<><<<>><<<>>>><>>>><<>><<>><<<>>><<>><<<<><<>>><<<>>><><<><>><>>><<>>><<<<><<><<<<><><<<>>><>>>><>>>><<<>>>><>><<<>>><>><><><<><>>><<>><<<>>><<<<>>>><<>><>>>><>>><<<>><<<>><<<<>>>><<<>><<<>>><>>>><<<<>><>><<><>>>><<<><>><<<>>>><<>>><>>><<<<>>>><<<><>>>><<<<><<<<>>><<<>>>><<<>>><<<>><<<<>>><<<<>><<<<>>>><<<<><<>>>><<>>><<>>><<<<>>>><><<<<>>>><<<>>>><>>>><<<><<><><<>><<<<>><<>><<<<>>>><<<>><<<>><<<><<<><<<<><<<>>><><>>>><>>><<<>>><<<>>><<<>><<<<>><<<<>>>><<<>>>><<>><<<>>><>>>><<>><>>>><>><<<<>>>><><<<>>>><<<>><<>>>><<<<><><<>>>><><<>><<<>><<<<>>><<<>>>><<<><>><<<><><<<<>><<<>><<<><<>>><<<>>><<<<>><>><<<><<<<>>><<<<><><><<<>><<<<>><<>><<<><<>><<<<>>><<<<>>>><<<>>><<>>>><<<<>>>><<<><<<>>>><<>>>><<<<>>><<>>>><<<>>><<<>><>>>><<<<>>><<>><<<>><<><>>>><<<><<<<>>><><<<<>><<<>>>><>><<><>>>><<<<>>><>>><<><>><><<<<>><>>><<>><<>>><<>><<>><<>>>><<<>>><>><<>>><<>>><>><><<<>><<<<>>>><<<>>>><<>><<><<>>><<>><<<>><>>><<>>>><<<<><<><<<<>><>>><<>><><<<><<<<>>>><<<>><<>>><<<<>>>><>>>><<<>>>><<<><<>><><<<<><<<>>><<<<>>><<<>>><<<>>><>><>><><<>>>><<>><<<>><<<>>><<<>>>><<><<<><>>><<<><<<>><<<>>><<>><<<>>><<>>><<<<>><>><><<<>>><<<>>>><>>><>>><<<>>><<<>>><<>>><<<<><<<<>><><<>>>><<<>>><<<><<<>>><><<>>>><<>>><<>><<<>>><<><<<>>><>><<>>><<>><<<><<>>><><<><<>>><<><><<<>>>><<<<>>>><<<>><<<<>><<<<><<<><>>>><<>>>><<><>>><<>>><<><>>>><<<<>>>><<<>><<<<>><>>><<<<>>>><<<<>>>><<<<>>>><<<<>>><><><<>>><<<>>>><<<<>><<<<><<<>><<><<><>>>><><<<>>><<>>>><<<>>>><<<<>>><<<<>>>><<<>><<<>><<<<><<<<>>>><<>><<>>>><<<<>>><<<>>><<>>><<>>>><><<<<>><<<>>><<<>><<<<>>><<<<>>>><>><>><<>>>><<<>><<<>>>><<<<>><<<<>><>>>><><>><<<<>><<<>><<<>>><><>>><<<<>>><<<>>>><<<>><><<<>><<<<>><<<<>>>><><<<>>><>><<<><>>>><<<>>>><>>>><<<>>>><<<><<<><<>>>><>><<<<>><<>>><<<<>>>><<>><<<<>>><<<>>><<<<>>>><>><<>><<<>>>><<<>>><<>>><<<>>><>>><<<<><<<<><<>>><>>\n"
  },
  {
    "path": "advent-of-code/2022/inputs/18",
    "content": "3,5,10\n8,13,17\n9,4,8\n8,8,18\n10,10,1\n12,9,14\n4,6,15\n4,10,15\n17,7,7\n17,6,9\n7,13,2\n16,4,9\n9,1,8\n5,8,14\n12,14,13\n3,7,8\n17,11,10\n11,17,14\n7,4,8\n3,11,6\n6,15,10\n6,7,5\n7,2,14\n4,7,7\n13,18,10\n9,2,11\n11,16,12\n1,10,7\n14,14,8\n4,9,15\n10,10,18\n17,9,4\n18,11,10\n14,5,7\n4,14,13\n1,11,8\n12,5,17\n9,7,4\n13,16,9\n10,18,12\n5,4,5\n4,15,10\n14,4,4\n6,4,5\n18,7,10\n5,6,3\n5,11,3\n12,10,1\n7,3,6\n8,6,3\n15,7,5\n3,8,8\n16,6,6\n5,3,8\n12,15,13\n5,4,11\n13,17,14\n15,11,7\n2,7,9\n7,1,7\n7,7,2\n7,7,17\n17,10,10\n13,14,14\n2,12,8\n6,10,3\n5,2,10\n3,8,12\n15,14,12\n12,17,14\n13,2,9\n12,2,11\n17,10,9\n3,3,7\n16,9,12\n8,12,2\n17,6,10\n3,10,4\n13,16,7\n15,11,4\n12,8,2\n17,12,11\n13,9,16\n3,4,9\n14,4,13\n13,2,13\n5,16,12\n10,18,11\n2,7,10\n14,6,13\n4,4,9\n5,5,7\n5,16,11\n3,15,9\n11,8,15\n15,15,8\n6,16,6\n9,14,17\n7,14,15\n13,10,2\n8,15,3\n2,7,13\n10,1,11\n13,13,14\n2,8,6\n6,12,4\n7,5,13\n7,3,14\n11,11,18\n5,3,7\n11,9,3\n10,17,12\n9,18,7\n14,3,6\n15,10,16\n13,8,16\n7,3,13\n13,2,10\n6,3,12\n10,7,17\n13,9,17\n15,11,15\n11,3,12\n2,10,13\n12,3,8\n8,14,5\n3,6,6\n16,14,10\n14,10,4\n10,18,9\n15,6,13\n12,2,10\n10,4,5\n14,11,17\n16,9,6\n3,7,7\n16,9,16\n11,1,8\n15,10,3\n12,10,17\n8,14,13\n4,5,7\n14,9,4\n4,12,3\n8,7,17\n16,14,8\n14,6,15\n10,17,9\n11,2,6\n6,15,4\n4,13,6\n1,8,10\n12,8,16\n4,12,14\n9,17,9\n6,16,11\n12,3,13\n13,2,11\n5,4,13\n13,9,2\n12,13,4\n3,15,10\n5,8,15\n12,4,5\n13,4,6\n10,12,17\n16,6,9\n9,10,16\n17,14,12\n14,16,7\n4,14,9\n4,3,9\n15,7,15\n10,14,5\n13,13,16\n11,7,2\n7,7,4\n12,4,10\n14,6,4\n8,9,16\n3,7,6\n13,16,13\n16,4,7\n4,3,6\n6,17,8\n10,16,14\n10,14,3\n10,1,6\n11,17,9\n2,9,7\n3,7,14\n4,5,3\n16,9,5\n16,9,13\n11,16,15\n5,5,5\n3,14,10\n4,14,6\n7,11,16\n15,7,6\n6,9,16\n15,12,14\n2,12,9\n15,14,14\n2,13,10\n17,8,10\n8,13,15\n16,6,10\n5,16,9\n11,16,5\n5,14,11\n2,11,7\n9,11,17\n8,16,12\n8,18,12\n14,7,3\n11,17,7\n9,16,10\n8,18,11\n13,6,15\n12,18,8\n12,3,7\n4,13,14\n6,16,10\n9,6,17\n9,12,16\n4,6,8\n13,4,7\n8,13,3\n3,14,9\n16,6,12\n9,16,7\n5,13,13\n18,10,9\n16,12,13\n15,5,9\n1,14,9\n6,4,9\n3,8,6\n10,15,5\n8,9,17\n12,3,11\n12,7,18\n7,9,18\n13,16,10\n5,4,7\n4,12,13\n14,14,14\n10,17,10\n6,7,18\n8,5,5\n5,13,3\n3,15,11\n15,7,7\n10,15,15\n7,14,5\n11,5,3\n15,14,4\n14,14,15\n16,5,8\n16,11,7\n5,3,14\n14,12,15\n9,18,8\n15,3,7\n15,7,13\n16,8,9\n10,11,2\n6,5,5\n3,14,5\n16,10,4\n8,8,1\n4,12,6\n8,2,6\n8,15,14\n15,5,5\n8,2,14\n12,10,2\n2,11,12\n15,16,12\n14,8,16\n14,15,4\n2,10,9\n15,14,9\n8,13,16\n14,4,8\n14,5,15\n9,15,14\n5,6,6\n4,14,11\n17,8,11\n5,15,10\n9,4,9\n12,4,4\n15,12,6\n5,13,16\n15,7,4\n11,8,18\n6,11,15\n17,8,7\n7,9,15\n14,15,12\n10,8,17\n12,14,5\n4,4,10\n10,4,4\n14,16,11\n17,10,13\n10,2,13\n15,6,14\n17,10,8\n9,16,4\n12,5,15\n13,16,8\n4,8,14\n17,8,8\n11,18,10\n4,8,16\n2,13,11\n17,8,14\n4,13,11\n2,8,12\n5,3,11\n18,13,8\n11,3,14\n1,9,12\n12,13,16\n13,4,13\n15,15,11\n8,10,17\n16,11,6\n8,16,10\n9,1,10\n1,8,7\n3,7,4\n11,4,4\n7,13,16\n9,6,4\n16,7,13\n11,6,15\n5,15,4\n7,14,3\n4,11,4\n3,10,12\n3,12,10\n10,16,13\n10,3,6\n10,3,5\n9,2,7\n9,3,14\n15,6,7\n13,3,7\n5,12,4\n16,5,6\n14,13,15\n17,8,6\n5,9,16\n17,10,5\n7,10,2\n5,14,12\n7,2,11\n16,10,14\n8,10,2\n13,4,14\n7,3,4\n12,1,10\n18,9,11\n8,14,15\n14,13,14\n9,9,17\n13,5,13\n2,14,10\n8,8,2\n2,10,7\n11,8,2\n8,17,7\n9,15,16\n11,17,12\n11,17,13\n2,10,5\n12,5,4\n6,17,4\n3,10,10\n11,16,13\n7,2,9\n7,14,4\n5,5,16\n14,14,6\n4,14,14\n17,7,10\n9,12,3\n5,13,4\n13,11,2\n10,15,3\n14,5,10\n14,7,16\n5,5,15\n4,7,5\n14,5,4\n8,10,16\n9,17,8\n7,12,17\n16,7,4\n17,8,12\n14,9,3\n6,10,16\n6,6,16\n7,13,3\n10,13,17\n17,9,11\n13,15,5\n15,14,15\n6,13,16\n12,17,8\n4,6,14\n10,17,8\n7,16,10\n13,8,2\n17,11,4\n15,14,8\n10,13,16\n2,8,8\n4,14,12\n9,16,5\n13,14,13\n13,7,17\n5,14,5\n13,14,16\n15,15,6\n7,7,16\n15,12,15\n7,4,14\n11,6,3\n2,12,10\n6,15,9\n11,15,5\n7,3,8\n4,15,9\n10,5,3\n14,15,5\n10,6,3\n16,4,6\n11,9,16\n9,7,18\n6,2,8\n4,5,13\n8,7,16\n12,3,10\n10,8,1\n4,9,8\n7,17,6\n7,4,16\n9,10,18\n13,15,8\n11,2,11\n14,4,7\n3,10,6\n4,7,15\n17,11,14\n6,16,4\n1,7,10\n8,4,5\n14,16,9\n11,13,2\n3,6,7\n5,15,9\n15,13,13\n10,4,15\n15,8,6\n8,3,13\n13,12,3\n15,4,10\n10,17,13\n11,5,14\n16,7,7\n17,6,11\n14,5,12\n2,7,7\n15,13,14\n3,14,6\n17,11,7\n10,11,17\n13,7,2\n3,11,4\n16,13,14\n4,2,10\n16,12,9\n17,6,12\n2,4,10\n6,16,5\n6,11,17\n15,9,16\n13,16,12\n13,5,5\n9,17,7\n5,6,13\n17,7,6\n11,9,18\n9,4,17\n10,5,16\n6,11,5\n5,4,6\n5,15,13\n8,2,11\n8,9,3\n6,17,6\n6,4,7\n14,3,7\n3,13,6\n10,3,10\n7,5,4\n12,4,16\n6,3,11\n9,12,2\n5,9,15\n5,13,15\n13,16,14\n11,16,9\n15,4,9\n14,10,16\n13,3,5\n7,17,10\n8,9,18\n16,9,11\n15,6,4\n15,12,13\n6,11,3\n17,9,12\n14,13,5\n2,10,8\n9,11,16\n5,7,16\n11,15,14\n3,11,5\n11,11,1\n5,6,14\n4,7,14\n3,9,14\n8,14,2\n12,3,14\n7,16,6\n6,3,10\n17,13,11\n14,6,5\n14,4,14\n7,8,3\n8,12,1\n4,6,5\n5,9,3\n15,3,11\n11,16,14\n2,9,5\n13,17,10\n2,10,10\n11,5,4\n6,6,3\n15,6,8\n13,8,3\n3,10,5\n8,16,14\n4,12,5\n4,9,3\n11,11,3\n6,9,2\n2,13,12\n14,10,13\n9,6,16\n13,15,13\n10,2,9\n4,6,3\n8,5,16\n5,17,10\n15,3,10\n3,13,9\n10,13,3\n4,10,14\n9,8,2\n3,6,12\n11,13,18\n16,12,6\n5,13,14\n4,7,16\n3,5,13\n8,3,12\n3,15,7\n16,5,9\n9,15,15\n7,12,1\n9,4,4\n14,7,14\n4,7,4\n12,5,5\n7,13,4\n16,6,7\n17,7,12\n8,10,18\n16,11,14\n15,16,7\n4,15,6\n7,12,16\n10,16,6\n4,5,6\n8,14,3\n5,12,11\n9,10,1\n15,10,14\n12,6,1\n11,4,6\n4,14,7\n16,14,6\n16,7,8\n11,6,11\n12,6,2\n14,14,4\n12,16,7\n7,16,13\n9,5,16\n9,17,13\n9,2,10\n3,9,15\n11,18,9\n4,6,12\n9,6,14\n4,3,7\n16,13,6\n11,13,15\n3,7,9\n15,14,10\n4,6,7\n10,7,4\n17,14,9\n5,6,15\n12,6,3\n11,14,4\n5,11,13\n11,14,5\n8,8,3\n11,9,2\n10,14,4\n12,6,16\n13,8,17\n17,6,7\n14,16,12\n9,18,9\n5,6,12\n14,11,4\n8,12,4\n8,15,16\n10,4,3\n6,12,3\n2,9,6\n3,14,12\n10,2,10\n9,4,12\n18,10,10\n4,5,14\n7,8,17\n11,15,11\n17,10,7\n8,12,17\n8,1,10\n11,3,15\n10,13,1\n8,16,13\n14,15,7\n14,7,4\n7,17,12\n12,4,13\n9,7,16\n7,3,12\n3,15,13\n5,12,16\n2,10,11\n11,8,1\n5,8,16\n3,5,7\n10,10,3\n16,12,8\n6,10,1\n4,13,7\n7,18,10\n18,10,11\n16,10,12\n8,11,16\n4,13,13\n12,16,5\n14,11,5\n5,9,14\n3,4,11\n18,13,10\n17,11,11\n7,8,1\n5,14,15\n8,17,14\n7,5,14\n3,5,14\n9,2,12\n9,15,3\n6,16,14\n9,8,3\n12,15,4\n9,2,14\n4,7,3\n14,6,7\n4,11,6\n17,9,6\n4,10,4\n2,13,13\n1,7,9\n10,5,13\n18,10,7\n7,10,17\n4,4,14\n3,10,15\n12,6,15\n10,10,17\n5,15,11\n17,12,7\n12,14,14\n4,4,8\n6,15,14\n13,16,5\n14,5,5\n4,4,6\n10,8,18\n13,17,8\n16,8,8\n12,2,13\n12,16,13\n5,3,5\n4,4,7\n9,5,15\n12,14,2\n12,4,6\n6,5,6\n13,8,5\n4,15,7\n17,12,6\n5,5,10\n11,14,16\n14,3,13\n18,7,9\n15,8,3\n1,8,8\n3,8,13\n11,13,17\n6,17,12\n7,12,15\n11,9,1\n15,9,15\n16,12,11\n12,6,17\n15,15,12\n9,16,12\n1,7,7\n6,4,12\n3,13,11\n3,9,12\n15,17,8\n5,7,3\n7,8,2\n9,14,5\n5,15,8\n10,15,4\n6,10,2\n4,5,5\n8,5,14\n4,5,10\n6,12,14\n7,4,6\n4,13,3\n14,5,16\n9,17,12\n4,14,15\n7,8,16\n15,15,7\n18,12,8\n10,9,2\n5,7,15\n10,4,6\n12,7,17\n10,16,12\n3,12,7\n5,3,12\n15,5,3\n16,15,10\n17,9,10\n9,4,15\n6,14,15\n6,17,9\n10,15,7\n4,11,5\n13,6,13\n9,3,6\n5,4,15\n15,14,7\n6,7,3\n12,12,16\n15,15,10\n16,10,7\n6,3,7\n8,7,2\n2,8,11\n6,8,3\n5,5,4\n5,15,12\n17,13,9\n13,7,3\n13,15,6\n2,9,11\n10,12,2\n8,11,3\n10,13,4\n12,9,2\n15,9,5\n7,10,3\n11,10,17\n7,7,3\n12,17,11\n8,8,15\n2,14,9\n8,8,16\n9,9,18\n5,15,5\n15,13,12\n5,12,15\n2,7,8\n18,12,11\n10,15,14\n16,12,12\n11,3,5\n11,10,18\n16,5,10\n7,16,14\n2,11,10\n14,10,15\n4,8,4\n13,7,16\n9,17,10\n13,4,11\n9,5,4\n7,3,10\n8,17,10\n17,8,5\n6,4,15\n9,17,4\n4,8,3\n13,16,6\n13,15,11\n6,12,16\n9,18,11\n4,14,8\n10,14,17\n6,3,5\n6,6,4\n11,14,15\n13,11,3\n12,13,2\n6,17,13\n4,11,16\n7,4,5\n12,3,6\n6,7,15\n17,13,8\n14,7,15\n11,7,3\n12,15,14\n11,2,15\n9,3,12\n12,16,11\n5,3,9\n12,16,15\n8,8,17\n4,12,4\n18,8,9\n4,12,15\n5,6,4\n10,5,4\n1,10,11\n16,13,11\n5,16,8\n9,4,14\n12,13,17\n11,13,4\n12,2,8\n8,17,12\n17,11,13\n13,10,16\n13,17,6\n9,14,2\n16,5,7\n16,9,7\n3,10,13\n14,4,5\n16,14,13\n8,4,8\n4,9,5\n8,12,3\n14,14,5\n12,10,16\n11,6,17\n16,6,8\n6,2,10\n14,3,11\n17,7,5\n3,9,5\n2,8,7\n5,5,12\n11,4,13\n10,7,16\n9,14,6\n17,11,12\n10,2,6\n9,11,18\n11,3,13\n13,6,16\n15,9,6\n7,14,2\n13,6,3\n9,4,16\n16,13,8\n8,17,5\n14,10,3\n10,2,5\n2,6,10\n11,1,10\n5,10,17\n2,13,4\n4,11,7\n5,14,3\n15,14,5\n14,16,14\n15,14,13\n16,11,11\n17,10,6\n4,17,7\n4,16,11\n12,8,1\n8,6,2\n15,5,10\n13,6,14\n18,9,10\n10,8,3\n10,14,16\n4,13,10\n8,7,3\n5,3,10\n7,10,16\n12,10,3\n9,6,15\n7,15,4\n8,4,15\n15,11,16\n14,4,15\n8,17,8\n12,6,4\n9,2,8\n9,14,4\n6,2,11\n16,7,10\n15,11,5\n6,8,2\n10,15,13\n12,15,5\n10,1,9\n3,14,8\n4,16,10\n2,12,12\n9,17,11\n8,15,5\n9,17,6\n16,8,14\n14,8,4\n3,15,8\n18,10,8\n7,2,7\n13,15,14\n5,4,14\n10,16,4\n14,5,14\n16,11,15\n9,3,7\n1,12,8\n15,5,6\n12,15,2\n4,8,15\n17,13,12\n5,8,3\n15,10,15\n3,11,13\n18,11,9\n8,5,3\n17,6,8\n16,7,6\n15,5,12\n9,14,3\n4,14,5\n3,9,7\n6,5,13\n5,11,6\n14,2,10\n14,15,8\n10,17,15\n8,1,12\n16,15,7\n13,11,4\n12,17,10\n6,14,7\n8,6,14\n8,9,1\n10,12,3\n12,18,11\n10,9,3\n5,14,14\n1,9,10\n5,13,5\n11,17,10\n16,8,5\n11,15,13\n6,16,9\n11,4,15\n5,10,2\n6,5,4\n17,12,13\n10,9,1\n6,9,15\n13,12,15\n7,4,15\n7,4,13\n5,6,16\n10,3,14\n2,13,9\n5,9,18\n8,6,15\n6,14,5\n14,17,8\n18,9,8\n13,5,15\n10,17,7\n5,7,13\n13,14,15\n11,11,2\n12,2,7\n12,11,2\n9,12,1\n15,16,8\n3,9,10\n9,16,13\n3,6,10\n5,15,14\n15,5,14\n12,18,10\n11,15,12\n14,16,5\n5,1,12\n6,5,8\n10,16,7\n4,5,8\n11,1,7\n8,2,9\n17,10,14\n14,8,15\n8,17,13\n15,4,11\n14,5,13\n14,6,3\n17,13,10\n15,7,3\n8,11,2\n8,3,5\n17,10,11\n16,7,12\n15,11,13\n16,12,5\n4,8,10\n7,5,3\n2,9,12\n6,15,6\n7,4,4\n13,3,8\n10,10,2\n9,1,6\n13,10,3\n11,4,2\n7,4,9\n2,9,10\n7,9,16\n15,13,5\n16,14,9\n7,17,11\n16,10,9\n13,10,15\n14,2,13\n9,2,9\n10,6,16\n12,5,16\n7,15,8\n11,3,8\n5,9,5\n7,3,11\n2,6,11\n2,10,6\n6,5,15\n9,18,12\n11,10,2\n4,3,11\n17,9,9\n10,18,10\n16,6,13\n14,4,12\n12,12,2\n6,13,4\n12,9,17\n15,5,11\n17,12,8\n2,15,11\n14,5,9\n16,12,10\n14,9,15\n10,13,2\n5,10,3\n3,7,5\n16,12,4\n10,9,15\n4,16,8\n6,3,8\n12,12,17\n15,6,12\n10,2,11\n13,9,5\n9,15,13\n7,9,2\n8,3,15\n17,5,10\n13,4,4\n11,2,12\n4,16,12\n13,12,4\n17,6,13\n15,8,15\n3,6,8\n2,9,4\n13,12,2\n8,3,6\n9,18,10\n3,4,7\n10,7,15\n5,3,6\n9,9,1\n7,2,12\n10,4,16\n14,11,3\n8,7,18\n11,2,13\n6,11,4\n9,10,3\n12,18,7\n15,5,4\n16,13,12\n16,15,8\n12,3,3\n16,11,5\n14,16,8\n11,3,4\n16,13,9\n9,2,5\n7,14,14\n13,11,5\n2,13,6\n8,13,2\n18,11,8\n12,9,15\n4,10,16\n18,8,7\n7,11,15\n6,8,17\n15,12,16\n4,6,13\n6,16,13\n6,14,3\n13,6,4\n15,9,13\n7,9,17\n4,12,16\n15,7,11\n16,14,7\n2,11,11\n10,1,13\n6,18,10\n15,13,11\n10,16,11\n13,3,13\n9,6,2\n14,13,3\n7,2,8\n12,2,6\n9,8,18\n3,13,12\n7,6,3\n3,7,12\n6,3,9\n9,8,17\n8,4,13\n12,15,7\n5,17,8\n16,16,8\n7,6,14\n10,9,17\n14,3,8\n4,11,15\n6,6,2\n13,6,6\n3,11,12\n15,6,6\n14,8,7\n5,16,6\n10,3,15\n9,8,1\n14,4,10\n11,17,6\n6,4,14\n14,11,15\n6,6,15\n11,12,15\n15,11,8\n7,18,8\n12,4,11\n10,3,13\n6,10,18\n10,16,15\n14,5,3\n14,13,11\n6,15,12\n10,2,8\n16,10,13\n16,8,11\n6,1,10\n9,16,8\n10,3,4\n16,6,5\n16,6,11\n8,15,15\n16,15,12\n8,15,13\n15,8,4\n3,6,9\n16,8,16\n6,15,11\n12,11,17\n10,2,12\n9,6,3\n11,12,16\n16,16,10\n7,2,13\n8,1,5\n6,4,13\n5,2,11\n6,14,16\n13,2,7\n9,18,13\n14,4,6\n15,13,6\n14,15,10\n8,7,1\n13,13,7\n14,16,6\n11,10,1\n8,17,11\n9,17,15\n6,11,16\n12,3,12\n17,12,10\n10,18,8\n16,8,7\n17,5,12\n11,5,6\n3,13,5\n10,5,15\n4,8,5\n1,10,9\n6,4,8\n11,15,6\n10,3,12\n11,5,16\n5,16,7\n6,15,13\n2,7,5\n3,5,8\n2,9,8\n9,14,15\n3,13,13\n4,15,13\n7,2,6\n2,8,14\n4,14,10\n11,6,5\n15,4,12\n11,12,18\n15,13,7\n12,16,12\n16,9,8\n16,9,15\n15,12,11\n7,15,5\n16,8,13\n3,12,12\n15,7,16\n14,2,12\n15,16,6\n9,17,5\n2,10,12\n14,14,7\n11,14,3\n8,4,14\n7,17,5\n7,11,17\n16,15,9\n13,4,5\n3,14,7\n8,6,17\n7,12,2\n13,13,3\n10,1,8\n13,17,7\n3,8,5\n12,8,17\n12,14,4\n4,9,9\n13,17,11\n5,9,2\n9,1,7\n11,15,4\n8,5,15\n3,8,11\n11,16,6\n4,8,11\n3,5,11\n13,9,3\n16,4,11\n18,8,13\n14,13,7\n13,3,11\n12,17,7\n6,3,6\n16,5,12\n4,4,5\n13,6,17\n3,9,13\n5,7,17\n14,8,14\n1,7,8\n14,7,2\n6,10,17\n10,15,6\n14,11,2\n9,3,4\n12,12,15\n14,5,6\n12,17,9\n11,16,7\n17,10,12\n13,5,8\n9,18,6\n16,11,12\n12,8,18\n17,8,9\n12,8,3\n1,11,12\n7,5,5\n3,11,7\n8,2,12\n3,9,4\n8,12,18\n10,7,2\n4,13,5\n13,1,7\n11,11,16\n14,14,11\n12,15,6\n9,17,14\n7,5,15\n13,12,16\n4,2,9\n4,15,8\n6,16,8\n6,5,16\n14,7,12\n18,13,9\n5,14,16\n8,14,16\n15,10,7\n13,2,12\n8,6,5\n6,15,5\n12,9,3\n3,10,14\n4,5,4\n16,5,11\n9,5,3\n4,3,8\n13,17,9\n14,9,16\n3,9,9\n13,15,7\n13,14,10\n4,7,9\n5,14,6\n3,3,8\n15,13,15\n3,3,12\n14,13,6\n13,3,12\n10,4,14\n15,7,14\n6,15,15\n11,2,10\n9,9,3\n14,6,12\n5,14,7\n17,7,13\n1,11,11\n7,15,7\n14,14,13\n15,3,8\n7,6,16\n16,4,8\n10,14,14\n10,2,7\n5,4,12\n4,9,6\n13,14,4\n16,8,12\n8,12,16\n12,7,2\n7,9,14\n10,8,16\n7,7,1\n3,15,6\n15,6,16\n2,11,15\n2,5,9\n16,13,13\n17,12,14\n5,11,12\n4,11,14\n10,13,14\n14,15,11\n7,15,9\n7,17,9\n6,3,13\n9,4,5\n17,9,13\n13,9,4\n7,15,16\n11,2,8\n4,11,2\n16,10,8\n14,15,6\n14,13,8\n14,5,8\n16,7,14\n17,11,5\n10,17,6\n2,12,11\n17,12,4\n4,16,9\n11,13,5\n15,2,9\n10,7,18\n10,5,6\n7,1,10\n6,7,14\n6,14,4\n9,5,17\n11,12,2\n13,3,14\n6,14,13\n3,9,11\n17,11,8\n8,4,7\n16,9,14\n16,8,15\n13,11,1\n9,2,13\n9,14,16\n6,17,11\n3,14,11\n10,5,17\n12,16,14\n10,11,16\n16,5,13\n9,16,15\n6,7,17\n2,8,9\n4,13,12\n6,8,16\n13,15,12\n11,11,15\n12,17,13\n2,9,9\n5,14,4\n3,6,13\n4,16,7\n5,5,13\n12,11,3\n8,11,17\n7,5,17\n3,12,5\n10,1,10\n11,3,7\n14,10,2\n8,13,5\n13,4,3\n16,11,8\n8,2,5\n8,4,16\n16,12,7\n17,11,6\n6,7,16\n16,11,9\n10,7,3\n4,6,9\n6,5,3\n7,17,14\n13,13,4\n16,12,14\n6,12,15\n16,11,4\n7,15,3\n2,13,7\n11,16,11\n10,5,2\n7,18,11\n15,4,6\n10,11,18\n4,13,15\n12,16,6\n3,16,10\n7,16,7\n5,10,15\n5,14,9\n14,17,7\n10,13,18\n6,4,6\n11,17,4\n10,6,17\n7,16,12\n16,12,15\n4,9,16\n9,15,6\n4,4,11\n5,11,16\n8,3,4\n15,10,5\n4,10,3\n3,4,8\n10,6,15\n6,9,1\n13,13,12\n6,17,10\n12,14,16\n14,13,4\n8,15,9\n16,9,4\n8,10,3\n14,10,14\n2,12,14\n14,3,5\n17,9,7\n16,10,6\n10,17,14\n13,14,3\n9,7,17\n9,12,17\n10,8,2\n11,6,1\n6,8,18\n6,14,2\n9,2,6\n13,9,18\n5,6,5\n1,11,10\n6,15,3\n12,5,6\n11,4,16\n9,3,11\n14,8,17\n2,7,11\n10,3,7\n16,15,11\n15,4,8\n3,13,7\n6,13,15\n14,8,5\n11,9,17\n5,15,15\n8,15,2\n8,16,7\n14,8,3\n11,3,6\n16,11,13\n13,13,17\n3,8,14\n14,17,9\n8,9,2\n6,12,2\n9,15,4\n4,12,9\n1,6,9\n5,7,4\n6,13,5\n6,9,18\n3,15,12\n7,11,4\n9,3,13\n3,12,14\n4,5,9\n2,6,9\n14,9,17\n12,12,3\n3,12,13\n2,7,14\n9,9,15\n9,3,5\n3,16,11\n9,5,13\n7,2,10\n15,5,13\n8,16,5\n8,5,2\n13,5,16\n5,4,4\n13,11,14\n11,3,11\n11,12,17\n8,10,1\n10,7,1\n4,3,10\n8,16,4\n12,17,6\n18,9,9\n17,5,8\n7,12,18\n7,15,15\n7,16,8\n16,14,12\n7,17,13\n6,5,11\n2,12,7\n5,3,13\n15,6,5\n17,12,12\n17,7,9\n1,10,12\n3,13,8\n4,11,12\n6,16,12\n12,2,14\n11,11,17\n13,13,15\n11,8,16\n18,12,9\n11,8,3\n7,9,4\n13,12,17\n12,12,13\n13,15,4\n11,2,9\n11,18,8\n4,7,8\n8,14,4\n9,10,17\n4,5,11\n16,4,10\n2,6,8\n15,2,8\n9,3,15\n5,10,16\n3,13,14\n4,8,6\n2,9,13\n12,16,8\n8,1,9\n8,2,13\n2,11,9\n15,11,3\n5,15,7\n13,11,15\n6,3,14\n10,11,1\n4,6,4\n4,12,7\n15,6,11\n15,11,14\n7,17,7\n10,16,5\n9,16,14\n5,16,10\n11,4,14\n5,10,14\n16,10,5\n13,3,10\n6,9,17\n6,18,12\n17,7,8\n13,17,12\n4,9,2\n13,14,6\n2,8,13\n8,1,11\n17,8,13\n5,10,4\n12,1,9\n2,9,14\n5,8,2\n1,12,10\n5,5,8\n7,5,6\n14,3,12\n14,17,11\n4,7,13\n17,13,7\n11,5,17\n13,13,5\n6,11,2\n10,18,6\n10,17,11\n18,11,7\n8,6,16\n8,11,1\n6,15,7\n5,13,7\n8,15,6\n5,15,6\n8,2,7\n15,12,4\n6,2,9\n1,9,11\n14,16,13\n17,7,11\n11,14,13\n11,2,14\n5,12,2\n9,13,5\n5,9,6\n13,3,6\n5,16,13\n3,6,11\n5,2,12\n11,15,3\n17,14,10\n7,3,7\n5,5,6\n2,14,8\n8,8,19\n8,2,8\n2,11,8\n7,18,12\n9,4,3\n3,14,13\n11,8,17\n9,10,2\n6,18,9\n6,14,6\n4,4,12\n11,16,10\n10,4,12\n5,7,5\n7,13,15\n1,10,8\n2,11,13\n17,5,11\n10,6,4\n3,5,9\n14,15,9\n16,10,15\n7,3,5\n5,7,2\n3,5,6\n7,1,11\n12,11,4\n10,6,2\n3,12,4\n1,12,9\n13,15,9\n13,3,4\n15,13,10\n14,13,13\n16,3,9\n5,8,4\n6,13,9\n8,3,10\n10,12,1\n11,4,17\n4,13,16\n14,11,14\n5,2,9\n9,15,9\n12,2,9\n1,10,5\n5,12,12\n11,1,9\n15,9,14\n6,12,5\n1,11,9\n13,1,10\n10,12,18\n12,17,12\n12,1,8\n9,7,3\n7,1,8\n2,13,8\n8,2,10\n15,8,12\n11,7,1\n11,14,14\n14,6,16\n11,10,4\n15,8,5\n11,18,14\n3,12,6\n13,7,15\n10,9,0\n7,15,14\n13,11,16\n15,16,10\n15,13,4\n9,13,16\n11,13,16\n7,12,3\n10,16,3\n10,3,9\n16,13,7\n3,7,11\n6,16,7\n15,16,9\n12,2,12\n5,12,17\n10,16,8\n11,2,5\n14,3,9\n6,2,13\n7,7,5\n15,9,4\n4,13,9\n14,12,3\n2,15,8\n15,16,11\n5,14,13\n11,15,7\n14,12,4\n6,4,4\n4,11,3\n14,12,6\n12,16,16\n5,6,11\n12,3,5\n12,13,3\n6,13,3\n12,4,12\n16,15,6\n12,4,14\n14,7,7\n1,13,12\n10,2,14\n16,10,10\n5,8,6\n14,14,10\n3,7,13\n4,9,14\n15,10,6\n14,4,9\n12,4,3\n2,6,13\n7,5,10\n15,17,10\n14,9,2\n3,8,9\n11,10,3\n5,8,1\n4,5,12\n3,8,10\n9,6,18\n13,13,2\n10,12,4\n12,5,3\n14,2,9\n8,15,4\n14,16,10\n16,4,14\n16,7,5\n7,6,4\n11,7,17\n1,7,11\n8,17,6\n12,4,15\n2,7,15\n8,18,8\n15,10,4\n2,4,11\n4,14,4\n4,10,6\n13,14,5\n7,6,15\n13,1,8\n9,4,13\n14,6,14\n9,9,16\n14,15,13\n6,5,2\n7,10,18\n7,16,15\n18,6,7\n2,7,12\n11,12,1\n2,12,13\n12,15,16\n17,5,9\n14,3,14\n3,8,7\n1,11,7\n1,8,11\n12,15,15\n12,16,9\n12,10,4\n5,5,14\n2,5,8\n10,4,17\n7,3,9\n9,1,9\n7,7,15\n3,4,12\n13,6,2\n4,17,9\n15,3,12\n12,9,16\n15,15,14\n11,7,16\n6,5,12\n13,7,7\n15,12,5\n7,9,3\n11,17,8\n4,10,13\n7,13,17\n15,15,13\n11,6,2\n6,4,16\n3,6,14\n11,1,11\n13,3,15\n13,8,14\n13,10,18\n15,10,2\n12,9,18\n9,15,5\n14,14,16\n6,4,11\n3,9,6\n8,6,4\n6,11,1\n15,9,8\n8,13,13\n8,16,6\n8,16,11\n8,3,7\n16,13,10\n7,14,16\n6,9,3\n6,14,14\n10,11,0\n6,12,6\n5,17,13\n14,7,5\n6,17,7\n14,12,5\n1,7,13\n8,4,4\n13,16,11\n5,6,8\n15,9,12\n18,11,11\n11,18,11\n7,4,7\n11,3,9\n18,7,7\n11,11,14\n9,3,9\n5,4,8\n7,13,14\n11,7,18\n17,4,8\n10,14,18\n15,7,10\n9,13,3\n16,14,14\n11,15,15\n12,10,0\n15,8,14\n14,16,15\n5,9,8\n13,7,4\n18,6,8\n11,17,11\n6,10,4\n10,14,2\n3,11,9\n14,3,10\n12,13,11\n11,3,10\n8,18,7\n10,18,7\n1,6,11\n4,9,4\n12,10,18\n9,1,11\n13,2,8\n14,4,11\n10,9,16\n7,11,2\n5,9,4\n6,15,8\n9,13,18\n10,4,13\n15,5,7\n17,15,9\n10,6,1\n2,6,6\n12,4,7\n8,16,9\n16,7,9\n10,6,14\n15,9,3\n10,6,18\n9,4,6\n8,13,11\n13,8,4\n4,11,9\n11,6,16\n12,5,14\n5,12,14\n8,4,6\n10,1,7\n18,10,12\n18,8,12\n12,7,5\n10,15,2\n13,3,3\n8,4,3\n6,6,17\n7,16,16\n15,15,5\n8,3,9\n4,12,12\n2,12,6\n9,13,2\n8,2,4\n15,4,13\n3,10,9\n2,14,7\n14,7,17\n2,5,6\n11,5,2\n6,2,6\n16,7,15\n7,15,10\n7,18,9\n16,8,6\n8,5,17\n18,12,7\n8,7,15\n4,6,6\n18,6,10\n13,5,4\n4,11,13\n7,15,6\n7,6,6\n3,14,14\n4,10,10\n13,5,14\n4,10,5\n3,5,12\n12,13,15\n9,11,1\n6,8,14\n6,1,9\n5,17,9\n3,7,10\n9,8,16\n7,5,9\n"
  },
  {
    "path": "advent-of-code/2022/inputs/19",
    "content": "Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 14 clay. Each geode robot costs 2 ore and 16 obsidian.\nBlueprint 2: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 15 clay. Each geode robot costs 2 ore and 7 obsidian.\nBlueprint 3: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.\nBlueprint 4: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 3 ore and 16 obsidian.\nBlueprint 5: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 2 ore and 10 obsidian.\nBlueprint 6: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 4 ore and 8 obsidian.\nBlueprint 7: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 9 clay. Each geode robot costs 2 ore and 20 obsidian.\nBlueprint 8: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 20 clay. Each geode robot costs 3 ore and 14 obsidian.\nBlueprint 9: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 3 ore and 18 obsidian.\nBlueprint 10: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 4 ore and 16 obsidian.\nBlueprint 11: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 3 ore and 15 obsidian.\nBlueprint 12: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 8 obsidian.\nBlueprint 13: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 2 ore and 17 obsidian.\nBlueprint 14: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 19 clay. Each geode robot costs 3 ore and 10 obsidian.\nBlueprint 15: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 17 clay. Each geode robot costs 4 ore and 20 obsidian.\nBlueprint 16: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 20 obsidian.\nBlueprint 17: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 12 clay. Each geode robot costs 3 ore and 15 obsidian.\nBlueprint 18: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 19 clay. Each geode robot costs 3 ore and 13 obsidian.\nBlueprint 19: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 18 clay. Each geode robot costs 2 ore and 19 obsidian.\nBlueprint 20: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 2 ore and 9 obsidian.\nBlueprint 21: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 2 ore and 20 obsidian.\nBlueprint 22: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 6 clay. Each geode robot costs 2 ore and 16 obsidian.\nBlueprint 23: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 6 clay. Each geode robot costs 4 ore and 11 obsidian.\nBlueprint 24: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 2 ore and 10 obsidian.\nBlueprint 25: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 14 obsidian.\nBlueprint 26: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 15 clay. Each geode robot costs 4 ore and 16 obsidian.\nBlueprint 27: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 4 ore and 11 obsidian.\nBlueprint 28: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 4 ore and 17 obsidian.\nBlueprint 29: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 11 clay. Each geode robot costs 3 ore and 14 obsidian.\nBlueprint 30: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 8 clay. Each geode robot costs 4 ore and 14 obsidian.\n"
  },
  {
    "path": "advent-of-code/2022/inputs/20",
    "content": "-7594\n-3313\n-7404\n-8208\n-9315\n-9537\n-5293\n860\n-1368\n1984\n7865\n3261\n-8361\n7267\n8401\n9525\n-6388\n1575\n-2979\n4074\n3379\n-491\n6952\n5987\n-4809\n7905\n5893\n-7169\n-4650\n-9473\n4438\n-8592\n-2454\n-110\n7510\n-2309\n-5571\n-8966\n5781\n905\n-7638\n-7436\n8821\n6952\n954\n6194\n-9722\n4210\n4548\n2907\n2543\n-6544\n2742\n-6822\n-5556\n-8895\n-9108\n-8759\n-2341\n7076\n-5188\n-9029\n5796\n-2045\n-8804\n3794\n3121\n7085\n-8338\n-3039\n6767\n3594\n2229\n5355\n6694\n1207\n-6718\n6920\n-4092\n-8567\n-6375\n8836\n244\n7560\n-7793\n-6655\n3756\n827\n-4075\n-9189\n-6625\n-4539\n-6433\n1742\n789\n-3230\n-2575\n8755\n8471\n4736\n3170\n-8943\n-2014\n-2729\n4700\n-1357\n2496\n746\n-3807\n9860\n1990\n-7597\n7366\n1432\n-1146\n-9647\n1332\n7913\n1234\n-1091\n4381\n5096\n3837\n952\n-8199\n-6018\n-581\n-6519\n7418\n274\n8781\n6382\n393\n5342\n-2353\n3534\n726\n-1895\n8540\n-5598\n-7041\n4927\n-3962\n-9798\n-7154\n-7497\n-3902\n-5906\n-5740\n1328\n7085\n-8173\n-5962\n-1706\n-8396\n2996\n-638\n3739\n7927\n-5041\n-8804\n-6869\n9210\n5838\n6646\n6211\n-6827\n-7068\n7788\n216\n-978\n-1190\n-6966\n-9187\n8438\n-7553\n4968\n4014\n-3818\n6693\n-2275\n8672\n4148\n9654\n-5520\n-5412\n-1689\n-8991\n1932\n-897\n-292\n9181\n3229\n-8960\n5333\n3810\n3938\n-1064\n9019\n-7495\n8516\n4642\n7434\n-7404\n-1823\n-2366\n715\n-6810\n-152\n-4154\n8479\n6389\n-3301\n-5421\n3424\n1726\n-5262\n-8135\n-9021\n-5901\n-8165\n-5152\n-1371\n-7666\n-4131\n-6878\n-9000\n-2303\n2689\n-4766\n-9607\n-292\n482\n9493\n-3764\n8361\n-436\n1694\n2458\n-96\n615\n9924\n-1306\n7557\n-8585\n291\n-7185\n-5387\n9841\n-3776\n5264\n6442\n1521\n3495\n761\n-5964\n-9123\n7595\n-5991\n5053\n7909\n-8804\n6012\n-4826\n-8081\n2728\n4402\n-5020\n247\n3388\n-2765\n-355\n8225\n1670\n-5092\n-7752\n-7594\n-1463\n-1518\n7141\n1974\n7673\n-9803\n-6573\n6616\n8998\n8434\n-8549\n3370\n-6046\n-8133\n-1190\n8190\n3525\n-4387\n3787\n-165\n490\n-9642\n-1014\n1721\n-4642\n-4636\n7182\n6870\n-9609\n2273\n839\n1247\n9654\n5613\n-8030\n-7587\n-8789\n2063\n8454\n4021\n9566\n2909\n9226\n4838\n58\n-657\n-82\n6871\n-6332\n-3012\n-4320\n8514\n2623\n-9294\n-3240\n-7936\n-8287\n4794\n-8718\n5235\n-5777\n-8847\n-8229\n564\n3204\n4950\n7962\n2844\n6639\n3507\n611\n-2513\n-6433\n-5194\n-4084\n-670\n3021\n-416\n-2309\n-5005\n-7518\n7207\n1259\n4790\n7801\n-1832\n-7692\n-176\n-3061\n-911\n7319\n-3908\n3050\n-5347\n5138\n2954\n9836\n-2356\n2775\n7565\n-6447\n-6480\n-3501\n-5695\n-254\n-5353\n-2538\n-2178\n-2532\n-7486\n5363\n8176\n837\n8438\n-2778\n9526\n3239\n-5365\n6775\n-7335\n-3886\n863\n6894\n-5439\n-6083\n-6479\n-5408\n-6783\n-4390\n-7032\n-5929\n-2115\n9778\n1148\n-1973\n3612\n-6204\n-2410\n-4825\n3015\n-3737\n-7273\n-5412\n6846\n-5157\n9397\n-5681\n5253\n8843\n1708\n-4796\n5860\n4739\n6276\n7041\n2566\n3470\n-6474\n8042\n9564\n-1936\n758\n-6420\n353\n9045\n8105\n6412\n6669\n8093\n2630\n-2275\n4337\n-6287\n3896\n2800\n-9557\n6789\n5264\n2756\n-7471\n6083\n-844\n-9186\n-9550\n669\n-1007\n1084\n150\n-4160\n-2950\n2120\n3350\n-9604\n-1102\n-355\n-5644\n4298\n8620\n-9017\n729\n201\n-2148\n3537\n4922\n-3863\n1200\n-4544\n6908\n7461\n-5902\n3184\n-5718\n-8506\n4482\n4660\n-384\n-4218\n-6858\n5161\n7827\n-7856\n7894\n2120\n2280\n8997\n-4150\n1939\n-1351\n9023\n2137\n-1656\n-9698\n5096\n7001\n8104\n-9274\n-2055\n-1627\n-2866\n-5020\n1543\n-6672\n-7601\n1399\n9446\n8338\n5236\n1400\n841\n3206\n-2650\n3519\n6161\n8982\n-8454\n-342\n1666\n-662\n-9294\n-170\n966\n4453\n9225\n8444\n8591\n7846\n-125\n-8517\n-6122\n-5371\n-1149\n-8818\n-4863\n-3537\n-859\n-5860\n7434\n6293\n-4037\n-8423\n8606\n9836\n6262\n7951\n15\n7550\n2927\n1295\n5831\n-5700\n789\n1484\n-4544\n6651\n2525\n-1342\n3295\n-7558\n-4797\n-6673\n-6663\n-2566\n4791\n-4663\n5856\n-1323\n6720\n1881\n-826\n-5116\n-1653\n353\n1913\n314\n7242\n2141\n7374\n2448\n5681\n3890\n-4020\n-2877\n-3510\n6333\n1369\n424\n7192\n6552\n-9173\n4443\n1429\n-3409\n-9622\n-4117\n8389\n9664\n-4650\n-4671\n4615\n3959\n5469\n6018\n-3038\n-7793\n-4445\n3737\n-8429\n3853\n7576\n9545\n-9895\n6295\n4253\n-3848\n6841\n-601\n-8764\n5063\n-6904\n-5577\n7003\n-5905\n-5156\n-3630\n2704\n-2625\n-2386\n7213\n380\n-9481\n-2845\n2808\n4411\n7658\n-7800\n-6080\n9612\n8190\n-150\n3911\n-5114\n-161\n6172\n-9083\n-152\n-2565\n6960\n-5897\n-3307\n-9226\n6214\n-3887\n-3792\n-2222\n-8301\n-1836\n7478\n-5831\n-6303\n-6240\n8677\n-8663\n5177\n4618\n-2326\n-4829\n2392\n4848\n-3393\n9443\n8452\n5455\n-340\n-5513\n1661\n-1966\n-2009\n-9334\n3433\n58\n-1011\n-3712\n1650\n-8973\n5584\n424\n9049\n-2629\n-9269\n-8940\n9342\n-4164\n-8823\n5079\n-5897\n5121\n-2009\n232\n1195\n1014\n5405\n-2122\n-7185\n8555\n5923\n576\n-5881\n3584\n-911\n-8612\n2254\n-8461\n-8819\n-1078\n6375\n-9792\n-8759\n-4612\n5707\n-937\n-5826\n-587\n3226\n7702\n5976\n5628\n-3836\n-7803\n4199\n8262\n9546\n3424\n3156\n7342\n-3580\n8787\n-35\n7607\n9951\n-4416\n-33\n207\n4857\n9397\n-7209\n-4454\n4712\n4989\n-5817\n-461\n7827\n-1077\n-9754\n2732\n4756\n-5434\n-9048\n2840\n-6710\n-5438\n-2200\n3451\n9205\n1578\n-5702\n-4730\n-4776\n-3737\n3974\n-3230\n640\n996\n-6287\n4823\n-7087\n481\n4999\n-1236\n-8045\n-3467\n9098\n946\n-601\n7594\n9772\n1183\n1683\n-974\n-7495\n6110\n8207\n-9299\n9564\n8135\n6925\n7380\n-2282\n2554\n521\n-4996\n8978\n-780\n-5851\n9388\n2488\n-6175\n5840\n6738\n-8875\n-1999\n-7447\n9098\n8739\n4054\n3470\n-801\n-9299\n-6027\n1377\n-1062\n-9315\n-1190\n132\n-8882\n-370\n6104\n-4927\n-3240\n2875\n5937\n-714\n-9541\n-2268\n-7663\n-483\n2618\n5012\n244\n3696\n9056\n5381\n-6255\n4741\n-270\n7790\n-3317\n1709\n8322\n1566\n5079\n8960\n4428\n5446\n5851\n-4642\n-3319\n6630\n3156\n7734\n9839\n-4390\n-5005\n-8165\n1973\n4402\n6408\n3863\n4514\n4470\n6177\n1081\n-7681\n-6084\n9122\n-966\n-5781\n-5166\n-3571\n4927\n6043\n8295\n1759\n3215\n-3737\n-3956\n-1260\n2935\n6407\n7530\n-5523\n-601\n-413\n4158\n4333\n4767\n-7856\n-6840\n2085\n-8262\n3038\n-3373\n-5367\n-6280\n9070\n2106\n-3499\n-8330\n-3688\n1207\n-257\n2173\n275\n552\n8129\n-6204\n8113\n-7936\n9470\n-6598\n-814\n-2722\n4965\n4700\n5096\n607\n3050\n-337\n-3822\n-429\n7324\n-4765\n1485\n-8576\n9309\n-808\n964\n2539\n-9918\n-7195\n-7944\n7539\n-3618\n7403\n8187\n-688\n482\n7466\n-6760\n5232\n-6382\n8592\n8266\n-302\n8849\n8605\n-7127\n4453\n-8091\n-8209\n-5739\n4427\n4510\n-5887\n-1648\n4277\n-8685\n-3892\n-2400\n-1863\n-4316\n-1484\n1775\n-753\n-670\n2480\n-5153\n-3160\n3341\n-2096\n4395\n-5229\n4837\n8139\n4589\n-8821\n-4485\n-419\n-1817\n8196\n-3663\n-3127\n5560\n4940\n-495\n-3160\n2063\n-8245\n-562\n3255\n7904\n6442\n9701\n1855\n-7111\n3795\n4927\n4373\n7201\n3629\n2219\n-9338\n7806\n-1306\n2169\n6065\n-7498\n233\n7927\n-6455\n1326\n1605\n-1423\n4366\n-4301\n3411\n-3544\n-1955\n-9138\n-5752\n-3856\n-2526\n1107\n5893\n2085\n1056\n-9294\n9525\n760\n-6165\n-8742\n6424\n5330\n-4443\n-8230\n1161\n-1686\n-1607\n-6447\n-3509\n4753\n-8727\n3594\n-5262\n1949\n1151\n-987\n-1849\n-3746\n991\n8268\n-1983\n8622\n-5740\n-4868\n-2760\n220\n789\n181\n2533\n-5526\n-2718\n7401\n-3330\n-760\n4097\n-4233\n-9776\n-8171\n1817\n9953\n-6621\n-1110\n-8372\n-9226\n8484\n4960\n-6911\n-5042\n-5629\n-4662\n-458\n4851\n-3864\n-8604\n-6151\n879\n-3201\n-2573\n5186\n7268\n-8685\n2829\n536\n-9196\n1810\n9282\n9321\n4588\n-7653\n3495\n8119\n3816\n-6603\n5703\n8118\n-7078\n8510\n3926\n5072\n1195\n-8948\n4927\n-5313\n5707\n-9778\n-5460\n5787\n7070\n8882\n-5975\n4\n4411\n2928\n-9502\n402\n6740\n9506\n-3111\n8806\n5525\n-795\n4225\n1322\n-4297\n-8850\n0\n7320\n4923\n6926\n-1511\n342\n-8209\n5854\n3797\n-9798\n9328\n6209\n-2073\n-2414\n3782\n112\n-8102\n607\n7961\n2529\n-8364\n-2532\n-8066\n-468\n7574\n-6604\n4919\n3995\n-1589\n-4055\n281\n8115\n8127\n-2711\n6846\n-9396\n-4020\n9206\n7577\n1195\n4386\n-853\n4447\n-7716\n-1511\n6331\n-6591\n2333\n-1030\n1768\n6989\n-7196\n482\n-9201\n-9049\n-8934\n4339\n8035\n-8764\n1915\n-9669\n-491\n-9294\n-7967\n1913\n2516\n-2027\n-7321\n9540\n-9484\n1699\n-2199\n-7318\n-4037\n8252\n-2216\n-3142\n-5005\n-8011\n-6212\n7601\n7712\n7525\n7514\n-6844\n7267\n8576\n-647\n7654\n7303\n7863\n-1121\n615\n-2123\n413\n-7349\n-8804\n-7044\n5405\n3433\n1403\n-2178\n-2649\n-402\n5079\n-4964\n834\n4964\n-5042\n2954\n8832\n-8939\n-5493\n-58\n5116\n7899\n-5948\n9664\n-4344\n-269\n7790\n-5153\n132\n-3915\n-4106\n-764\n-8205\n-2694\n-5851\n9372\n2634\n-8384\n-7562\n-292\n5519\n7009\n8389\n-891\n-7889\n1478\n933\n5193\n-3794\n4170\n-5734\n6003\n5627\n1790\n6698\n-3588\n8474\n6289\n-1652\n-2159\n5864\n-5681\n-5089\n-78\n-2878\n-8908\n5429\n5853\n-7001\n3828\n-3698\n3541\n-9550\n2913\n626\n6868\n-1604\n8104\n-8369\n3265\n5736\n4894\n2426\n-1148\n-562\n-4030\n-6245\n-7755\n-7752\n7075\n133\n5913\n3363\n2790\n1456\n-5313\n5266\n-4187\n285\n-2980\n1995\n592\n4490\n-2845\n-3848\n-2302\n-1669\n-9166\n9095\n3991\n8000\n-1554\n8842\n5346\n9755\n2900\n-5149\n-6209\n-1881\n1113\n-4822\n576\n4981\n-8296\n-8878\n-1330\n-4730\n6803\n6825\n8238\n3959\n-2025\n-2872\n-4490\n780\n-1566\n3698\n-6252\n144\n-2573\n2341\n6569\n3727\n-1614\n7403\n69\n9855\n9250\n5787\n7283\n1456\n-9872\n-2473\n1234\n2885\n-4166\n-2988\n-626\n9031\n6893\n-8635\n5346\n3080\n-6174\n-1479\n-8869\n1089\n-7895\n-6150\n8452\n6868\n7883\n2106\n1955\n-7831\n5819\n6994\n-8253\n739\n-9396\n-2206\n7380\n-9698\n-3238\n9443\n9591\n6869\n-3143\n9070\n-3968\n-4868\n2678\n-8377\n8270\n7696\n-5902\n-6163\n4283\n8692\n5711\n9544\n-8209\n-5323\n-1609\n-4407\n5002\n-7803\n-1375\n6456\n110\n3153\n-5412\n-2326\n3159\n-1637\n6538\n-8634\n7560\n-4764\n3666\n-6653\n-9136\n6373\n-8679\n3204\n1029\n6846\n-7808\n-5192\n3911\n3454\n7013\n-2403\n253\n3018\n-9845\n-1428\n-3940\n5693\n-7075\n-4802\n-6004\n-5106\n6401\n4866\n-1292\n1351\n-4842\n7213\n-3330\n-1836\n3520\n6899\n-7138\n2089\n-4375\n-3178\n-6209\n-3325\n-6705\n-4490\n-6407\n-2384\n-9488\n1699\n4141\n-4031\n-7583\n-1694\n1913\n9700\n-9949\n1573\n-2319\n-5830\n-9735\n-5388\n-7795\n9772\n1105\n9342\n-232\n-1479\n-2638\n-5685\n-7877\n8818\n1675\n-494\n-4117\n-4145\n-6165\n3847\n-5840\n-5745\n9940\n-6162\n5196\n7654\n9368\n-869\n2899\n-7733\n-933\n-7513\n4989\n-8493\n-220\n2900\n8577\n7579\n-7698\n5041\n-9061\n-8698\n-3560\n6416\n-176\n-161\n1880\n-6298\n775\n-8490\n-8601\n6699\n1720\n-528\n7136\n7752\n8704\n-4014\n-6787\n-9044\n9355\n-2196\n5986\n8429\n1770\n2306\n1104\n4300\n174\n-8830\n6518\n-269\n-7256\n-7144\n4074\n1565\n-5260\n3196\n554\n9897\n6659\n929\n-9568\n-5561\n-850\n-418\n-7897\n4262\n4323\n-2262\n5456\n3449\n-745\n-8045\n-4188\n-3403\n-5819\n9692\n-6005\n1025\n-1825\n6914\n-7954\n-4538\n7696\n-3185\n-8742\n-6348\n5831\n-6185\n2873\n7638\n7913\n769\n-9108\n-2250\n-4678\n640\n-9406\n-6432\n-5234\n-4517\n-6713\n9566\n-4667\n-2784\n8595\n-1845\n-9895\n6302\n-9184\n7870\n2983\n6727\n-8295\n19\n-6298\n-8611\n9762\n-7596\n3993\n4923\n380\n-2302\n-1613\n5173\n-3973\n-3752\n-2595\n-909\n-2134\n1486\n-6184\n-4682\n-3882\n3853\n-7333\n1865\n1104\n1882\n-8840\n-8226\n8065\n5860\n8234\n-7910\n-346\n-5179\n6717\n-6497\n-8281\n6886\n4463\n8264\n-7253\n5405\n-4062\n820\n4237\n-5303\n-9473\n-2639\n-587\n-6110\n-3996\n1734\n-8024\n-2982\n-6783\n-4109\n4875\n-4927\n2689\n-2055\n1223\n-8445\n2698\n4757\n-8066\n4328\n-1975\n6348\n-1750\n-9311\n3345\n1708\n-2619\n-3571\n-4125\n9372\n4968\n-2077\n6988\n6752\n5780\n2319\n-1257\n-6807\n-5213\n3387\n3397\n462\n-3375\n7667\n-8537\n-1781\n9664\n4816\n-9221\n8151\n-4649\n-269\n-1282\n-539\n-7613\n-7041\n2999\n7639\n1208\n-4871\n5835\n3784\n-2440\n7537\n247\n-9592\n-6151\n-1839\n1021\n-3011\n6822\n3271\n-4387\n8170\n1430\n9075\n9098\n3544\n-3334\n-1146\n8856\n-9091\n5782\n-4021\n35\n-1134\n-3380\n-3009\n-9375\n4111\n-5380\n-7753\n-1236\n-7722\n-1653\n555\n-1304\n8037\n-134\n9025\n-1282\n-5354\n-8061\n2821\n7296\n-4560\n8145\n3292\n-6280\n3464\n-6020\n-1378\n5692\n-465\n-5032\n-9585\n305\n-3665\n-427\n9474\n-3323\n6669\n-4697\n272\n-7511\n-5464\n3541\n-5520\n1852\n-4796\n1063\n-2351\n7627\n-3590\n-7\n6758\n-2430\n7676\n8942\n-1656\n3640\n6565\n769\n7790\n9463\n-8281\n-7349\n-2450\n7136\n3454\n-8493\n5036\n2403\n-7756\n-3672\n6177\n7428\n-2483\n-9036\n1829\n3248\n-8578\n3050\n-2159\n-2123\n-4267\n-3867\n-4187\n-4096\n3229\n-458\n-8872\n7552\n2015\n2035\n-2867\n-2555\n-4018\n-201\n8727\n-3986\n-5305\n1227\n3514\n2750\n-5270\n-7326\n9120\n7896\n5173\n-475\n2465\n-10000\n8934\n-860\n807\n7077\n-190\n9711\n9403\n7374\n3583\n6785\n-8771\n2759\n5161\n7692\n-1262\n-251\n-662\n748\n-5101\n-2709\n-7857\n622\n-2020\n7087\n2713\n-2568\n3786\n-8209\n-2505\n7587\n-5804\n5913\n114\n423\n2164\n-3192\n-662\n-5149\n-2115\n-5660\n-4192\n-3102\n-6976\n4989\n7133\n-7865\n-7364\n-5883\n6934\n-5774\n6883\n4063\n6841\n-9564\n9431\n-7793\n-5266\n-7889\n8099\n-9293\n4122\n7275\n1332\n1172\n3537\n-1823\n-2732\n4158\n-339\n-2228\n4718\n7009\n9620\n4626\n1575\n-4838\n-4138\n-3202\n-6033\n7446\n-2706\n3959\n5873\n7141\n3026\n-8122\n2566\n-3616\n-2716\n-4257\n-2966\n-4151\n3786\n2655\n9571\n-580\n-3723\n8372\n-4042\n-5718\n-6297\n-6844\n-9226\n-9919\n-9201\n-4853\n-3324\n-671\n9368\n3460\n3244\n-7520\n-588\n-7349\n-5419\n-4881\n-4953\n1258\n9043\n6212\n-8426\n-5739\n-7472\n-523\n-5776\n-2522\n6755\n-8301\n271\n4828\n-8164\n3993\n-6638\n3987\n7787\n-3409\n8622\n462\n6263\n-9653\n-5850\n-7803\n1482\n-171\n6517\n-2492\n-7920\n4589\n7141\n-3294\n-8612\n7491\n4158\n-2148\n-365\n6359\n-1880\n-5878\n-165\n-3275\n6408\n8397\n-8954\n-1605\n4851\n-3180\n1908\n-4351\n568\n-1138\n3403\n-1880\n6736\n4272\n804\n9323\n-6147\n8732\n4675\n-2376\n970\n8405\n3589\n2828\n2266\n-6215\n-9598\n4589\n-6718\n3005\n7283\n1698\n1932\n-8820\n-4949\n30\n5134\n5758\n7207\n-6014\n7788\n3636\n4589\n-3571\n3619\n-8996\n-5953\n2187\n9183\n-4443\n-2703\n4589\n739\n4540\n-490\n-711\n-9948\n5453\n-2598\n-3443\n-6929\n-1791\n1699\n8563\n-9551\n6569\n5425\n-8910\n5321\n-5493\n2769\n7777\n3037\n4356\n-2787\n-2354\n-8295\n4703\n8391\n-4826\n4923\n-3441\n9650\n-7037\n-3162\n-8629\n-8950\n3428\n-9698\n-9311\n-4702\n-3863\n-9986\n-2012\n1234\n-427\n-4164\n9564\n-490\n-7762\n-5869\n3744\n7588\n5156\n-1457\n-5330\n-9653\n-4143\n7240\n1842\n-220\n9311\n-1160\n-3247\n-9041\n455\n-14\n-7594\n6883\n6431\n-5032\n-8618\n-3465\n-711\n6333\n803\n4923\n-8244\n7891\n9368\n8039\n-1518\n-7353\n-8330\n-5440\n1390\n-4955\n1345\n4985\n4589\n-1836\n2618\n870\n1168\n-9065\n4589\n-2302\n7583\n7595\n1694\n8989\n-8651\n8343\n-8862\n-7666\n-4528\n4097\n-8521\n2747\n165\n856\n996\n-7689\n-2995\n1927\n-3963\n2664\n275\n-3996\n7262\n-5014\n-1845\n-4\n-3182\n-5542\n-4891\n-797\n9801\n9534\n-7596\n-5426\n5141\n-8173\n6695\n9426\n-8450\n316\n-92\n-6312\n9218\n4335\n9288\n813\n6751\n6727\n8178\n2543\n-7583\n8824\n-150\n32\n2471\n-1359\n-8464\n-4055\n-6306\n3363\n9627\n-6733\n9604\n1634\n62\n4589\n6945\n-3114\n1116\n-6438\n1998\n-3670\n-5767\n-4139\n-1225\n2286\n-9436\n6738\n-9467\n4428\n8354\n4471\n-4890\n-8564\n5253\n-2009\n-105\n8879\n-2172\n-8685\n-1724\n-7110\n250\n4655\n2938\n1207\n2154\n2001\n7663\n-1803\n19\n-5863\n8641\n-1257\n-7378\n-3320\n-6312\n9068\n-8493\n5519\n6855\n-4940\n-302\n-3946\n6456\n-8910\n-425\n-3481\n9415\n5986\n-9291\n54\n-74\n2454\n3548\n-7991\n1409\n-3492\n2236\n552\n-2838\n-8356\n-2475\n9056\n1216\n-6020\n-3114\n-6098\n-9609\n-9258\n-6432\n-6019\n1476\n-4348\n8677\n4141\n3666\n-6932\n3548\n-3852\n-10\n6359\n-9598\n-4664\n-6741\n3457\n4675\n-146\n-974\n1084\n3064\n-3963\n-8135\n-8736\n-3931\n7423\n2250\n-3267\n167\n-6832\n1973\n-2305\n-5412\n-5997\n-7127\n159\n9506\n9825\n-1789\n-8736\n2782\n3640\n4870\n-903\n6216\n7552\n2219\n-8789\n-3220\n7374\n-3497\n-4587\n977\n-8806\n462\n2529\n-5432\n-3008\n-355\n2570\n-523\n3470\n-8390\n-5081\n7595\n-2428\n6958\n-524\n-6827\n-8117\n-8206\n2972\n-4934\n-8910\n9839\n-3761\n4663\n-7061\n6958\n8606\n2124\n-3497\n5467\n1089\n-5446\n-7981\n570\n6706\n138\n-5345\n-3243\n-6535\n-6699\n-9000\n170\n6717\n5828\n4031\n-1862\n-5856\n-2966\n-883\n-4603\n4837\n7283\n8238\n9644\n3057\n-5249\n-9568\n7800\n-8615\n1345\n-1944\n-1119\n-8616\n8564\n-3303\n-3238\n9063\n-1992\n9660\n-7582\n6217\n-4481\n9940\n-1729\n9056\n3414\n2429\n6594\n2760\n-3198\n-6340\n-6323\n-9976\n-7741\n8333\n-5330\n-3892\n3790\n7550\n-6187\n7086\n-9080\n8941\n-2276\n8355\n-1306\n249\n-4937\n6181\n-2388\n-8709\n-6556\n2187\n6759\n-1325\n-4208\n-4347\n-2471\n-2629\n-1125\n402\n8019\n3741\n3039\n-7453\n-6179\n9357\n-4707\n-2623\n3301\n-5948\n-9264\n1901\n1500\n-737\n6504\n5854\n-1527\n8606\n-3109\n4654\n4239\n7560\n-2988\n-2138\n6159\n6462\n5795\n4618\n-6877\n7143\n-6716\n-2960\n112\n8067\n2017\n9483\n-8384\n9690\n5978\n-4595\n9210\n-1726\n8143\n2808\n5175\n-1931\n-1860\n-3240\n2566\n9654\n-640\n-2452\n185\n-8671\n4932\n2333\n-3162\n-8574\n-4145\n-461\n-5156\n7450\n9523\n3819\n-1708\n-9141\n649\n-7138\n-7330\n5986\n-7357\n4100\n-8918\n-3723\n638\n1988\n8530\n264\n-6579\n3514\n1915\n1243\n-7820\n4336\n-9375\n7192\n2937\n-8627\n2468\n-9843\n-2457\n-3077\n-3831\n-745\n8190\n675\n-8684\n-9224\n-9199\n-9000\n-2275\n-688\n-9667\n-6955\n4964\n4510\n5006\n-3821\n-5483\n5892\n-9445\n257\n441\n-6923\n-4736\n-8303\n1521\n2244\n6035\n-3319\n906\n7383\n9490\n3424\n-7721\n-626\n-211\n-3764\n-8744\n-5469\n-2716\n6844\n9225\n-5460\n-9000\n-5917\n1993\n-7375\n4132\n3959\n-450\n4447\n2940\n6159\n-1972\n-8805\n-132\n-7642\n7346\n4950\n-1353\n-4707\n-1131\n-9786\n-8426\n3301\n-9802\n7525\n-9464\n3863\n7143\n-171\n2020\n-601\n6699\n6281\n-5222\n7213\n9230\n1453\n-6488\n-6752\n-4827\n-941\n-5167\n3881\n4929\n1507\n8050\n3010\n-2847\n4572\n3874\n5558\n8115\n946\n-1125\n2054\n9368\n7086\n-3756\n-1475\n-3162\n-5492\n1056\n-1310\n9221\n-1239\n5330\n-171\n-8671\n464\n4015\n-6125\n3594\n3228\n8864\n-2123\n4999\n-8356\n-8060\n5896\n3187\n7774\n2533\n6789\n-9026\n-6638\n-5290\n8704\n4851\n4380\n9477\n6731\n2873\n-2654\n1207\n-8818\n-1895\n989\n-111\n6925\n4302\n-1430\n-1551\n2063\n-495\n-8364\n-9585\n9206\n3109\n102\n3401\n-9187\n9656\n6988\n-6884\n506\n-3978\n6043\n-6194\n5613\n6452\n-1877\n7003\n1463\n-2419\n9403\n-8990\n-3450\n-7218\n-8043\n-1078\n8757\n9958\n2313\n6264\n1555\n-5981\n-9348\n-2410\n-3243\n-9792\n-9451\n8373\n5310\n6639\n2483\n-5298\n-191\n1060\n760\n-6580\n8127\n-8382\n-2439\n3615\n7525\n-1126\n-5738\n-3327\n-6632\n2460\n-6285\n27\n188\n-9941\n6821\n3057\n-1430\n8891\n-9053\n-3759\n7931\n-3127\n4028\n8128\n4900\n-9980\n-7738\n52\n2930\n-2440\n-1078\n-4938\n2174\n1071\n9860\n-1653\n-3718\n-3106\n-4634\n-2080\n-780\n6214\n-7266\n-9017\n-6673\n-9899\n3292\n-3789\n2501\n9029\n5052\n-4442\n-9279\n-9235\n-4334\n342\n-1889\n-4953\n-1279\n-4117\n-5086\n-9115\n3772\n6900\n-1508\n3764\n-6150\n6555\n-4301\n9685\n3915\n-7200\n820\n7371\n6278\n3979\n-5150\n7801\n-7227\n-3122\n-4421\n-8135\n-9944\n-3254\n-3295\n-4964\n-4695\n2761\n4283\n-2838\n4753\n1104\n-5390\n-3789\n6825\n-1965\n1683\n-6936\n-2034\n-8666\n-3089\n-9027\n9062\n-962\n-322\n6641\n-5041\n-3737\n-3822\n-6850\n8952\n6594\n5273\n-5064\n1640\n-600\n-9351\n-5211\n-6705\n-6884\n824\n-1479\n8759\n-2204\n-4434\n-9265\n-7857\n-3228\n3089\n-1920\n2382\n2355\n-8068\n-7939\n-3042\n-1671\n2988\n-6298\n-2115\n8147\n1481\n3607\n-6337\n-4381\n7044\n-3162\n-558\n5719\n8231\n8051\n-4884\n3594\n1646\n7114\n-6125\n-7994\n-1541\n-6921\n3736\n3853\n7901\n-4237\n7905\n-7413\n812\n-5506\n3367\n754\n-7027\n-626\n9383\n-1159\n4676\n1793\n1762\n-5371\n6594\n-3614\n-8493\n-8410\n-7350\n3330\n-9412\n4130\n5053\n-3863\n112\n-426\n7531\n-3180\n-5684\n3010\n3524\n5868\n-8618\n-6840\n-2066\n5670\n5838\n-1980\n-3484\n-6867\n4675\n464\n-384\n4014\n-7527\n-8352\n3406\n4122\n6382\n-5089\n5868\n-1581\n-2283\n-2809\n-7834\n-3670\n1432\n6752\n-5887\n-6972\n-4034\n-9221\n-5963\n1247\n5519\n-8087\n-4746\n-7863\n-8547\n-1757\n1671\n5279\n1799\n7764\n3350\n1172\n-2450\n6755\n-8872\n-6500\n-7012\n4031\n-2619\n1237\n-2743\n-3247\n-737\n2899\n6386\n4755\n7790\n9550\n-3697\n-3167\n4514\n5284\n526\n-1750\n542\n-521\n-3573\n2356\n7894\n-2238\n7466\n2706\n5153\n-602\n-2716\n-3537\n2098\n8262\n970\n-630\n-1724\n-9561\n-5906\n-2853\n-1372\n-4989\n1998\n-1160\n-5842\n-3313\n3059\n-2695\n-9499\n7595\n9907\n1577\n-6358\n9860\n-2706\n-9097\n-6239\n-1300\n8125\n-233\n4979\n-7597\n-7138\n-4128\n-935\n-8219\n8592\n-3205\n5367\n9996\n-4713\n-3809\n-7486\n2437\n4312\n2355\n-271\n2254\n-5794\n2756\n9432\n-9871\n-6347\n-8745\n-8716\n2434\n5216\n4630\n-9911\n3297\n7421\n9664\n8239\n3983\n-7387\n3405\n8877\n-7782\n-8983\n7150\n8212\n4579\n4097\n-5033\n3085\n-8356\n-1094\n-1412\n-4155\n3951\n8874\n-4931\n-6637\n-1071\n7169\n5716\n-4746\n1034\n-9201\n-2625\n-5131\n-3042\n8462\n-6635\n-4321\n-3872\n-780\n4218\n4837\n-2716\n2566\n4825\n4141\n-9342\n-3407\n-7721\n9880\n-6433\n-318\n3089\n-9044\n5077\n1467\n-8224\n9358\n-1893\n-2638\n9232\n4304\n-7003\n-8718\n-7270\n-4212\n3109\n4298\n3883\n-4131\n-2384\n2601\n34\n-9495\n-9634\n2790\n565\n1078\n9049\n9862\n-7372\n5905\n3137\n-775\n385\n586\n-9041\n7677\n-2728\n5670\n3234\n-2956\n5946\n359\n-7759\n-4687\n2141\n8264\n-3934\n9062\n-6580\n-3762\n-5223\n-5280\n4941\n4626\n-3815\n4724\n4999\n-4644\n2623\n8787\n2577\n-6638\n8077\n-1577\n5235\n4680\n-3126\n-1703\n1913\n-5081\n2934\n-8206\n-3025\n7380\n-7807\n9835\n1110\n-6214\n-7130\n-3996\n-4657\n5600\n-40\n-9565\n1476\n7421\n-5957\n-9604\n3969\n-5341\n9036\n-792\n3819\n7633\n2587\n-3889\n-7446\n1276\n-8287\n-6962\n1009\n8389\n5891\n-2896\n4463\n-4671\n1745\n4485\n-6428\n-4953\n6720\n934\n2254\n9880\n6095\n-6972\n-1605\n-1564\n-82\n8401\n-4840\n-541\n-3599\n-8868\n4703\n-6655\n-9496\n9205\n-6929\n1939\n-8974\n-4953\n-5906\n-2045\n54\n-5020\n894\n-6751\n2941\n-2115\n2219\n-6165\n-1931\n5917\n-5053\n-1292\n4792\n-9414\n-8814\n-1720\n-5944\n-6932\n-7640\n4897\n6693\n-808\n-6644\n-9265\n-3224\n-8847\n7275\n5990\n6727\n-2018\n-7020\n-1479\n9652\n6805\n-1075\n-4641\n-2070\n6032\n-4746\n-9009\n4782\n2402\n6251\n-9044\n-7345\n2547\n9350\n-592\n7130\n-1181\n-2708\n9375\n-843\n4254\n-6867\n-1669\n1998\n-7729\n-6325\n1288\n759\n-3612\n129\n5797\n-4291\n-7275\n2061\n4968\n-5754\n-6669\n-4763\n7731\n-6285\n8776\n5767\n-621\n1642\n1226\n3234\n1476\n8440\n-4651\n-3628\n-435\n-5488\n3687\n-143\n-7353\n-9450\n2234\n-6799\n4846\n2373\n5042\n-9448\n8853\n9581\n-3172\n-7196\n35\n-8840\n-3086\n252\n9685\n3501\n4431\n-2326\n-3831\n746\n4186\n-3275\n-3973\n-640\n8104\n-9572\n8193\n-92\n-5625\n7635\n-2215\n3300\n-977\n9091\n-4139\n1009\n-5209\n-178\n1512\n-2596\n-2934\n1155\n1652\n8777\n4343\n9731\n9760\n9070\n-5918\n2286\n-4891\n-1484\n-7404\n6362\n6068\n-5017\n-1337\n6735\n-1686\n-4770\n-8006\n-9751\n-9239\n-6312\n-9184\n675\n-6884\n-3661\n8778\n1654\n5034\n-6614\n-6087\n-6525\n-269\n-9449\n8299\n3006\n-5957\n353\n1507\n8083\n1810\n-6204\n-144\n-1027\n5795\n-4092\n-6474\n6636\n-3024\n-6071\n4651\n5732\n-6151\n-8316\n5620\n-5092\n-1427\n8252\n15\n-1859\n-7878\n-5143\n287\n-5530\n1927\n-955\n-1823\n2508\n1299\n509\n-8612\n4021\n1262\n-8791\n-3978\n759\n2641\n4333\n-4938\n-3084\n-9116\n6675\n6951\n-7593\n3258\n-2499\n-2337\n2547\n2974\n-110\n8893\n-7538\n-2151\n-5146\n-9789\n2869\n-7339\n-9980\n-4746\n-9117\n-6591\n-2376\n-9253\n-9116\n6232\n-2159\n-2838\n-4119\n-8626\n-3369\n-6568\n8479\n8524\n-1881\n-8233\n-7353\n8445\n6540\n-4390\n1274\n9545\n-8211\n-6448\n-8277\n102\n7790\n2707\n-190\n-9581\n4800\n3658\n7467\n-6889\n814\n-2206\n6281\n5405\n7374\n-3794\n190\n8479\n6531\n-1243\n2048\n-7099\n-5632\n5077\n9652\n9470\n-3661\n6516\n7933\n5560\n9973\n1155\n-8364\n-6638\n-419\n-8493\n-600\n1604\n369\n-7395\n-8612\n-4055\n-7752\n-6382\n1021\n1523\n-4825\n6629\n-3893\n8916\n-2677\n-814\n7372\n-6923\n6214\n1383\n-8273\n2187\n-6877\n7403\n673\n4989\n9095\n6180\n-2539\n-7990\n-2066\n5063\n-9021\n-1170\n2931\n5260\n-4381\n-878\n3948\n-1325\n4964\n-5394\n-4610\n-6672\n8876\n-8900\n6572\n5158\n4501\n-2623\n963\n-8626\n4486\n-3818\n-4416\n9499\n4298\n3915\n8299\n3671\n-7749\n-3414\n8093\n4131\n879\n-9189\n-5499\n-5670\n8470\n7588\n316\n-8604\n363\n-5316\n3246\n7010\n8399\n1443\n-9658\n-8206\n-9406\n9430\n-2109\n-2305\n-6454\n7720\n-4905\n-4587\n7601\n-6904\n7461\n7951\n-9675\n-191\n-3806\n841\n9171\n-4822\n-7395\n4682\n-1505\n-7880\n-7498\n9591\n-9606\n-3904\n-4237\n2410\n-3537\n-3290\n5319\n2799\n-8209\n-4008\n9068\n-3956\n2759\n-8676\n-6179\n9839\n4276\n-8068\n4329\n4630\n-4853\n1358\n151\n-1686\n-4085\n-2333\n1615\n2477\n2698\n6041\n-2092\n9365\n-5742\n3765\n3727\n2742\n6013\n9618\n6281\n4834\n-9291\n-3089\n-2940\n5039\n-2331\n-2202\n-2687\n-2148\n2829\n-7345\n8304\n7184\n-7793\n-3862\n9364\n-3202\n1771\n5063\n-1077\n-8536\n-5776\n3325\n-7701\n-8818\n6248\n9020\n8125\n4453\n1878\n1825\n-4166\n-4160\n4253\n7086\n3816\n-7689\n-2322\n7413\n1195\n977\n-8146\n8092\n-343\n6205\n4131\n-4739\n-5434\n-7495\n-4991\n-7075\n-2291\n4950\n-3160\n3039\n952\n7891\n-5861\n-893\n-8385\n3786\n-3927\n-1818\n8285\n1161\n-461\n-1097\n6163\n812\n-7700\n-4085\n-7020\n4801\n8548\n-5316\n9631\n-402\n2465\n240\n9274\n1880\n-96\n3391\n-9754\n3313\n-6179\n4438\n385\n-1170\n-5354\n7421\n5895\n-5711\n-3666\n-9756\n-1639\n14\n-4387\n1532\n8476\n3114\n-7878\n8556\n1237\n-1022\n-8157\n2927\n3722\n-6380\n-7597\n7856\n-9802\n-1412\n5285\n-6752\n5896\n-8358\n-1924\n-292\n-882\n-5493\n-804\n-6863\n-5606\n-4411\n5656\n-3822\n8327\n-1859\n2709\n-3560\n2756\n-1724\n5343\n-5320\n-7793\n-8334\n-5141\n-8330\n9957\n3244\n7311\n9181\n-2238\n-523\n-9096\n2263\n-7742\n-6601\n2252\n8193\n9393\n9863\n6558\n1909\n4988\n-4913\n-1320\n3898\n3962\n-6507\n-6904\n-5373\n262\n3038\n2049\n5740\n9568\n2759\n-6942\n6934\n9388\n9210\n6561\n-6208\n-3240\n197\n3204\n9227\n-663\n-2480\n7640\n-4083\n7529\n-1372\n-8264\n-1763\n5351\n-3594\n-1562\n7892\n951\n1843\n-366\n1762\n-3641\n3961\n-8227\n1345\n-5955\n-2305\n-7378\n4923\n-5324\n-5549\n3948\n-780\n8927\n4063\n62\n-5975\n-4044\n-2928\n-7175\n8600\n-6544\n-6248\n-9093\n5130\n7216\n-3164\n-3260\n-8780\n6135\n1880\n9609\n-7020\n-2200\n4506\n-4170\n3455\n2417\n-6670\n8080\n-8287\n8776\n3676\n9745\n-2838\n2447\n-9605\n9483\n-6979\n5289\n7136\n9462\n2615\n9113\n2441\n-3510\n-6895\n-755\n-8779\n9464\n-8064\n-6526\n7426\n-8830\n6855\n-7512\n-9136\n-9437\n-8064\n5311\n5105\n-3863\n-8560\n35\n-5826\n-6029\n-1292\n4110\n2181\n-4303\n6918\n-2277\n7246\n1975\n-8727\n-3357\n604\n3698\n-637\n6489\n-2104\n1071\n-5287\n-7567\n-9022\n2900\n4309\n9622\n-4281\n9347\n6683\n6307\n-323\n-1170\n2800\n-5961\n5913\n54\n3009\n2410\n-7178\n-1980\n9486\n-8338\n-396\n709\n882\n4964\n982\n-4351\n-5989\n-3855\n1578\n1518\n5412\n2474\n-2020\n-5795\n-3922\n505\n-305\n-2202\n2017\n-8940\n-8764\n6594\n9313\n-7501\n2272\n4551\n6671\n5782\n-5542\n3583\n-8919\n9692\n3702\n-2558\n-2188\n5067\n6752\n8876\n2468\n-6358\n7197\n1575\n4726\n-1193\n4965\n-969\n-2204\n5552\n1881\n4520\n-7677\n-1511\n-8690\n6579\n5236\n-4977\n-3059\n-2014\n-806\n-2970\n8071\n-8791\n-5483\n5462\n6892\n-926\n-8334\n7607\n784\n5429\n-9949\n-8377\n2806\n6782\n2400\n-4223\n-1446\n-3697\n7506\n8803\n-9161\n2531\n-6474\n-692\n-7222\n4482\n5351\n-4504\n-418\n-4844\n-1337\n6885\n6722\n6177\n1622\n-4536\n-159\n-2445\n8713\n-828\n-1237\n5036\n6767\n-8036\n5395\n1727\n6760\n81\n-2540\n-2606\n-688\n6449\n-4371\n-5845\n5725\n-9975\n9922\n-4977\n-2499\n-9394\n-4930\n8499\n-5368\n-7931\n8893\n-4588\n6045\n-4390\n-1951\n2749\n2305\n-7442\n9260\n3461\n7777\n-3209\n-1412\n-3348\n-3219\n9518\n-8176\n4650\n-6827\n-3234\n9320\n-3067\n4490\n-3024\n-8428\n380\n-232\n4919\n5145\n6452\n-5380\n1345\n6710\n7143\n4262\n2373\n6591\n4474\n305\n-3943\n-6019\n2089\n-5304\n-3956\n-3752\n-4106\n5663\n-9121\n-7638\n-1904\n-1130\n-2292\n3117\n4898\n3755\n9049\n-4644\n-585\n-9754\n8533\n-4014\n-11\n129\n-4348\n9738\n353\n3271\n-7004\n7565\n3031\n-8847\n-5381\n8434\n3363\n-2009\n3989\n-7183\n5480\n5779\n-4907\n552\n9821\n-780\n8916\n8527\n-1685\n9838\n-1525\n6706\n-304\n-6923\n359\n1320\n-1266\n4333\n-2443\n-8381\n-9605\n-2657\n3257\n4473\n4761\n-9422\n2954\n3336\n4790\n4850\n383\n6424\n-3931\n-9892\n5860\n-4588\n-2587\n752\n4558\n2612\n-387\n-7969\n-5141\n3837\n-2080\n-6515\n924\n3354\n9297\n-502\n-8795\n-9449\n5839\n6229\n7554\n-1542\n-8838\n-4973\n1422\n4390\n-8157\n-8429\n4959\n-9276\n-9814\n-6580\n-9311\n9388\n-1479\n-6632\n8279\n-6977\n-8133\n-8152\n8080\n-2156\n4682\n-7486\n-6225\n-9322\n6424\n2864\n8267\n5060\n-9299\n2556\n-371\n-6573\n3258\n1413\n-6103\n-5381\n-4301\n-1999\n570\n-8615\n6043\n8538\n6569\n-8454\n-3185\n-5513\n9432\n2725\n-1474\n-662\n-7020\n3096\n8703\n-2680\n8622\n-8946\n-1372\n-7497\n-130\n-4119\n9940\n-8358\n-9635\n3455\n-9723\n-621\n-2956\n9992\n-2009\n5679\n-3617\n7305\n8592\n2423\n692\n4959\n-9565\n5617\n-6667\n-9364\n5868\n9534\n-775\n4077\n-4229\n5069\n-3667\n-2539\n8344\n6815\n7371\n-4021\n1820\n114\n-8103\n-7700\n-935\n-4381\n8274\n-909\n1853\n-1216\n7438\n-4695\n4439\n-6151\n9226\n3922\n2285\n-5625\n8945\n6402\n2224\n-740\n7583\n-8356\n1789\n8285\n6810\n6182\n6076\n-7736\n-759\n-9606\n5333\n8163\n-3145\n-3749\n-9215\n5026\n8553\n4619\n-9116\n-6184\n-4884\n2930\n-3413\n4512\n1476\n5234\n946\n-3583\n5781\n-4569\n1854\n-1342\n7626\n-8950\n-3061\n2426\n9909\n-5489\n-7803\n-8493\n7825\n5469\n6394\n8333\n9830\n1668\n1386\n2058\n3904\n8129\n-903\n7003\n185\n1018\n-7863\n4252\n-1697\n-4429\n8389\n6295\n4731\n2702\n6009\n2024\n-8086\n-2364\n769\n-9689\n1576\n6009\n114\n-9211\n380\n6323\n-7223\n2014\n-5343\n-146\n-6798\n-8612\n5063\n-6781\n-962\n-1390\n-6201\n4566\n7421\n-3993\n-6697\n6212\n9818\n-5200\n3717\n4074\n-2022\n-4645\n1873\n3033\n-4042\n-9975\n-2595\n7670\n-2074\n8396\n5072\n-1671\n-2169\n3139\n-9786\n-490\n-1501\n-2055\n-8894\n-6125\n9062\n6344\n9743\n-410\n-3956\n4999\n-6384\n-6405\n5509\n-8896\n7206\n-9297\n2400\n-2956\n3910\n7892\n-5369\n9499\n-9713\n8397\n5346\n-1807\n-5065\n-1685\n-134\n-1378\n2124\n2782\n-4277\n-2912\n69\n-6877\n-933\n7918\n5266\n2927\n-134\n9688\n-7874\n31\n-8406\n-7939\n-6581\n-775\n-2073\n-9949\n570\n8958\n3078\n3727\n4233\n-4529\n-8923\n-3253\n-8441\n-3195\n-4897\n-7587\n6104\n4291\n5077\n-3409\n-9128\n5460\n464\n-35\n1880\n-2331\n-3915\n6727\n6194\n-8075\n-7629\n769\n9904\n9743\n-5414\n-4416\n5258\n-1372\n-6996\n-750\n4408\n-3930\n9755\n6059\n4097\n3089\n9019\n2792\n-7495\n-8372\n6104\n-9342\n4724\n-6447\n1999\n2089\n300\n-8334\n-8801\n6544\n9317\n-6445\n-4342\n7702\n6668\n1476\n6159\n-4085\n-7\n8282\n6382\n626\n-7931\n9786\n960\n-6396\n-2743\n6086\n-8611\n-4538\n-7434\n9887\n-8642\n-8806\n7183\n2280\n2595\n-2706\n-79\n5324\n666\n475\n1723\n-6768\n-366\n6140\n-7466\n8426\n-7037\n-4443\n1820\n7428\n-4579\n-527\n9897\n8852\n6841\n6518\n-7205\n-6704\n-6036\n-6626\n803\n-5219\n3371\n789\n-8454\n7471\n5728\n9019\n5627\n-4441\n4373\n-2224\n-1559\n7588\n-8173\n6699\n-4375\n-7663\n7830\n4548\n-7353\n-2144\n5707\n-3496\n-3492\n-6969\n4029\n5693\n2704\n-5860\n8818\n-7120\n9336\n-859\n-4029\n7539\n413\n-3783\n423\n-9159\n2470\n-5370\n-9267\n-5403\n-9079\n-9153\n3047\n2981\n-4008\n-5207\n-9912\n5858\n-4782\n7515\n-6663\n-1934\n-1369\n-7012\n2161\n-9647\n6914\n-8135\n-5381\n5818\n-251\n4447\n-6701\n-8801\n-5423\n-3718\n3226\n3110\n-773\n70\n3669\n-6403\n-502\n-4825\n7087\n3745\n-2301\n1235\n5839\n6176\n3133\n745\n-3202\n5795\n-4438\n-8206\n-241\n7535\n1207\n8004\n-3289\n-4838\n5291\n-2624\n-6398\n934\n8736\n-4528\n9953\n1860\n-2826\n-3706\n-6736\n5279\n-4645\n7584\n4324\n-795\n-8990\n2084\n5648\n9914\n1498\n157\n-5094\n9321\n-6491\n4090\n4989\n6304\n240\n2785\n-6335\n1084\n6658\n-5321\n-1142\n8724\n-4059\n775\n1415\n-7555\n-8224\n1503\n14\n5067\n-6427\n-631\n-4116\n6157\n-1940\n-3324\n-1305\n305\n-9592\n9259\n7667\n-486\n-7349\n-3363\n626\n-7453\n-4746\n5285\n-1837\n3253\n5962\n9945\n1058\n-6884\n-584\n7701\n-7853\n-1907\n8054\n-4529\n-5538\n8824\n-45\n4613\n2417\n104\n-9083\n8564\n-1499\n-6339\n-8900\n-6019\n2811\n4049\n8648\n-8864\n-7889\n5480\n-631\n-6055\n2934\n4937\n9332\n8925\n7796\n-7563\n5132\n-2638\n-9100\n-6966\n-3235\n8891\n-7130\n5740\n-5792\n-5345\n9332\n7539\n5691\n8204\n19\n-4517\n2694\n5173\n-7130\n5289\n-6323\n1296\n5288\n-2064\n9839\n4332\n-5145\n7723\n-588\n5753\n-7666\n7287\n-4356\n-794\n-6259\n-8718\n-8230\n8479\n-5029\n1274\n-4582\n-8266\n-1692\n-9199\n-3848\n-7688\n3466\n769\n6532\n498\n-2027\n9023\n5343\n7255\n8474\n5383\n7328\n5723\n3722\n-7257\n-6808\n3879\n-4593\n-8424\n9211\n-3735\n-7326\n-8493\n7555\n-9798\n-3213\n6024\n3579\n-2061\n6106\n-5489\n8576\n-3725\n3704\n1854\n-9157\n9678\n7814\n9505\n34\n-621\n9321\n4272\n7409\n-9116\n-7977\n-2693\n-2606\n-3821\n-1649\n2623\n1678\n8462\n3594\n2156\n-6396\n-493\n7656\n6172\n1880\n6297\n-5156\n970\n-6433\n-9173\n-8181\n-2156\n-2787\n-7115\n-2607\n"
  },
  {
    "path": "git-hooks/prepare-commit-msg",
    "content": "#!/usr/bin/env ruby\n\nmessage = File.read(ARGV[0])\n\nexit 0 unless message.start_with? \"\\n\"\n\nprefixes = [\n  [%r{^other/clrs/(\\d+)/(\\d+)/(\\d+)\\.},    -> { \"clrs; exercise #{$1.to_i}.#{$2.to_i}.#{$3.to_i} – \" }],\n  [%r{^other/clrs/(\\d+)/problems/(\\d+)\\.}, -> {\n    chapter, number = $1, $2\n    title = File.read(\"other/clrs/#$1/problems/#$2.markdown\")[/\\A#+\\s+(.*)/, 1].downcase rescue \"FAILED TO GET TITLE\"\n    \"clrs; problem #{chapter.to_i}.#{number.to_i} – #{title}\"\n  }],\n]\n\nfiles = `git diff-index --cached --name-only HEAD`.split(\"\\n\")\n\nexit 0 if files.empty?\n\nfirst = files.first\n\nprefixes.each do |regexp, title|\n  next unless regexp =~ first\n  prefix = $&\n  header = title.()\n\n  break unless files.all? { |file| file.start_with? prefix }\n\n  File.write ARGV[0], header + message\nend\n"
  },
  {
    "path": "go/gopl/.ruby-version",
    "content": "2.3.3\n"
  },
  {
    "path": "go/gopl/01/01/echo.go",
    "content": "// Exercise 1.1: Modify the echo program to also print os.Args[0], the name of\n// the command that invoked it.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n)\n\nvar out io.Writer = os.Stdout\n\nfunc main() {\n\techo(os.Args)\n}\n\nfunc echo(args []string) {\n\tfmt.Fprintln(out, strings.Join(args, \" \"))\n}\n"
  },
  {
    "path": "go/gopl/01/01/echo_test.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"testing\"\n)\n\nfunc TestEcho(t *testing.T) {\n\tout = new(bytes.Buffer)\n\n\targs := []string{\"ls\", \"-la\", \"whatever\"}\n\twant := \"ls -la whatever\\n\"\n\n\techo(args)\n\tgot := out.(*bytes.Buffer).String()\n\n\tif got != want {\n\t\tt.Errorf(\"echo(%q) = %q, want %q\", args, got, want)\n\t}\n}\n"
  },
  {
    "path": "go/gopl/01/02/echo.go",
    "content": "// Exercise 1.2: Modify the echo program to print the index and value of each\n// of its arguments, one per line.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n)\n\nvar out io.Writer = os.Stdout\n\nfunc main() {\n\techo(os.Args)\n}\n\nfunc echo(args []string) {\n\tfor i, arg := range args {\n\t\tfmt.Fprintf(out, \"%d %s\\n\", i, arg)\n\t}\n}\n"
  },
  {
    "path": "go/gopl/01/02/echo_test.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"testing\"\n)\n\nfunc TestEcho(t *testing.T) {\n\tout = new(bytes.Buffer)\n\n\targs := []string{\"ls\", \"-la\", \"whatever\"}\n\twant := \"0 ls\\n1 -la\\n2 whatever\\n\"\n\n\techo(args)\n\tgot := out.(*bytes.Buffer).String()\n\n\tif got != want {\n\t\tt.Errorf(\"echo(%q) = %q, want %q\", args, got, want)\n\t}\n}\n"
  },
  {
    "path": "go/gopl/01/03/echo.go",
    "content": "// Exercise 1.3: Experiment to measure the difference in running time between\n// our potentially inefficient versions and the one that users strings.Join\n// (Section 1.6 illustrates part of the time package, and Section 11.4 shows\n// how to write benchmark tests for systematic performance evaluation.)\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc main() {\n\techo1(os.Stdout, os.Args[1:])\n}\n\nfunc echo1(out io.Writer, args []string) {\n\tvar s, sep string\n\tfor i := 0; i < len(args); i++ {\n\t\ts += sep + args[i]\n\t\tsep = \" \"\n\t}\n\tfmt.Fprintln(out, s)\n}\n\nfunc echo2(out io.Writer, args []string) {\n\tvar s, sep string\n\tfor _, arg := range args {\n\t\ts += sep + arg\n\t\tsep = \" \"\n\t}\n\tfmt.Fprintln(out, s)\n}\n\nfunc echo3(out io.Writer, args []string) {\n\tfmt.Fprintln(out, strings.Join(args, \" \"))\n}\n"
  },
  {
    "path": "go/gopl/01/03/echo_test.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"testing\"\n)\n\nvar testInput = strings.Split(`\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean dictum lacinia\npurus, at rutrum erat vulputate id. Vestibulum vel elementum metus, in\nvehicula sem. Nullam vitae magna hendrerit, sodales erat vel, placerat sapien.\nInteger pharetra, lectus a scelerisque imperdiet, tortor leo sagittis nisi, in\npellentesque quam ipsum a turpis. Morbi nec neque porta, dapibus velit at,\nmattis elit. Praesent elementum nisl est, in facilisis lacus ullamcorper eu.\nPraesent sed eros a nisi vulputate viverra nec et tortor. Maecenas volutpat\nsed purus et fermentum. Sed pulvinar dolor ut diam imperdiet dictum. Nullam\nvenenatis odio nisi, vestibulum dignissim mauris auctor id. Mauris sagittis\nneque interdum dignissim vulputate. Curabitur congue tempus lectus.\nPellentesque habitant morbi tristique senectus et netus et malesuada fames ac\nturpis egestas. Ut consequat convallis urna, et venenatis nisl laoreet at.\nProin id porta odio, nec luctus justo.\n`, \" \")\n\nfunc TestEcho1(t *testing.T) {\n\tout := new(bytes.Buffer)\n\n\targs := []string{\"ls\", \"-la\", \"whatever\"}\n\twant := \"ls -la whatever\\n\"\n\n\techo1(out, args)\n\n\tgot := out.String()\n\n\tif got != want {\n\t\tt.Errorf(\"echo(%q) = %q, want %q\", args, got, want)\n\t}\n}\n\nfunc TestEcho2(t *testing.T) {\n\tout := new(bytes.Buffer)\n\n\targs := []string{\"ls\", \"-la\", \"whatever\"}\n\twant := \"ls -la whatever\\n\"\n\n\techo2(out, args)\n\n\tgot := out.String()\n\n\tif got != want {\n\t\tt.Errorf(\"echo(%q) = %q, want %q\", args, got, want)\n\t}\n}\n\nfunc TestEcho3(t *testing.T) {\n\tout := new(bytes.Buffer)\n\n\targs := []string{\"ls\", \"-la\", \"whatever\"}\n\twant := \"ls -la whatever\\n\"\n\n\techo3(out, args)\n\n\tgot := out.String()\n\n\tif got != want {\n\t\tt.Errorf(\"echo(%q) = %q, want %q\", args, got, want)\n\t}\n}\n\nfunc BenchmarkEcho1(b *testing.B) {\n\tout := new(bytes.Buffer)\n\tfor i := 0; i < b.N; i++ {\n\t\techo1(out, testInput)\n\t}\n}\n\nfunc BenchmarkEcho2(b *testing.B) {\n\tout := new(bytes.Buffer)\n\tfor i := 0; i < b.N; i++ {\n\t\techo2(out, testInput)\n\t}\n}\n\nfunc BenchmarkEcho3(b *testing.B) {\n\tout := new(bytes.Buffer)\n\tfor i := 0; i < b.N; i++ {\n\t\techo3(out, testInput)\n\t}\n}\n"
  },
  {
    "path": "go/gopl/01/04/dup.go",
    "content": "// Exercise 1.4: Modify dup2 to print the names of all files in which each\n// duplicated line occurs.\n\npackage main\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n)\n\nvar out io.Writer = os.Stdout\n\nfunc main() {\n\tdup2(os.Stdout, os.Args[1:])\n}\n\nfunc dup2(out io.Writer, files []string) {\n\tcounts := make(map[string]int)\n\tlocations := make(map[string]map[string]bool)\n\n\tif len(files) == 0 {\n\t\tcountLines(os.Stdin, \"<stdout>\", counts, locations)\n\t} else {\n\t\tfor _, filename := range files {\n\t\t\tf, err := os.Open(filename)\n\t\t\tif err != nil {\n\t\t\t\tfmt.Fprintf(os.Stderr, \"dup: %v\\n\", err)\n\t\t\t}\n\t\t\tcountLines(f, filename, counts, locations)\n\t\t\tf.Close()\n\t\t}\n\t}\n\tfor line, n := range counts {\n\t\tif n > 1 {\n\t\t\tfmt.Fprintf(out, \"%d\\t%s\", n, line)\n\n\t\t\tfor location, _ := range locations[line] {\n\t\t\t\tfmt.Fprintf(out, \" %s\", location)\n\t\t\t}\n\n\t\t\tfmt.Fprintf(out, \"\\n\")\n\t\t}\n\t}\n}\n\nfunc countLines(f *os.File, filename string, counts map[string]int, locations map[string]map[string]bool) {\n\tinput := bufio.NewScanner(f)\n\tfor input.Scan() {\n\t\ttext := input.Text()\n\t\tcounts[text]++\n\n\t\tif locations[text] == nil {\n\t\t\tlocations[text] = make(map[string]bool)\n\t\t}\n\n\t\tlocations[text][filename] = true\n\t}\n}\n"
  },
  {
    "path": "go/gopl/01/04/dup_test.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"sort\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestDup(t *testing.T) {\n\tout := new(bytes.Buffer)\n\n\targs := []string{\"fixtures/first\", \"fixtures/second\", \"fixtures/third\"}\n\twant := []string{\"\", \"2\\tthree fixtures/first fixtures/second\", \"2\\tfive fixtures/second fixtures/third\", \"2\\tseven fixtures/third\"}\n\n\tdup2(out, args)\n\n\tgot := strings.Split(out.String(), \"\\n\")\n\n\tsort.Strings(want)\n\tsort.Strings(got)\n\n\tif strings.Join(got, \"\\n\") != strings.Join(want, \"\\n\") {\n\t\tt.Errorf(\"result = %q\\nwant %q\", got, want)\n\t}\n}\n"
  },
  {
    "path": "go/gopl/01/04/fixtures/first",
    "content": "one\ntwo\nthree\n"
  },
  {
    "path": "go/gopl/01/04/fixtures/second",
    "content": "three\nfour\nfive\n"
  },
  {
    "path": "go/gopl/01/04/fixtures/third",
    "content": "five\nsix\nseven\nseven\n"
  },
  {
    "path": "go/gopl/01/05/lissajous.go",
    "content": "// Exercise 1.5: Change the Lissajous program's color palette to green on\n// black, for added authenticity. To create the web color #RRGGBB, use\n// color.RGBA{0xRR, 0xGG, 0xBB, 0xff} where each pair of hexadecimal digits\n// represents the intensity of the red, green, or blue component of the pixel.\npackage main\n\nimport (\n\t\"image\"\n\t\"image/color\"\n\t\"image/gif\"\n\t\"io\"\n\t\"math\"\n\t\"math/rand\"\n\t\"os\"\n)\n\nvar palette = []color.Color{color.Black, color.RGBA{0x00, 0xFF, 0x00, 0xFF}}\n\nconst (\n\tforegroundIndex = 0\n\tbackgroundIndex = 1\n)\n\nfunc main() {\n\tlissajous(os.Stdout)\n}\n\nfunc lissajous(out io.Writer) {\n\tconst (\n\t\tcycles  = 5\n\t\tres     = 0.001\n\t\tsize    = 100\n\t\tnframes = 64\n\t\tdelay   = 8\n\t)\n\n\tfreq := rand.Float64() * 3.0\n\tanim := gif.GIF{LoopCount: nframes}\n\tphase := 0.0\n\tfor i := 0; i < nframes; i++ {\n\t\trect := image.Rect(0, 0, 2*size+1, 2*size+1)\n\t\timg := image.NewPaletted(rect, palette)\n\t\tfor t := 0.0; t < cycles*2*math.Pi; t += res {\n\t\t\tx := math.Sin(t)\n\t\t\ty := math.Sin(t*freq + phase)\n\t\t\timg.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), backgroundIndex)\n\t\t}\n\t\tphase += 0.1\n\t\tanim.Delay = append(anim.Delay, delay)\n\t\tanim.Image = append(anim.Image, img)\n\t}\n\tgif.EncodeAll(out, &anim)\n}\n"
  },
  {
    "path": "go/gopl/01/06/lissajous.go",
    "content": "// Exercise 1.06: Modify the Lissajous program to produce images in multiple\n// colors by adding more values to palette and then displaying them by changing\n// the third argument of SetColorIndex in some interesting way.\npackage main\n\nimport (\n\t\"image\"\n\t\"image/color\"\n\t\"image/gif\"\n\t\"io\"\n\t\"math\"\n\t\"math/rand\"\n\t\"os\"\n)\n\nvar palette = []color.Color{\n\tcolor.Black,\n\tcolor.RGBA{0x00, 0xFF, 0x00, 0xFF},\n\tcolor.RGBA{0xFF, 0x00, 0x00, 0xFF},\n\tcolor.RGBA{0x00, 0x00, 0xFF, 0xFF},\n\tcolor.RGBA{0xFF, 0x00, 0xFF, 0xFF},\n\tcolor.RGBA{0xFF, 0xFF, 0x00, 0xFF},\n}\n\nconst (\n\tforegroundIndex = 0\n\tbackgroundIndex = 1\n)\n\nfunc main() {\n\tlissajous(os.Stdout)\n}\n\nfunc lissajous(out io.Writer) {\n\tconst (\n\t\tcycles  = 5\n\t\tres     = 0.001\n\t\tsize    = 100\n\t\tnframes = 64\n\t\tdelay   = 8\n\t)\n\n\tfreq := rand.Float64() * 3.0\n\tanim := gif.GIF{LoopCount: nframes}\n\tphase := 0.0\n\tfor i := 0; i < nframes; i++ {\n\t\trect := image.Rect(0, 0, 2*size+1, 2*size+1)\n\t\timg := image.NewPaletted(rect, palette)\n\t\tfor t := 0.0; t < cycles*2*math.Pi; t += res {\n\t\t\tx := math.Sin(t)\n\t\t\ty := math.Sin(t*freq + phase)\n\t\t\timg.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), uint8(t/(2*math.Pi))+1)\n\t\t}\n\t\tphase += 0.1\n\t\tanim.Delay = append(anim.Delay, delay)\n\t\tanim.Image = append(anim.Image, img)\n\t}\n\tgif.EncodeAll(out, &anim)\n}\n"
  },
  {
    "path": "go/gopl/01/07/fetch.go",
    "content": "// Exercise 1.7: The function call io.Copy(dst, src) reads from src and writes\n// to dst. Use it instead of ioutil.ReadAll to copy the response body to\n// os.Stdout without requiring a buffer large enough to hold the entire stream.\n// Be sure to check the error result of io.Copy.\npackage main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n)\n\nfunc main() {\n\tfor _, url := range os.Args[1:] {\n\t\tresp, err := http.Get(url)\n\n\t\tif err != nil {\n\t\t\tfmt.Fprintf(os.Stderr, \"fetch: %v\\n\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\n\t\t_, err = io.Copy(os.Stdout, resp.Body)\n\n\t\tif err != nil {\n\t\t\tfmt.Fprintf(os.Stderr, \"fetch: reading %s: %v\\n\", url, err)\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/gopl/01/08/fetch.go",
    "content": "// Exercise 1.8: Modify fetch to add the prefix http:// to each argument URL if\n// it is missing. You might want to use strings.HasPrefix.\npackage main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc main() {\n\tfor _, url := range os.Args[1:] {\n\t\tif !strings.HasPrefix(url, \"http://\") && !strings.HasPrefix(url, \"https://\") {\n\t\t\turl = \"http://\" + url\n\t\t}\n\n\t\tresp, err := http.Get(url)\n\n\t\tif err != nil {\n\t\t\tfmt.Fprintf(os.Stderr, \"fetch: %v\\n\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\n\t\t_, err = io.Copy(os.Stdout, resp.Body)\n\n\t\tif err != nil {\n\t\t\tfmt.Fprintf(os.Stderr, \"fetch: reading %s: %v\\n\", url, err)\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/gopl/01/09/fetch.go",
    "content": "// Exercise 1.9: Modify fetch to also print the HTTP status code, found in\n// resp.Status\npackage main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc main() {\n\tfor _, url := range os.Args[1:] {\n\t\tif !strings.HasPrefix(url, \"http://\") && !strings.HasPrefix(url, \"https://\") {\n\t\t\turl = \"http://\" + url\n\t\t}\n\n\t\tresp, err := http.Get(url)\n\n\t\tif err != nil {\n\t\t\tfmt.Fprintf(os.Stderr, \"fetch: %v\\n\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\n\t\tfmt.Println(resp.Status)\n\n\t\t_, err = io.Copy(os.Stdout, resp.Body)\n\n\t\tif err != nil {\n\t\t\tfmt.Fprintf(os.Stderr, \"fetch: reading %s: %v\\n\", url, err)\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "go/gopl/Gemfile",
    "content": "source :rubygems\n\ngem 'guard'\ngem 'guard-shell'\ngem 'thor'\ngem 'term-ansicolor'\ngem 'rb-fsevent', require: false\ngem 'rb-inotify', require: false\n"
  },
  {
    "path": "go/gopl/README.markdown",
    "content": "# The Go Programming Language\n\nThis is some code I've written while reading [The Go Programming Language](http://www.gopl.io/).\nI'm trying to solve all exercises one by one. I initially decided not to do\nthe exercises of the book, but they just turned out to be too much fun.\nIdeally they will help me get a bit more familiar with the language before I\ntry to do something with it.\n"
  },
  {
    "path": "go/gopl/Thorfile",
    "content": "require 'term/ansicolor'\n\nclass Exercise\n  class << self\n    def next\n      current_chapter = chapters(false).last\n      last_exercise   = exercises_in_chapter(current_chapter).last\n      next_exercise   = last_exercise.to_i + 1\n\n      new current_chapter, next_exercise\n    end\n\n    def each\n      chapters.each do |chapter|\n        exercises_in_chapter(chapter).each do |number|\n          yield new chapter, number\n        end\n      end\n    end\n\n    def each_with_test\n      each do |exercise|\n        next unless exercise.has_test?\n        yield exercise\n      end\n    end\n\n    private\n\n    def chapters\n      Dir['*'].grep(/^(\\d+)$/).sort.map(&:to_i)\n    end\n\n    def exercises_in_chapter(chapter)\n      chapter = format \"%02d\", chapter.to_i\n      Dir[\"#{chapter}/*\"].grep(%r{^(?:\\d+)/(\\d+)$}) { $1.to_i }.sort\n    end\n  end\n\n  def initialize(chapter, number)\n    @chapter = chapter.to_i\n    @number = number.to_i\n  end\n\n  def name\n    format \"%d.%02d\", @chapter, @number\n  end\n\n  def run\n    files = Dir.glob('*.go').reject { |name| name.end_with?('_test.go') }\n    raise \"Don't know how to run multiple files yet\" if files.count != 1\n    file = files.first\n\n    cd { system \"go run #{file}\" }\n  end\n\n  def run_test(stdout: true)\n    raise \"No tests found in #{path}\" unless has_test?\n\n    command = \"go test\"\n    command += \" > /dev/null 2>&1\" unless stdout\n\n    cd { system command }\n  end\n\n  def run_benchmark\n    raise \"No tests found in #{path}\" unless has_test?\n\n    cd { system \"go test -bench=. -benchmem\" }\n  end\n\n  def has_test?\n    Dir[\"#{path}/*_test.go\"] != []\n  end\n\n  private\n\n  def cd\n    Dir.chdir(path) { yield }\n  end\n\n  def path\n    format \"%02d/%02d\", @chapter, @number\n  end\nend\n\nclass Run < Thor\n  include Term::ANSIColor\n\n  desc :exercise, 'Runs an exercise or its tests'\n  method_option :chapter, type: :numeric, desc: 'The chapter number'\n  method_option :number, type: :numeric, desc: 'The exercise number'\n  def exercise(chapter, number)\n    exercise = Exercise.new(chapter, number)\n    exercise.run\n  end\n\n  desc :test, 'Runs the tests of an exercise'\n  method_option :chapter, type: :numeric, desc: 'The chapter number'\n  method_option :number, type: :numeric, desc: 'The exercise number'\n  def test(chapter, number)\n    exercise = Exercise.new(chapter, number)\n    exit exercise.run_test ? 0 : 1\n  end\n\n  desc :benchmark, 'Runs the benchmark of an exercise'\n  method_option :chapter, type: :numeric, desc: 'The chapter number'\n  method_option :number, type: :numeric, desc: 'The exercise number'\n  def benchmark(chapter, number)\n    exercise = Exercise.new(chapter, number)\n    exit exercise.run_benchmark ? 0 : 1\n  end\n\n  desc :all, 'Runs all the tests'\n  def all\n    Exercise.each_with_test do |exercise|\n      print bold(\"#{exercise.name}: \")\n      success = exercise.run_test stdout: false\n      if success\n        puts \"success\"\n      else\n        puts red(\"FAILURE\")\n        exit(1) unless success\n      end\n    end\n\n    puts green(\"OK\")\n  end\nend\n"
  },
  {
    "path": "haskell/aryth/Ast.hs",
    "content": "module Ast (\n  Expr(..),\n  BinaryOp(..),\n  Statement(..),\n  build\n) where\n\nimport qualified Data.Map as M\nimport Data.List (nub, intercalate, (\\\\))\nimport Control.Applicative ((<$>))\n\ndata BinaryOp = Add\n              | Sub\n              | Mul\n              | Div\n              | Exp\n  deriving (Eq, Show)\n\ndata Expr = Number Float\n          | Name String\n          | Call String [Expr]\n          | Binary BinaryOp Expr Expr\n  deriving (Eq)\n  \ndata Statement = Expr Expr\n               | Assignment String Expr\n               | Definition String [String] Expr\n  deriving (Eq)\n\ninstance Show Statement where\n  show (Expr expr)           = show expr\n  show (Assignment var expr) = var ++ \" = \" ++ show expr\n  show (Definition name args body) = name ++ \"(\" ++ intercalate \", \" args ++ \") { \" ++ show body ++ \" }\"\n\ninstance Show Expr where\n  show (Number n) = show n\n  show (Name v) = v\n  show (Call name args) = name ++ \"(\" ++ intercalate \", \" (map show args) ++ \")\"\n  show (Binary op a b) = \"(\" ++ show a ++ \" \" ++ symbol op ++ \" \" ++ show b ++ \")\"\n\ninstance Num Expr where\n  (+) = Binary Add\n  (*) = Binary Mul\n  (-) = Binary Sub\n  abs = undefined\n  signum = undefined\n  fromInteger = Number . fromIntegral\n\ninstance Fractional Expr where\n  (/) = Binary Div\n  fromRational = Number . fromRational\n  \ninstance Floating Expr where\n  (**)  = Binary Exp\n  pi    = undefined\n  exp   = undefined\n  log   = undefined\n  sin   = undefined\n  cos   = undefined\n  asin  = undefined\n  atan  = undefined\n  acos  = undefined\n  sinh  = undefined\n  cosh  = undefined\n  asinh = undefined\n  atanh = undefined\n  acosh = undefined\n\nsymbol :: BinaryOp -> String\nsymbol Add = \"+\"\nsymbol Sub = \"-\"\nsymbol Mul = \"*\"\nsymbol Div = \"/\"\nsymbol Exp = \"^\"\n  \nshowOp :: (Show s) => String -> s -> s -> String\nshowOp op a b = \"(\" ++ show a ++ \" \" ++ op ++ \" \" ++ show b ++ \")\"\n\nsomeExpr :: Expr\nsomeExpr = (3 + 1) * 3 - 1 / 2 + 2 ** 1 ** 2\n\nvariables :: Expr -> [String]\nvariables = nub . nonUnique\n  where nonUnique (Number _)     = []\n        nonUnique (Name n)       = [n]\n        nonUnique (Binary _ a b) = variables a ++ variables b\n\nbuild :: String -> [String] -> Expr -> Either String Statement\nbuild name args body | length args /= length (nub args)    = Left $ \"Duplicate argument name: \" ++ show args\n                     | not . null $ variables body \\\\ args = Left $ \"Undefined arguments: \" ++ show (variables body \\\\ args)\n                     | otherwise = Right $ Definition name args body\n\nmain = do\n  print $ show someExpr\n  print $ 1 + Call \"foo\" [1, 2, Name \"a\" + 1]\n"
  },
  {
    "path": "haskell/aryth/Interpreter.hs",
    "content": "import Ast\nimport Parser\nimport World\nimport qualified Data.Map as M\nimport Control.Monad (forM)\n\nexec :: World -> Statement -> (Computation (Maybe Float), World)\nexec world (Expr expr) = (Just `fmap` evaluate world expr, world)\nexec world (Assignment name expr) = case evaluate world expr of\n  Failure err -> (Failure err, world)\n  Success val -> (Success Nothing, M.insert name (Value val) world)\nexec world (Definition name args body) = (Success Nothing, world')\n  where world' = M.insert name (Function (FuncDef args body)) world\n\nprocess :: World -> IO ()\nprocess world = do\n  putStr \"> \"\n  input <- getLine\n  case input of\n    \"q\" -> return ()\n    \"defs\" -> do\n      forM (M.toAscList world) $ \\(n, i) -> putStrLn $ n ++ \": \" ++ show i\n      process world\n    _ -> case parseAst input of\n      Left err -> do\n        putStrLn \"Parsing error:\"\n        putStrLn $ concat $ map (\\s -> \"  \" ++ s ++ \"\\n\") (lines (show err))\n        process world\n      Right stmt ->\n        let (comp, world') = exec world stmt in\n        case comp of\n          Failure msg -> print msg >> process world'\n          Success (Just val) -> print val >> process world'\n          Success Nothing -> process world'\n  \nmain = process caladan\nm = main"
  },
  {
    "path": "haskell/aryth/Parser.hs",
    "content": "module Parser (\n  parseAst\n) where\n\nimport Ast\nimport Data.List (intercalate)\nimport Text.ParserCombinators.Parsec\nimport Text.ParserCombinators.Parsec.Expr (buildExpressionParser, Assoc(..), OperatorTable(..), Operator(..))\nimport qualified Text.ParserCombinators.Parsec.Token as P\nimport Text.ParserCombinators.Parsec.Language (emptyDef)\nimport Control.Monad (liftM, forM)\n\nlexer      = P.makeTokenParser emptyDef\n\nwhiteSpace = P.whiteSpace lexer\nnatural    = P.natural lexer\nparens     = P.parens lexer\nreservedOp = P.reservedOp lexer\nidentifier = P.identifier lexer\ncomma      = P.comma lexer\nbraces     = P.braces lexer\n\nstatement = (try definition >>= either fail return)\n            <|> try assignment\n            <|> liftM Expr expr\n\nassignment = do\n  name <- identifier\n  reservedOp \"=\"\n  value <- expr\n  return $ Assignment name value\n  \ncall = do\n  name <- identifier\n  args <- parens (sepBy expr comma)\n  return $ Call name args\n\ndefinition = do\n  name <- identifier\n  args <- parens (sepBy identifier comma)\n  body <- braces expr\n  return $ build name args body\n\nexpr = buildExpressionParser table term\n        <?> \"expression\"\n\nterm = try call\n        <|> parens expr\n        <|> liftM (Number . fromIntegral) natural\n        <|> liftM Name identifier\n        <?> \"simple expression\"\n\ntable :: OperatorTable Char () Expr\ntable = [ [binary \"^\" Exp AssocRight],\n          [binary \"*\" Mul AssocLeft, binary \"/\" Div AssocLeft],\n          [binary \"+\" Add AssocLeft, binary \"-\" Sub AssocLeft]\n        ]\n\nbinary symbol op assoc = Infix (reservedOp symbol >> return (Binary op)) assoc\n\nparseAst input = parse parser \"(ast input)\" input \n  where parser = do\n          whiteSpace\n          ast <- statement\n          eof\n          return ast\n\ncodes = [\n    \"1 + 2\",\n    \"f(a,b)\",\n    \"f(c, d) { c + d }\",\n    \"f(a, a) { 1 }\",\n    \"f(a) { 1 }\",\n    \"f(x) { x + c }\"\n  ]\n\nmain = do\n  forM codes $ \\code -> do\n    case parseAst code of\n      Left err -> putStrLn $ code ++ \": \" ++ intercalate \" | \" (lines (show err))\n      Right ast -> putStrLn $ code ++ \": \" ++ show ast\n  return ()\n"
  },
  {
    "path": "haskell/aryth/World.hs",
    "content": "{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}\n\nmodule World (\n  World,\n  Inhabitant(..),\n  Computation(..),\n  ComputationError(..),\n  FuncDef(..),\n  evaluate,\n  caladan\n) where\n  \nimport Ast\nimport qualified Data.Map as M\nimport Data.List (intercalate)\nimport Control.Monad (liftM2, mapM)\nimport Control.Monad.Error --(Error(..), throwError, MonadError(..))\n\ndata FuncDef = FuncDef { args :: [String], body :: Expr } deriving (Eq, Show)\n\ndata Inhabitant = Value Float\n                | Function FuncDef\n  deriving (Eq)\n\ntype World = M.Map String Inhabitant\n\nnewtype ComputationError = ComputationError { msgOf :: String } deriving (Show, Eq)\n\ndata Computation a = Success a | Failure ComputationError deriving (Show, Eq)\n\ninstance Functor Computation where\n  f `fmap` Success a = Success (f a)\n  f `fmap` Failure e = Failure e\n\ninstance Monad Computation where\n  return x = Success x\n  (Failure err) >>= _ = Failure err\n  (Success x) >>= f = f x\n\ninstance MonadError ComputationError Computation where\n  throwError = Failure\n  catchError = undefined\n\ninstance Error ComputationError where\n  noMsg  = ComputationError \"What the phukk?\"\n  strMsg = ComputationError \n\ninstance Show Inhabitant where\n  show (Value float) = show float\n  show (Function (FuncDef args body)) = \"f(\" ++ intercalate \", \" args ++ \") { \" ++ show body ++ \" }\"\n\nevaluate :: World -> Expr -> Computation Float\nevaluate world (Number n) = return n\nevaluate world (Binary op a b) = liftM2 (apply op) (evaluate world a) (evaluate world b)\nevaluate world (Name name) = maybe err return (value world name)\n  where err = throwError (strMsg $ \"Undefined variable `\" ++ name ++ \"'\")\nevaluate world (Call name exprs) = do\n    FuncDef args body <- maybe undefinedFunc return (function world name)\n    params <- evaluate world `mapM` exprs\n    funcWorld <- bind args params\n    evaluate funcWorld body\n  where undefinedFunc = throwError (strMsg $ \"Undefined function `\" ++ name ++ \"'\")\n\nbind :: [String] -> [Float] -> Computation World\nbind names values\n  | length names == length values = return $ M.fromList (zip names (map Value values))\n  | otherwise                     = throwError (strMsg $ \"Supplied arguments \" ++ show values ++ \" for \" ++ show names)\n\nvalue :: World -> String -> Maybe Float\nvalue world name = do\n  Value val <- M.lookup name world\n  return val\n  \nfunction :: World -> String -> Maybe FuncDef\nfunction world name = do\n  Function def <- M.lookup name world\n  return def\n\napply :: BinaryOp -> Float -> Float -> Float\napply Add = (+)\napply Sub = (-)\napply Mul = (*)\napply Div = (/)\napply Exp = (**)\n\ncaladan :: World\ncaladan = M.fromList [\n    (\"paul\", Value 3.14),\n    (\"jessica\", Value 2.71), \n    (\"larodi\", Function (FuncDef [] (Number 1))),\n    (\"add\", Function (FuncDef [\"a\", \"b\"] (Name \"a\" + Name \"b\"))),\n    (\"f\", Function (FuncDef [\"a\"] (Name \"a\" + Name \"a\")))\n  ]\n\nmain = do\n  print $ evaluate caladan (1 + 2)\n  print $ evaluate caladan (1 + 2 + Name \"paul\")\n  print $ evaluate caladan (1 + 2 + Name \"larodi\")\n  print $ evaluate caladan (Call \"foo\" [1.4, 2])\n  print $ evaluate caladan (Call \"add\" [Name \"jessica\", 2])\n  print $ evaluate caladan (Call \"f\" [1])\n  print $ evaluate caladan (Call \"larodi\" [])\n  return ()\n\n"
  },
  {
    "path": "haskell/programming_haskell/Chapter01.hs",
    "content": "product' (x:xs) = x * product xs\nproduct' []   = 1\n\nqsort []     = []\nqsort (x:xs) = qsort larger ++ [x] ++ qsort smaller\n               where\n                   smaller = [a | a <- xs, a <= x]\n                   larger = [b | b <- xs, b > x]\n"
  },
  {
    "path": "haskell/programming_haskell/Chapter04.hs",
    "content": "halve :: [a] -> ([a], [a])\nhalve l = splitAt ((length l) `div` 2) l\n\nsafetail1 :: [a] -> [a]\nsafetail1 x = if (null x) then [] else tail x\n\nsafetail2 :: [a] -> [a]\nsafetail2 l | null l    = []\n            | otherwise = tail l\n            \nsafetail3 :: [a] -> [a]\nsafetail3 (x:xs) = xs\nsafetail3 _      = []"
  },
  {
    "path": "haskell/programming_haskell/Chapter05.hs",
    "content": "squareSum :: Int -> Int\nsquareSum n = sum [x ^ 2 | x <- [1..n]]\n\nreplicate2 :: Int -> a -> [a]\nreplicate2 n x = [x | _ <- [1..n]]\n\npairs xs = zip xs (tail xs)\n\npyths :: Int -> [(Int, Int, Int)]\npyths n = [(x, y, z) | z <- [1..], y <- [1..z], x <- [1..y], x ^ 2 + y ^ 2 == z ^ 2]\n\nperfects :: Int -> [Int]\nperfects x = [n | n <- [1..x], (sum (factors n)) == n]\n    where factors n = [a | a <- [1..(n-1)], n `mod` a == 0]\n\nfind :: Eq a => a -> [(a, b)] -> [b]\nfind k t = [v | (k', v) <- t, k == k']\n\npositions :: Eq a => a -> [a] -> [Int]\npositions x xs = find x (zip xs [0..])\n\nscalarproduct :: [Int] -> [Int] -> Int\nscalarproduct xs ys = sum [ x * y | (x, y) <- zip xs ys]\n\nmain = print (scalarproduct [1, 2, 3] [4, 5, 6])\n--main = print (perfects 500)\n--main = print (positions False [True, False, False, True, False])\n--main = print (take 10 (pyths 10))"
  },
  {
    "path": "haskell/programming_haskell/Chapter06.hs",
    "content": "(^^) :: Int -> Int -> Int\nx ^^ 0       = 1\nx ^^ (a + 1) = x * (x ^ a)\n\nand' :: [Bool] -> Bool\nand' []     = True\nand' (x:xs) = x && and xs\n\nconcat' :: [[a]] -> [a]\nconcat' xss = [ x | xs <- xss, x <- xs]\n\nreplicate' :: Int -> a -> [a]\nreplicate' 0 _       = []\nreplicate' (n + 1) x = x:replicate n x\n\n(!!!) :: [a] -> Int -> a\n(x:xs) !!! 0       = x\n(x:xs) !!! (a + 1) = xs !!! a\n\nelm :: Eq a => a -> [a] -> Bool\ne `elm` []                 = False\ne `elm` (x:xs) | e == x    = True\n               | otherwise = e `elm` xs\n\nmerge :: Ord a => [a] -> [a] -> [a]\nmerge xs []         = xs\nmerge [] ys         = ys\nmerge (x:xs) (y:ys) | x <= y    = x:merge xs (y:ys)\n                    | otherwise = y:merge (x:xs) ys\n\nhalve :: [a] -> ([a], [a])\nhalve l = splitAt ((length l) `div` 2) l\n\nmergesort :: Ord a => [a] -> [a]\nmergesort []  = []\nmergesort [a] = [a]\nmergesort xs  = merge (mergesort left) (mergesort right)\n    where (left, right) = halve xs\n\nsum' :: [Int] -> Int\nsum' []     = 0\nsum' (x:xs) = x + sum' xs\n\ntake' :: Num a => Int -> [a] -> [a]\ntake' 0 _            = []\ntake' _ []           = []\ntake' (n + 1) (x:xs) = x:(take' n xs)\n\nlast' :: [a] -> a\nlast' [x]    = x\nlast' (x:xs) = last' xs\n\n--main = print (take' 12 [1, 2, 3, 4, 5])\n--main = print (mergesort [5, 4, 2, 8, 11, 3, 23, 9])\n--main = print (halve [1])\n--main = print (merge [2, 5, 6] [1, 3, 4])\n--main = print (5 `elm` [1, 2, 3])\n--main = print ([1, 2, 3, 4] !!! 1)\n--main = print (concat [[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n--main = print (2 ^ 8)"
  },
  {
    "path": "haskell/programming_haskell/Chapter07.hs",
    "content": "all' :: (a -> Bool) -> [a] -> Bool\nall' _ [] = True\nall' p (x:xs) | p x       = all' p xs\n              | otherwise = False\n    \nany' :: (a -> Bool) -> [a] -> Bool\nany' _ [] = False\nany' p (x:xs) | p x       = True\n              | otherwise = any' p xs\n\nall'' :: (a -> Bool) -> ([a] -> Bool)\nall'' p = foldr (&&) True . map p\n\nany'' :: (a -> Bool) -> ([a] -> Bool)\nany'' p = foldr (||) False . map p\n\ntakeWhile' :: (a -> Bool) -> [a] -> [a]\ntakeWhile' p []     = []\ntakeWhile' p (x:xs) | p x       = x:takeWhile p xs\n                    | otherwise = []\n                    \ndropWhile' :: (a -> Bool) -> [a] -> [a]\ndropWhile' p []     = []\ndropWhile' p (x:xs) | p x       = dropWhile' p xs\n                    | otherwise = x:xs\n                    \nmap' :: (a -> b) -> [a] -> [b]\nmap' f = foldr ((:) . f) []\n--map' f = foldr (\\x xs -> f x:xs) []\n\nfilter' :: (a -> Bool) -> [a] -> [a]\nfilter' p = foldr (\\x xs -> if p x then x:xs else xs) []\n\ndec2int :: [Int] -> Int\ndec2int = foldl ((+) . (*10)) 0\n--dec2int = foldl (\\s n -> s * 10 + n) 0\n\ncurry' :: ((a, b) -> c) -> a -> b -> c\ncurry' f = \\x y -> f (x, y)\n\nuncurry' :: (a -> b -> c) -> (a, b) -> c\nuncurry' f = \\(x, y) -> f x y\n\nadd' (x, y) = x + y\nadd'' x y = x + y\n\nunfold :: (a -> Bool) -> (a -> b) -> (a -> a) -> a -> [b]\nunfold p h t x | p x       = []\n               | otherwise = h x : unfold p h t (t x)\n\nmap'' :: (a -> b) -> [a] -> [b]                  \nmap'' f = unfold null (f . head) tail\n\niterate' :: (a -> a) -> a -> [a]\niterate' = unfold (\\_ -> False) id\n\nmain = print (take 10 (iterate' (*2) 1))\n--main = print (take 10 (map'' (*2) [1..]))\n--main = print (uncurry' add'' (1, 5))\n--main = print (curry add' 1 2)\n--main = print (sse [1, 2, 3, 4, 5])\n--main = print (dec2int [1, 2, 3])\n--main = print (take 10 (filter' even [1..]))\n--main = print (dropWhile' odd [1, 3, 5, 7, 8, 9, 11])"
  },
  {
    "path": "haskell/programming_haskell/Chapter09.hs",
    "content": "import IO\n\ngetLine' :: IO String\ngetLine' = do x <- getChar\n              if x == '\\n' then\n                  return []\n                else\n                  do xs <- getLine\n                     return (x:xs)\n\nstrlen :: IO ()\nstrlen = do putStr \"Enter a string: \"\n            xs <- getLine\n            putStr \"The string has \"\n            putStr (show (length xs))\n            putStrLn \" characters\"\n            \nbeep :: IO ()\nbeep = putStr \"\\BEL\"\n\ncls :: IO ()\ncls = putStr \"\\ESC[2J\"\n\ntype Pos = (Int, Int)\n\ngoto :: Pos -> IO ()\ngoto (x, y) = putStr (\"\\ESC[\" ++ show y ++ \";\" ++ show x ++ \"H\")\n\nwriteat :: Pos -> String -> IO ()\nwriteat p xs = do goto p\n                  putStr xs\n                  \nseqn :: [IO a] -> IO ()\nseqn [] = return ()\nseqn (ac:acs) = do ac\n                   seqn acs\n\n\n\n\n-- Game of Life --\nwidth = 50\nheight = 50\n\ntype Board = [Pos]\n\nglider :: [Pos]\nglider = [(4, 2), (2, 3), (4, 3), (3, 4), (4, 4)]\n\nshowcells :: Board -> IO ()\nshowcells b = seqn [ writeat p \"*\" | p <- b]\n\nisAlive :: Board -> Pos -> Bool\nisAlive b p = elem p b\n\nisEmpty :: Board -> Pos -> Bool\nisEmpty b p = not (isAlive b p)\n\nneighbs :: Pos -> [Pos]\nneighbs (x, y) = map wrap [(x - 1, y - 1), (x, y - 1),\n                           (x + 1, y - 1), (x - 1, y),\n                           (x + 1, y), (x - 1, y + 1),\n                           (x, y + 1), (x + 1, y + 1)]\nwrap :: Pos -> Pos\nwrap (x, y) = (((x - 1) `mod` width) + 1, ((y - 1) `mod` height) + 1)\n\nliveneighbs :: Board -> Pos -> Int\nliveneighbs b = length . filter (isAlive b) . neighbs\n\nsurvivors :: Board -> [Pos]\nsurvivors b = [p | p <- b, elem (liveneighbs b p) [2, 3]]\n\nrmdups :: Eq a => [a] -> [a]\nrmdups []     = []\nrmdups (x:xs) = x:rmdups (filter (/= x) xs)\n\nbirths :: Board -> [Pos]\n--births b = [(x, y) | x <- [1..width], y <- [1..height], isEmpty b (x, y), liveneighbs b (x, y) == 3]\nbirths b = [(x, y) | (x, y) <- rmdups (concat (map neighbs b)), \n                     isEmpty b (x, y), \n                     liveneighbs b (x, y) == 3]\n                     \nnextgen :: Board -> Board\nnextgen b = survivors b ++ births b\n\nlife b = do cls\n            showcells b\n            wait 50000\n            life (nextgen b)\n\nwait :: Int -> IO ()\nwait n = seqn [ return () | _ <- [1..n]] -- Rather unimaginative\n"
  },
  {
    "path": "haskell/programming_haskell/Nim.hs",
    "content": "import Data.Char\n\ntype Pos = (Int, Int)\n\nbeep :: IO ()\nbeep = putStr \"\\BEL\"\n\ncls :: IO ()\ncls = putStr \"\\ESC[2J\"\n\ngoto :: Pos -> IO ()\ngoto (x, y) = putStr (\"\\ESC[\" ++ show y ++ \";\" ++ show x ++ \"H\")\n\nwriteat :: Pos -> String -> IO ()\nwriteat p xs = do goto p\n                  putStr xs\n                  \nseqn :: [IO a] -> IO ()\nseqn [] = return ()\nseqn (ac:acs) = do ac\n                   seqn acs\n                   \ntype Board = [Int]\ndata Player = First | Second\n\nother :: Player -> Player\nother First  = Second\nother Second = First\n\nname :: Player -> String\nname First  = \"N1\"\nname Second = \"N2\"\n\ninitial :: Board\ninitial = [5, 4, 3, 2, 1]\n\nshowboard :: Board -> IO ()\nshowboard b = do cls\n                 seqn [writeat (1, y) (show y ++ \": \" ++ line t) | (y, t) <- zip [1..5] b]\n                    \nline :: Int -> String\nline tokens = (replicate tokens '*') ++ (replicate 5 ' ')\n\nmove :: Board -> Player -> IO ()\nmove board player = do cls\n                       showboard board\n                       if complete board then\n                             writeat (1, 6) (\"Winner: \" ++ name (other player) ++ \"\\n\")\n                           else do writeat (1, 6) (name player ++ \" (row-number): \")\n                                   input <- getLine\n                                   case process board input of\n                                        [row, number] -> move (takeAt board (row - 1) number) (other player)\n                                        [] -> do beep\n                                                 move board player\n\ncomplete :: Board -> Bool\ncomplete [0, 0, 0, 0, 0] = True\ncomplete _               = False\n\nchr2num :: Char -> Int\nchr2num c | (ord '0' <= ord c) && (ord c <= ord '9') = ord c - ord '0'\n          | otherwise                                = -1\n\ntakeAt :: Board -> Int -> Int -> Board\ntakeAt (x:xs) 0       n = x - n:xs\ntakeAt (x:xs) (r + 1) n = x:takeAt xs r n\n\nat :: Board -> Int -> Int          \nat board row = board !! (row - 1)\n\nfeasible :: Board -> Int -> Int -> Bool\nfeasible b r n = and [r >= 1, r <= 5, n >= 1, n <= (at b r)]\n\nprocess :: Board -> String -> [Int]\nprocess b [r, '-', n] | feasible b (chr2num r) (chr2num n) = [(chr2num r), (chr2num n)] \nprocess b _ = []\n\nf = main\nmain = move initial First"
  },
  {
    "path": "haskell/programming_haskell/README",
    "content": "Exercises from Programming Haskell, carried out of curiosity."
  },
  {
    "path": "haskell/real_world_haskell/Find.hs",
    "content": "{-# LANGUAGE ScopedTypeVariables #-}\n\nimport Control.Monad\nimport System.Directory (Permissions(..), getModificationTime,\n    getPermissions, getDirectoryContents, doesDirectoryExist)\nimport System.Time (ClockTime(..))\nimport System.FilePath ((</>), takeExtension)\nimport Control.Exception\nimport System.IO (IOMode(..), hClose, hFileSize, openFile)\n\ngetRecursiveContents :: FilePath -> IO [FilePath]\ngetRecursiveContents top = do\n    names <- getDirectoryContents top\n    let proper = filter (`notElem` [\".\", \"..\"]) names\n    paths <- forM proper $ \\name -> do\n        let path = top </> name\n        isDir <- doesDirectoryExist path\n        if isDir\n            then getRecursiveContents path\n            else return [path]\n    return (concat paths)\n\n\n\nsimpleFind :: (FilePath -> Bool) -> FilePath -> IO [FilePath]\nsimpleFind p path = do\n    names <- getRecursiveContents path\n    return (filter p names)\n\n\n\ntype Predicate = FilePath -> Permissions -> Maybe Integer -> ClockTime -> Bool\n\nbetterFind :: Predicate -> FilePath -> IO [FilePath]\nbetterFind p path = do\n    paths <- getRecursiveContents path\n    filterM check paths\n    where check name = do\n            perms <- getPermissions name\n            size <- getFileSize name\n            modified <- getModificationTime name\n            return (p name perms size modified)\n\ngetFileSize :: FilePath -> IO (Maybe Integer)\ngetFileSize path = handle (\\(_ :: IOException) -> return Nothing) $ do\n    bracket (openFile path ReadMode) hClose $ \\h -> do\n        size <- hFileSize h\n        return (Just size)\n\ntype InfoP a = FilePath -> Permissions -> Maybe Integer -> ClockTime -> a\n\npathP :: InfoP FilePath\npathP p _ _ _ = p\n\nsizeP :: InfoP Integer\nsizeP _ _ (Just size) _ = size\nsizeP _ _ Nothing     _ = -1\n\nliftPath :: (FilePath -> a) -> InfoP a\nliftPath f = \\n _ _ _ -> f n\n\nliftP :: (a -> b -> c) -> InfoP a -> b -> InfoP c\nliftP o f r = \\n p s m -> f n p s m `o` r\n\nlift2P :: (a -> b -> c) -> InfoP a -> InfoP b -> InfoP c\nlift2P o l r = \\n p s m -> l n p s m `o` r n p s m\n\ngreaterP, lesserP :: (Ord a) => InfoP a -> a -> InfoP Bool\ngreaterP = liftP (>)\nlesserP  = liftP (<)\n\nandP, orP :: InfoP Bool -> InfoP Bool -> InfoP Bool\nandP = lift2P (&&)\norP = lift2P (||)\n    \nequalP :: (Eq a) => InfoP a -> a -> InfoP Bool\nequalP = liftP (==)\n\n(==?) = equalP\n(&&?) = andP\n(>?) = greaterP\n(<?) = lesserP\n\ninfix 4 ==?\ninfixr 3 &&?\ninfix 4 >?\n\n\n\nmain = do\n    paths <- betterFind (sizeP >? 20 &&? sizeP <? 30 &&? liftPath takeExtension ==? \".rb\") \"/work/pyfmi/site/app/helpers\"\n    forM paths $ \\p -> do\n        putStrLn p"
  },
  {
    "path": "haskell/real_world_haskell/Glob.hs",
    "content": "import System.Directory (doesDirectoryExist, doesFileExist, getCurrentDirectory, getDirectoryContents)\nimport System.FilePath (dropTrailingPathSeparator, splitFileName, (</>))\nimport Control.Monad (forM, filterM, mapM, liftM)\nimport Text.Regex.Posix ((=~))\n\nglobToRegex :: String -> String\nglobToRegex cs = '^' : globToRegex' cs ++ \"$\"\n\nglobToRegex' :: String -> String\nglobToRegex' \"\"           = \"\"\n\nglobToRegex' ('*':cs)     = \".*\" ++ globToRegex' cs\nglobToRegex' ('?':cs)     = '.' : globToRegex' cs\n\nglobToRegex' ('[':'!':c:cs) = \"[^\" ++ c :charClass cs\nglobToRegex' ('[':c:cs)     = '[' : c : charClass cs\nglobToRegex' ('[':_)        = error \"uncompleted character class\"\n\nglobToRegex' (c:cs)       = escape c ++ globToRegex' cs\n\nescape :: Char -> String\nescape c | c `elem` regexChars = \"\\\\\" ++ [c]\n         | otherwise           = [c]\n    where regexChars = \"\\\\().^$]|+\"\n\ncharClass :: String -> String\ncharClass (']':cs) = ']' : globToRegex' cs\ncharClass (c:cs)   = c : charClass cs\ncharClass []       = error \"unterminated character class\"\n\ndotless :: [FilePath] -> [FilePath]\ndotless (\".\":xs)  = dotless xs\ndotless (\"..\":xs) = dotless xs\ndotless (x:xs)    = (x:dotless xs)\ndotless []        = []\n\nlsLa :: FilePath -> IO [FilePath]\nlsLa dir = do contents <- (liftM dotless) (getDirectoryContents dir)\n              files <- filterM doesFileExist (map (dir </>) contents)\n              directories <- filterM doesDirectoryExist (map (dir </>) contents)\n              nestedFiles <- mapM lsLa directories\n              return $ files ++ (concat nestedFiles)\n\nmatch :: String -> String -> IO [FilePath]\nmatch dir glob = case splitFileName glob of\n                    (\"\", fileGlob) -> do \n                        result <- getDirectoryContents dir\n                        return $ filter (=~ globToRegex fileGlob) (map (dir </>) (dotless result))\n                    (dirGlob, fileGlob) -> do\n                        matches <- match dir (dropTrailingPathSeparator dirGlob)\n                        dirs <- filterM doesDirectoryExist matches\n                        files <- mapM (`match` fileGlob) dirs\n                        return $ concat files\n\nmain = match \"../..\" \"*a*/*haskell\"\n{- }\nmain = do dir <- getCurrentDirectory\n          files <- lsLa dir\n          forM files putStrLn\n          return ()\n-}\n--main = do dir <- getCurrentDirectory\n--         getDirectoryContents dir\n"
  },
  {
    "path": "haskell/real_world_haskell/PgmParser.hs",
    "content": "-- The non-improved version of the PGM parser\nimport qualified Data.ByteString.Lazy.Char8 as L8\nimport qualified Data.ByteString.Lazy as L\nimport Data.Char (isSpace, chr, isDigit)\nimport System.IO (IOMode(..), hClose, hFileSize, openFile)\nimport Word (Word8)\nimport Control.Applicative ((<$>))\n\ndata Greymap = Greymap {\n    greyWidth :: Int,\n    greyHeight :: Int,\n    greyMax :: Int,\n    greyData :: L.ByteString\n} deriving (Eq)\n\ninstance Show Greymap where\n    show (Greymap w h m _) = \"Greymap \" ++ show w ++ \"x\" ++ show h ++ \" \" ++ show m\n\ndata ParseState = ParseState {\n    string :: L.ByteString,\n    offset :: Integer\n} deriving (Show)\n\nnewtype Parse a = Parse {\n  runParse :: ParseState -> Either String (a, ParseState)\n}\n\nidentity :: a -> Parse a\nidentity a = Parse (\\s -> Right (a, s))\n\nparse :: Parse a -> L.ByteString -> Either String a\nparse parser init =\n  case runParse parser (ParseState init 0) of\n    Left error        -> Left error\n    Right (result, _) -> Right result\n\nparseByte :: Parse Word8\nparseByte = \n  getState ==> \\state ->\n      case L.uncons (string state) of\n          Nothing -> bail \"not enough input\"\n          Just (char, remainder) -> putState newState ==> \\_ -> identity char\n              where newState = state { string = remainder, offset = newOffset }\n                    newOffset = (offset state) + 1\n              \ngetState :: Parse ParseState\ngetState = Parse (\\s -> Right (s, s))\n\nputState :: ParseState -> Parse ()\nputState s = Parse (\\_ -> Right ((), s))\n\n(==>) :: Parse a -> (a -> Parse b) -> Parse b\nfirst ==> second = Parse  result\n  where result init =\n          case runParse first init of\n                Left msg -> Left msg\n                Right (result, newState) -> runParse (second result) newState\n\nbail :: String -> Parse a\nbail err = Parse $ \\s -> Left $\n    \"byte offset \" ++ show (offset s) ++ \": \" ++ err\n    \ninstance Functor Parse where\n  fmap f parser = parser ==> \\result -> identity (f result)\n\nw2c :: Word8 -> Char\nw2c = chr . fromIntegral\n\nparseChar :: Parse Char\nparseChar = w2c <$> parseByte\n                      \npeekByte :: Parse (Maybe Word8)\npeekByte = (fmap fst . L.uncons . string) <$> getState\n\npeekChar :: Parse (Maybe Char)\npeekChar = fmap w2c <$> peekByte\n\nparseWhile :: (Word8 -> Bool) -> Parse [Word8]\nparseWhile p = (fmap p <$> peekByte) ==> \\mp ->\n                if mp == Just True\n                  then parseByte ==> \\b -> (b:) <$> parseWhile p\n                  else identity []\n\nparseWhileWith :: (Word8 -> a) -> (a -> Bool) -> Parse [a]\nparseWhileWith f p = fmap f <$> parseWhile (p . f)\n\nparseNat :: Parse Int\nparseNat = parseWhileWith w2c isDigit ==> \\digits ->\n           if null digits\n             then bail \"no more input\"\n             else let n = read digits\n                  in if n < 0\n                       then bail \"Integer overflow\"\n                       else identity n\n                       \n(==>&) :: Parse a -> Parse b -> Parse b\np ==>& f = p ==> \\_ -> f\n\nskipSpaces :: Parse ()\nskipSpaces = parseWhileWith w2c isSpace ==>& identity ()\n\nassert :: Bool -> String -> Parse ()\nassert True _    = identity ()\nassert False msg = bail msg\n\nparseBytes :: Int -> Parse L.ByteString\nparseBytes n =\n  getState ==> \\st ->\n  let n' = fromIntegral n\n      (h, t) = L.splitAt n' (string st)\n      st' = st { offset = offset st + fromIntegral (L.length h), string = t }\n  in putState st' ==>&\n      assert (L.length h == n') \"end of input\" ==>&\n      identity h\n            \nparseRawPGM =\n  parseWhileWith w2c notWhite ==> \\header -> skipSpaces ==>&\n    assert (header == \"P5\") \"Bad header\" ==>&\n    parseNat ==> \\width -> skipSpaces ==>&\n    parseNat ==> \\height -> skipSpaces ==>&\n    parseNat ==> \\maxGrey -> parseByte ==>&\n    assert (maxGrey <= 255) \"Max grey is far too big\" ==>&\n    parseBytes (width * height) ==> \\bytes ->\n    identity $ Greymap width height maxGrey bytes\n  where notWhite = (`notElem` \" \\r\\n\\t\")\n\nmain = do handle <- openFile \"./sample/foo.pgm\" ReadMode\n          contents <- L8.hGetContents handle\n          print (parse parseRawPGM contents)"
  },
  {
    "path": "haskell/real_world_haskell/PgmSimple.hs",
    "content": "-- The non-improved version of the PGM parser\nimport qualified Data.ByteString.Lazy.Char8 as L8\nimport qualified Data.ByteString.Lazy as L\nimport Data.Char (isSpace)\nimport System.IO (IOMode(..), hClose, hFileSize, openFile)\n\ndata Greymap = Greymap {\n    greyWidth :: Int,\n    greyHeight :: Int,\n    greyMax :: Int,\n    greyData :: L.ByteString\n} deriving (Eq)\n\ninstance Show Greymap where\n    show (Greymap w h m _) = \"Greymap \" ++ show w ++ \"x\" ++ show h ++ \" \" ++ show m\n    \n\nmatchHeader :: L.ByteString -> L.ByteString -> Maybe L.ByteString\nmatchHeader prefix str\n    | prefix `L8.isPrefixOf` str = Just (L8.dropWhile isSpace (L.drop (L.length prefix) str))\n    | otherwise = Nothing\n    \ngetNat :: L.ByteString -> Maybe (Int, L.ByteString)\ngetNat str = case L8.readInt str of\n                Nothing -> Nothing\n                Just (num, rest) | num < 0   -> Nothing\n                                 | otherwise -> Just (fromIntegral num, rest)\ngetBytes :: Int -> L.ByteString -> Maybe (L.ByteString, L.ByteString)\ngetBytes num str = let count            = fromIntegral num\n                       both@(prefix, _) = L.splitAt count str\n                   in if L.length prefix < count\n                      then Nothing\n                      else Just both\n\nparseP5 :: L.ByteString -> Maybe (Greymap, L.ByteString)\n\nparseP5 s =\n  case matchHeader (L8.pack \"P5\") s of\n    Nothing -> Nothing\n    Just s1 ->\n      case getNat s1 of\n        Nothing -> Nothing\n        Just (width, s2) ->\n          case getNat (L8.dropWhile isSpace s2) of\n            Nothing -> Nothing\n            Just (height, s3) ->\n              case getNat (L8.dropWhile isSpace s3) of\n                Nothing -> Nothing\n                Just (maxGrey, s4)\n                  | maxGrey > 255 -> Nothing\n                  | otherwise ->\n                    case getBytes 1 s4 of\n                      Nothing -> Nothing\n                      Just (_, s5) ->\n                        case getBytes (width * height) s5 of\n                          Nothing -> Nothing\n                          Just (bitmap, s6) ->\n                            Just (Greymap width height maxGrey bitmap, s6)\n\n(>>?) :: Maybe a -> (a -> Maybe b) -> Maybe b\nNothing >>? _ = Nothing\nJust a >>? f  = f a\n\nparseP5_take2 :: L.ByteString -> Maybe (Greymap, L.ByteString)\nparseP5_take2 s =\n    matchHeader (L8.pack \"P5\") s        >>?\n    \\s -> skipSpace ((), s)             >>?\n    (getNat . snd)                      >>?\n    skipSpace                           >>?\n    \\(width, s) -> getNat s             >>?\n    skipSpace                           >>?\n    \\(height, s) -> getNat s            >>?\n    \\(maxGrey, s) -> getBytes 1 s       >>?\n    (getBytes (width * height) . snd)   >>?\n    \\(bitmap, s) -> Just (Greymap width height maxGrey bitmap, s)\n  \nskipSpace :: (a, L.ByteString) -> Maybe (a, L.ByteString)\nskipSpace (a, s) = Just (a, L8.dropWhile isSpace s)\n\n\nmain = do handle <- openFile \"./sample/foo.pgm\" ReadMode\n          contents <- L8.hGetContents handle\n          print (parseP5_take2 contents)\n"
  },
  {
    "path": "haskell/real_world_haskell/Traverse.hs",
    "content": "{-# LANGUAGE ScopedTypeVariables #-}\n\nimport Control.Monad (liftM, forM)\nimport Control.Exception (IOException(..), handle, bracket)\nimport System.Directory (Permissions(..), getPermissions, getModificationTime, getDirectoryContents,\n    doesDirectoryExist)\nimport System.FilePath ((</>), takeFileName, takeExtension)\nimport System.Time (ClockTime(..))\nimport System.IO (IOMode(..), openFile, hClose, hFileSize)\n\ndata Info = Info {\n    infoPath :: FilePath,\n    infoPerms :: Maybe Permissions,\n    infoSize :: Maybe Integer,\n    infoModTime :: Maybe ClockTime\n} deriving (Eq, Ord, Show)\n\nmaybeIO :: IO a -> IO (Maybe a)\nmaybeIO action = handle (\\(_ :: IOException) -> return Nothing) (liftM Just action)\n\ngetInfo :: FilePath -> IO Info\ngetInfo path = do\n    perms <- maybeIO (getPermissions path)\n    size <- maybeIO (bracket (openFile path ReadMode) hClose hFileSize)\n    modificationTime <- maybeIO (getModificationTime path)\n    return $ Info path perms size modificationTime\n\ntraverse :: ([Info] -> [Info]) -> FilePath -> IO [Info]\ntraverse order path = do\n    names <- getUsefulContents path\n    contents <- mapM getInfo (path : map (path </>) names)\n    liftM concat $ forM (order contents) $ \\info -> do\n        if isDirectory info && infoPath info /= path\n            then traverse order (infoPath info)\n            else return [info]\n\nisDirectory :: Info -> Bool\nisDirectory = maybe False searchable . infoPerms\n  \ngetUsefulContents :: FilePath -> IO [FilePath]\ngetUsefulContents path = do \n    names <- getDirectoryContents path\n    return $ filter (`notElem` [\".\", \"..\"]) names\n\n\n\ndata Iterate seed = Done     { unwrap :: seed }\n                  | Skip     { unwrap :: seed }\n                  | Continue { unwrap :: seed }\n                    deriving (Show)\ntype Iterator seed = seed -> Info -> Iterate seed\n\nfoldTree :: Iterator a -> a -> FilePath -> IO a\nfoldTree iter initSeed path = do\n    endSeed <- fold initSeed path\n    return (unwrap endSeed)\n  where\n    fold seed subpath = getUsefulContents subpath >>= walk seed\n    \n    walk seed (name:names) = do\n        let path' = path </> name\n        info <- getInfo path'\n        case iter seed info of\n            done@(Done _)   -> return done\n            Skip seed'      -> walk seed' names\n            Continue seed'\n                | isDirectory info -> do\n                    next <- fold seed' path'\n                    case next of\n                        done@(Done _) -> return done\n                        seed''        -> walk (unwrap seed'') names\n                | otherwise        -> walk seed' names\n    walk seed _ = return (Continue seed)\n                                \nfirstThreeRubyFiles :: Iterator [FilePath]\nfirstThreeRubyFiles files info\n    | length files == 3     \n        = Done files\n    | isDirectory info && takeFileName path == \".svn\"\n        = Skip files\n    | extension == \".rb\"\n        = Continue (path:files)\n    | otherwise\n        = Continue files\n        \n  where extension = takeExtension path\n        path = infoPath info\n    \n        \nmain = do\n    names <- foldTree firstThreeRubyFiles [] \"/work/pyfmi/site/app/\"\n    forM names putStrLn\n    return ()"
  },
  {
    "path": "haskell/real_world_haskell/json/Main.hs",
    "content": "module Main () where\n\nimport SimpleJSON\nimport PutJSON\n\nmain = putJValue (JObject [(\"foo\", JNumber 1), (\"bar\", JBool False)])"
  },
  {
    "path": "haskell/real_world_haskell/json/Prettify.hs",
    "content": "module Prettify where\n\ndata Doc = Empty\n         | Char Char\n         | Text String\n         | Line\n         | Concat Doc Doc\n         | Union Doc Doc\n           deriving (Show, Eq)\n\nempty :: Doc\nempty = Empty\n\nchar :: Char -> Doc\nchar c = Char c\n\ntext :: String -> Doc\ntext \"\" = Empty\ntext s  = Text s\n\ndouble :: Double -> Doc\ndouble d = text (show d)\n\nline :: Doc\nline = Line\n\n(<>) :: Doc -> Doc -> Doc\nEmpty <> y = y\nx <> Empty = x\nx <> y = x `Concat` y\n\nhcat :: [Doc] -> Doc\nhcat = fold (<>)\n\nfold :: (Doc -> Doc -> Doc) -> [Doc] -> Doc\nfold f = foldr f empty\n\nfsep :: [Doc] -> Doc\nfsep = fold (</>)\n\n(</>) :: Doc -> Doc -> Doc\nx </> y = x <> softline <> y\n\nsoftline :: Doc\nsoftline = group line\n\ngroup :: Doc -> Doc\ngroup x = flatten x `Union` x\n\nflatten :: Doc -> Doc\nflatten (x `Concat` y)  = flatten x `Concat` flatten y\nflatten Line            = Char ' '\nflatten (x `Union` _)   = flatten x\nflatten other           = other\n\ncompact :: Doc -> String\ncompact x = transform [x]\n    where transform [] = \"\"\n          transform (d:ds) =\n              case d of\n                  Empty         -> transform ds\n                  Char c        -> c : transform ds\n                  Text s        -> s ++ transform ds\n                  Line          -> '\\n' : transform ds\n                  a `Concat` b  -> transform (a:b:ds)\n                  _ `Union` b   -> transform (b:ds)\n\n\npunctuate :: Doc -> [Doc] -> [Doc]\npunctuate p []      = []\npunctuate p [d]     = [d]\npunctuate p (d:ds)  = (d <> p) : punctuate p ds\n                  \npretty :: Int -> Doc -> String\npretty width x = best 0 [x]\n    where best col (d:ds) =\n            case d of\n                Empty           -> best col ds\n                Char c          -> c : best (col + 1) ds\n                Text s          -> s ++ best (col + length s) ds\n                Line            -> '\\n' : best 0 ds\n                a `Concat` b    -> best col (a:b:ds)\n                a `Union` b     -> nicest col (best col (a:ds)) (best col (b:ds))\n          best _ _ = \"\"\n          nicest col a b | (width - least) `fits` a = a\n                         | otherwise                = b\n                         where least = min width col\n\n\nnest :: Int -> Int -> Doc -> String\nnest shiftwidth width x = best 0 0 [x]\n     where best i len (d:ds) =\n             case d of\n                 Empty           -> best i len ds\n                 Char c          -> c:best indent (len + 1) ds\n                     where indent = \n                             case c of\n                                 '{' -> i + 1\n                                 '}' -> i - 1\n                                 '[' -> i + 1\n                                 ']' -> i - 1\n                                 otherwise -> i\n                 Text str        -> str ++ best i (len + (length str)) ds\n                 Line            -> \"\\n\" ++ shift ++ best i (length shift) ds\n                     where shift = (replicate (i * shiftwidth) ' ')\n                 a `Concat` b    -> best i len (a:b:ds)\n                 a `Union` b     -> nicest len (best i len (a:ds)) (best i len (b:ds))\n           best _ _ _ = \"\"\n           nicest pad x y | (width - pad) `fits` x = x\n                          | otherwise                = y\n                          -- where least = min width pad\n\n\n\nfits :: Int -> String -> Bool\nw `fits` _ | w < 0  = False\nw `fits` \"\"         = True\nw `fits` ('\\n':_)   = True\nw `fits` (c:cs)     = (w - 1) `fits` cs\n          "
  },
  {
    "path": "haskell/real_world_haskell/json/PrettyJSON.hs",
    "content": "module PrettyJSON (renderJValue) where\n\nimport Numeric (showHex)\nimport Data.Bits (shiftR, (.&.))\nimport Data.Char (ord)\n\nimport SimpleJSON (JValue(..))\nimport Prettify (Doc, (<>), char, double, fsep, hcat, punctuate, text, compact, pretty, nest)\n\nstring :: String -> Doc\nstring = enclose '\"' '\"' .hcat . map oneChar\n\nenclose :: Char -> Char -> Doc -> Doc\nenclose left right x = char left <> x <> char right\n\noneChar :: Char -> Doc\noneChar c = case lookup c simpleEscapes of\n              Just r -> text r\n              Nothing | mustEscape c -> hexEscape c\n                      | otherwise    -> char c\n    where mustEscape c = c < ' ' || c == '\\x7f' || c > '\\xff'\n\nsmallHex :: Int -> Doc\nsmallHex x = text \"\\\\u\"\n          <> text (replicate (4 - length h) '0')\n          <> text h\n    where h = showHex x \"\"\n    \nastral :: Int -> Doc\nastral n = smallHex (a + 0xd800) <> smallHex (b + 0xdc00)\n    where a = (n `shiftR` 10) .&. 0x3ff\n          b = n .&. 0x3ff\n          \nhexEscape :: Char -> Doc\nhexEscape c | d < 0x10000 = smallHex d\n            | otherwise   = astral (d - 010000)\n    where d = ord c\n\nsimpleEscapes :: [(Char, String)]\nsimpleEscapes = zipWith ch \"\\b\\n\\f\\r\\t\\\\\\\"/\" \"bnfrt\\\\\\\"/\"\n    where ch a b = (a, ['\\\\', b])\n\nseries :: Char -> Char -> (a -> Doc) -> [a] -> Doc\nseries open close item = enclose open close .\n    fsep . punctuate (char ',') . map item\n\nrenderJValue :: JValue -> Doc\nrenderJValue (JBool True)   = text \"true\"\nrenderJValue (JBool False)  = text \"false\"\nrenderJValue JNull          = text \"null\"\nrenderJValue (JNumber num)  = double num\nrenderJValue (JString str)  = string str\nrenderJValue (JArray ary)   = series '[' ']' renderJValue ary\nrenderJValue (JObject obj)  = series '{' '}' field obj\n    where field (name, val) = string name <> text \": \" <> renderJValue val\n    \nvalue = renderJValue (JObject [(\"f\", JNumber 1), (\"z\", JArray [JString \"Foo\", JBool True, JNull]), (\"q\", JBool True)])\n\nmain = putStrLn (nest 2 13 value)\n\n-- TODO Rewrite Prettify.pretty in a more senseful way\n-- http://book.realworldhaskell.org/read/writing-a-library-working-with-json-data.html"
  },
  {
    "path": "haskell/real_world_haskell/json/PrettyStub.hs",
    "content": "module PrettyStub where\n\ndata Doc = ToBeDefined\n           deriving (Show)\n           \n(<>) :: Doc -> Doc -> Doc\na <> b = undefined\n\nchar :: Char -> Doc\nchar c = undefined\n\nhcat :: [Doc] -> Doc\nhcat xs = undefined\n\ntext :: String -> Doc\ntext str = undefined\n\ndouble :: Double -> Doc\ndouble num = undefined\n\nfsep :: [Doc] -> Doc\nfsep xs = undefined\n"
  },
  {
    "path": "haskell/real_world_haskell/json/PutJSON.hs",
    "content": "module PutJSON where\n    \nimport Data.List (intercalate)\nimport SimpleJSON\n\nrenderJValue :: JValue -> String\n\nrenderJValue (JString s)    = show s\nrenderJValue (JNumber n)    = show n\nrenderJValue (JBool True)   = \"true\"\nrenderJValue (JBool False)  = \"false\"\nrenderJValue JNull          = \"null\"\n\nrenderJValue (JObject o)    =  \"{\" ++ pairs o ++ \"}\"\n    where pairs [] = \"\"\n          pairs ps = intercalate \", \" (map renderPair ps)\n          renderPair (k, v) = show k ++ \": \" ++ renderJValue v\n          \nrenderJValue (JArray a)     = \"[\" ++ values a ++ \"]\"\n    where values [] = \"\"\n          values vs = intercalate \", \" (map renderJValue vs)\n          \nputJValue :: JValue -> IO ()\nputJValue v = putStrLn (renderJValue v)"
  },
  {
    "path": "haskell/real_world_haskell/json/README",
    "content": "Code from chapter 5 of Real World Haskell\nhttp://book.realworldhaskell.org/read/writing-a-library-working-with-json-data.html"
  },
  {
    "path": "haskell/real_world_haskell/json/SimpleJSON.hs",
    "content": "{-# LANGUAGE TypeSynonymInstances, OverlappingInstances #-}\n\nmodule SimpleJSON\n    (\n        JValue(..),\n        getString,\n        getInt,\n        getDouble,\n        getBool,\n        getObject,\n        getArray,\n        isNull\n    ) where\n\nnewtype JAry a = JAry {\n      fromJAry :: [a]\n    } deriving (Eq, Ord, Show)\n    \nnewtype JObj a = JObj {\n      fromJObj :: [(String, a)]\n    } deriving (Eq, Ord, Show)\n\ndata JValue = JString String\n            | JNumber Double\n            | JBool Bool\n            | JNull\n            | JObject (JObj JValue)\n            | JArray (JAry JValue)\n              deriving (Eq, Ord, Show)\n\ngetString :: JValue -> Maybe String\ngetString (JString s) = Just s\ngetString _           = Nothing\n\ngetInt (JNumber n) = Just n\ngetInt _           = Nothing\n\ngetDouble (JNumber n) = Just n\ngetDouble _           = Nothing\n\ngetBool (JBool b) = Just b\ngetBool _         = Nothing\n\ngetObject (JObject o) = Just o\ngetObject _           = Nothing\n\ngetArray (JArray a) = Just a\ngetArray _          = Nothing\n\nisNull v = v == JNull\n\ntype JSONError = String\nclass JSON a where\n    toJValue   :: a -> JValue\n    fromJValue :: JValue -> Either JSONError a\n\ninstance JSON JValue where\n    toJValue   = id\n    fromJValue = Right\n\ninstance JSON Bool where\n    toJValue             = JBool\n    fromJValue (JBool b) = Right b\n    fromJValue _         = Left \"not a JSON boolean\"\n    \ninstance JSON String where\n    toJValue               = JString\n    fromJValue (JString s) = Right s\n    fromJValue _           = Left \"not a JSON string\"\n\ndoubleToJValue :: (Double -> a) -> JValue -> Either JSONError a\ndoubleToJValue f (JNumber v) = Right (f v)\ndoubleToJValue _ _           = Left \"not a JSON number\"\n\ninstance JSON Int where\n    toJValue   = JNumber . realToFrac\n    fromJValue = doubleToJValue round\n    \ninstance JSON Integer where\n    toJValue   = JNumber . realToFrac\n    fromJValue = doubleToJValue round\n\ninstance JSON Double where\n    toJValue   = JNumber\n    fromJValue = doubleToJValue id\n\njaryFromJValue :: (JSON a) => JValue -> Either JSONError (JAry a)\njaryFromJValue (JArray (JAry a)) = whenRight JAry (mapEithers fromJValue a)\njaryFromJValue _ = Left \"not a JSON array\"\n\nwhenRight :: (b -> c) -> Either a b -> Either a c\nwhenRight _ (Left err) = Left err\nwhenRight f (Right a)  = Right (f a)\n\nmapEithers :: (a -> Either b c) -> [a] -> Either b [c]\nmapEithers f (x:xs) = case mapEithers f xs of\n                        Left err -> Left err\n                        Right ys -> case f x of\n                                      Left err -> Left err\n                                      Right y -> Right (y:ys)\nmapEithers _ _ = Right []\n\njaryToJValue :: (JSON a) => JAry a -> JValue\njaryToJValue = JArray . JAry . map toJValue . fromJAry\n\ninstance (JSON a) => JSON (JAry a) where\n    toJValue      = jaryToJValue\n    fromJValue    = jaryFromJValue\n    \nlistToJValues :: (JSON a) => [a] -> [JValue]\nlistToJValues = map toJValue\n\njvaluesToJAry :: [JValue] -> JAry JValue\njvaluesToJAry = JAry\n\njaryOfJValuesToJValue :: JAry JValue -> JValue\njaryOfJValuesToJValue = JArray\n"
  },
  {
    "path": "java/tdd_by_example/Money.java",
    "content": "import java.util.HashMap;\nimport java.util.Map;\n\n\npublic class Money implements Expression {\n\tprotected int amount;\n\tprotected String currency;\n\t\n\tpublic Money(int amount, String currency) {\n\t\tthis.amount = amount;\n\t\tthis.currency = currency;\n\t}\n\t\n\t@Override\n\tpublic boolean equals(Object object) {\n\t\tMoney money = (Money) object;\n\t\treturn money.amount == this.amount && money.currency().equals(this.currency());\n\t}\n\n\tpublic static Money dollar(int amount) {\n\t\treturn new Money(amount, \"USD\");\n\t}\n\t\n\tpublic static Money franc(int amount) {\n\t\treturn new Money(amount, \"CHF\");\n\t}\n\t\n\tpublic Expression times(int multiplier) {\n\t\treturn new Money(amount * multiplier, currency);\n\t}\n\n\tpublic String currency() {\n\t\treturn currency;\n\t}\n\n\tpublic Expression plus(Expression addend) {\n\t\treturn new Sum(this, addend);\n\t}\n\n\tpublic Money reduce(Bank bank, String to) {\n\t\treturn new Money(amount / bank.rate(currency, to), to);\n\t}\n\t\n\t@Override\n\tpublic String toString() {\n\t\treturn amount + \" \" + currency;\n\t}\n}\n\ninterface Expression {\n\tMoney reduce(Bank bank, String to);\n\tExpression times(int multiplier);\n\tExpression plus(Expression addend);\n}\n\nclass Sum implements Expression {\n\tExpression augend;\n\tExpression addend;\n\n\tpublic Sum(Expression augend, Expression addend) {\n\t\tthis.augend = augend;\n\t\tthis.addend = addend;\n\t}\n\n\tpublic Money reduce(Bank bank, String to) {\n\t\tint amount = augend.reduce(bank, to).amount + addend.reduce(bank, to).amount;\n\t\treturn new Money(amount, to);\n\t}\n\n\tpublic Expression plus(Expression addend) {\n\t\treturn new Sum(this, addend);\n\t}\n\n\tpublic Expression times(int multiplier) {\n\t\treturn new Sum(augend.times(multiplier), addend.times(multiplier));\n\t}\n}\n\nclass Bank {\n\t\n\tprivate Map<Pair, Integer> rates = new HashMap<Pair, Integer>();\n\n\tpublic Money reduce(Expression source, String to) {\n\t\treturn source.reduce(this, to);\n\t}\n\n\tpublic void addRate(String from, String to, int amount) {\n\t\trates.put(new Pair(from, to), amount);\n\t}\n\t\n\tint rate(String from, String to) {\n\t\tif (from.equals(to)) return 1;\n\t\treturn rates.get(new Pair(from, to));\n\t}\n}\n\nclass Pair {\n\tprivate String from;\n\tprivate String to;\n\t\n\tPair(String from, String to) {\n\t\tthis.from = from;\n\t\tthis.to = to;\n\t}\n\t\n\t@Override\n\tpublic boolean equals(Object obj) {\n\t\tPair pair = (Pair) obj;\n\t\treturn from.equals(pair.from) && to.equals(pair.to);\n\t}\n\t\n\t@Override\n\tpublic int hashCode() {\n\t\treturn 0;\n\t}\n}\n"
  },
  {
    "path": "java/tdd_by_example/MoneyTest.java",
    "content": "import junit.framework.TestCase;\n\n\npublic class MoneyTest extends TestCase {\n\tpublic void testMultiplication() {\n\t\tMoney five = Money.dollar(5);\n\t\tassertEquals(Money.dollar(10), five.times(2));\n\t\tassertEquals(Money.dollar(15), five.times(3));\n\t}\n\t\n\tpublic void testEquality() {\n\t\tassertTrue(Money.dollar(5).equals(Money.dollar(5)));\n\t\tassertFalse(Money.dollar(5).equals(Money.dollar(6)));\n\t\tassertTrue(Money.franc(5).equals(Money.franc(5)));\n\t}\n\t\n\tpublic void testSimpleAddition() {\n\t\tMoney five = Money.dollar(5);\n\t\tExpression sum = five.plus(five);\n\t\tBank bank = new Bank();\n\t\tMoney reduced = bank.reduce(sum, \"USD\");\n\t\tassertEquals(Money.dollar(10), reduced);\n\t}\n\t\n\tpublic void testCurrency() {\n\t\tassertEquals(\"USD\", Money.dollar(1).currency());\n\t\tassertEquals(\"CHF\", Money.franc(1).currency());\n\t}\n\t\n\tpublic void testPlusReturnsSumm() {\n\t\tMoney five = Money.dollar(5);\n\t\tMoney ten = Money.dollar(10);\n\t\tExpression result = five.plus(ten);\n\t\tSum sum = (Sum) result;\n\t\tassertEquals(five, sum.augend);\n\t\tassertEquals(ten, sum.addend);\n\t}\n\t\n\tpublic void testReduceSum() {\n\t\tExpression sum = new Sum(Money.dollar(3), Money.dollar(4));\n\t\tBank bank = new Bank();\n\t\tMoney result = bank.reduce(sum, \"USD\");\n\t\tassertEquals(Money.dollar(7), result);\n\t}\n\t\n\tpublic void testReduceMoney() {\n\t\tBank bank = new Bank();\n\t\tMoney result = bank.reduce(Money.dollar(1), \"USD\");\n\t\tassertEquals(Money.dollar(1), result);\n\t}\n\t\n\tpublic void testReduceMoneyDifferentCurreny() {\n\t\tBank bank = new Bank();\n\t\tbank.addRate(\"CHF\", \"USD\", 2);\n\t\tMoney result = bank.reduce(Money.franc(2), \"USD\");\n\t\tassertEquals(Money.dollar(1), result);\n\t}\n\t\n\tpublic void testIdentityRate() {\n\t\tassertEquals(1, new Bank().rate(\"USD\", \"USD\"));\n\t}\n\t\n\tpublic void testMixedAddition() {\n\t\tExpression fiveBucks = Money.dollar(5);\n\t\tExpression tenFrancs = Money.franc(10);\n\t\tBank bank = new Bank();\n\t\tbank.addRate(\"CHF\", \"USD\", 2);\n\t\tMoney result = bank.reduce(fiveBucks.plus(tenFrancs), \"USD\");\n\t\tassertEquals(Money.dollar(10), result);\n\t}\n\t\n\tpublic void testSumPlusMoney() {\n\t\tExpression fiveBucks = Money.dollar(5);\n\t\tExpression tenFrancs = Money.franc(10);\n\t\tBank bank = new Bank();\n\t\tbank.addRate(\"CHF\", \"USD\", 2);\n\t\tExpression sum = new Sum(fiveBucks, tenFrancs).plus(fiveBucks);\n\t\tMoney result = bank.reduce(sum, \"USD\");\n\t\tassertEquals(Money.dollar(15), result);\n\t}\n\t\n\tpublic void testSumTimes() {\n\t\tExpression fiveBucks = Money.dollar(5);\n\t\tExpression tenFrancs = Money.franc(10);\n\t\tBank bank = new Bank();\n\t\tbank.addRate(\"CHF\", \"USD\", 2);\n\t\tExpression sum = new Sum(fiveBucks, tenFrancs).times(2);\n\t\tMoney result = bank.reduce(sum, \"USD\");\n\t\tassertEquals(Money.dollar(20), result);\n\t}\n\t\n}\n"
  },
  {
    "path": "java/tdd_by_example/README",
    "content": "Try-outs from Test-Driven Development by Kent Beck\n==================================================\n\nThe book advocates doing TDD in very small increments, writing the\nsimplest test possible, followed by the simplest implementation possible\nand then refactoring. Known as the red/green/refactory cycle. The curious\nthing is that the steps are really tiny and that after writing the test\nyou should make it pass as quick as possible, even if that means returning\na constant or \"Faking it\" some other way. This way you get a test that you\nknow works and refactor \"in the green\".\n\nAnother curious thing is that when you follow this approach, you end up\nhaving very high coverage, since you basically don't write code you have\nno test for. Overall, you're progressing slower, but you should end up\nhaving a very nice test suite in the end.\n\nThe examples here were done following the book very closely. Different\ncommits represent the result after the end of each chapter (with one\nskipped).\n\n\n\nOne can find the book here:\n * http://www.amazon.com/Test-Driven-Development-Addison-Wesley-Signature/dp/0321146530\n"
  },
  {
    "path": "other/7languages/erlang/day1/count_to_ten.erl",
    "content": "-module(count_to_ten).\n-export([count_to_ten/0]).\n\ncount_to_ten() -> count_to(1, 10).\n\ncount_to(X, X) -> io:format(\"~p.~nDone!~n\", [X]);\ncount_to(A, B) -> io:format(\"~p...~n\", [A]), count_to(A + 1, B).\n\ncount(X) -> io:format(\"~p...~n\", [X]).\n"
  },
  {
    "path": "other/7languages/erlang/day1/result_of.erl",
    "content": "-module(result_of).\n-export([result_of/1]).\n\nresult_of(success) -> io:format(\"Success.~n\");\nresult_of({error, Message}) -> io:format(\"Error occurred: ~s.~n\", [Message]).\n"
  },
  {
    "path": "other/7languages/erlang/day1/word_count.erl",
    "content": "% Seven Languages in Seven Weeks, Erlang, day 1, exercise 1:\n%\n%   Write a function that uses recursion to return the number of\n%   words in a string.\n%\n% This is an awful exercise, given the language features introduced so far\n% (pattern matching, lists, function definition). Thus, the solution is a\n% hand-rolled state machine that counts transitions from space to character.\n-module(word_count).\n-export([word_count/1]).\n\nword_count(String) -> word_count(String, space, 0).\n\nword_count([32 | T], space, Count) -> word_count(T, space, Count);\nword_count([ _ | T], space, Count) -> word_count(T, character, Count + 1);\nword_count([32 | T], character, Count) -> word_count(T, space, Count);\nword_count([ _ | T], character, Count) -> word_count(T, character, Count);\nword_count([], _, Count) -> Count.\n"
  },
  {
    "path": "other/7languages/erlang/day2/pseudo_dict.erl",
    "content": "-module(pseudo_dict).\n-export([value_in/2]).\n\nvalue_in([{Key, Value} | _], Key) -> Value;\nvalue_in([_ | Tail], Key) -> value_in(Tail, Key);\nvalue_in([], _) -> undefined.\n"
  },
  {
    "path": "other/7languages/erlang/day2/tictactoe.erl",
    "content": "-module(tictactoe).\n-export([outcome/1]).\n\noutcome([W, W, W, _, _, _, _, _, _]) -> W;\noutcome([_, _, _, W, W, W, _, _, _]) -> W;\noutcome([_, _, _, _, _, _, W, W, W]) -> W;\noutcome([W, _, _, W, _, _, W, _, _]) -> W;\noutcome([_, W, _, _, W, _, _, W, _]) -> W;\noutcome([_, _, W, _, _, W, _, _, W]) -> W;\noutcome([W, _, _, _, W, _, _, _, W]) -> W;\noutcome([_, _, W, _, W, _, W, _, _]) -> W;\noutcome(Board) ->\n    case lists:all(fun(E) -> (E =:= x) or (E == o) end, Board) of\n        true -> cat;\n        false -> no_winner\n    end.\n"
  },
  {
    "path": "other/7languages/erlang/day2/total_price.erl",
    "content": "-module(total_price).\n-export([total_price/1]).\n\ntotal_price(ShoppingList) ->\n  [{Item, Quantity * Price} || {Item, Quantity, Price} <- ShoppingList].\n"
  },
  {
    "path": "other/7languages/io/day2/1/loop.io",
    "content": "fib := method(number,\n    a := 1\n    b := 1\n    (number - 2) repeat (\n        b = a + b\n        a = b - a\n    )\n    b\n)\n\nfib(1) println\nfib(2) println\nfib(3) println\nfib(4) println\nfib(5) println\nfib(6) println\nfib(7) println\nfib(8) println\nfib(9) println\nfib(10) println\n"
  },
  {
    "path": "other/7languages/io/day2/1/recursive.io",
    "content": "fib := method(number,\n    if(number == 1 or number == 2, 1, fib(number - 1) + fib(number - 2))\n)\n\nfib(1) println\nfib(2) println\nfib(3) println\nfib(4) println\nfib(5) println\nfib(6) println\nfib(7) println\nfib(8) println\nfib(9) println\nfib(10) println\n"
  },
  {
    "path": "other/7languages/io/day2/2.io",
    "content": "Number oldDivide := Number getSlot(\"/\")\nNumber / = method(arg,\n    if(arg == 0, 0, call target oldDivide(arg))\n)\n\n(1 / 2) println\n(2 / 3) println\n(3 / 0) println\n"
  },
  {
    "path": "other/7languages/io/day2/3.io",
    "content": "sum := method(lists, lists map(sum) sum)\n\n(sum(list(list(1, 2), list(3, 4))) == 10) println\n(sum(list(list(1), list(2, 3))) == 6) println\n"
  },
  {
    "path": "other/7languages/io/day2/4.io",
    "content": "List myAverage := method(\n    isEmpty ifTrue(Exception raise(\"List has no elements\"))\n    select(proto != Number) isEmpty ifFalse(Exception raise(\"List contains non-number elements\"))\n    sum / size\n)\n\n(list(1, 2, 3) myAverage == 2) println\n(list(1, 2, 3, 4) myAverage == 2.5) println\ntry(list() myAverage) error println\ntry(list(22, 0xF, \"Sofia\") myAverage) error println\n"
  },
  {
    "path": "other/7languages/io/day2/5.io",
    "content": "Matrix := Object clone do(\n    dim := method(x, y,\n        self items := list() setSize(y) map(list() setSize(x))\n        self\n    )\n    set := method(x, y, value,\n        items at(y) atPut(x, value)\n    )\n    get := method(x, y,\n        items at(y) at(x)\n    )\n)\n\nm := Matrix clone dim(2, 4)\nm set(0, 0, \"top left\")\nm set(1, 3, \"bottom right\")\nm get(0, 0) println\nm get(1, 3) println\n"
  },
  {
    "path": "other/7languages/io/day2/6.io",
    "content": "Matrix := Object clone do(\n    dim := method(x, y,\n        self items := list() setSize(y) map(list() setSize(x))\n        self\n    )\n    set := method(x, y, value,\n        items at(y) atPut(x, value)\n    )\n    get := method(x, y,\n        items at(y) at(x)\n    )\n    transpose := method(\n        n := items at(0) size\n        transposedItems := list\n        for(i, 0, n - 1, transposedItems append(items map(at(i))))\n        newMatrix := Matrix clone\n        newMatrix items := transposedItems\n        newMatrix\n    )\n)\n\nm := Matrix clone dim(2, 4)\nm set(0, 3, \"top right\")\nm set(1, 0, \"bottom left\")\n\nt := m transpose\n(t get(3, 0) == m get(0, 3)) println\n(t get(0, 1) == m get(1, 0)) println\n"
  },
  {
    "path": "other/7languages/io/day2/7.io",
    "content": "Matrix := Object clone do(\n    dim := method(x, y,\n        withItems list() setSize(y) map(list() setSize(x))\n    )\n    withItems := method(items,\n        self items := items\n        self\n    )\n    set := method(x, y, value,\n        items at(y) atPut(x, value)\n    )\n    get := method(x, y,\n        items at(y) at(x)\n    )\n    saveTo := method(filename,\n        file := File with(filename)\n        file remove\n        file openForUpdating\n        file write(items map(join(\",\")) join(\"\\n\"))\n        file close\n    )\n    readFrom := method(filename,\n        file := File with(filename)\n        file openForReading\n        readItems := file readLines map(split(\",\") map(asNumber))\n        file close\n        withItems(readItems)\n    )\n)\n\noriginal := Matrix clone withItems(list(list(1, 2), list(3, 4)))\noriginal saveTo(\"matrix.txt\")\n\nreloaded := Matrix clone readFrom(\"matrix.txt\")\nreloaded items println\n(reloaded items == original items) println\n\nFile with(\"matrix.txt\") remove\n"
  },
  {
    "path": "other/7languages/io/day2/8.io",
    "content": "guesses := 10\nguess := nil\nlastGuess := nil\nnumber := (Random value * 100) floor + 1\n\nloop(\n    lastGuess = guess\n    guess = File standardInput readLine(\"Your guess: \") asNumber\n    guesses = guesses - 1\n\n    (guess == number) ifTrue(writeln(\"You got it. Congratulations!\"); break)\n    (guesses == 0) ifTrue(writeln(\"Sorry, you failed. The number was: \", number); break)\n\n    lastGuess ifNonNil(\n        thisDistance := (number - guess) abs\n        lastDistance := (number - lastGuess) abs\n        if(thisDistance > lastDistance, \"Colder\", \"Hotter\") print\n    ) ifNil (\n        \"Nope\" print\n    )\n    writeln(\". \", guesses, \" guesses left\")\n)\n"
  },
  {
    "path": "other/7languages/io/day2/reflection.io",
    "content": "Object ancestors := method(\n    prototype := self proto\n    if(prototype != Object,\n        writeln(\"Slots of \", prototype type, \"\\n------------------\")\n        prototype slotNames foreach(slotName, writeln(slotName))\n        writeln\n        prototype ancestors\n    )\n)\n\nAnimal := Object clone\nAnimal speak := method(\"ambiguous animal noise\" println)\n\nDuck := Animal clone\nDuck speak := method(\"quack\" println)\nDuck walk := method(\"waddle\" println)\n\ndisco := Duck clone\ndisco ancestors\n"
  },
  {
    "path": "other/7languages/io/day3/1.io",
    "content": "Builder := Object clone\nBuilder spacing := 0\n\nBuilder forward := method(\n    printWithSpacing(\"<\", call message name, \">\")\n    increaseSpacing\n    call message arguments foreach(arg,\n        content := self doMessage(arg)\n        if(content type == \"Sequence\", printWithSpacing(content))\n    )\n    decreaseSpacing\n    printWithSpacing(\"</\", call message name, \">\")\n)\nBuilder increaseSpacing := method(self spacing := spacing + 1)\nBuilder decreaseSpacing := method(self spacing := spacing - 1)\nBuilder printWithSpacing := method(\n    spacing repeat(\"    \" print)\n    call delegateToMethod(self, \"writeln\")\n)\n\nBuilder ul(\n    li(\"Io\"),\n    li(\"Lua\"),\n    li(\"JavaScript\")\n)\n"
  },
  {
    "path": "other/7languages/io/day3/2.io",
    "content": "squareBrackets := method(call evalArgs)\n\n[1, 2, 3, 4] println\n[1 + 2, 2 + 3, 3 + 4] println\n"
  },
  {
    "path": "other/7languages/io/day3/3.io",
    "content": "OperatorTable addAssignOperator(\":\", \"makeHashPair\")\n\nCoolBuilder := Object clone do(\n    spacing := 0\n    forward := method(\n        tagName := call message name\n        items := call message arguments\n\n        if(items at(0) ?name == \"curlyBrackets\",\n                printWithSpacing(\"<\", tagName, \" \", AttributesPrinter makeAttributesString(items removeFirst), \">\")\n            ,\n                printWithSpacing(\"<\", tagName, \">\")\n        )\n        printContents(items)\n        printWithSpacing(\"</\", tagName, \">\")\n    )\n    printContents := method(contents,\n        self spacing = spacing + 1\n        contents foreach(item,\n            content := self doMessage(item)\n            if(content type == \"Sequence\", printWithSpacing(content))\n        )\n        self spacing = spacing - 1\n    )\n    printWithSpacing := method(\n        spacing repeat(\"    \" print)\n        call delegateToMethod(self, \"writeln\")\n    )\n)\n\nAttributesPrinter := Map clone do(\n    makeAttributesString := method(msg,\n        printer := AttributesPrinter clone\n        printer doMessage(msg)\n        printer map(key, value, key .. \"=\\\"\" .. value .. \"\\\"\") join(\" \")\n    )\n    curlyBrackets := method(\n        call message arguments foreach(arg, doMessage(arg))\n    )\n    makeHashPair := method(\n        self atPut(\n            call evalArgAt(0) asMutable removePrefix(\"\\\"\") removeSuffix(\"\\\"\"),\n            call evalArgAt(1)\n        )\n    )\n)\n\ndoFile(\"3.xml.io\")\n"
  },
  {
    "path": "other/7languages/io/day3/3.xml.io",
    "content": "CoolBuilder ul(\n    li({\"class\": \"important\", \"id\": \"io\"}, \"Io\"),\n    li({\"id\": \"lua\"}, \"Lua\"),\n    li(\"JavaScript\")\n)\n"
  },
  {
    "path": "other/7languages/io/day3/actors.io",
    "content": "slower := Object clone\nfaster := Object clone\n\nslower start := method(wait(2); writeln(\"slowly\"))\nfaster start := method(wait(1); writeln(\"quickly\"))\n\nslower start; faster start\nslower @@start; faster @@start; wait(3)\n"
  },
  {
    "path": "other/7languages/io/day3/builder.io",
    "content": "Builder := Object clone\n\nBuilder forward := method(\n    writeln(\"<\", call message name, \">\")\n    call message arguments foreach(arg,\n        content := self doMessage(arg)\n        content println\n        if(content type == \"Sequence\", writeln(content))\n    )\n    writeln(\"</\", call message name, \">\")\n)\n\nBuilder ul(\n    li(\"Io\"),\n    li(\"Lua\"),\n    li(\"JavaScript\")\n)\n"
  },
  {
    "path": "other/7languages/io/day3/coroutine.io",
    "content": "vizzini := Object clone\nvizzini talk := method(\n    \"Fezzik, are there rocks ahead?\" println\n    yield\n    \"No more rhymes now, I mean it\" println\n    yield\n)\n\nfezzik := Object clone\nfezzik rhyme := method(\n    yield\n    \"If there are, we'll all be dead\" println\n    yield\n    \"Anybody want a peanut?\" println\n)\n\nvizzini @@talk; fezzik @@rhyme\nCoroutine currentCoroutine pause\n"
  },
  {
    "path": "other/7languages/io/day3/futures.io",
    "content": "Lobby countAMillion := method(\n    writeln(\"Counter started\")\n    for(i, 1, 1000000, \"\")\n    \"Counter done\"\n)\ncounter := Lobby @countAMillion \nwriteln(\"Starting counter...\")\nwriteln(counter)\nwriteln(\"Exiting\")\n"
  },
  {
    "path": "other/7languages/io/day3/phonebook.io",
    "content": "OperatorTable addAssignOperator(\":\", \"atPutNumber\")\n\ncurlyBrackets := method(\n    r := Map clone\n    call message arguments foreach(arg,\n        r doMessage(arg)\n    )\n    r\n)\n\nMap atPutNumber := method(\n    self atPut(\n        call evalArgAt(0) asMutable removePrefix(\"\\\"\") removeSuffix(\"\\\"\"),\n        call evalArgAt(1)\n    )\n)\n\nphoneNumbers := doString(\"{\\\"Bob Smith\\\": \\\"5195551212\\\", \\\"Mary Walsh\\\": \\\"4162223434\\\"}\")\nphoneNumbers keys println\nphoneNumbers values println\n"
  },
  {
    "path": "other/7languages/prolog/day1/food.prolog",
    "content": "food_type(velveeta, cheese).\nfood_type(ritz, cracker).\nfood_type(spam, meat).\nfood_type(sausage, meat).\nfood_type(jolt, soda).\nfood_type(twinkie, dessert).\n\nflavor(sweet, dessert).\nflavor(savory, meat).\nflavor(savory, cheese).\nflavor(sweet, soda).\n\nfood_flavor(X, Y) :- food_type(X, Z), flavor(Y, Z).\n"
  },
  {
    "path": "other/7languages/prolog/day1/friends.prolog",
    "content": "likes(wallace, cheese).\nlikes(grommit, cheese).\nlikes(wendolene, sheep).\n\nfriend(X, Y) :- \\+(X = Y), likes(X, Z), likes(Y, Z).\n\n"
  },
  {
    "path": "other/7languages/prolog/day1/map.prolog",
    "content": "different(red, green). different(red, blue).\ndifferent(green, red). different(green, blue).\ndifferent(blue, red). different(blue, green).\n\ncoloring(Alabama, Mississippi, Georgia, Tennessee, Florida) :-\n  different(Mississippi, Tennessee),\n  different(Mississippi, Alabama),\n  different(Alabama, Tennessee),\n  different(Alabama, Mississippi),\n  different(Alabama, Georgia),\n  different(Alabama, Florida),\n  different(Georgia, Florida),\n  different(Georgia, Tennessee).\n"
  },
  {
    "path": "other/7languages/prolog/day2/2.1.prolog",
    "content": "reversed(X, Y) :- reversed(X, [], Y).\n\nreversed([], X, X).\nreversed([X|Y], W, Z) :- reversed(Y, [X|W], Z).\n"
  },
  {
    "path": "other/7languages/prolog/day2/2.2.2.prolog",
    "content": "smallest(Min, [Min]).\nsmallest(Min, [A, B | Tail]) :- A =< B, smallest(Min, [A | Tail]).\nsmallest(Min, [A, B | Tail]) :- A >= B, smallest(Min, [B | Tail]).\n"
  },
  {
    "path": "other/7languages/prolog/day2/2.2.prolog",
    "content": "smallest(Number, List) :- member(Number, List), less_or_equal_than(Number, List).\n\nmember(Number, [Number|_]).\nmember(Number, [_|Tail]) :- member(Number, Tail).\n\nless_or_equal_than(Number, []).\nless_or_equal_than(Number, [Head|Tail]) :- Number =< Head, less_or_equal_than(Number, Tail).\n"
  },
  {
    "path": "other/7languages/prolog/day2/2.3.prolog",
    "content": "sorted([H | T], B, C) :- inserted(H, B, B1), sorted(T, B1, C).\nsorted([], X, X).\n\ninserted(A, [], [A]).\ninserted(A, [H | T], [A, H | T]) :- A < H.\ninserted(A, [H | T1], [H | T2]) :- H < A, inserted(A, T1, T2).\n"
  },
  {
    "path": "other/7languages/prolog/day2/concatenate.prolog",
    "content": "concatenate([], List, List).\nconcatenate([Head|Tail1], List, [Head|Tail2]) :- concatenate(Tail1, List, Tail2).\n"
  },
  {
    "path": "other/7languages/prolog/day2/fibonacci.prolog",
    "content": "fib(0, 1).\nfib(1, 1).\nfib(X, Y) :- S1 is X - 1, S2 is X - 2, fib(S1, F1), fib(S2, F2), Y is F1 + F2.\n"
  },
  {
    "path": "other/7languages/prolog/day2/list_math.prolog",
    "content": "count(0, []).\ncount(Count, [_|Tail]) :- count(TailCount, Tail), Count is TailCount + 1.\n\nsum(0, []).\nsum(Total, [Head|Tail]) :- sum(TailTotal, Tail), Total is TailTotal + Head.\n\naverage(Average, List) :- count(Count, List), sum(Sum, List), Average is Sum / Count.\n"
  },
  {
    "path": "other/7languages/prolog/day3/queens.prolog",
    "content": "valid_queen((Row, Col)) :- between(1, 8, Row), between(1, 8, Col).\n\nvalid_board([]).\nvalid_board([Head | Tail]) :- valid_queen(Head), valid_board(Tail).\n\nrows([], []).\nrows([(Row, _) | QueensTail], [Row | RowsTail]) :- rows(QueensTail, RowsTail).\n\ncols([], []).\ncols([(_, Col) | QueensTail], [Col | ColsTail]) :- cols(QueensTail, ColsTail).\n\ndiags1([], []).\ndiags1([(Row, Col) | QueensTail], [Diagonal | DiagonalsTail]) :-\n  Diagonal is Col - Row,\n  diags1(QueensTail, DiagonalsTail).\n\ndiags2([], []).\ndiags2([(Row, Col) | QueensTail], [Diagonal | DiagonalsTail]) :-\n  Diagonal is Col + Row,\n  diags2(QueensTail, DiagonalsTail).\n\neight_queens(Board) :-\n  length(Board, 8),\n  valid_board(Board),\n\n  rows(Board, Rows),\n  cols(Board, Cols),\n  diags1(Board, Diags1),\n  diags2(Board, Diags2),\n\n  is_set(Rows),\n  is_set(Cols),\n  is_set(Diags1),\n  is_set(Diags2).\n"
  },
  {
    "path": "other/7languages/prolog/day3/sudoku.prolog",
    "content": "domain([]).\ndomain([Head | Tail]) :- between(1, 4, Head), domain(Tail).\n\nvalid([]).\nvalid([Head | Tail]) :- is_set(Head), valid(Tail).\n\nsudoku(Puzzle, Solution) :-\n  Puzzle = Solution,\n  Puzzle = [S11, S12, S13, S14,\n            S21, S22, S23, S24,\n            S31, S32, S33, S34,\n            S41, S42, S43, S44],\n\n  domain(Puzzle),\n\n  Row1 = [S11, S12, S13, S14],\n  Row2 = [S21, S22, S23, S24],\n  Row3 = [S31, S32, S33, S34],\n  Row4 = [S41, S42, S43, S44],\n\n  Col1 = [S11, S21, S31, S41],\n  Col2 = [S12, S22, S32, S42],\n  Col3 = [S13, S23, S33, S43],\n  Col4 = [S14, S24, S34, S44],\n\n  Square1 = [S11, S12, S21, S22],\n  Square2 = [S13, S14, S23, S24],\n  Square3 = [S31, S32, S41, S42],\n  Square4 = [S33, S34, S43, S44],\n\n  valid([Row1, Row2, Row3, Row4,\n         Col1, Col2, Col3, Col4,\n         Square1, Square2, Square3, Square4]).\n\n"
  },
  {
    "path": "other/7languages/prolog/other/einstein.prolog",
    "content": "/*\n  Einstein's riddle\n\n  In a street there are five houses, painted five different colors.\n  In each house lives a person of different nationality.\n  These five homeowners each drink a different kind of beverage, smoke\n  different brand of cigar and keep a different pet.\n\n    1. The Brit lives in a red house.\n    2. The Swede keeps dogs as pets.\n    3. The Dane drinks tea.\n    4. The green house is next to, and on the left of the white house.\n    5. The owner of the green house drinks coffee.\n    6. The person who smokes Pall Mall rears birds.\n    7. The owner of the yellow house smokes Dunhill.\n    8. The man living in the centre house drinks milk.\n    9. The Norwegian lives in the first house.\n    10. The man who smokes Blends lives next to the one who keeps cats.\n    11. The man who keeps horses lives next to the man who smokes Dunhill.\n    12. The man who smokes Blue Master drinks beer.\n    13. The German smokes Prince.\n    14. The Norwegian lives next to the blue house.\n    15. The man who smokes Blends has a neighbour who drinks water.\n\n  Who owns the fish?\n*/\n\nnationality(Nationality) :- member(Nationality, [brit, swede, dane, norwegian, german]).\ncolor(Color) :- member(Color, [green, yellow, white, red, blue]).\npet(Pet) :- member(Pet, [fish, dogs, birds, horses, cats]).\nbeverage(Beverage) :- member(Beverage, [tea, coffee, milk, beer, water]).\ncigars(Brand) :- member(Brand, [pall_mall, dunhill, blends, prince, blue_master]).\n\nperson([Nation, Color, Pet, Beverage, Cigars]) :- nationality(Nation), color(Color), pet(Pet), beverage(Beverage), cigars(Cigars).\n\nhas(Thing, Person) :- nationality(Thing), Person = [Thing, _, _, _, _].\nhas(Thing, Person) :- color(Thing), Person = [_, Thing, _, _, _].\nhas(Thing, Person) :- pet(Thing), Person = [_, _, Thing, _, _].\nhas(Thing, Person) :- beverage(Thing), Person = [_, _, _, Thing, _].\nhas(Thing, Person) :- cigars(Thing), Person = [_, _, _, _, Thing].\n\nsame(A, B, People) :- has(A, Person), has(B, Person), member(Person, People).\n\nfirst_house(A, People) :- has(A, Person), People = [Person, _, _, _, _].\ncenter_house(A, People) :- has(A, Person), People = [_, _, Person, _, _].\nleft_of(A, B, People) :- has(A, PersonA), has(B, PersonB), nextto(PersonA, PersonB, People).\nneighbours(A, B, People) :- left_of(A, B, People); left_of(B, A, People).\n\nsolution(People) :-\n  People = [_, _, _, _, _],\n\n  same(brit, red, People),\n  same(swede, dogs, People),\n  same(dane, tea, People),\n  left_of(green, white, People),\n  same(green, coffee, People),\n  same(birds, pall_mall, People),\n  same(yellow, dunhill, People),\n  center_house(milk, People),\n  first_house(norwegian, People),\n  neighbours(blends, cats, People),\n  neighbours(horses, dunhill, People),\n  same(beer, blue_master, People),\n  same(german, prince, People),\n  neighbours(norwegian, blue, People),\n  neighbours(blends, water, People),\n\n  maplist(person, People),\n  flatten(People, Items),\n  is_set(Items).\n\nhas_fish(Nationality) :- solution(Solution), member([Nationality, _, fish, _, _], Solution).\n"
  },
  {
    "path": "other/7languages/scala/day1/1.scala",
    "content": "object Player extends Enumeration {\n  val X = Value(\"X\")\n  val O = Value(\"O\")\n\n  def fromChar(char : Char) : Player.Value = {\n    char match {\n      case 'X' => X\n      case 'O' => O\n      case ' ' => null\n      case _   => throw new AssertionError(\"Illegal character \" + char)\n    }\n  }\n}\n\nimport Player.X\nimport Player.O\n\nobject Board {\n  val rows = List((0, 1, 2), (3, 4, 5), (6, 7, 8))\n  val columns = List((0, 3, 6), (1, 4, 7), (2, 5, 8))\n  val diagonals = List((0, 4, 8), (2, 4, 6))\n  val lanes = rows ::: columns ::: diagonals\n}\n\nclass Board(marks : List[Player.Value]) {\n  assert(marks.length == 9)\n\n  def this(boardAsString : String) {\n    this(boardAsString.map(Player.fromChar).toList)\n    assert(boardAsString.matches(\"^[XO ]{9}$\"))\n  }\n\n  def winner() : Player.Value = {\n    val markedLanes = Board.lanes.map(marksOnLane)\n    markedLanes.foreach { lane =>\n      lane match {\n        case (X, X, X) => return X\n        case (O, O, O) => return O\n        case _ =>\n      }\n    }\n    return null\n  }\n\n  def marksOnLane(lane : (Int, Int, Int)) : (Player.Value, Player.Value, Player.Value) = {\n    (marks(lane._1), marks(lane._2), marks(lane._3))\n  }\n}\n\nprintln(new Board(\"XXXO  X  \").winner) // X\nprintln(new Board(\"X  O  X  \").winner) // null\nprintln(new Board(\"XO OO XO \").winner) // O\nprintln(new Board(\"XO OX XOX\").winner) // X\n"
  },
  {
    "path": "other/7languages/scala/day1/2.scala",
    "content": "object Player extends Enumeration {\n  val X = Value(\"X\")\n  val O = Value(\"O\")\n\n  def other(value : Value) = if (value == X) { O } else { X }\n  def asChar(value : Value) : Char = {\n    value match {\n      case X => 'X'\n      case O => 'O'\n      case null => ' '\n    }\n  }\n}\n\nimport Player.X\nimport Player.O\n\nobject Board {\n  val rows = List((0, 1, 2), (3, 4, 5), (6, 7, 8))\n  val columns = List((0, 3, 6), (1, 4, 7), (2, 5, 8))\n  val diagonals = List((0, 4, 8), (2, 4, 6))\n  val lanes = rows ::: columns ::: diagonals\n}\n\nclass Board {\n  var marks : Array[Player.Value] = Array(null, null, null, null, null, null, null, null, null)\n\n  def apply(square : Int) = marks(square)\n  def marksOnLane(lane : (Int, Int, Int)) = (marks(lane._1), marks(lane._2), marks(lane._3))\n  def taken(square : Int) = marks(square) != null\n  def isFull = marks.forall(_ != null)\n  def hasWinner = winner != null\n\n  def placeMark(player : Player.Value, square : Int) {\n    marks(square) = player\n  }\n\n  def winner : Player.Value = {\n    val markedLanes = Board.lanes.map(marksOnLane)\n    markedLanes.foreach { lane =>\n      lane match {\n        case (X, X, X) => return X\n        case (O, O, O) => return O\n        case _ =>\n      }\n    }\n    return null\n  }\n}\n\nobject GridRenderer {\n  def render(grid : Seq[Char]) = new GridRenderer(grid).render\n}\n\nclass GridRenderer(grid : Seq[Char]) {\n  def render {\n    println(separator)\n    for (row <- 0 to 2) {\n      println(rowLine(row))\n      println(separator)\n    }\n  }\n\n  def separator = \"+---+---+---+\"\n  def rowLine(row : Int) = \"| %c | %c | %c |\".format(at(row, 0), at(row, 1), at(row, 2))\n  def at(row : Int, column : Int) = grid(row * 3 + column)\n}\n\nclass Game {\n  var currentPlayer = X\n  val board = new Board\n\n  def play {\n    renderSquareNumbers\n\n    while (inProgress) {\n      playOn(readPosition)\n      renderBoard\n      switchPlayer\n    }\n\n    showOutcome\n  }\n\n  def inProgress = !(board.hasWinner || board.isFull)\n  def renderBoard = GridRenderer render board.marks.map(Player.asChar)\n  def renderSquareNumbers = GridRenderer render '1'.to('9')\n  def playOn(square : Int) = board.placeMark(currentPlayer, square)\n  def switchPlayer = this.currentPlayer = Player.other(currentPlayer)\n\n  def showOutcome {\n    if (board.winner != null) {\n      println(\"The winner is player \" + board.winner + \".\")\n    } else {\n      println(\"The game was a tie.\")\n    }\n  }\n\n  def readPosition : Int = {\n    while (true) {\n      print(\"Player \" + currentPlayer + \"'s turn. Pick square (1-9): \")\n      try {\n        val input = Console.readInt - 1\n        if (!0.to(8).contains(input)) {\n          println(\"Specify the square with a number from 1 to 9\")\n        } else if (board.taken(input)) {\n          println(\"Square is taken. Try another one\")\n        } else {\n          return input\n        }\n      } catch {\n        case e: NumberFormatException => println(\"Please enter an integer between 1 and 9.\")\n      }\n    }\n\n    throw new AssertionError(\"Unreachable code :P\")\n  }\n}\n\nnew Game().play\n"
  },
  {
    "path": "other/7languages/scala/day2/1.scala",
    "content": "val strings = List(\"Foo\", \"Bar\", \"Baz\")\nval totalSize = (0 /: strings) { _ + _.size }\nprintln(totalSize)\n"
  },
  {
    "path": "other/7languages/scala/day2/2.scala",
    "content": "class Person(name: String, catchPhrase: String) {\n  def greet() = println(greeting)\n  protected def greeting() = \"Hi, I am %s. %s\".format(name, catchPhrase)\n}\n\nobject Censor {\n  val censoredWords = Map(\n    \"Shoot\" -> \"Puckey\",\n    \"Darn\" -> \"Breans\"\n  )\n}\n\ntrait Censor extends Person {\n  override protected def greeting(): String = {\n    (super.greeting /: Censor.censoredWords) { (greeting, replacement) =>\n      greeting.replace(replacement._1, replacement._2)\n    }\n  }\n}\n\nvar homer = new Person(\"Homer Simpsons\", \"Darn. Shoot! Darn it to Shoot\") with Censor\nhomer.greet()\n"
  },
  {
    "path": "other/7languages/scala/day2/3.scala",
    "content": "class Person(name: String, catchPhrase: String) {\n  def greet() = println(greeting)\n  protected def greeting() = \"Hi, I am %s. %s\".format(name, catchPhrase)\n}\n\nobject Censor {\n  val censoredWords = readWordsFromFile\n\n  private def readWordsFromFile: Map[String, String] = {\n    val emptyMap: Map[String, String] = Map.empty\n    val linesInFile = scala.io.Source.fromFile(\"censored_words.txt\").getLines\n    linesInFile.\n      map(_.trim.split(\": +\")).\n      filter(_.length == 2).\n      foldLeft(emptyMap) { (map, words) => map + (words(0) -> words(1)) }\n  }\n}\n\ntrait Censor extends Person {\n  override protected def greeting(): String = {\n    (super.greeting /: Censor.censoredWords) { (greeting, replacement) =>\n      greeting.replace(replacement._1, replacement._2)\n    }\n  }\n}\n\nvar homer = new Person(\"Homer Simpsons\", \"Darn. Shoot! Darn it to Shoot.\") with Censor\nhomer.greet()\n\n"
  },
  {
    "path": "other/7languages/scala/day2/censored_words.txt",
    "content": "Shoot: Puckey\nDarn: Beans\n"
  },
  {
    "path": "other/7languages/scala/day3/sizer.scala",
    "content": "import scala.io._\nimport scala.actors._\nimport Actor._\n\nobject PageLoader {\n  def getPageSize(url: String)  = Source.fromURL(url).mkString.length\n}\n\nval urls = List(\"http://www.amazon.com/\", \"http://www.google.com/\", \"http://www.cnn.com/\")\n\ndef timeMethod(method: () => Unit) = {\n  val start = System.nanoTime\n  method()\n  val end = System.nanoTime\n  println(\"Method took \" + (end - start)/1000000000.0 + \" seconds.\")\n}\n\ndef getPageSizeSequentially() = {\n  for (url <- urls) {\n    println(\"Size for \" + url + \": \" + PageLoader.getPageSize(url))\n  }\n}\n\ndef getPageSizeConcurrently() = {\n  val caller = self\n\n  for (url <- urls) {\n    caller ! (url, PageLoader.getPageSize(url))\n  }\n\n  for (i <- 1 to urls.size) {\n    receive {\n      case (url, size) => println(\"Size for \" + url + \": \" + size)\n    }\n  }\n}\n\nprintln(\"Sequential run:\")\ntimeMethod { getPageSizeSequentially }\n\nprintln(\"Concurrent run:\")\ntimeMethod { getPageSizeConcurrently }\n"
  },
  {
    "path": "other/clrs/.gitignore",
    "content": "__pycache__\n*.pyc\n"
  },
  {
    "path": "other/clrs/.powrc",
    "content": "export LC_ALL=en_US.utf-8\nexport LANG=en_US.utf-8\nsource \".rvmrc\"\n"
  },
  {
    "path": "other/clrs/.ruby-version",
    "content": "2.7.2\n"
  },
  {
    "path": "other/clrs/.rvmrc",
    "content": "rvm --create 2.0.0@playground\n"
  },
  {
    "path": "other/clrs/01/01/01.markdown",
    "content": "> Give a real-world example that requires sorting or a real-world example\n> that requires computing a convex hull.\n\nA real-world example of sorting is pretty straightforward - for example, every\nweb page that renders a list alphabetically needs to sort the entries - a\ncatalog, an index or whatever.\n\nI have no clue why we need to compute convex hulls, but Wikipedia says that\nthere are a bunch of applications.\n"
  },
  {
    "path": "other/clrs/01/01/02.markdown",
    "content": "> Other than speed, what other measures of efficiency might one use in a\n> real-world setting?\n\nMemory usage and resource utilization (network, database) are good answers.\n"
  },
  {
    "path": "other/clrs/01/01/03.markdown",
    "content": "> Select a data structure that you have seen previously, and discuss its\n> strengths and limitations.\n\nLet's take the singly-linked list.\n\nStrengths:\n\n* It does not need sequential space in memory\n* We can insert a new element at any place\n\nLimitations:\n\n* Random access is $\\mathcal{O}(n)$\n* It takes additional memory for the links\n"
  },
  {
    "path": "other/clrs/01/01/04.markdown",
    "content": "> How are the shortest-path and traveling-salesman problems given above\n> similar? How are they different?\n\nThey are similar, because each of then has to walk a graph and find a path in\nthem.\n\nThe difference is the constraint on the solution. The shortest-path requires\njust a path between two points, while the traveling salesman requires a path\nbetween more points that returns to the first point.\n"
  },
  {
    "path": "other/clrs/01/01/05.markdown",
    "content": "> Come up with a real-world problem in which only the best solution will do.\n> Then come up with one in which a solution that is \"approximately\" the best\n> is good enough.\n\nSorting a catalog is a problem, where only the best solution will do. An\n\"approximately\" sorted catalog won't be that useful.\n\nFinding the shortest path between two points in a city is a problem, where\ngood-enough will do. It might not be the fastest way, but you will still get\nthere.\n"
  },
  {
    "path": "other/clrs/01/02/01.markdown",
    "content": "> Give an example of an application that requires algorithmic content at\n> the application level, and discuss the function of the algorithms\n> involved.\n\nGoogle Maps when finding a route between two places.\n\nThe algorithms are an essential part of this use case, since the route is what\nthe user cares for the most.\n"
  },
  {
    "path": "other/clrs/01/02/02.markdown",
    "content": "> Suppose we are comparing implementations of insetion sort and merge sort on\n> the same machine. For inputs of size $n$, insertion sort runs in $ 8n\\^{2} $\n> steps, while merge sort runs in $ 64n\\lg{n} $ steps. For which values of $n$\n> does insertion sort beat merge sort?\n\nAt $ n > 43 $ merge sort beats insertion sort.\n"
  },
  {
    "path": "other/clrs/01/02/03.markdown",
    "content": "> What is the smallest value of $n$ such that an algorithm whose running time\n> is $ 100n\\^{2} $ runs faster than an algorithm whose running time is $\n> 2\\^{n} $ on the same machine?\n\nAt $ n > 14 $, the first algorithm runs faster.\n"
  },
  {
    "path": "other/clrs/01/problems/01.markdown",
    "content": "## Comparison of running times\n\n> For each function $ f(n) $ and time $ t $ in the following table, determine\n> the largest size $ n $ of a problem that can be solved in time $ t $,\n> assuming that the algorithm to solve the problem takes $ f(n) $\n> microseconds.\n\n|              | 1 second          | 1 minute                  | 1 hour                  | 1 day                     | 1 month                    | 1 year                       | 1 century                          |\n|:------------:| -----------------:| -------------------------:| -----------------------:| -------------------------:| --------------------------:| ----------------------------:| ----------------------------------:|\n| $ \\lg{n}   $ | $ 2\\^{10\\^6}    $ | $ 2\\^{6 \\cdot 10\\^7}    $ | $ 2\\^{36 \\cdot 10\\^8} $ | $ 2\\^{864 \\cdot 10\\^8}  $ | $ 2\\^{25920 \\cdot 10\\^8} $ | $ 2\\^{315360 \\cdot 10\\^8}  $ | $ 2\\^{31556736 \\cdot 10\\^8}      $ |\n| $ \\sqrt{n} $ | $ 10\\^{12}      $ | $ 36 \\cdot 10\\^{14}     $ | $ 1296 \\cdot 10\\^{16} $ | $ 746496 \\cdot 10\\^{16} $ | $ 6718464 \\cdot 10\\^{18} $ | $ 994519296 \\cdot 10\\^{18} $ | $ 995827586973696 \\cdot 10\\^{16} $ |\n| $ n        $ | $ 10\\^6         $ | $ 6 \\cdot 10\\^7         $ | $ 36 \\cdot 10\\^{8}    $ | $ 864 \\cdot 10\\^{8}     $ | $ 2592 \\cdot 10\\^{9}     $ | $ 31536 \\cdot 10\\^{9}      $ | $ 31556736 \\cdot 10\\^{8}         $ |\n| $ n\\lg{n}  $ | $ 62746         $ | $ 2801417               $ | $ 133378058           $ | $ 2755147513            $ | $ 71870856404            $ | $ 797633893349             $ | $ 68654697441062                 $ |\n| $ n\\^2     $ | $ 1000          $ | $ 7745                  $ | $ 60000               $ | $ 293938                $ | $ 1609968                $ | $ 5615692                  $ | $ 56175382                       $ |\n| $ n\\^3     $ | $ 100           $ | $ 391                   $ | $ 1532                $ | $ 4420                  $ | $ 13736                  $ | $ 31593                    $ | $ 146677                         $ |\n| $ 2\\^n     $ | $ 19            $ | $ 25                    $ | $ 31                  $ | $ 36                    $ | $ 41                     $ | $ 44                       $ | $ 51                             $ |\n| $ n!       $ | $ 9             $ | $ 11                    $ | $ 12                  $ | $ 13                    $ | $ 15                     $ | $ 16                       $ | $ 17                             $ |\n"
  },
  {
    "path": "other/clrs/02/01/01.dot",
    "content": "digraph g {\n  node [shape=box style=filled fillcolor=white];\n\n  subgraph cluster_A {\n    A1 [label=\"31\" fillcolor=gray];\n    A2 [label=\"41\" fillcolor=black fontcolor=white];\n    A3 [label=\"59\"];\n    A4 [label=\"26\"];\n    A5 [label=\"41\"];\n    A6 [label=\"58\"];\n\n    { rank=same; A1, A2, A3, A4, A5, A6 }\n    A1 -> A2 -> A3 -> A4 -> A5 -> A6 [style=invis];\n  }\n\n  subgraph cluster_B {\n    B1 [label=\"31\"];\n    B2 [label=\"41\" fillcolor=gray];\n    B3 [label=\"59\" fillcolor=black fontcolor=white];\n    B4 [label=\"26\"];\n    B5 [label=\"41\"];\n    B6 [label=\"58\"];\n\n    { rank=same; B1, B2, B3, B4, B5, B6 }\n    B1 -> B2 -> B3 -> B4 -> B5 -> B6 [style=invis];\n  }\n\n  subgraph cluster_C {\n    C1 [label=\"31\" fillcolor=gray];\n    C2 [label=\"41\" fillcolor=gray];\n    C3 [label=\"59\" fillcolor=gray];\n    C4 [label=\"26\" fillcolor=black fontcolor=white];\n    C5 [label=\"41\"];\n    C6 [label=\"58\"];\n\n    { rank=same; C1, C2, C3, C4, C5, C6 }\n    C1 -> C2 -> C3 -> C4 [color=gray];\n    C4 -> C1 [constraint=false];\n    C4 -> C5 -> C6 [style=invis];\n  }\n\n  subgraph cluster_D {\n    D1 [label=\"26\"];\n    D2 [label=\"31\"];\n    D3 [label=\"41\" fillcolor=gray];\n    D4 [label=\"59\" fillcolor=gray];\n    D5 [label=\"41\" fillcolor=black fontcolor=white];\n    D6 [label=\"58\"];\n\n    { rank=same; D1, D2, D3, D4, D5, D6 }\n    D1 -> D2 -> D3 -> D4 -> D5 -> D6 [style=invis];\n    D4 -> D5 [constraint=false color=gray];\n    D5 -> D4 [constraint=false color=black];\n  }\n\n  subgraph cluster_E {\n    E1 [label=\"26\"];\n    E2 [label=\"31\"];\n    E3 [label=\"41\"];\n    E4 [label=\"41\" fillcolor=gray];\n    E5 [label=\"59\" fillcolor=gray];\n    E6 [label=\"58\" fillcolor=black fontcolor=white];\n\n    { rank=same; E1, E2, E3, E4, E5, E6 }\n    E1 -> E2 -> E3 -> E4 -> E5 -> E6 [style=invis];\n    E5 -> E6 [constraint=false color=gray];\n    E6 -> E5 [constraint=false color=black];\n  }\n\n  subgraph cluster_F {\n    F1 [label=\"26\"];\n    F2 [label=\"31\"];\n    F3 [label=\"41\"];\n    F4 [label=\"41\"];\n    F5 [label=\"58\"];\n    F6 [label=\"59\"];\n\n    { rank=same; F1, F2, F3, F4, F5, F6 }\n    F1 -> F2 -> F3 -> F4 -> F5 -> F6 [style=invis];\n  }\n\n  A1 -> B1 -> C1 -> D1 -> E1 -> F1 [style=invis];\n}\n"
  },
  {
    "path": "other/clrs/02/01/01.markdown",
    "content": "> Using figure 2.4 as a model, illustrate the operations of _Insertion-Sort_ on the array $ A = \\langle 31, 41, 59, 26, 41, 58 \\rangle $.\n\nWow, this took a while to implement. Graphviz sucks.\n"
  },
  {
    "path": "other/clrs/02/01/02.markdown",
    "content": "> Rewrite the _Insertion-Sort_ procedure to sort into nonincreasing instead of nondecreasing order.\n\nThe only thing we need to do, is flip the comparison:\n\n    for j = 2 to A.length\n        key = A[j]\n        i = j - 1\n        while i > 0 and A[i] < key\n            A[i + 1] = A[i]\n            i = i - 1\n        A[i + 1] = key\n"
  },
  {
    "path": "other/clrs/02/01/03.markdown",
    "content": "> Consider the **searching problem**:\n>\n> **Input**: A sequence of $ n $ numbers $ A = \\langle a_1, a_2, \\ldots, a_n \\rangle $\n> and a value $\\nu$.\n>\n> **Output**: And index $i$ such that $ \\nu = A[i] $ or the special value $\\mathrm{NIL}$ if $\\nu$ does\n> not appear in $A$\n>\n> Write the pseudocode for *linear search*, which scans through the sequence, looking\n> for $\\nu$. Using a loop invariant, prove that your algorithm is correct. Make sure that\n> your loop invariant fulfills the three necessary properties.\n\nThe pseudocode looks like this:\n\n    SEARCH(A, v):\n      for i = 1 to A.length\n          if A[i] == v\n              return i\n      return NIL\n\nI'm going to state the loop invariant as:\n\n> At the start of each iteration of the for loop, the subarray $A[1..i - 1]$ consists\n> of elements that are different than $\\nu$.\n\nHere are the three properties:\n\n---\n\n#### Initialization\n\nInitially the subarray is the empty array, so proving it is trivial.\n\n#### Maintenance\n\nOn each step, we know that $A[1..i-1]$ does not contain $\\nu$. We compare it with $A[i]$. If they are the same, we return $i$, which is a correct result. Otherwise, we continue to the next step. We have already insured that $A[A..i-1]$ does not contain $\\nu$ and that $A[i]$ is different from $\\nu$, so this step preserves the invariant.\n\n#### Termination\n\nThe loop terminates when $i > A.length$. Since $i$ increases by $1$ and $i > A.length$, we know that all the elements in $A$ have been checked and it has been found that $\\nu$ is not among them. Thus, we return $\\mathrm{NIL}$.\n\n---\n"
  },
  {
    "path": "other/clrs/02/01/04.markdown",
    "content": "> Consider the problem of adding two $n$-bit binary integers, stored in two n-element arrays\n> $A$ and $B$. The sum of the two integers should be stored in binary form in an\n> $(n + 1)$-element array $C$. State the problem formally and write pseudocode for adding\n> the two integers.\n\nI'm just happy that I don't need to write the loop invariant, since that seems tedious.\n\nThe formal statement:\n\n---\n\n**Input**: An array of booleans $A = \\langle a_1, a_2, \\ldots, a_n \\rangle$, an array of\nbooleans $B = \\langle b_1, b_2, \\ldots, b_n \\rangle$, each representing an integer stored\nin binary format (each digit is a number, either 0 or 1, least-significant digit first) and each of length $n$.\n\n**Output**: An array $C = \\langle c_1, c_2, \\ldots, c_{n+1} \\rangle$ that such that\n$C' = A' + B'$, where $A'$, $B'$ and $C'$ are the integers, represented by $A$, $B$ and $C$.\n\n---\n\nHere is the pseudocode:\n\n    ADD-BINARY(A, B):\n      C = new integer[A.length + 1]\n\n      carry = 0\n      for i = 1 to A.length\n          C[i] = (A[i] + B[i] + carry) % 2  // remainder\n          carry = (A[i] + B[i] + carry) / 2 // quotient\n      C[i] = carry\n\n      return C\n"
  },
  {
    "path": "other/clrs/02/02/01.markdown",
    "content": "> Express the function $ n^3 / 1000 - 100n^2 - 100n + 3 $ in terms of $\\Theta$-notation\n\nIt is as simple as $\\Theta(n^3)$.\n"
  },
  {
    "path": "other/clrs/02/02/02.markdown",
    "content": "> Consider sorting $n$ numbers in an array $A$ by first finding the smallest\n> element of $A$ and exchanging it with the element in $A[1]$. Then find the\n> second smallest element of $A$, and exchange it with $A[2]$. Continue in\n> this manner for the first $n - 1$ elements of $A$. Write pseudocode for this\n> algorithm, which is known as **selection sort**. What loop invariants does\n> this algorithm maintain? Why does it need to run for only the first $n - 1$\n> elements, rather than for all $n$ elements? Give the best-case and the\n> worst-case running times of selection sort in $\\Theta$-notation.\n\n## Pseudocode\n\n    SELECTION-SORT(A):\n      for i = 1 to A.length - 1\n          min = i\n          for j = i + 1 to A.length\n              if A[j] < A[min]\n                  min = j\n          temp = A[i]\n          A[i] = A[min]\n          A[min] = temp\n\n## Loop invariants\n\n> At the start of each iteration of the outer **for** loop, the subarray\n> $A[1..i - 1]$ contains the smallest $i - 1$ elements of the array, sorted\n> in nondecreasing order.\n\nAnd:\n\n> At the start of each iteration of the inner **for** loop, $A[min]$ is the\n> smallest number in the subarray $A[i..j - 1]$.\n\n## Why $n - 1$ elements?\n\nIn the final step, the algorithm will be left with two elements to compare. It\nwill store the smaller one in $A[n-1]$ and leave the larger in $A[n]$. The\nfinal one will be the largest element of the array, since all the previous\niteration would have sorted all but the last two elements (the outer loop\ninvariant). If we do it $n$ times, we will end up with a redundant step that\nsorts a single-element subarray.\n\n## Running times\n\nIn the best-case time (the array is sorted), the body of the if is never\ninvoked. The number of operations (counting the comparison as one operation)\nis:\n\n$$ (n - 1)(\\frac{n + 2}{2} + 4) $$\n\nIn the worst-case time (the array is reversed), the body of the if is invoked\non every occasion, which doubles the number of steps in the inner loop, that\nis:\n\n$$ (n - 1)(n + 6) $$\n\nBoth are clearly $\\Theta(n^2)$.\n"
  },
  {
    "path": "other/clrs/02/02/03.markdown",
    "content": "> Consider linear search again (see exercise 2.1-3). How many elements of the\n> input sequence need to be checked on the average, assuming that the element\n> being searched for is equally likely to be any element in the array? How\n> about the worst case? What are the average-case and worst-case running times\n> of linear search in $\\Theta$-notation? Justify your answers.\n\nIf the element is present in the sequence, half of the elements are likely to\nbe checked before it is found in the average case. In the worst case, all of\nthem will be checked. That is, $n/2$ checks for the average case and $n$ for\nthe worst case. Both of them are $\\Theta(n)$.\n"
  },
  {
    "path": "other/clrs/02/02/04.markdown",
    "content": "> How can we modify almost any algorithm to have a good best-case running time?\n\nWe can modify it to handle the best-case efficiently. For example, if we\nmodify merge-sort to check if the array is sorted and just return it, the\nbest-case running time will be $\\Theta(n)$.\n"
  },
  {
    "path": "other/clrs/02/03/01.dot",
    "content": "digraph G {\n  rankdir=BT;\n  { node[shape=box]; rank=same; 03, 41, 52, 26, 38, 57, 09, 49 }\n\n  node[shape=record];\n\n  { rank=same;\n    a1[label=\"03|41\"];\n    a2[label=\"26|52\"];\n    a3[label=\"38|57\"];\n    a4[label=\"09|49\"];\n  }\n\n  { rank=same;\n    b1[label=\"03|26|41|52\"];\n    b2[label=\"09|38|49|57\"];\n  }\n\n  c1[label=\"03|09|26|38|41|49|52|57\"];\n\n  03 -> a1; 41 -> a1;\n  52 -> a2; 26 -> a2;\n  38 -> a3; 57 -> a3;\n  09 -> a4; 49 -> a4;\n\n  a1 -> b1; a2 -> b1;\n  a3 -> b2; a4 -> b2;\n\n  b1 -> c1; b2 -> c1;\n}\n"
  },
  {
    "path": "other/clrs/02/03/01.markdown",
    "content": "> Using Figure 2.4 as a model, illustrate the operation of merge sort on the\n> array $A = \\langle 3, 41, 52, 26, 38, 57, 9, 49 \\rangle$.\n\nThis is perfect for graphviz!\n"
  },
  {
    "path": "other/clrs/02/03/02.c",
    "content": "#include <stdio.h>\n\nvoid merge(int A[], int p, int q, int r) {\n    int i, j, k;\n\n    int n1 = q - p + 1;\n    int n2 = r - q;\n\n    int L[n1];\n    int R[n2];\n\n    for (i = 0; i < n1; i++)\n        L[i] = A[p + i];\n    for (j = 0; j < n2; j++)\n        R[j] = A[q + j + 1];\n\n    for(i = 0, j = 0, k = p; k <= r; k++) {\n        if (i == n1) {\n            A[k] = R[j++];\n        } else if (j == n2) {\n            A[k] = L[i++];\n        } else if (L[i] <= R[j]) {\n            A[k] = L[i++];\n        } else {\n            A[k] = R[j++];\n        }\n    }\n}\n\nvoid merge_sort(int A[], int p, int r) {\n    if (p < r) {\n        int q = (p + r) / 2;\n        merge_sort(A, p, q);\n        merge_sort(A, q + 1, r);\n        merge(A, p, q, r);\n    }\n}\n"
  },
  {
    "path": "other/clrs/02/03/02.markdown",
    "content": "> Rewrite the *MERGE* procedure so that it does not use sentinels, instead\n> stopping once either array L or R has had all its elements copied back to A\n> and then copying the remainder of the other array back into A.\n\nHere is a simple modification:\n\n    MERGE(A, p, q, r)\n      n1 = q - p + 1\n      n2 = r - q\n      let L[1..n₁] and R[1..n₂] be new arrays\n      for i = 1 to n₁\n          L[i] = A[p + i - 1]\n      for j = 1 to n₂\n          R[j] = A[q + j]\n      i = 1\n      j = 1\n      for k = p to r\n          if i > n₁\n              A[k] = R[j]\n              j = j + 1\n          else if j > n₂\n              A[k] = L[i]\n              i = i + 1\n          else if L[i] ≤ R[j]\n              A[k] = L[i]\n              i = i + 1\n          else\n              A[k] = R[j]\n              j = j + 1\n"
  },
  {
    "path": "other/clrs/02/03/02.test.c",
    "content": "#include \"02.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(trivial_case) {\n    int expected[] = {1},\n        actual[]   = {1};\n\n    merge_sort(actual, 0, 1);\n\n    ASSERT_SAME_ARRAYS(actual, expected);\n}\n\nTEST(chapter_example) {\n    int expected[] = {1, 2, 2, 3, 4, 5, 6, 7},\n        actual[]   = {5, 2, 4, 7, 1, 3, 2, 6};\n\n    merge_sort(actual, 0, 7);\n\n    ASSERT_SAME_ARRAYS(actual, expected);\n}\n\nTEST(exercise_example) {\n    int expected[] = {3, 9, 26, 38, 41, 49, 52, 57},\n        actual[]   = {3, 41, 52, 26, 38, 57, 9, 49};\n\n    merge_sort(actual, 0, 7);\n\n    ASSERT_SAME_ARRAYS(actual, expected);\n}\n\nTEST(reversed_merge) {\n    int actual[]   = {5, 6, 7, 8, 9, 0, 1, 2, 3, 4},\n        expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};\n\n    merge_sort(actual, 0, 9);\n\n    ASSERT_SAME_ARRAYS(actual, expected);\n}\n"
  },
  {
    "path": "other/clrs/02/03/03.markdown",
    "content": "> Use mathematical induction to show that when $n$ is an exact power of 2, the\n> solution of the recurrence\n>\n> $$ T(n) = \\begin{cases}\n>      2           & \\text{if } n = 2, \\\\\\\\\n>      2T(n/2) + n & \\text{if } n = 2^k, \\text{for } k > 1.\n>    \\end{cases} $$\n>\n> is $T(n) = n\\lg{n}$\n\nBoy, this is going to be a lot of $\\LaTeX$.\n\nFirst, let's establish a function on which we're going to perform induction:\n\n$$ F(k) = T(2^k) $$\n\nWe want to prove that:\n\n$$ F(k) = 2^k \\lg{2^k} $$\n\n**Base.** It is simple enough:\n\n$$ F(1) = T(2) = 2 = 2\\lg2 = 2^1\\lg{2^1} $$\n\n**Step.** We assume that:\n\n$$ F(k) = 2^k \\lg{2^k} $$\n\nWe prove it for $k + 1$:\n\n$$ \\begin{aligned}\n   F(k + 1) & = T(2^{k+1})= 2T(\\frac{2^{k+1}}{2}) + 2^{k+1} = \\\\\\\\\n            & = 2T(2^k) + 2^{k+1} = 2 \\cdot 2^k \\lg{2^k} + 2^{k+1} = \\\\\\\\\n            & = 2^{k+1}(\\lg{2^k} + 1) = 2^{k+1}(\\lg{2^k} + \\lg2) = \\\\\\\\\n            & = 2^{k+1}\\lg{2^{k+1}}\n   \\end{aligned} $$\n\n□\n"
  },
  {
    "path": "other/clrs/02/03/04.markdown",
    "content": "> We can express insertion sort as a recursive procedure as follows. In order\n> to sort $A[1..n]$, we recursively sort $A[1..n-1]$ and then insert $A[n]$\n> into the sorted array $A[1..n-1]$. Write a recurrence for the running time\n> of this recursive version of insertion sort.\n\nThe recurrence is\n\n$$ T(n) =\n   \\begin{cases}\n     \\Theta(1) & \\text{if } n = 1, \\\\\\\\\n     T(n-1) + C(n-1) & \\text{otherwise}.\n   \\end{cases} $$\n\nwhere $C(n)$ is the time to insert an element in a sorted array of $n$\nelements.\n"
  },
  {
    "path": "other/clrs/02/03/05.c",
    "content": "// Indices in the C code are different\nint binary_search(int A[], int length, int v) {\n    int low  = 0;\n    int high = length;\n\n    int mid;\n    while (low < high) {\n        mid = (low + high) / 2;\n\n        if (A[mid] == v)\n            return mid;\n        else if (A[mid] < v)\n            low = mid + 1;\n        else\n            high = mid;\n    }\n\n    return -1;\n}\n"
  },
  {
    "path": "other/clrs/02/03/05.markdown",
    "content": "> Referring back to the searching problem (see Exercise 2.1-3), observe that\n> if the sequence A is sorted, we can check the midpoint of the sequence\n> against $\\nu$ and eliminate half of the sequence from further consideration.\n> The **binary search** algorithm repeats this procedure, halving the size of\n> the remaining portion of the sequence each time. Write pseudocode, either\n> iterative or recursive, for binary search. Argue that the worst-case running\n> time of binary search is $\\Theta(\\lg{n})$.\n\nHere's the presudocode:\n\n    BINARY-SEARCH(A, v):\n      low = 1\n      high = A.length\n\n      while low <= high\n          mid = (low + high) / 2\n          if A[mid] == v\n              return mid\n          if A[mid] < v\n              low = mid + 1\n          else\n              high = mid - 1\n\n      return NIL\n\nThe argument is fairly straightforward and I will make it brief:\n\n$$ T(n+1) = T(n/2) + c $$\n\nThis is the recurrence shown in the chapter text, and we know, that this is\nlogarithmic time.\n"
  },
  {
    "path": "other/clrs/02/03/05.test.c",
    "content": "#include \"05.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(array_empty) {\n    int array[] = {};\n    int length = 0;\n\n    ASSERT_EQUALS(binary_search(array, length, 1), -1);\n}\n\nTEST(array_one_element) {\n    int array[] = {1};\n    int length = 1;\n\n    ASSERT_EQUALS(binary_search(array, length, 1), 0);\n\n    ASSERT_EQUALS(binary_search(array, length, 0), -1);\n    ASSERT_EQUALS(binary_search(array, length, 2), -1);\n}\n\nTEST(array_odd_elements) {\n    int array[] = {2, 4, 6, 8, 10};\n    int length = 5;\n\n    ASSERT_EQUALS(binary_search(array, length, 2), 0);\n    ASSERT_EQUALS(binary_search(array, length, 4), 1);\n    ASSERT_EQUALS(binary_search(array, length, 6), 2);\n    ASSERT_EQUALS(binary_search(array, length, 8), 3);\n    ASSERT_EQUALS(binary_search(array, length, 10), 4);\n\n    ASSERT_EQUALS(binary_search(array, length, 1), -1);\n    ASSERT_EQUALS(binary_search(array, length, 3), -1);\n    ASSERT_EQUALS(binary_search(array, length, 5), -1);\n    ASSERT_EQUALS(binary_search(array, length, 7), -1);\n    ASSERT_EQUALS(binary_search(array, length, 9), -1);\n    ASSERT_EQUALS(binary_search(array, length, 11), -1);\n}\n\nTEST(array_even_elements) {\n    int array[] = {2, 4, 6, 8, 10, 12};\n    int length = 6;\n\n    ASSERT_EQUALS(binary_search(array, length, 2), 0);\n    ASSERT_EQUALS(binary_search(array, length, 4), 1);\n    ASSERT_EQUALS(binary_search(array, length, 6), 2);\n    ASSERT_EQUALS(binary_search(array, length, 8), 3);\n    ASSERT_EQUALS(binary_search(array, length, 10), 4);\n    ASSERT_EQUALS(binary_search(array, length, 12), 5);\n\n    ASSERT_EQUALS(binary_search(array, length, 1), -1);\n    ASSERT_EQUALS(binary_search(array, length, 3), -1);\n    ASSERT_EQUALS(binary_search(array, length, 5), -1);\n    ASSERT_EQUALS(binary_search(array, length, 7), -1);\n    ASSERT_EQUALS(binary_search(array, length, 9), -1);\n    ASSERT_EQUALS(binary_search(array, length, 11), -1);\n    ASSERT_EQUALS(binary_search(array, length, 13), -1);\n}\n"
  },
  {
    "path": "other/clrs/02/03/06.markdown",
    "content": "> Observe that the while loop line 5-7 of the *INSERTION-SORT* procedure in\n> Section 2.1 uses a linear search to scan (backward) through the sorted\n> subarray $A[i..j-1]$. Can we use a binary search (see Exercise 2.3-5)\n> instead to improve the overall worst-case running time of insertion sort to\n> $\\Theta(n\\lg{n})$?\n\nNo. Even if it finds the position in logarithmic time, it still needs to shift\nall elements after it to the right, which is linear in the worst case. It will\nperform the same number of swaps, although it would reduce the number of\ncomparisons.\n"
  },
  {
    "path": "other/clrs/02/03/07.markdown",
    "content": "> ★ Describe a $\\Theta(n\\lg{n})$-time algorithm that, given a set $S$ of $n$\n> integers and another integer $x$, determines whether or not there exists two\n> elements of $S$ whose sum is exactly $x$.\n\nFirst we sort $S$. Afterwards, we iterate it and for each element $i$ we\nperform a binary search to see if there is an element equal to $x - i$. If one\nis found, the algorithm returns true. Otherwise, it returns false.\n\nWe iterate $n$ elements and perform binary search for each on in an $n$-sized\narray, which leads to $\\Theta(n\\lg{n})$-time. If we sort first (with merge\nsort) it will introduce another $\\Theta(n\\lg{n})$ time, that would change the\nconstant in the final algorithm, but not the asymptotic time.\n\nHere's the pseudocode:\n\n    PAIR-EXISTS(S, x):\n      A = MERGE-SORT(S)\n\n      for i = 1 to S.length\n          if BINARY-SEARCH(A, x - S[i]) != NIL\n              return true\n\n      return false\n\n"
  },
  {
    "path": "other/clrs/02/problems/01.c",
    "content": "#include <stdlib.h>\n#include <string.h>\n\n#define INSERTION_SORT_TRESHOLD 20\n#define SELECTION_SORT_TRESHOLD 15\n\nvoid merge(int A[], int p, int q, int r) {\n    int i, j, k;\n\n    int n1 = q - p + 1;\n    int n2 = r - q;\n\n#ifdef MERGE_HEAP_ALLOCATION\n    int *L = calloc(n1, sizeof(int));\n    int *R = calloc(n2, sizeof(int));\n#else\n    int L[n1];\n    int R[n2];\n#endif\n\n    memcpy(L, A + p, n1 * sizeof(int));\n    memcpy(R, A + q + 1, n2 * sizeof(int));\n\n    for(i = 0, j = 0, k = p; k <= r; k++) {\n        if (i == n1) {\n            A[k] = R[j++];\n        } else if (j == n2) {\n            A[k] = L[i++];\n        } else if (L[i] <= R[j]) {\n            A[k] = L[i++];\n        } else {\n            A[k] = R[j++];\n        }\n    }\n\n#ifdef MERGE_HEAP_ALLOCATION\n    free(L);\n    free(R);\n#endif\n}\n\nvoid merge_sort(int A[], int p, int r) {\n    if (p < r) {\n        int q = (p + r) / 2;\n        merge_sort(A, p, q);\n        merge_sort(A, q + 1, r);\n        merge(A, p, q, r);\n    }\n}\n\nvoid insertion_sort(int A[], int p, int r) {\n    int i, j, key;\n\n    for (j = p + 1; j <= r; j++) {\n        key = A[j];\n        i = j - 1;\n        while (i >= p && A[i] > key) {\n            A[i + 1] = A[i];\n            i = i - 1;\n        }\n        A[i + 1] = key;\n    }\n}\n\nvoid selection_sort(int A[], int p, int r) {\n    int min, temp;\n    for (int i = p; i < r; i++) {\n        min = i;\n        for (int j = i + 1; j <= r; j++)\n            if (A[j] < A[min])\n                min = j;\n        temp = A[i];\n        A[i] = A[min];\n        A[min] = temp;\n    }\n}\n\nvoid mixed_sort_insertion(int A[], int p, int r) {\n    if (p >= r) return;\n\n    if (r - p < INSERTION_SORT_TRESHOLD) {\n        insertion_sort(A, p, r);\n    } else {\n        int q = (p + r) / 2;\n        mixed_sort_insertion(A, p, q);\n        mixed_sort_insertion(A, q + 1, r);\n        merge(A, p, q, r);\n    }\n}\n\nvoid mixed_sort_selection(int A[], int p, int r) {\n    if (p >= r) return;\n\n    if (r - p < SELECTION_SORT_TRESHOLD) {\n        selection_sort(A, p, r);\n    } else {\n        int q = (p + r) / 2;\n        mixed_sort_selection(A, p, q);\n        mixed_sort_selection(A, q + 1, r);\n        merge(A, p, q, r);\n    }\n}\n"
  },
  {
    "path": "other/clrs/02/problems/01.markdown",
    "content": "## Insertion sort on small arrays in merge sort\n\n> Although merge sort runs in $\\Theta(\\lg{n})$ worst-case time and insertion\n> sort runs in $\\Theta(n^2)$ worst-case time, the constant factors in\n> insertion sort can make it faster in practice for small problem sizes on\n> many machines. Thus, it makes sense to **coarsen** the leaves of the\n> recursion by using insertion sort within merge sort when subproblems become\n> sufficiently small. Consider a modification to merge sort in which $n/k$\n> sublists of length $k$ are sorted using insertion sort and then merged using\n> the standard merging mechanism, where $k$ is a value to be determined.\n>\n> 1. Show that insertion sort can sort the $n/k$ sublists, each of length $k$,\n>    in $\\Theta(nk)$ worst-case time.\n> 2. Show how to merge the sublists in $\\Theta(n\\lg(n/k))$ worst-case time.\n> 3. Given that the modified algorithm runs in $\\Theta(nk + n\\lg(n/k))$\n>    worst-case time, what is the largest value of $k$ as a function of $n$\n>    for which the modified algorithm has the same running time as standard\n>    merge sort, in terms of $\\Theta$-notation?\n> 4. How should we choose $k$ in practice?\n\n### 1. Sorting sublists\n\nThis is simple enough. We know that sorting each list takes $ak^2 + bk + c$\nfor some constants $a$, $b$ and $c$. We have $n/k$ of those, thus:\n\n$$ \\frac{n}{k}(ak^2 + bk + c) = ank + bn + \\frac{cn}{k} = \\Theta(nk) $$\n\n### 2. Merging sublists\n\nThis is a bit trickier. Sorting $a$ sublists of length $k$ each takes:\n\n$$ T(a) = \\begin{cases}\n     0            & \\text{if } a = 1, \\\\\\\\\n     2T(a/2) + ak & \\text{if } a = 2^p, \\text{if } p > 0.\n  \\end{cases} $$\n\nThis makes sense, since merging one sublist is trivial and merging $a$\nsublists means splitting dividing them in two groups of $a/2$ lists, merging\neach group recursively and then combining the results in $ak$ steps, since\nhave two arrays, each of length $\\frac{a}{2}k$.\n\nI don't know the master theorem yet, but it seems to me that the recurrence is\nactually $ak\\lg{a}$. Let's try to prove this via induction:\n\n**Base**. Simple as ever:\n\n$$ T(1) = 1k\\lg1 = k \\cdot 0 = 0 $$\n\n**Step**. We assume that $T(a) = ak\\lg{a}$ and we calculate $T(2a)$:\n\n$$ \\begin{aligned}\n     T(2a) &= 2T(a) + 2ak = 2(T(a) + ak) = 2(ak\\lg{a} + ak) = \\\\\\\\\n           &= 2ak(\\lg{a} + 1) = 2ak(\\lg{a} + \\lg{2}) = 2ak\\lg(2a)\n   \\end{aligned} $$\n\nThis proves it. Now if we substitue the number of sublists $n/k$ for $a$:\n\n$$ T(n/k) = \\frac{n}{k}k\\lg{\\frac{n}{k}} = n\\lg(n/k) $$\n\nWhile this is exact only when $n/k$ is a power of 2, it tells us that the\noverall time complexity of the merge is $\\Theta(n\\lg(n/k))$.\n\n### 3. The largest value of k\n\nThe largest value is $k = \\lg{n}$. If we substitute, we get:\n\n$$ \\Theta(n\\lg{n} + n\\lg{\\frac{n}{\\lg{n}}}) = \\Theta(n\\lg{n}) $$\n\nIf $k = f(n) > \\lg{n}$, the complexity will be $\\Theta(nf(n))$, which is\nlarger running time than merge sort.\n\n### 4. The value of k in practice\n\nIt's constant factors, so we just figure out when insertion sort beats merge\nsort, exactly as we did in exercise 1.2.2, and pick that number for $k$.\n\n### Runtime comparison\n\nI'm implemented this in C and in Python. I added selection for completeness\nsake in the C version. I ran two variants, depending on whether `merge()`\nallocates its arrays on the stack or on the heap (stack won't work for huge\narrays). Here are the results:\n\n    STACK ALLOCATION\n    ================\n    merge-sort      = 0.173352\n    mixed-insertion = 0.150485\n    mixed-selection = 0.165806\n\n    HEAP ALLOCATION\n    ===============\n    merge-sort      = 1.731111\n    mixed-insertion = 0.903480\n    mixed-selection = 1.017437\n\nHere's the results I got from Python:\n\n    merge-sort = 2.6207s\n    mixed-sort = 1.4959s\n\nI can safely conclude that this approach is faster.\n"
  },
  {
    "path": "other/clrs/02/problems/01.py",
    "content": "from itertools import repeat\n\ndef insertion_sort(A, p, r):\n    for j in range(p + 1, r + 1):\n        key = A[j]\n        i = j - 1\n        while i >= p and A[i] > key:\n            A[i + 1] = A[i]\n            i = i - 1\n        A[i + 1] = key\n\ndef merge(A, p, q, r):\n    n1 = q - p + 1\n    n2 = r - q\n\n    L = list(repeat(None, n1))\n    R = list(repeat(None, n2))\n\n    for i in range(n1):\n        L[i] = A[p + i]\n\n    for j in range(n2):\n        R[j] = A[q + j + 1]\n\n    i = 0\n    j = 0\n    for k in range(p, r + 1):\n        if i == n1:\n            A[k] = R[j]\n            j += 1\n        elif j == n2:\n            A[k] = L[i]\n            i += 1\n        elif L[i] <= R[j]:\n            A[k] = L[i]\n            i += 1\n        else:\n            A[k] = R[j]\n            j += 1\n\ndef merge_sort(A, p, r):\n    if p < r:\n        q = int((p + r) / 2)\n        merge_sort(A, p, q)\n        merge_sort(A, q + 1, r)\n        merge(A, p, q, r)\n\ndef mixed_sort(A, p, r):\n    if p >= r: return\n\n    if r - p < 20:\n        insertion_sort(A, p, r)\n    else:\n        q = int((p + r) / 2)\n        mixed_sort(A, p, q)\n        mixed_sort(A, q + 1, r)\n        merge(A, p, q, r)\n"
  },
  {
    "path": "other/clrs/02/problems/01.run.c",
    "content": "#include <stdlib.h>\n#include <stdio.h>\n#include <time.h>\n\n#define SIZE 400000\n#define SEED 300\n#define MERGE_HEAP_ALLOCATION\n\n#include \"01.c\"\n\n#define TIME(message, sort) \\\n    randomize_array(array, SIZE, SEED); \\\n    timer_start_time = clock(); \\\n    sort(array, 0, SIZE - 1); \\\n    printf(message \" = %f\\n\", (double) (clock() - timer_start_time) / CLOCKS_PER_SEC); \\\n    check_sorted(array, SIZE);\n\nstatic clock_t timer_start_time;\n\nvoid randomize_array(int array[], unsigned length, unsigned int seed) {\n    srand(seed);\n    for (unsigned i = 0; i < length; i++) {\n        array[i] = rand() % 1000 + 1;\n    }\n}\n\nvoid check_sorted(int array[], int length) {\n    for (int i = 1; i < length; i++) {\n        if (array[i - 1] > array[i]) {\n            printf(\"%d %d %d %d\\n\", i - 1, i, array[i - 1], array[i]);\n            fprintf(stderr, \"...but the array is not sorted!\");\n            exit(1);\n        }\n    }\n}\n\nint main() {\n    int *array = calloc(SIZE, sizeof(int));\n\n    TIME(\"merge-sort     \", merge_sort);\n    TIME(\"merge-insertion\", mixed_sort_insertion);\n    TIME(\"merge-selection\", mixed_sort_selection);\n\n    return 0;\n}\n"
  },
  {
    "path": "other/clrs/02/problems/01.run.py",
    "content": "import os.path as path\nimport random\nimport time\n\nfilename = path.join(path.dirname(__file__), '01.py')\nexec(open(filename).read())\n\ndef report_time(name, func):\n    begin = time.time()\n    func()\n    end = time.time()\n    print(\"{:} = {:.4f}s\".format(name, end - begin))\n\narray = []\nrandom.seed(300)\nfor _ in range(10000):\n    array.append(random.randint(0, 999))\n\nreport_time('merge-sort', lambda: merge_sort(array[:], 0, len(array) - 1))\nreport_time('mixed-sort', lambda: mixed_sort(array[:], 0, len(array) - 1))\n"
  },
  {
    "path": "other/clrs/02/problems/02.markdown",
    "content": "## Correctness of bubblesort\n\n> Bubblesort is popular, but inefficient, sorting algorithm. It works by\n> repeatedly swapping adjancent elements that are out of order.\n>\n>     BUBBLESORT(A)\n>       for i to A.length - 1\n>           for j = A.length downto i + 1\n>               if A[j] < A[j - 1]\n>                   exchange A[j] with A[j - 1]\n>\n> 1. Let $A'$ denote the output of *BUBBLESORT(A)*. To prove that *BUBBLESORT*\n>    is correct, we need to prove that it terminates and that\n>\n>    $$ A'[1] \\leq A'[2] \\leq \\cdots \\leq A'[n] \\tag{2.3}$$\n>\n>    where $n = A.length$. In order to show that *BUBBLESORT* actually sorts,\n>    what else do we need to prove?\n>\n> 2. State precisely a loop invariant for the **for** loop in lines 2-4, and\n>    prove that this loop invariant holds. Your proof should use the structure\n>    of the loop invariant proof presented in this chapter.\n>\n> 3. Using the termination condition of the loop invariant proved in part (2),\n>    state a loop invariant for the **for** loop in lines 1-4 that will allow\n>    you to prove inequality (2.3). Your proof should use the structure of the\n>    loop invariant proof presented in this chapter.\n>\n> 4. What is the worst-case running time of bubblesort? How does it compare to\n>    the running time of insertion sort?\n\n### 1. What else?\n\nWe need to prove that $A'$ consists of the original elements in $A$, although\nin (possibly) different order.\n\n### 2. Inner loop invariant\n\n> At the start of each iteration of the **for** loop of lines 2-4, (1) the\n> subarray $A[j...]$ consists of elements that were in $A[j...]$ before\n> entering the inner loop (possibly) in different order and (2) $A[j]$ is the\n> smallest of those elements.\n\n**Initialization:** It holds trivially, because $A[j...]$ consists of only\none element and it is the last element of $A$ when execution starts the inner\nloop.\n\n**Maintenance:** On each step, we replace $A[j]$ with $A[j - 1]$ if it is\nsmaller. Because we're only adding the previous element and possibly swapping\ntwo values (1) holds. Since $A[j-1]$ becomes the smallest of $A[j]$ and\n$A[j-1]$ and the loop invariant states that $A[j]$ is the smallest one in\n$A[j...]$, we know that (2) holds.\n\n**Termination:** After the loop terminates, we will get $j = i$. This implies\nthat $A[i]$ is the smallest element of the subarray $A[i...]$ and array\ncontains the original elements in some order.\n\n### 3. Outer loop invariant\n\n> At the start of each iteration, $A[1..i-1]$ consists of sorted elements, all\n> of which are smaller or equal to the ones in $A[i...]$.\n\n**Initialization:** Initially we have the empty array, which holds trivially.\n\n**Maintenance:** The invariant of the inner loop tells us that on each\niteration, $A[i]$ becomes the smallest element of $A[i...]$ while the rest get\nshuffled. This impliest that at the end of the loop:\n\n$$ A[i] < A[k] \\text{, for } i < k $$\n\n**Termination:** The loop terminates with $i = n$, where $n$ is the length of\nthe array. Substituting the $n$ for $i$ in the invariant, we have that the\nsubarray $A[1..n]$ consists of the original elements, but in sorted order.\nThis is the entire array, so the entire array is sorted.\n\n### 4. Worst-case running time?\n\nThe number of comparisons is\n\n$$ n - 1, n - 2, \\cdots , 1 = \\frac{n(n - 1)}{2} $$\n\nWhich is a quadratic function. The swaps are at most the same ammount, which\nmeans that the worst-case complexity is $\\Theta(n^2)$.\n\nInsertion sort has the same worst-case complexity. In general, the best-case\ncomplexity of both algorithms should be $\\Theta(n)$, but this implementation\nof bubble-sort has $\\Theta(n^2)$ best-case complexity. That can be fixed by\nreturning if no swaps happened in an iteration of the outer loop.\n\nFurthermore, bubble-sort should be even slower than insertion sort, because\nthe swaps imply a lot more assignments than what insertion sort does.\n"
  },
  {
    "path": "other/clrs/02/problems/03.markdown",
    "content": "## Correctness of Horner's rule\n\n> The following code fragment implements Horner's rule for evaluating a\n> polynomial\n>\n> $$ \\begin{aligned}\n>    P(x) &= \\sum_{k=0}^n a_kx^k = \\\\\\\\\n>         &= a_0 + x(a_1 + x(a_2 + \\cdots + x(a_{n-1} + xa_n) \\cdots))\n>    \\end{aligned} $$\n>\n> given the coefficients $a_0, a_1, \\ldots ,a_n$ and a value for $x$:\n>\n>     y = 0\n>     for i = n downto 0\n>         y = aᵢ + x·y\n>\n> 1. In terms of $\\Theta$-notation, what is the running time of this code\n>    fragment for Horner's rule?\n>\n> 2. Write pseudocode to implement the naive polynomial-evaluation algorithm\n>    that computes each term of the polynomial from scratch. What is the\n>    running time of this algorithm? How does it compare to Horner's rule?\n>\n> 3. Consider the following loop invariant:\n>    > At the start of each iteration of the **for** loop of lines 2-3,\n>    >\n>    > $$ y = \\sum_{k=0}^{n-(i+1)}a_{k+i+1}x^k $$\n>    >\n>    > Interpret a summation with no terms as equaling 0. Following the\n>    > structure of the loop invariant proof presented in this chapter, use\n>    > this loop invariant to show that, at termination,\n>    > $y = \\sum_{k=0}^na_kx^k$.\n>\n> 4. Conclude by arguing that the given code fragment correctly evaluates a\n>    polynomial characterized by the coefficients $a_0,a_1,\\ldots,a_n$.\n\n### 1. Running time\n\nObviously $\\Theta(n)$.\n\n### 2. Naive algorithm\n\nWe assume that we have no exponentiation in the language. Thus:\n\n    y = 0\n    for i = 0 to n\n        m = 1\n        for k = 1 to i\n            m = m·x\n        y = y + aᵢ·m\n\nThe running time is $\\Theta(n^2)$, because of the nested loop. It is,\nobviosly, slower.\n\n### 3. The loop invariant\n\n**Initialization:** It is pretty trivial, since the summation has no terms,\nwhich implies $y = 0$.\n\n**Maintenance:** By using the loop invariant, in the end of the $i$-th\niteration, we have:\n\n$$ \\begin{aligned}\n     y &= a_i + x\\sum_{k=0}^{n-(i+1)}a_{k+i+1}x^k\n        = a_ix^0 + \\sum_{k=0}^{n-i-1}a_{k+i+1}x^{k+1} = \\\\\\\\\n       &= a_ix^0 \\sum_{k=1}^{n-i}a_{k+i}x^k\n        = \\sum_{k=0}^{n-i}a_{k+i}x^k\n  \\end{aligned} $$\n\n**Termination:** The loop terminates at $i = -1$. If we substitute, we get:\n\n$$ y = \\sum_{k=0}^{n-i-1}a_{k+i+1}x^k = \\sum_{k=0}^na_kx^k $$\n\n### 4. Conclude\n\nIt should be fairly obvious, but the invariant of the loop is a sum that\nequals a polynomial with the given coefficients.\n"
  },
  {
    "path": "other/clrs/02/problems/04.c",
    "content": "#include <stdio.h>\n\nint merge(int A[], int p, int q, int r) {\n    int i, j, k, inversions = 0;\n\n    int n1 = q - p + 1;\n    int n2 = r - q;\n\n    int L[n1];\n    int R[n2];\n\n    for (i = 0; i < n1; i++) L[i] = A[p + i];\n    for (j = 0; j < n2; j++) R[j] = A[q + j + 1];\n\n    for(i = 0, j = 0, k = p; k <= r; k++) {\n        if (i == n1) {\n            A[k] = R[j++];\n        } else if (j == n2) {\n            A[k] = L[i++];\n        } else if (L[i] <= R[j]) {\n            A[k] = L[i++];\n        } else {\n            A[k] = R[j++];\n            inversions += n1 - i;\n        }\n    }\n\n    return inversions;\n}\n\nint merge_sort(int A[], int p, int r) {\n    if (p < r) {\n        int inversions = 0;\n        int q = (p + r) / 2;\n        inversions += merge_sort(A, p, q);\n        inversions += merge_sort(A, q + 1, r);\n        inversions += merge(A, p, q, r);\n        return inversions;\n    } else {\n        return 0;\n    }\n}\n"
  },
  {
    "path": "other/clrs/02/problems/04.markdown",
    "content": "## Inversions\n\n> Let $A[1..n]$ be an array of $n$ distinct numbers. If $i < j$ and\n> $A[i] > A[j]$, then the pair $(i, j)$ is called an inversion of $A$.\n>\n> 1. List the five inversions in the array $\\langle 2, 3, 8, 6, 1 \\rangle$.\n> 2. What array with elements from the set $\\lbrace 1, 2, \\ldots, n \\rbrace$\n>    has the most inversions? How many does it have?\n> 3. What is the relationship between the running time of insertion sort and\n>    the number of inversions in the input array? Justify your answer.\n> 4. Give an algorithm that determines the number of inversions in any\n>    permutation of n elements in $\\Theta(n\\lg{n})$ worst-case time. (Hint:\n>    Modify merge sort).\n\n### 1. The five inversions\n\n$\\langle 2, 1 \\rangle$, $\\langle 3, 1 \\rangle$, $\\langle 8, 6 \\rangle$,\n$\\langle 8, 1 \\rangle$ and $\\langle 6, 1 \\rangle$.\n\n### 2. Array with most inversions\n\nIt is the reversed array, that is $\\langle n, n-1, \\ldots , 1 \\rangle$. It has\n$(n-1) + (n-2) + \\cdots + 1 = \\frac{n(n-1)}{2}$ inversions.\n\n### 3. Relationship with insertion sort\n\nInsertion sort performs the body of the inner loop once for each inversion.\nDue to the nature of the algorithm, on each $k$-th iteration, if $A[1..k]$ has\n$m$ inversions with $A[k]$, they are in $A[k-m..k-1]$ (since the elements\nbefore $k$ are sorted). Thus, the inner loop needs to execute its body $m$\ntimes. This process does not introduce new inversions and each outer loop\niteration resolves exactly $m$ inversions, where $m$ is the distance the\nelement is \"pushed towards the front of the array\".\n\nThus, the running time is $\\Theta(n + d)$, where $d$ is the number of\ninversions ($n$ comes from the outer loop).\n\n### 4. Calculating inversions\n\nWe just modify merge sort (in exercise 2.3.2) to return the number of\ninversions:\n\n    MERGE-SORT(A, p, r):\n      if p < r\n          inversions = 0\n          q = (p + r) / 2\n          inversions += merge_sort(A, p, q)\n          inversions += merge_sort(A, q + 1, r)\n          inversions += merge(A, p, q, r)\n          return inversions\n      else\n          return 0\n\n    MERGE(A, p, q, r)\n      n1 = q - p + 1\n      n2 = r - q\n      let L[1..n₁] and R[1..n₂] be new arrays\n      for i = 1 to n₁\n          L[i] = A[p + i - 1]\n      for j = 1 to n₂\n          R[j] = A[q + j]\n      i = 1\n      j = 1\n      for k = p to r\n          if i > n₁\n              A[k] = R[j]\n              j = j + 1\n          else if j > n₂\n              A[k] = L[i]\n              i = i + 1\n          else if L[i] ≤ R[j]\n              A[k] = L[i]\n              i = i + 1\n          else\n              A[k] = R[j]\n              j = j + 1\n              inversions += n₁ - i\n      return inversions\n\n"
  },
  {
    "path": "other/clrs/02/problems/04.test.c",
    "content": "#include \"04.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(trivial_case) {\n    int array[] = {1},\n        inversions = merge_sort(array, 0, 1);\n\n    ASSERT_EQUALS(inversions, 0);\n}\n\nTEST(problem_example) {\n    int array[]    = {2, 3, 8, 6, 1},\n        inversions = merge_sort(array, 0, 4);\n\n    ASSERT_EQUALS(inversions, 5);\n}\n\nTEST(chapter_example) {\n    int array[]    = {5, 2, 4, 7, 1, 3, 2, 6},\n        inversions = merge_sort(array, 0, 7);\n\n    ASSERT_EQUALS(inversions, 14);\n}\n\n\nTEST(reversed_array) {\n    int array[]    = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0},\n        inversions = merge_sort(array, 0, 9);\n\n    ASSERT_EQUALS(inversions, 45);\n}\n"
  },
  {
    "path": "other/clrs/03/01/01.markdown",
    "content": "> Let $f(n)$ + $g(n)$ be asymptotically nonnegative functions. Using the basic\n> definition of $\\Theta$-notation, prove that $\\max(f(n), g(n)) = \\Theta(f(n) + g(n))$.\n\nFrom \"asymptotically nonnegative\", we can assume that\n\n$$\\begin{aligned}\n    \\exists n_1, n_2: & f(n) \\geq 0 & \\text{for } n > n_1 \\\\\\\\\n                      & g(n) \\geq 0 & \\text{for } n > n_2\n   \\end{aligned}$$\n\nLet $n_0 = max(n_1, n_2)$. Some obvious things for $n > n_0$:\n\n$$\n   f(n) \\leq \\max(f(n), g(n)) \\\\\\\\\n   g(n) \\leq \\max(f(n), g(n)) \\\\\\\\\n   \\big(f(n) + g(n)\\big)/2 \\leq \\max(f(n), g(n)) \\\\\\\\\n   \\max(f(n), g(n)) \\leq f(n) + g(n)\n$$\n\nFrom the last two inequalities, we get:\n\n$$ 0 \\leq \\frac{1}{2}\\big(f(n) + g(n)\\big) \\leq \\min\\big(f(n), g(n)\\big)\n     \\leq f(n) + g(n) \\quad \\text{for } n > n_0 $$\n\nWhich is the definition of $\\Theta(f(n) + g(n))$ with $c_1 = 1/2, c_2 = 1$.\n"
  },
  {
    "path": "other/clrs/03/01/02.markdown",
    "content": "> Show that for any real constants $a$ and $b$, where $b > 0$,\n>\n> $$(n + a)^b = \\Theta(n^b)$$\n\nQuite simply:\n\n$$(n + a)^b = \\binom{n}0n^b + \\binom{n}1n^{b-1}b + \\cdots + \\binom{n}0a^b$$\n\nThe most significant term is $n^b$ and this is obviously polynomially tightly\nbound.\n"
  },
  {
    "path": "other/clrs/03/01/03.markdown",
    "content": "> Explain why the statement, \"The running time of algorithm $A$ is at least\n> $O(n^2)$ is meaningless.\n\nThe $O$-notation provides an upper bound. \"At least\" implies a lower bound.\n"
  },
  {
    "path": "other/clrs/03/01/04.markdown",
    "content": "> Is $2^{n+1} = O(2^n)$? Is $2^{2n} = O(2^n)$?\n\nYes, because if we choose $2$ for both constants in the $O$-notation\ndefinition, we get an equality.\n\nNo, because $\\nexists c: 2^n \\cdot 2^n \\leq c 2^n$.\n"
  },
  {
    "path": "other/clrs/03/01/05.markdown",
    "content": "> Prove Theorem 3.1\n\nThe theorem states:\n\n> For any two functions $f(n)$ and $g(n)$, we have $f(n) = \\Theta(g(n))$ if and\n> only if $f(n) = O(g(n))$ and $f(n) = \\Omega(g(n))$.\n\nFrom $f(n) = \\Theta(g(n))$, we have that:\n\n$$ 0 \\leq c_1g(n) \\leq f(n) \\leq c_2g(n) \\quad \\text{for } n > n_0$$\n\nWe can pick the constants from here and use them in the definitions of $O$ and\n$\\Omega$ to show that both hold.\n\nFrom $f(n) = \\Omega(g(n))$ and $f(n) = O(g(n))$:\n\n$$ 0 \\leq c_3g(n) \\leq f(n) \\quad \\text{for all } n \\geq n_1 \\\\\\\\\n   0 \\leq f(n) \\leq c_4g(n) \\quad \\text{for all } n \\geq n_2 $$\n\nIf we let $n_3 = \\max(n_1, n_2)$ and merge the inequalities, we get:\n\n$$ 0 \\leq c_3g(n) \\leq f(n) \\leq c_4g(n) \\quad \\text{for all } n > n_3 $$\n\nWhich is the definiition of $\\Theta$.\n"
  },
  {
    "path": "other/clrs/03/01/06.markdown",
    "content": "> Prove that the running time of an algorithm is $\\Theta(g(n))$ if and only if\n> its worst-case running time is $O(g(n))$ and its best-case running time is\n> $\\Omega(g(n))$.\n\nIf $T_w$ is the worst-case running time and $T_b$ is the best-case running\ntime, we know that:\n\n$$ 0 \\leq c_1g(n) \\leq T_b(n) \\quad \\text{for } n > n_b \\\\\\\\\n   0 \\leq T_w(n) \\leq c_2g(n) \\quad \\text{for } n > n_w $$\n\nCombining them we get:\n\n$$ 0 \\leq c_1g(n) \\leq T_b(n) \\leq T_w(n) \\leq c_2g(n)\n   \\quad \\text{for } n > \\max(n_b, n_w) $$\n\nSince the running time is bound between $T_b$ and $T_w$ and the above is the\ndefinition of the $\\Theta$-notation, we have our proof.\n"
  },
  {
    "path": "other/clrs/03/01/07.markdown",
    "content": "> Prove $o(g(n)) \\cap \\omega(g(n))$ is the empty set.\n\nFrom each term we know that for any positive constant $c > 0$:\n\n$$ \\begin{aligned}\n     \\exists & n_1 > 0 : 0 \\leq f(n) < cg(n) \\\\\\\\\n     \\exists & n_2 > 0 : 0 \\leq cg(n) < f(n)\n   \\end{aligned} $$\n\nIf we pick $n_0 = max(n_1, n_2)$, from the problem definition we get:\n\n$$ f(n) < cg(n) < f(n) $$\n\nWhich obviously has no solutions. Thus, such function $f(n)$ exists, which\nmeans that the intersection is the empty set.\n"
  },
  {
    "path": "other/clrs/03/01/08.markdown",
    "content": "> We can extend our notation to the case of two parameters $n$ and $m$ that\n> can go to infinity independently at different rates. For a given function\n> $g(n, m)$ we denote $O(g(n, m))$ the set of functions:\n>\n> $$ \\begin{aligned}\n>      O(g(n, m)) = \\lbrace f(n, m):\n>        &\\text{there exist positive constants } c, n_0, \\text{ and } m_0 \\\\\\\\\n>        &\\text{such that } 0 \\leq f(n, m) \\leq cg(n, m) \\\\\\\\\n>        &\\text{for all } n \\geq n_0 \\text{ or } m \\geq m_0. \\rbrace\n>    \\end{aligned} $$\n>\n> Give corresponding definitions for $\\Omega(g(n, m))$ and $\\Theta(g(n, m))$.\n\nIn the University of Sofia, we woud have writen that tersely.\n\n$$ \\begin{aligned}\n     \\Omega(g(n, m)) = \\lbrace f(n, m):\n       &\\text{there exist positive constants } c, n_0, \\text{ and } m_0 \\\\\\\\\n       &\\text{such that } 0 \\leq cg(n, m) \\leq f(n, m) \\\\\\\\\n       &\\text{for all } n \\geq n_0 \\text{ or } m \\geq m_0. \\rbrace\n   \\end{aligned} $$\n\n$$ \\begin{aligned}\n     \\Theta(g(n, m)) = \\lbrace f(n, m):\n       &\\text{there exist positive constants } c_1, c_2, n_0, \\text{ and } m_0 \\\\\\\\\n       &\\text{such that } 0 \\leq c_1g(n, m) \\leq f(n, m) \\leq c_2g(n, m) \\\\\\\\\n       &\\text{for all } n \\geq n_0 \\text{ or } m \\geq m_0. \\rbrace\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/03/02/01.markdown",
    "content": "> Show that if $f(n)$ and $g(n)$ are monotonically increasing functions, then\n> so are the functions $f(n) + g(n)$ and $f(g(n))$, and if $f(n)$ and $g(n)$\n> are in addition nonnegative, then $f(n) \\cdot g(n)$ is monotonically\n> increasing.\n\nSo:\n\n$$ f(m) \\leq f(n) \\quad \\text{for } m \\leq n \\\\\\\\\n   g(m) \\leq f(n) \\quad \\text{for } m \\leq n \\\\\\\\ $$\n\nWhen we combine them, we get:\n\n$$ f(m) + g(m) \\leq f(n) + g(n) $$\n\nWhich proves the first function.\n\nThen:\n\n$$ f(g(m)) \\leq f(g(n)) \\quad \\text{for } m \\leq n $$\n\nThis is true, since $g(m) > g(n)$ and $f(n)$ is monotonically increasing.\n\nIf both functions are nonnegative, then we can multiply the two inequalities\nand we get:\n\n$$ f(m) \\cdot g(m) \\leq f(n) \\cdot g(n) $$\n"
  },
  {
    "path": "other/clrs/03/02/02.markdown",
    "content": "> Prove equation (3.16)\n>\n> $$ a^{\\log_bc} = c^{\\log_ba} $$\n\n$$ \\begin{aligned}\n   a^{\\log_bc} = a^{\\frac{\\log_ac}{\\log_ab}} = \\big(a^{\\log_ac})^\\frac{1}{\\log_ab}\n   = c^{\\log_ba}\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/03/02/03.markdown",
    "content": "> Prove equation (3.19). Also prove that $n! = \\omega(2^n)$ and $n! = o(n^n)$.\n>\n> $$ \\lg(n!) = \\Theta(n\\lg{n}) \\tag{3.19} $$\n\nWe use **Stirling's approximation**:\n\n$$ \\begin{aligned}\n   \\lg(n!) &= \\lg\\Bigg(\\sqrt{2\\pi{n}}\\Big(\\frac{n}{e}\\Big)^n\\Big(1+\\Theta(\\frac{1}{n})\\Big)\\Bigg)\n      = \\lg\\sqrt{2\\pi{n}} + \\lg\\Big(\\frac{n}{e}\\Big)^n + \\lg\\Big(1+\\Theta(\\frac{1}{n})\\Big) = \\\\\\\\\n     &= \\Theta(\\sqrt{n}) + n\\lg{\\frac{n}{e}} + \\lg\\Big(\\Theta(1) + \\Theta(\\frac{1}{n})\\Big)\n      = \\Theta(\\sqrt{n}) + \\Theta(n\\lg{n}) + \\Theta(\\frac{1}{n}) = \\\\\\\\\n     &= \\Theta(n\\lg{n})\n   \\end{aligned}\n$$\n\nThe other two are kind of obvious:\n\n$$\n  \\forall n > 3:\n  2^n = \\underbrace{2 \\cdot 2 \\cdot \\cdots \\cdot 2}_\\text{n times} <\n        1 \\cdot 2 \\cdot \\cdots \\cdot n = n!\n        \\quad\\Rightarrow\\quad n! = \\omega(2^n)\n$$\n\nAnd:\n\n$$\n  \\forall n > 1 :\n  n! = 1 \\cdot 2 \\cdot \\cdots n < \\underbrace{n \\cdot n \\cdot \\cdots \\cdot n}_\\text{n times}\n     = n^n \\quad \\text{for }\n     \\quad\\Rightarrow\\quad n! = o(n^n)\n$$\n"
  },
  {
    "path": "other/clrs/03/02/04.markdown",
    "content": "> $\\star$ Is the function $\\lceil \\lg{n} \\rceil!$ polynomially bounded? Is\n> the function $\\lceil \\lg\\lg{n} \\rceil$ polynomially bounded?\n\nIf we take the definition of polynomially bound:\n\n$$ f(n) \\leq cn^k $$\n\nand take the logarithm of each side, we get:\n\n$$ \\lg{f(n)} \\leq \\lg{c} + k\\lg{n} $$\n\nThus, a function is polynomially bound if $\\lg{f(n)} = \\Theta(\\lg{n})$.\n\nIf we let $m = \\lceil \\lg{n} \\rceil$, from the previous exercise we know that:\n\n$$ \\lg{m!} = \\Theta(m\\lg{m}) = \\Theta(\\lceil\\lg{n}\\rceil\\lg\\lceil\\lg{n}\\rceil) $$\n\nThus, it is not polynomially bounded. As for the other, if le let $p = \\lceil\n\\lg\\lg{n} \\rceil$:\n\n$$ \\begin{aligned}\n   \\lg{p!} &= \\Theta(p\\lg{p}) = \\Theta(\\lceil\\lg\\lg{n}\\rceil\\lg\\lceil\\lg\\lg{n}\\rceil)\n            = \\Theta(\\lg\\lg{n}\\lg\\lg\\lg{n}) = o(\\lg\\lg{n}\\lg\\lg{n}) \\\\\\\\\n           &= o(\\lg^2\\lg{n}) = o(\\lg{n})\n   \\end{aligned} $$\n\nThe last follows from the statement in the chapter that polylogarithmic\nfunctions grow slower than polynomial functions.\n"
  },
  {
    "path": "other/clrs/03/02/05.markdown",
    "content": "> $\\star$ Which is asymptotically larger: $\\lg(\\lg^\\*n)$ or $\\lg^\\*(\\lg{n})$.\n\nThe second, because:\n\n$$ \\lg^\\*(\\lg{n}) = \\lg^\\*n - 1 > \\lg(\\lg^\\*(n)) $$\n"
  },
  {
    "path": "other/clrs/03/02/06.markdown",
    "content": "> Show that the golden ratio $\\phi$ and its conjugate $\\hat \\phi$ both satisfy\n> the equation $x^2 = x + 1$.\n\nThis is so obvious, that it is painful:\n\n$$ \\phi^2 - \\phi - 1 = \\bigg(\\frac{1 + \\sqrt5}{2}\\bigg)^2 - \\frac{1 + \\sqrt5}{2} - 1\n   = \\frac{1 + 2\\sqrt{5} + 5 - 2 - 2\\sqrt{5} - 4}{4} = 0$$\n\nAnd now the conjugate:\n\n$$ \\hat\\phi^2 - \\hat\\phi - 1 = \\bigg(\\frac{1 - \\sqrt5}{2}\\bigg)^2 - \\frac{1 - \\sqrt5}{2} - 1\n   = \\frac{1 - 2\\sqrt{5} + 5 - 2 + 2\\sqrt{5} - 4}{4} = 0$$\n"
  },
  {
    "path": "other/clrs/03/02/07.markdown",
    "content": "> Proove by induction that the $i$th Fibonacci number satisfies the equality\n>\n> $$ F_i = \\frac{\\phi^i - \\hat{\\phi^i}}{\\sqrt5} $$\n\nI've done this [earlier in plain text](https://github.com/skanev/playground/blob/master/scheme/sicp/01/13.scm). Let's do it properly, in $LaTeX$.\n\n**Base**:\n\n$$ \\frac{\\phi^0 - \\hat{\\phi^0}}{\\sqrt{5}} = \\frac{1 - 1}{\\sqrt{5}} = 0 = F_0 $$\n\n$$ \\frac{\\phi - \\hat{\\phi}}{\\sqrt{5}} = \\frac{1 + \\sqrt{5} - 1 + \\sqrt{5}}{2\\sqrt{5}} = 1 = F_1 $$\n\n**Step**:\n\n$$ F_{n + 2} = F_{n + 1} + F_n\n   = \\frac{\\phi^{n+1} - \\hat\\phi^{n+1}}{\\sqrt{5}} + \\frac{\\phi^n - \\hat{\\phi^n}}{\\sqrt{5}}\n   = \\frac{\\phi^n(\\phi + 1) - \\hat{\\phi^n}(\\hat\\phi + 1)}{\\sqrt{5}}\n   = \\frac{\\phi^n\\phi^2 - \\hat{\\phi^n}\\hat{\\phi^2}}{\\sqrt{5}}\n   = \\frac{\\phi^{n+2} + \\hat\\phi^{n+2}}{\\sqrt{5}}\n$$\n"
  },
  {
    "path": "other/clrs/03/02/08.markdown",
    "content": "> Show that $k\\ln{k} = \\Theta(n)$ implies $k = \\Theta(n/\\ln{n})$.\n\nFrom the symmetry of $\\Theta$:\n\n$$ k\\ln{k} = \\Theta(n) \\Rightarrow n = \\Theta(k\\ln{k}) $$\n\nLets find $\\ln{n}$:\n\n$$ \\ln{n} = \\Theta(\\ln(k\\ln{k})) = \\Theta(\\ln{k} + \\ln\\ln{k}) = \\Theta(\\ln{k})$$\n\nLet's divide the two:\n\n$$ \\frac{n}{\\ln{n}} = \\frac{\\Theta(k\\ln{k})}{\\Theta(\\ln{k})}\n   = \\Theta{\\frac{k\\ln{k}}{\\ln{k}}} = \\Theta(k) $$\n"
  },
  {
    "path": "other/clrs/03/problems/01.markdown",
    "content": "## Asymptotic behavior of polynomials\n\n> Let\n>\n> $$ p(n) = \\sum_{i=0}^da_in^i $$\n>\n> where $a_d > 0$, be a degree-$d$ polynomial in $n$, and let $k$ be a\n> constant. Use the definitions of the asymptotic notations to prove the\n> following properties.\n>\n> 1. If $k \\geq d$, then $p(n) = O(n^k)$.\n> 2. If $k \\leq d$, then $p(n) = \\Omega(n^k)$.\n> 3. If $k = d$, then $p(n) = \\Theta(n^k)$.\n> 4. If $k > d$, then $p(n) = o(n^k)$.\n> 5. If $k < d$, then $p(n) = \\omega(n^k)$.\n\nThis is very boring. I'm just going to examine half of one case, since\neverything else follows easliy from it.\n\nLet's see that $p(n) = O(n^d)$. We need do pick $c = a_d + b$, such that:\n\n$$ \\sum_{i=0}^d = a_dn^d + a_{d-1}n^{d-1} + \\ldots + a_1n + a_0 \\leq cn^d $$\n\nWhen we divide by $n^d$, we get:\n\n$$ c = a_d + b \\geq a_d + \\frac{a_{d-1}}n + \\frac{a_{d-2}}{n^2} + \\ldots + \\frac{a_0}{n^d} $$\n\nOr:\n\n$$  b \\geq \\frac{a_{d-1}}n + \\frac{a_{d-2}}{n^2} + \\ldots + \\frac{a_0}{n^d} $$\n\nIf we choose $b = 1$, then we can choose $n_0$ to be:\n\n$$ n_0 = \\max(da_{d-1}, d\\sqrt{a_{d-2}}, \\ldots, d\\sqrt[d]{a_0}) $$\n\nNow we have $n_0$ and $c$, such that:\n\n$$ p(n) \\leq cn^d \\quad \\text{for } n \\geq n_0 $$\n\nWhich is the definition of $O(n^d)$. By chosing $b = -1$ we can prove the\n$\\Omega(n^d)$ inequality and thus the $\\Theta(n^d)$ inequality.\n\nIt's very similar to proove the other inequalities.\n"
  },
  {
    "path": "other/clrs/03/problems/02.markdown",
    "content": "## Relative asymptotic growths\n\n> Indicate for each pair of expressions $(A, B)$ in the table below, whether\n> $A$ is $O$, $o$, $\\Omega$, $\\omega$, or $\\Theta$ of $B$. Assume that $k \\geq 1$,\n> $\\epsilon > 0$, and $c > 1$ are constants. Your answer should be in the form\n> of the table with \"yes\" or \"no\" written in each box.\n\n|       A      |        B      | $O$ | $o$ | $\\Omega$ | $\\omega$ | $\\Theta$ |\n|:------------:|:-------------:|:---:|:---:|:--------:|:--------:|:--------:|\n| $\\lg^kn$     | $n^\\epsilon$  | yes | yes | no       | no       | no       |\n| $n^k$        | $c^n$         | yes | yes | no       | no       | no       |\n| $\\sqrt{n}$   | $n^{\\sin{n}}$ | no  | no  | no       | no       | no       |\n| $2^n$        | $2^{n/2}$     | no  | no  | yes      | yes      | no       |\n| $n^{\\lg{c}}$ | $c^{\\lg{n}}$  | yes | no  | yes      | no       | yes      |\n| $\\lg(n!)$    | $\\lg(n^n)$    | yes | no  | yes      | no       | yes      |\n"
  },
  {
    "path": "other/clrs/03/problems/03.markdown",
    "content": "## Ordering by asymptotic growth rates\n\n> 1. Rank the following functions by order of growth; that is, find an\n>    arrangement $g_1, g_2, \\ldots , g_{30}$ of the functions $g_1 =\n>    \\Omega(g_2), g_2 = \\Omega(g_3), \\ldots, g_{29} = \\Omega(g_{30}) $.\n>    Partition your list into equivalence classes such that functions $f(n)$\n>    and $g(n)$ are in the same class if and only if $f(n) = \\Theta(g(n))$.\n>\n> 2. Give an example of a single nonnegative function $f(n)$ such that for all\n>    functions $g_i(n)$ in part (1), $f(n)$ is neither $O(g_i(n))$ nor\n>    $\\Omega(g_i(n))$.\n>\n> |                   |                      |                       |                 |            |                 |\n> |:-----------------:|:--------------------:|:---------------------:|:---------------:|:----------:|:---------------:|\n> | $\\lg(\\lg^*n)$     | $2^{\\lg^*n}$         | $(\\sqrt{2})^{\\lg{n}}$ | $n^2$           | $n!$       | $(\\lg{n})!$     |\n> | $(\\frac{3}{2})^n$ | $n^3$                | $\\lg^2{n}$            | $\\lg(n!)$       | $2^{2^n}$  | $n^{1/\\lg{n}}$  |\n> | $\\ln{\\ln{n}}$     | $\\lg^*n$             | $n \\cdot 2^n$         | $n^{\\lg\\lg{n}}$ | $\\ln{n}$   | $1$             |\n> | $2^{\\lg{n}}$      | $(\\lg{n})^{\\lg{n}}$  | $e^n$                 | $4^{\\lg{n}}$    | $(n + 1)!$ | $\\sqrt{\\lg{n}}$ |\n> | $\\lg^*(\\lg{n})$   | $2^{\\sqrt{2\\lg{n}}}$ | $n$                   | $2^n$           | $n\\lg{n}$  | $2^{2^{n + 1}}$ |\n\n\nSome facts:\n\n$$ (\\sqrt{2})^{\\lg{n}} = \\sqrt{n} $$\n$$ \\sqrt{2}^{\\lg{n}} = 2^{1/2\\lg{n}} = 2^{\\lg{\\sqrt{n}}} = \\sqrt{n} $$\n$$ n! < n^n = 2^{\\lg{n^n}} = 2^{n\\lg{n}} $$\n$$ n^{1/\\lg{n}} = n^{\\log_n{2}} = 2$$\n$$ n^{\\lg{\\lg{n}}} = (2^{\\lg{n}})^{\\lg\\lg{n}} = (2^{\\lg\\lg{n}})^{\\lg{n}} = (\\lg{n})^{\\lg{n}} $$\n$$ \\lg^2{n} = 2^\\{\\lg{\\lg^2{n}}} = o(2^{\\sqrt{2\\lg{n}}}) $$\n\nThe order is thus:\n\n1. $1 = n^{1/\\lg{n}}$\n2. $\\lg(\\lg^*n)$\n3. $\\lg^{\\*}n \\simeq \\lg^{\\*}(\\lg{n})$\n4. $2^{\\lg^*n}$\n5. $\\ln{\\ln{n}}$\n6. $\\sqrt{\\lg{n}}$\n7. $\\ln{n}$\n8. $\\lg^2{n}$\n9. $2^{\\sqrt{2\\lg{n}}}$\n10. $(\\sqrt{2})^{\\lg{n}}$\n11. $n = 2^{\\lg{n}}$\n12. $n\\lg{n} \\simeq \\lg(n!)$\n13. $n^2 = 1 4^{\\lg{n}}$\n14. $n^3$\n15. $n^{\\lg\\lg{n}} = (\\lg{n})^{\\lg{n}}$\n16. $(\\frac{3}{2})^n$\n17. $2^n$\n18. $n \\cdot 2^n$\n19. $e^n$\n20. $n!$\n21. $(n + 1)!$\n22. $2^{2^n}$\n23. $2^{2^{n + 1}}$\n\n---\n\nThe asked function can be:\n\n$$ 2^{2^{(n + 1)\\sin{x}}} $$\n"
  },
  {
    "path": "other/clrs/03/problems/04.markdown",
    "content": "## Asymptotic notation properties\n\n> Let $f(n)$ and $g(n)$ be asymptotically positive functions. Prove or\n> disprove each of the following conjectures.\n>\n> 1. $ f(n) = O(g(n)) \\text{ implies } g(n) = O(f(n)) $\n> 2. $ f(n) + g(n) = \\Theta(\\min(f(n), g(n))) $\n> 3. $ f(n) = O(g(n)) \\text{ implies } \\lg(f(n)) = O(lg(g(n))), \\text{ where }\n>    \\lg(g(n)) \\geq 1 \\text{ and } f(n) \\geq 1 \\text{ for all sufficiently\n>    large n} $\n> 4. $ f(n) = O(g(n)) \\text{ implies } 2^{f(n)} = O(2^{g(n)}). $\n> 5. $ f(n) = O((f(n))^2) $\n> 6. $ f(n) = O(g(n)) \\text{ implies } g(n) = \\Omega(f(n)) $\n> 7. $ f(n) = \\Theta(f(n/2)) $\n> 8. $ f(n) + o(f(n)) = \\Theta(f(n)) $\n\n### a. $ f(n) = O(g(n)) \\text{ implies } g(n) = O(f(n)) $\n\n**Incorrect**. It's easy to see that $n = O(n^2)$, but $n^2 \\neq O(n)$.\n\n### b. $ f(n) + g(n) = \\Theta(\\min(f(n), g(n))) $\n\n**Incorrect**. Simply $n^2 + n \\neq \\Theta(\\min(n^2, n)) = \\Theta(n) $\n\n### c. $ f(n) = O(g(n)) \\Rightarrow \\lg(f(n)) = O(lg(g(n))) \\text{ if } \\lg(g(n)) \\geq 1, f(n) \\geq 1 $\n\n**Correct**. We can do this, because $f(n) \\geq 1$ after a certain $n \\geq n_0$.\n\n$$ \\exists c, n_0 : \\forall n \\geq n_0 : 0 \\leq f(n) \\leq cg(n) \\\\\\\\\n   \\Downarrow \\\\\\\\\n   0 \\leq \\lg{f(n)} \\leq \\lg(cg(n)) = \\lg{c} + \\lg{g(n)}$$\n\nWe need to prove that:\n\n$$ \\lg{f(n)} \\leq d\\lg{g(n)} $$\n\nWe can easily find $d$:\n\n$$ d = \\frac{\\lg{c} + \\lg{g(n)}}{\\lg{g(n)}} = \\frac{\\lg{c}}{\\lg{g}} + 1 \\leq \\lg{c} + 1 $$\n\nThe last step is valid, because $\\lg{g(n)} \\geq 1$.\n\n### d. $ f(n) = O(g(n)) \\Rightarrow 2^{f(n)} = O(2^{g(n)}). $\n\n**Incorrect**, because $2n = O(n)$, but $2^{2n} = 4^n \\neq O(2^n)$.\n\n### e. $ f(n) = O((f(n))^2) $\n\n**Correct**. $0 \\leq f(n) \\leq cf^2(n)$ is trivial when $f(n) \\geq 1$.\n\nIt would be incorrect if $f(n) < 1$ for all $n$, but we are usually not\ninterested in such functions.\n\n### f. $ f(n) = O(g(n)) \\Rightarrow g(n) = \\Omega(f(n)) $\n\n**Correct**. From the first, we know that:\n\n$$ 0 \\leq f(n) \\leq cg(n) $$\n\nWe need to prove that:\n\n$$ 0 \\leq df(n) \\leq g(n) $$\n\nWhich is straightforward with $d = 1/c$.\n\n### g. $ f(n) = \\Theta(f(n/2)) $\n\n**Incorrect**. Let's pick $f(n) = 2^{n}$. We will need to prove that:\n\n$$ \\exists c_1, c_2, n: \\forall n \\geq n_0 : 0 \\leq c_1 \\cdot 2^{n/2} \\leq 2^n\n   \\leq c_2 \\cdot 2^{n/2} $$\n\nWhich is obviously untrue.\n\n### h. $ f(n) + o(f(n)) = \\Theta(f(n)) $\n\n**Correct**. Let $g(n) = o(f(n))$. We need to proove that:\n\n$$ c_1f(n) \\leq f(n) + g(n) \\leq c_2f(n) $$\n\nWe know that:\n\n$$ \\forall c \\exists n_0 \\forall n \\geq n_0 : cg(n) < f(n) $$\n\nThus, if we pick $c_1 = 1$ and $c_2 = 2$, it holds.\n"
  },
  {
    "path": "other/clrs/03/problems/05.markdown",
    "content": "## Variations on $O$ and $\\Omega$\n\n> Some authors define $\\Omega$ in a slightly different way than we do; let's\n> use $\\mathop{\\Omega}^{\\infty}$ (read \"omega infinity\") for this alternative\n> definition. We say that $f(n) = \\mathop{\\Omega}^{\\infty}(g(n))$ if there\n> exists a positive constant $c$ such that $f(n) \\geq cg(n) \\geq 0$ for\n> infinitely many integers $n$.\n>\n> 1. Show that for any two functions $f(n)$ and $g(n)$ that are asymptotically\n>    nonnegative, either $f(n) = O(g(n))$ or $f(n) =\n>    \\mathop{\\Omega}^{\\infty}(g(n))$ or both, whereas this is not true if we\n>    use $\\Omega$ in place of $\\mathop{\\Omega}^{\\infty}$.\n> 2. Describe the potential advantages and disadvantages of using\n>    $\\mathop{\\Omega}^{\\infty}$ instead of $\\Omega$ to characterize the\n>    running times of programs.\n> 3. Some authors also define $O$ in a slightly different manner; let's use\n>    $O'$ for the alternative definition. We say that $f(n) = O'(g(n))$ if and\n>    only if $|f(n)| = O(g(n))$. What happens to each direction of the \"if and\n>    only if\" in Theorem 3.1 if we substitute $O'$ for $O$ but we still use\n>    $\\Omega$?\n> 4. Some authors define $\\tilde{O}$ (read \"soft-oh\") to mean $O$ with\n>    logarithmic factors ignored:\n>    $$ \\tilde{O} = \\lbrace f(n) : \\exists c > 0, k > 0 n_0 \\forall n \\geq n_0: 0 \\leq f(n) \\leq\n>                            cg(n)\\lg^k(n) \\rbrace $$\n>    Define $\\tilde{\\Omega}$ and $\\tilde{\\Theta}$ in a similar manner. Prove\n>    the corresponding analog to Theorem 3.1.\n\n### Omega infinity\n\nWe need to compare:\n\n$$ cg(n) \\leq f(n) $$\n\nEither this holds for an infinite number of integers or for a finite one (or\nzero). If the former, we have $\\mathop{\\Omega}^{\\infty}$. If it is a finite\nnumber, then the largest is $n_0$ and we have that:\n\n$$ \\forall n > n_0: f(n) < cg(n) $$\n\nWhich is sufficient for $f(n) = O(g(n))$. Both can hold if $f(n) = g(n)$,\nobviously.\n\nIt's not true for $\\Omega$, because $n = \\mathop{\\Omega}^{\\infty}(n^{\\sin{n}})$,\nbut $n \\neq \\Omega(n^{\\sin{n}})$.\n\n### Potential advantages\n\nI can't think of anything meaningful. It lets us reason for functions like\n$n^{\\sin{n}}$, but I'm not sure that lower bound is the most useful thing\nhere.\n\n### $O'$\n\nTheorem 3.1 will change the \"if and only if\" to \"implies\", that is, $\\Theta\n\\Rightarrow O'$, but not the other way around. This can be illustrated by\n$f(n) = n \\cdot \\sin{n}$, which is $O'(n)$, but not $O(n)$ or $\\Theta(n)$.\n\n### Soft-oh\n\nI'm uncertain how we should define $\\tilde{\\Omega}$. I assume that $n =\n\\tilde{\\Omega}(n\\lg{n})$. In that case,\n\n$$ \\tilde{\\Omega} = \\lbrace f(n) : \\exists c, k, n \\forall n > n_0 :\n   0 \\leq cg(n) \\lg^{-k}(n) \\leq f(n) \\rbrace $$\n\nAnd:\n\n$$ \\tilde{\\Theta} = \\lbrace f(n) : \\exists c_1, c_2, k_1, k_2, n \\forall n > n_0 :\n   0 \\leq c_1g(n) \\lg^{-k_1}(n) \\leq f(n) \\leq c_2g(n) \\lg^{k_2}(n)\\rbrace $$\n\nProving the theorem is very trivial.\n"
  },
  {
    "path": "other/clrs/03/problems/06.markdown",
    "content": "## Iterated functions\n\n> We can apply the iteration operator $\\*$ used in the $\\lg^\\*$ function to any\n> monotonically increasing function $f(n)$ over the reals. For a given\n> constant $c \\in \\mathbb{R}$, we define the iterated function $f_c^*$ by\n>\n> $$ f_c^*(n) = min \\lbrace i \\geq 0 : f^{(i)}(n) \\leq c \\rbrace $$\n>\n> which need not be well defined in all cases. In other words, the quantity\n> $f_c^*(n)$ is the number of iterated applications of the function $f$\n> required to reduce its argument down to $c$ or less.\n>\n> For each of the following functions $f(n)$ and constants $c$, give as tight\n> a bound as possible on $f_c^*(n)$.\n\n| $ f(n) $     | $ c $ | $ f_c^*(n) $                     |\n|:------------:|:-----:|:--------------------------------:|\n| $ n - 1 $    | $ 0 $ | $ \\Theta(n) $                    |\n| $ \\lg{n} $   | $ 1 $ | $ \\Theta(\\lg^*{n}) $             |\n| $ n / 2 $    | $ 1 $ | $ \\Theta(\\lg{n}) $               |\n| $ n / 2 $    | $ 2 $ | $ \\Theta(\\lg{n}) $               |\n| $ \\sqrt{n} $ | $ 2 $ | $ \\Theta(\\lg\\lg{n}) $            |\n| $ \\sqrt{n} $ | $ 1 $ | *does not converge*              |\n| $ n^{1/3} $  | $ 2 $ | $ \\Theta(\\log_3{\\lg{n}}) $       |\n| $ n/\\lg{n} $ | $ 2 $ | $ \\omega(\\lg\\lg{n}), o(\\lg{n}) $ |\n"
  },
  {
    "path": "other/clrs/04/01/01.markdown",
    "content": "> What does *FIND-MAXIMUM-SUBARRAY* return when all elements of $A$ are\n> negative?\n\nIt will return a single-element array with the largest negative integer.\n"
  },
  {
    "path": "other/clrs/04/01/02.markdown",
    "content": "> Write pseudocode for the brute-force method of solving the maximum-subarray\n> problem. Your procedure should run in $\\Theta(n^2)$ time.\n\n    FIND-MAX-SUBARRAY(A, low, high)\n      left = 0\n      right = 0\n      sum = -∞\n      for i = low to high\n          current-sum = 0\n          for j = i to high\n\t      current-sum += A[j]\n\t      if sum < current-sum\n\t          sum = current-sum\n\t\t  left = i\n\t\t  right = j\n      return (left, right, sum)\n"
  },
  {
    "path": "other/clrs/04/01/03.c",
    "content": "#include <limits.h>\n\n#define CROSSOVER_POINT 37\n\n// A struct to represent the tuple\n\ntypedef struct {\n    unsigned left;\n    unsigned right;\n    int sum;\n} max_subarray;\n\n// The brute force approach\n\nmax_subarray find_maximum_subarray_brute(int A[], unsigned low, unsigned high) {\n    max_subarray result = {0, 0, INT_MIN};\n\n    for (int i = low; i < high; i++) {\n        int current_sum = 0;\n        for (int j = i; j < high; j++) {\n            current_sum += A[j];\n            if (result.sum < current_sum) {\n                result.left = i;\n                result.right = j + 1;\n                result.sum = current_sum;\n            }\n        }\n    }\n\n    return result;\n}\n\n// The divide-and-conquer solution\n\nmax_subarray find_max_crossing_subarray(int A[], unsigned low, unsigned mid, unsigned high) {\n    max_subarray result = {-1, -1, 0};\n    int sum = 0,\n        left_sum = INT_MIN,\n        right_sum = INT_MIN;\n\n    for (int i = mid - 1; i >= (int) low; i--) {\n        sum += A[i];\n        if (sum > left_sum) {\n            left_sum = sum;\n            result.left = i;\n        }\n    }\n\n    sum = 0;\n\n    for (int j = mid; j < high; j++) {\n        sum += A[j];\n        if (sum > right_sum) {\n            right_sum = sum;\n            result.right = j + 1;\n        }\n    }\n\n    result.sum = left_sum + right_sum;\n    return result;\n}\n\nmax_subarray find_maximum_subarray(int A[], unsigned low, unsigned high) {\n    if (high == low + 1) {\n        max_subarray result = {low, high, A[low]};\n        return result;\n    } else {\n        unsigned mid = (low + high) / 2;\n        max_subarray left = find_maximum_subarray(A, low, mid);\n        max_subarray right = find_maximum_subarray(A, mid, high);\n        max_subarray cross = find_max_crossing_subarray(A, low, mid, high);\n\n        if (left.sum >= right.sum && left.sum >= cross.sum) {\n            return left;\n        } else if (right.sum >= left.sum && right.sum >= cross.sum) {\n            return right;\n        } else {\n            return cross;\n        }\n    }\n}\n\n// The mixed algorithm\n\nmax_subarray find_maximum_subarray_mixed(int A[], unsigned low, unsigned high) {\n    if (high - low < CROSSOVER_POINT) {\n        return find_maximum_subarray_brute(A, low, high);\n    } else {\n        unsigned mid = (low + high) / 2;\n        max_subarray left = find_maximum_subarray_mixed(A, low, mid);\n        max_subarray right = find_maximum_subarray_mixed(A, mid, high);\n        max_subarray cross = find_max_crossing_subarray(A, low, mid, high);\n\n        if (left.sum >= right.sum && left.sum >= cross.sum) {\n            return left;\n        } else if (right.sum >= left.sum && right.sum >= cross.sum) {\n            return right;\n        } else {\n            return cross;\n        }\n    }\n}\n"
  },
  {
    "path": "other/clrs/04/01/03.markdown",
    "content": "> Implement both the brute-force and recursive algorithms for the\n> maximum-subarray problem on your own computer. What problem size $n_0$ gives\n> the crossover point at which the recursive algorithm beats the brute-force\n> algorithm? Then, change the base case of the recursive algorithm to use the\n> brute-force algorithm whenever the problem size is less than $n_0$. Does\n> that change the crossover point?\n\nOn my computer, $n_0$ is 37.\n\nIf the algorithm is modified to used divide in conquer when $n \\geq 37$ and the\nbrute-force approach when $n$ is less, the performance at the crossover point\nalmost doubles. The performance at $n_0 - 1$ stays the same, though (or even\ngets worse, because of the added overhead).\n\nWhat I find interesting is that if we set $n_0 = 20$ and used the mixed\napproach to sort $40$ elements, it is still faster than both.\n"
  },
  {
    "path": "other/clrs/04/01/03.run.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n#include \"03.c\"\n#include \"../../build/ext/debug_helpers.h\"\n\n#define SIZE CROSSOVER_POINT * 200\n\n#ifndef SEED\n#define SEED 300\n#endif\n\nstatic clock_t timer_start_time;\n\n#define TIME(times, message, subarray, size) \\\n    timer_start_time = clock(); \\\n    for (int i = 0; i < times; i++) { \\\n        answer = subarray(array, 0, size); \\\n    } \\\n    printf(message \" = %f\\n\", (double) (clock() - timer_start_time) / CLOCKS_PER_SEC); \\\n    check_right_answer(expected, answer);\n\nvoid randomize_array(int array[], unsigned length, unsigned int seed) {\n    srand(seed);\n    for (unsigned i = 0; i < length; i++) {\n        array[i] = rand() % 101 - 50;\n    }\n}\n\nvoid check_right_answer(max_subarray expected, max_subarray actual) {\n    if (expected.sum != actual.sum) {\n        printf(\"%u %u %d\\n\", expected.left, expected.right, expected.sum);\n        printf(\"%u %u %d\\n\", actual.left, actual.right, actual.sum);\n        fprintf(stderr, \"Incorrect result ;(\\n\");\n        exit(1);\n    }\n}\n\nint main() {\n    int array[SIZE];\n    randomize_array(array, SIZE, SEED);\n    max_subarray expected, answer;\n\n    expected = find_maximum_subarray(array, 0, CROSSOVER_POINT);\n    printf(\"%d elements, 10000 times...\\n\", CROSSOVER_POINT);\n    TIME(10000, \"brute-force       \", find_maximum_subarray_brute, CROSSOVER_POINT);\n    TIME(10000, \"divide-and-conquer\", find_maximum_subarray, CROSSOVER_POINT);\n    TIME(10000, \"mixed             \", find_maximum_subarray_mixed, CROSSOVER_POINT);\n\n    printf(\"=============================\\n\");\n\n    expected = find_maximum_subarray(array, 0, SIZE);\n    printf(\"%d elements, 1 time...\\n\", SIZE);\n    TIME(1, \"brute-force       \", find_maximum_subarray_brute, SIZE);\n    TIME(1, \"divide-and-conquer\", find_maximum_subarray, SIZE);\n    TIME(1, \"mixed             \", find_maximum_subarray_mixed, SIZE);\n\n    exit(0);\n}\n"
  },
  {
    "path": "other/clrs/04/01/03.test.c",
    "content": "#include \"03.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(chapter_example_brute) {\n    int array[] = { 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 };\n    max_subarray result = find_maximum_subarray_brute(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_EQUALS(result.left, 7);\n    ASSERT_EQUALS(result.right, 11);\n    ASSERT_EQUALS(result.sum, 43);\n}\n\nTEST(chapter_example_divide_and_conquer) {\n    int array[] = { 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 };\n    max_subarray result = find_maximum_subarray(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_EQUALS(result.left, 7);\n    ASSERT_EQUALS(result.right, 11);\n    ASSERT_EQUALS(result.sum, 43);\n}\n\nTEST(chapter_example_mixed) {\n    int array[] = { 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 };\n    max_subarray result = find_maximum_subarray_mixed(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_EQUALS(result.left, 7);\n    ASSERT_EQUALS(result.right, 11);\n    ASSERT_EQUALS(result.sum, 43);\n}\n"
  },
  {
    "path": "other/clrs/04/01/04.c",
    "content": "#include <limits.h>\n\ntypedef struct {\n    unsigned left;\n    unsigned right;\n    int sum;\n} max_subarray;\n\nmax_subarray find_max_crossing_subarray(int A[], unsigned low, unsigned mid, unsigned high) {\n    max_subarray result = {mid + 1, mid, 0};\n    int sum = 0,\n        left_sum = INT_MIN,\n        right_sum = INT_MIN;\n\n    for (int i = mid - 1; i >= (int) low; i--) {\n        sum += A[i];\n        if (sum > left_sum) {\n            left_sum = sum;\n            result.left = i;\n        }\n    }\n\n    sum = 0;\n\n    for (int j = mid; j < high; j++) {\n        sum += A[j];\n        if (sum > right_sum) {\n            right_sum = sum;\n            result.right = j + 1;\n        }\n    }\n\n    if (left_sum + right_sum < 0) {\n        max_subarray empty = { mid, mid, 0 };\n        return empty;\n    } else {\n        result.sum = left_sum + right_sum;\n        return result;\n    }\n}\n\nmax_subarray find_maximum_subarray(int A[], unsigned low, unsigned high) {\n    if (high == low + 1) {\n        if (A[low] < 0) {\n            max_subarray empty = {low, low, 0};\n            return empty;\n        } else {\n            max_subarray result = {low, high, A[low]};\n            return result;\n        }\n    } else {\n        unsigned mid = (low + high) / 2;\n        max_subarray left = find_maximum_subarray(A, low, mid);\n        max_subarray right = find_maximum_subarray(A, mid, high);\n        max_subarray cross = find_max_crossing_subarray(A, low, mid, high);\n\n        if (left.sum >= right.sum && left.sum >= cross.sum) {\n            return left;\n        } else if (right.sum >= left.sum && right.sum >= cross.sum) {\n            return right;\n        } else {\n            return cross;\n        }\n    }\n}\n"
  },
  {
    "path": "other/clrs/04/01/04.markdown",
    "content": "> Suppose we change the definition of the maximum-subarray problem to allow\n> the result to be an empty subarray, where the sum of the values of an empty\n> subarray is 0. How would you change any of the algorithms that do not allow\n> empty subarrays to permit an empty subarray to be the result?\n\nWe need to modify two things - the base case of the algorithm and the\nsubroutine that finds the maximum subarray crossing the midpoint.\n\nThe base case needs to return an empty array if `A[low]` is negative.\n\nThe subroutine needs to return an empty array in case the maximum subarray has\na negative sum.\n"
  },
  {
    "path": "other/clrs/04/01/04.test.c",
    "content": "#include \"04.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(chapter_example) {\n    int array[] = { 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 };\n    max_subarray result = find_maximum_subarray(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_EQUALS(result.left, 7);\n    ASSERT_EQUALS(result.right, 11);\n    ASSERT_EQUALS(result.sum, 43);\n}\n\nTEST(negative_numbers) {\n    int array[] = { -4, -2, -8, -1, -2, -5 };\n    max_subarray result = find_maximum_subarray(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_EQUALS(result.left, result.right);\n    ASSERT_EQUALS(result.sum, 0);\n}\n\nTEST(trivial_case_negative_numbers) {\n    int array[] = { -4 };\n    max_subarray result = find_maximum_subarray(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_EQUALS(result.sum, 0);\n    ASSERT_EQUALS(result.left, result.right);\n}\n\nTEST(trivial_case_positive_numbers) {\n    int array[] = { 4 };\n    max_subarray result = find_maximum_subarray(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_EQUALS(result.left, 0);\n    ASSERT_EQUALS(result.right, 1);\n    ASSERT_EQUALS(result.sum, 4);\n}\n"
  },
  {
    "path": "other/clrs/04/01/05.c",
    "content": "typedef struct {\n    unsigned left;\n    unsigned right;\n    int sum;\n} max_subarray;\n\nmax_subarray find_maximum_subarray(int A[], unsigned low, unsigned high) {\n    max_subarray suffixes[high - low];\n\n    suffixes[0].left = low;\n    suffixes[0].right = low + 1;\n    suffixes[0].sum = A[low];\n\n    for (int i = low + 1; i < high; i++) {\n        if (suffixes[i - 1].sum < 0) {\n            suffixes[i].left = i;\n            suffixes[i].right = i + 1;\n            suffixes[i].sum = A[i];\n        } else {\n            max_subarray *previous = &suffixes[i - 1];\n            suffixes[i].left = previous->left;\n            suffixes[i].right = i + 1;\n            suffixes[i].sum = previous->sum + A[i];\n        }\n    }\n\n    max_subarray *max = &suffixes[0];\n\n    for (int i = low + 1; i < high; i++) {\n        if (max->sum < suffixes[i].sum) {\n            max = &suffixes[i];\n        }\n    }\n\n    return *max;\n}\n"
  },
  {
    "path": "other/clrs/04/01/05.markdown",
    "content": "> Use the following ideas to develop a nonrecursive, linear-time algorithm for\n> the maximum-subarray problem. Start at the left end of the array, and\n> progress toward the right, keeping track of the maximum subarray seen so\n> far. Knowing a maximum subarray $A[1..j]$, extend the answer to find a\n> maximum subarray ending at index $j + 1$ by using the following observation:\n> a maximum subarray $A[i..j+1]$, for some $1 \\leq i \\leq j + 1$. Determine a\n> maximum subarray of the form $A[i..j+1]$ in constant time based on knowing a\n> maximum subarray ending at index $j$.\n\nWe need to build an array $S$ that holds the maximum subarrays ending on each\nindex of $A$. That is, $S[j]$ holds information about the maximum subarray\nending on $j$.\n\nWe first loop through the input to build $S$. Afterwards, we do what they\nsuggest in the text. This is $n + n = 2n = \\Theta(n)$.\n"
  },
  {
    "path": "other/clrs/04/01/05.test.c",
    "content": "#include <stdlib.h>\n#include <limits.h>\n#include \"05.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(chapter_example) {\n    int array[] = { 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 };\n    max_subarray result = find_maximum_subarray(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_EQUALS(result.left, 7);\n    ASSERT_EQUALS(result.right, 11);\n    ASSERT_EQUALS(result.sum, 43);\n}\n\nTEST(negative_numbers) {\n    int array[] = { -4, -2, -8, -1, -2, -5 };\n    max_subarray result = find_maximum_subarray(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_EQUALS(result.left, 3);\n    ASSERT_EQUALS(result.right, 4);\n    ASSERT_EQUALS(result.sum, -1);\n}\n\nTEST(trivial_case_negative_numbers) {\n    int array[] = { -4 };\n    max_subarray result = find_maximum_subarray(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_EQUALS(result.left, 0);\n    ASSERT_EQUALS(result.right, 1);\n    ASSERT_EQUALS(result.sum, -4);\n}\n\nTEST(trivial_case_positive_numbers) {\n    int array[] = { 4 };\n    max_subarray result = find_maximum_subarray(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_EQUALS(result.left, 0);\n    ASSERT_EQUALS(result.right, 1);\n    ASSERT_EQUALS(result.sum, 4);\n}\n\nvoid generate_random_array(int array[], unsigned size, unsigned seed);\nmax_subarray find_maximum_subarray_brute(int A[], unsigned low, unsigned high);\n\nTEST(comparison_with_brute_force) {\n    int size = 50;\n    int array[size];\n    max_subarray expected, actual;\n\n    for (int i = 0; i < 10000; i++) {\n        generate_random_array(array, size, i);\n        actual   = find_maximum_subarray_brute(array, 0, size);\n        expected = find_maximum_subarray(array, 0, size);\n        ASSERT_EQUALS(expected.sum, actual.sum);\n    }\n}\n\nmax_subarray find_maximum_subarray_brute(int A[], unsigned low, unsigned high) {\n    max_subarray result = {0, 0, INT_MIN};\n\n    for (int i = low; i < high; i++) {\n        int current_sum = 0;\n        for (int j = i; j < high; j++) {\n            current_sum += A[j];\n            if (result.sum < current_sum) {\n                result.left = i;\n                result.right = j + 1;\n                result.sum = current_sum;\n            }\n        }\n    }\n\n    return result;\n}\n\nvoid generate_random_array(int array[], unsigned size, unsigned seed) {\n    srand(seed);\n    for (unsigned i = 0; i < size; i++) {\n        array[i] = rand() % 101 - 50;\n    }\n}\n"
  },
  {
    "path": "other/clrs/04/02/01.markdown",
    "content": "> Use Strassen's algorithm to compute the matrix product\n>\n> $$ \\begin{pmatrix}\n>    1 & 2 \\\\\\\\\n>    7 & 5\n>    \\end{pmatrix}\n>    \\begin{pmatrix}\n>    6 & 8 \\\\\\\\\n>    4 & 2\n>    \\end{pmatrix} $$\n>\n> Show your work.\n\nThe first matrices are:\n\n$$\nS_1 = 6 \\quad S_2 =  4 \\quad S_3 = 12 \\quad S_4 = -2 \\quad S_5 = 5 \\\\\\\\\nS_6 = 8 \\quad S_7 = -2 \\quad S_8 =  6 \\quad S_9 = -6 \\quad S_{10} = 14\n$$\n\nThe products are:\n\n$$\nP_1 = 1 \\cdot 6 = 6 \\qquad\nP_2 = 4 \\cdot 2 = 8 \\\\\\\\\nP_3 = 6 \\cdot 12 = 72 \\qquad\nP_4 = (-2) \\cdot 5 = -10 \\\\\\\\\nP_5 = 6 \\cdot 8 = 48 \\qquad\nP_6 = (-2) \\cdot 6 = -12 \\\\\\\\\nP_7 = (-6) \\cdot 14 = -84\n$$\n\nThe four matrices are:\n\n$$\nC_{11} = 48 + (-10) - 8 + (-12) = 18 \\\\\\\\\nC_{12} = 6 + 8 = 14 \\\\\\\\\nC_{21} = 72 + (-10) = 62 \\\\\\\\\nC_{22} = 48 + 6 - 72 - (-84) = 66\n$$\n\nThe result is:\n\n$$ \\begin{pmatrix}\n   18 & 14 \\\\\\\\\n   62 & 66\n   \\end{pmatrix} $$\n"
  },
  {
    "path": "other/clrs/04/02/02.c",
    "content": "#include <alloca.h>\n#include <stdio.h>\n\n// The matrix representation. One structure to fit both a matrix and a\n// submatrix.\n\ntypedef struct {\n    int x;\n    int y;\n    int size;\n    int original_size;\n    int *data;\n} matrix;\n\n// Functions to index matrices\n\nint get(matrix m, int x, int y) {\n    return m.data[m.original_size * (m.x + x) + m.y + y];\n};\n\nvoid put(matrix m, int x, int y, int value) {\n    m.data[m.original_size * (m.x + x) + m.y + y] = value;\n};\n\n// Matrix building\n\nmatrix create_matrix(int size, int *data) {\n    matrix result;\n    result.x = 0;\n    result.y = 0;\n    result.size = size;\n    result.original_size = size;\n    result.data = data;\n\n    return result;\n}\n\nmatrix submatrix(matrix A, int x, int y, int size) {\n    matrix result;\n    result.x = A.x + x;\n    result.y = A.y + y;\n    result.size = size;\n    result.original_size = A.original_size;\n    result.data = A.data;\n    return result;\n}\n\n#define INIT_ON_STACK(m_, size_) \\\n    m_.x = 0; \\\n    m_.y = 0; \\\n    m_.size = size_; \\\n    m_.original_size = size_; \\\n    m_.data = alloca(size_ * size_ * sizeof(int));\n\n// Adding and subtracting matrices\n\nvoid plus(matrix C, matrix A, matrix B) {\n    for (int i = 0; i < C.size; i++) {\n        for (int j = 0; j < C.size; j++) {\n            put(C, i, j, get(A, i, j) + get(B, i, j));\n        }\n    }\n}\n\nvoid minus(matrix C, matrix A, matrix B) {\n    for (int i = 0; i < C.size; i++) {\n        for (int j = 0; j < C.size; j++) {\n            put(C, i, j, get(A, i, j) - get(B, i, j));\n        }\n    }\n}\n\nvoid add(matrix T, matrix S) {\n    for (int i = 0; i < T.size; i++) {\n        for (int j = 0; j < T.size; j++) {\n            put(T, i, j, get(T, i, j) + get(S, i, j));\n        }\n    }\n}\nvoid sub(matrix T, matrix S) {\n    for (int i = 0; i < T.size; i++) {\n        for (int j = 0; j < T.size; j++) {\n            put(T, i, j, get(T, i, j) - get(S, i, j));\n        }\n    }\n}\n\nvoid zero(matrix m) {\n    for (int i = 0; i < m.size; i++) {\n        for (int j = 0; j < m.size; j++) {\n            put(m, i, j, 0);\n        }\n    }\n}\n\n// A function to print matrices\n\nvoid print_matrix(matrix m) {\n    printf(\"%dx%d (+%d+%d) (%d)\\n\", m.size, m.size, m.x, m.y, m.original_size);\n    printf(\"==============\\n\");\n    for (int i = 0; i < m.size; i++) {\n        for (int j = 0; j < m.size; j++) {\n            printf(\"%4d\", get(m, i, j));\n        }\n        printf(\"\\n\");\n    }\n    printf(\"\\n\");\n}\n\n// Strassen's algorithm\n\nvoid strassen(matrix C, matrix A, matrix B) {\n    int size = A.size,\n        half = size / 2;\n\n    if (A.size == 1) {\n        put(C, 0, 0, get(A, 0, 0) * get(B, 0, 0));\n    } else {\n        matrix s1, s2, s3, s4, s5, s6, s7, s8, s9, s10;\n        matrix p1, p2, p3, p4, p5, p6, p7;\n\n        INIT_ON_STACK(s1, half);\n        INIT_ON_STACK(s2, half);\n        INIT_ON_STACK(s3, half);\n        INIT_ON_STACK(s4, half);\n        INIT_ON_STACK(s5, half);\n        INIT_ON_STACK(s6, half);\n        INIT_ON_STACK(s7, half);\n        INIT_ON_STACK(s8, half);\n        INIT_ON_STACK(s9, half);\n        INIT_ON_STACK(s10, half);\n\n        INIT_ON_STACK(p1, half);\n        INIT_ON_STACK(p2, half);\n        INIT_ON_STACK(p3, half);\n        INIT_ON_STACK(p4, half);\n        INIT_ON_STACK(p5, half);\n        INIT_ON_STACK(p6, half);\n        INIT_ON_STACK(p7, half);\n\n        matrix a11 = submatrix(A,    0,    0, half);\n        matrix a12 = submatrix(A,    0, half, half);\n        matrix a21 = submatrix(A, half,    0, half);\n        matrix a22 = submatrix(A, half, half, half);\n\n        matrix b11 = submatrix(B,    0,    0, half);\n        matrix b12 = submatrix(B,    0, half, half);\n        matrix b21 = submatrix(B, half,    0, half);\n        matrix b22 = submatrix(B, half, half, half);\n\n        matrix c11 = submatrix(C,    0,    0, half);\n        matrix c12 = submatrix(C,    0, half, half);\n        matrix c21 = submatrix(C, half,    0, half);\n        matrix c22 = submatrix(C, half, half, half);\n\n        minus(s1, b12, b22);\n        plus(s2,  a11, a12);\n        plus(s3,  a21, a22);\n        minus(s4, b21, b11);\n        plus(s5,  a11, a22);\n        plus(s6,  b11, b22);\n        minus(s7, a12, a22);\n        plus(s8,  b21, b22);\n        minus(s9, a11, a21);\n        plus(s10, b11, b12);\n\n        strassen(p1, a11, s1);\n        strassen(p2, s2, b22);\n        strassen(p3, s3, b11);\n        strassen(p4, a22, s4);\n        strassen(p5, s5, s6);\n        strassen(p6, s7, s8);\n        strassen(p7, s9, s10);\n\n        zero(c11);\n        zero(c12);\n        zero(c21);\n        zero(c22);\n\n        add(c11, p5);\n        add(c11, p4);\n        sub(c11, p2);\n        add(c11, p6);\n\n        add(c12, p1);\n        add(c12, p2);\n\n        add(c21, p3);\n        add(c21, p4);\n\n        add(c22, p5);\n        add(c22, p1);\n        sub(c22, p3);\n        sub(c22, p7);\n    }\n}\n"
  },
  {
    "path": "other/clrs/04/02/02.markdown",
    "content": "> Write pseudocode for Strassen's algorithm\n\nPseudocode is for sissies. Let's write it in C!\n\n_60 minutes later:_ OK, bad decision.\n"
  },
  {
    "path": "other/clrs/04/02/02.test.c",
    "content": "#include \"02.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n\n#define SIZE 8\n#define CHECKS 1000\n#define MAX_ELEMENT_SIZE 10\n\nvoid multiply(matrix C, matrix A, matrix B) {\n    for (int i = 0; i < C.size; i++) {\n        for (int j = 0; j < C.size; j++) {\n            int result = 0;\n\n            for (int k = 0; k < C.size; k++) {\n                result += get(A, i, k) * get(B, k, j);\n            }\n\n            put(C, i, j, result);\n        }\n    }\n}\n\nTEST(random_matches) {\n    int a[SIZE * SIZE];\n    int b[SIZE * SIZE];\n    int c[SIZE * SIZE];\n    int d[SIZE * SIZE];\n\n    matrix A = create_matrix(SIZE, a);\n    matrix B = create_matrix(SIZE, b);\n    matrix C = create_matrix(SIZE, c);\n    matrix D = create_matrix(SIZE, d);\n\n    for (unsigned seed = 0; seed < CHECKS; seed++) {\n        srand(seed);\n\n        for (int i = 0; i < SIZE; i++) {\n            for (int j = 0; j < SIZE; j++) {\n                put(A, i, j, rand() % MAX_ELEMENT_SIZE);\n                put(B, i, j, rand() % MAX_ELEMENT_SIZE);\n            }\n        }\n\n        strassen(C, A, B);\n        multiply(D, A, B);\n\n        for (int i = 0; i < SIZE; i++) {\n            for (int j = 0; j < SIZE; j++) {\n                ASSERT_EQUALS(get(C, i, j), get(D, i, j));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "other/clrs/04/02/03.markdown",
    "content": "> How would you modify Strassen's algorithm to multiply $n \\times n$ matrices\n> in which $n$ is not an exact power of 2? Show that the resulting algorithm\n> runs in time $\\Theta(n^{\\lg7})$.\n\nI'm not sure what resulting algorithm we have in mind. In any case, we can\njust extend it to an $n \\times n$ matrix and pad it with zeroes. It's\nobviously $\\Theta(n^{\\lg7})$.\n"
  },
  {
    "path": "other/clrs/04/02/04.markdown",
    "content": "> What is the largest $k$ such that if you can multiply $3 \\times 3$ matrices\n> using $k$ multiplications (not assuming commutativity of multiplication),\n> then you can multiply $n \\times n$ matrices is time $o(n^{\\lg7})$? What\n> would the running time of this algorithm be?\n\nIf we apply divide and conquer on this, we get the following recurrence:\n\n$$ T(n) = kT(n/3) + \\Theta(n) $$\n\nThe master method tells us that if $k$ is large enough, the complexity of this\nrecurrence is $\\Theta(n^{\\log_{3}k})$. We need to solve:\n\n$$\nn^{\\log_3k} < n^{\\lg7} \\\\\\\\\n\\Downarrow \\\\\\\\\n\\log_3k < \\lg7 \\\\\\\\\n\\Downarrow \\\\\\\\\nk < 3^{\\lg7} \\approx 21.84986\n$$\n"
  },
  {
    "path": "other/clrs/04/02/05.markdown",
    "content": "> V. Pan has discovered a way of multiplying $68 \\times 68$ matrices using\n> $132,464$ multiplications, a way of multiplying $70 \\times 70$ matrices\n> using $143,640$ multiplications, and a way of multiplying $72 \\times 72$\n> matrices using $155,424$ multiplications. Which method yields the best\n> asymptotic running time when used in a divide-and-conquer\n> matrix-multiplication algorithm? How does it compare to Strassen's\n> algorithm?\n\nUsing what we know from the last exercise, we need to pick the smalles of the\nfollowing:\n\n$$ \\log_{68} 132464 \\approx 2.795128 \\\\\\\\\n   \\log_{70} 143640 \\approx 2.795122 \\\\\\\\\n   \\log_{72} 155424 \\approx 2.795147 $$\n\nThe fastest one asymptotically is $70 \\times 70$ using $143,640$.\n"
  },
  {
    "path": "other/clrs/04/02/06.markdown",
    "content": "> How quickly can you multiply a $kn \\times n$ matrix by an $n \\times kn$\n> matrix, using Strassen's algorithm as a subroutine? Answer the same question\n> with the order of the input matrices reversed.\n\n$(kn \\times n)(n \\times kn)$ produces a $kn \\times kn$ matrix. This produces\n$k^2$ multiplications of $n \\times n$ matrices.\n\n$(n \\times kn)(kn \\times n)$ produces an $n \\times n$ matrix. This produces\n$k$ multiplications and $k - 1$ additions.\n"
  },
  {
    "path": "other/clrs/04/02/07.markdown",
    "content": "> Show how to multiply the complex numbers $a + bi$ and $c + di$ using only\n> three multiplications of real numbers. The algorithm should take $a$, $b$,\n> $c$ and $d$ as input and produce the real component $ac - bd$ and the\n> imaginary component $ad + bc$ separately.\n\nSimple enough. The three multiplications are:\n\n$$ A = (a + b)(c + d) = ac + ad + bc + bd \\\\\\\\\n   B = ac \\quad\\qquad\n   C = bd $$\n\nThe result is:\n\n$$ (B - C) + (A - B - C)i $$\n"
  },
  {
    "path": "other/clrs/04/03/01.markdown",
    "content": "> Show that the solution of $T(n)  = T(n - 1) + n$ is $O(n^2)$\n\nWe guess $T(n) \\le cn^2$ for a particular $c$. Then:\n\n$$ T(n) \\le c(n-1)^2 + n = cn^2 - 2cn + c + n$$\n\nIf we pick $c = 1$ we have:\n\n$$ n^2 - 2n + 1 + n = n^2 - n + 1 \\le n^2 \\text{ for } n \\ge 1 $$\n"
  },
  {
    "path": "other/clrs/04/03/02.markdown",
    "content": "> Show that the solution of $T(n) = T(\\lceil n/2 \\rceil) + 1$ is $O(\\lg{n})$\n\nWe guess $T(n) \\le c\\lg(n - 2)$:\n\n$$ T(n) \\le c\\lg(\\lceil n/2 \\rceil - 2) + 1\n        \\le c\\lg(n/2 + 1 - 2) + 1\n\t\\le c\\lg((n - 2)/2) + 1\n\t\\le c\\lg(n - 2) - c\\lg2 + 1\n\t\\le c\\lg(n - 2) $$\n"
  },
  {
    "path": "other/clrs/04/03/03.markdown",
    "content": "> We saw that the solution of $T(n) = 2T(\\lfloor n/2 \\rfloor) + n$ is\n> $O(n\\lg{n})$. Show that the solution of this recurrence is also\n> $\\Omega(n\\lg{n})$. Conclude that the solution is $\\Theta(n\\lg{n})$.\n\nFirst we guess $T(n) \\le cn\\lg{n}$:\n\n$$ \\begin{aligned}\n   T(n) & \\le 2c\\lfloor n/2 \\rfloor\\lg{\\lfloor n/2 \\rfloor} + n \\\\\\\\\n        & \\le cn\\lg(n/2) + n \\\\\\\\\n\t& \\le cn\\lg{n} - cn\\lg{2} + n \\\\\\\\\n\t& \\le cn\\lg{n} + (1 - c)n \\\\\\\\\n\t& \\le cn\\lg{n} \\\\\\\\\n\t& \\text{for } c \\ge 0\n   \\end{aligned} $$\n\nNext we guess $T(n) \\ge c(n+2)\\lg(n+2)$:\n\n$$ \\begin{aligned}\n   T(n) & \\ge 2c(\\lfloor n/2 \\rfloor + 2)(\\lg(\\lfloor n/2 \\rfloor + 2) + n \\\\\\\\\n        & \\ge 2c(n/2 - 1 + 2)(\\lg(n/2 - 1 + 2) + n \\\\\\\\\n        & \\ge 2c\\frac{n+2}{2}\\lg\\frac{n+2}{2} + n \\\\\\\\\n        & \\ge c(n+2)\\lg(n+2) - c(n+2)\\lg2 + n \\\\\\\\\n        & \\ge c(n+2)\\lg(n+2) + (1 - c)n - 2c \\qquad \\text{for } n \\ge 2c/(1-c), 0 < c < 1 \\\\\\\\\n        & \\ge c(n+2)\\lg(n+2)\n   \\end{aligned} $$\n\n"
  },
  {
    "path": "other/clrs/04/03/04.markdown",
    "content": "> Show that by making a different inductive hyptohesis, we can overcome the\n> difficulty with the boundary condition $T(1) = 1$ for recurrence (4.19)\n> without adjusting the boundary conditions for the inductive proof.\n\nWe shall make the guess $T(n) \\le n\\lg{n} + n$:\n\n$$ \\begin{aligned}\n     T(n) & \\le 2(c\\lfloor n/2 \\rfloor\\lg{\\lfloor n/2 \\rfloor} + \\lfloor n/2 \\rfloor) + n \\\\\\\\\n          & \\le 2c(n/2)\\lg(n/2) + 2(n/2) + n \\\\\\\\\n          & \\le cn\\lg(n/2) + 2n \\\\\\\\\n          & \\le cn\\lg(n/2) + 2n \\\\\\\\\n          & \\le cn\\lg{n} - cn\\lg{2} + 2n \\\\\\\\\n          & \\le cn\\lg{n} + (2 - c)n \\qquad (c \\ge 1)\\\\\\\\\n          & \\le cn\\lg{n} + n\n   \\end{aligned} $$\n\nThis time, the boundary condition is:\n\n$$ T(1) = 1 \\le cn\\lg{n} + n = 0 + 1 = 1 $$\n"
  },
  {
    "path": "other/clrs/04/03/05.markdown",
    "content": "> Show that $\\Theta(n\\lg{n})$ is the solution to the \"exact\" recurrence (4.3)\n> for merge sort.\n\nThe recurrence is:\n\n$$ T(n) = T(\\lfloor n/2 \\rfloor) + T(\\lceil n/2 \\rceil) + \\Theta(n) $$\n\nLet's guess $T(n) \\le c(n - 2)\\lg(n -2)$:\n\n$$ \\begin{aligned}\n     T(n) & \\le c(\\lfloor n/2 \\rfloor - 2)\\lg(\\lfloor n/2 \\rfloor - 2) + c(\\lceil n/2 \\rceil -2 )\\lg(\\lceil n/2 \\rceil - 2) + dn \\\\\\\\\n          & \\le c(n/2 - 2)\\lg(n/2 - 2) + c(n/2 + 1 -2 )\\lg(n/2 + 1 - 2) + dn \\\\\\\\\n          & \\le c(n/2 - 1)\\lg(n/2 - 1) + c(n/2 - 1 )\\lg(n/2 - 1) + dn \\\\\\\\\n          & \\le c\\frac{n-2}{2}\\lg\\frac{n-2}{2} + c\\frac{n-2}{2}\\lg\\frac{n-2}{2} + dn \\\\\\\\\n          & \\le c(n-2)\\lg\\frac{n-2}{2} + dn \\\\\\\\\n          & \\le c(n-2)\\lg(n-2) - c(n-2) + dn \\\\\\\\\n          & \\le c(n-2)\\lg(n-2) + (d - c)n + 2c \\qquad (c > d, n > 2c)\\\\\\\\\n          & \\le c(n-2)\\lg(n-2)\n   \\end{aligned} $$\n\nThis is $\\Theta(n\\lg{n})$. $\\Omega(n\\lg{n})$ is very similar.\n"
  },
  {
    "path": "other/clrs/04/03/06.markdown",
    "content": "> Show that the solution to $T(n) = 2T(\\lfloor n/2 \\rfloor + 17) + n$ is\n> $O(n\\lg{n})$\n\nLet's guess $T(n) \\le c(n-a)\\lg(n-a)$:\n\n$$ \\begin{aligned}\n   T(n) & \\le 2c(\\lfloor n/2 \\rfloor + 17 - a)\\lg(\\lfloor n/2 \\rfloor + 17 - a) + n \\\\\\\\\n        & \\le 2c(n/2 + 1 + 17 - a)\\lg(n/2 + 1 + 17 - a) + n \\\\\\\\\n        & \\le c(n + 36 - 2a)\\lg\\frac{n + 36 - 2a}{2} + n \\\\\\\\\n        & \\le c(n + 36 - 2a)\\lg(n + 36 - 2a) - c(n + 36 - 2a) + n & (c > 1, n > n_0 = f(a))\\\\\\\\\n        & \\le c(n + 36 - 2a)\\lg(n + 36 - 2a) & (a \\ge 36) \\\\\\\\\n        & \\le c(n - a)\\lg(n - a)\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/04/03/07.markdown",
    "content": "> Using the master method in Section 4.5, you can show that the solution to\n> the recurrence $T(n) = 4T(n/3) + n$ is $T(n) = \\Theta(n^{\\log_{3}4})$. Show\n> that a substitution proof with the assumption $T(n) \\leq cn^{\\log_{3}4}$\n> fails. Then show how to subtract off a lower-order term to make the\n> substitution proof work.\n\nFirst we guess $T(n) \\le cn^{\\log_3{4}}$. Thus:\n\n$$ \\begin{aligned}\n   T(n) & \\le 4c(n/3)^{\\log_3{4}} + n \\\\\\\\\n        & \\le cn^{\\log_3{4}} + n\n   \\end{aligned} $$\n\nDead-end!\n\nLet's guess $T(n) \\le cn^{\\log_3{4}} - n$. Thus:\n\n$$ \\begin{aligned}\n   T(n) & \\le 4\\Big(c(n/3)^{\\log_3{4}} - n\\Big) + n \\\\\\\\\n        & \\le cn^{\\log_3{4}} - 4n + n \\\\\\\\\n        & \\le cn^{\\log_3{4}} - 3n \\\\\\\\\n        & \\le cn^{\\log_3{4}} - n\n   \\end{aligned} $$\n\nWe're done!\n"
  },
  {
    "path": "other/clrs/04/03/08.markdown",
    "content": "> Using the master method in Section 4.5, you can show that the solution to\n> the recurrence $T(n) = 4T(n/2) + n^2$ is $T(n) = \\Theta(n^2)$. Show that a\n> substitution proof with the assumption $T(n) \\leq cn^2$ fails. Then show how\n> to subtract off a lower-order term to make the substitution proof work.\n\nWell:\n\n$$ T(n) \\le 4c(n/2)^2 + n^2 \\leq cn^2 + n^2 \\leq (c + 1)n^2 $$\n\nDead-end!\n\nNow we guess $T(n) \\le cn^2 - n$:\n\n$$ \\begin{aligned}\n     T(n) & \\le 4\\Big(c(n/2)^2 - n/2\\Big) + n \\\\\\\\\n          & \\le cn^2 - 2n + n \\\\\\\\\n          & \\le cn^2 - n\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/04/03/09.markdown",
    "content": "> Solve the recurrence $T(n) = 3T(\\sqrt{n}) + \\log{n}$ by making a change of\n> variables. Your solution should be asymptotically tight. Do now worry about\n> whether values are integral.\n\nLet's go this way:\n\n$$ \\begin{aligned}\n       T(n) & = 3T(\\sqrt{n}) + \\lg{n} & \\text{rename } m = \\lg{n} \\\\\\\\\n     T(2^m) & = 3T(2^{m/2}) + m \\\\\\\\\n       S(m) & = 3S(m/2) + m\n   \\end{aligned} $$\n\nNow we guess $S(m) \\le cm^{\\lg{3}} + dm$:\n\n$$ \\begin{aligned}\n     S(m) & \\le 3\\Big(c(m/2)^{\\lg{3}} + d(m/2)\\Big) + m \\\\\\\\\n          & \\le cm^{\\lg{3}} + (\\frac{3}{2}d + 1)m & (d \\le -2) \\\\\\\\\n          & \\le cm^{\\lg{3}} + dm\n   \\end{aligned} $$\n\nThen we guess $S(m) \\ge cm^{\\lg{3}} + dm$:\n\n$$ \\begin{aligned}\n     S(m) & \\ge 3\\Big(c(m/2)^{\\lg{3}} + d(m/2)\\Big) + m \\\\\\\\\n          & \\ge cm^{\\lg{3}} + (\\frac{3}{2}d + 1)m & (d \\ge -2) \\\\\\\\\n          & \\ge cm^{\\lg{3}} + dm\n   \\end{aligned} $$\n\nThus:\n\n$$ \\begin{aligned}\n     S(m) & = \\Theta(m^{\\lg{3}}) \\\\\\\\\n     T(n) & = \\Theta(\\lg^{\\lg{3}}{n})\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/04/04/01.dot",
    "content": "digraph tree {\n  node[shape=none];\n  edge[dir=none];\n\n  { rank=same;\n    a1[label=\"n\"]\n    as[label=\"n\"]\n  }\n\n  { rank=same;\n    b1[label=\"n/2\"];\n    b2[label=\"n/2\"];\n    b3[label=\"n/2\"];\n    bs[label=\"3n/2\"];\n  }\n\n  { rank=same;\n    c1[label=\"n/4\"];\n    c2[label=\"n/4\"];\n    c3[label=\"n/4\"];\n    c4[label=\"n/4\"];\n    c5[label=\"n/4\"];\n    c6[label=\"n/4\"];\n    c7[label=\"n/4\"];\n    c8[label=\"n/4\"];\n    c9[label=\"n/4\"];\n    cs[label=\"9n/4\"];\n  }\n\n  { rank=same;\n    z1[label=\"T(1)\"];\n    z2[label=\"T(1)\"];\n    z3[label=\"T(1)\"];\n    z4[label=\"T(1)\"];\n    z5[label=\"T(1)\"];\n    z6[label=\"T(1)\"];\n    z7[label=\"T(1)\"];\n    z8[label=\"T(1)\"];\n    z9[label=\"T(1)\"];\n    zs[label=\"(3/2)ⁱn\"];\n  }\n\n  a1 -> b1; a1 -> b2; a1 -> b3;\n\n  b1 -> c1; b1 -> c2; b1 -> c3;\n  b2 -> c4; b2 -> c5; b2 -> c6;\n  b3 -> c7; b3 -> c8; b3 -> c9;\n\n  { edge[style=dotted]\n    c1 -> z1; c2 -> z2; c3 -> z3;\n    c4 -> z4; c5 -> z5; c6 -> z6;\n    c7 -> z7; c8 -> z8; c9 -> z9;\n  }\n  { edge[style=invis]\n    as -> bs -> cs -> zs;\n  }\n}\n"
  },
  {
    "path": "other/clrs/04/04/01.markdown",
    "content": "> Use a reccursion tree to determine a good asymptotic upper bound on the\n> recurrence $T(n) = 3T(\\lfloor n/2 \\rfloor) + n$. Use the substitution method\n> to verify your answer.\n\nLet's just ignore the floor, it makes no difference whatsoever.\n\nThe tree is of depth $\\lg{n}$ and has $\\Theta(3^{\\lg{2}}) = \\Theta(2^{\\lg{n}})$ leaves. Thus:\n\n$$ \\begin{aligned}\n   T(n) &= \\sum_{i=0}^{\\lg{n}-1}\\Big(\\frac{3}{2}\\Big)^i n + \\Theta(n^{\\lg3}) \\\\\\\\\n        &= n\\frac{(3/2)^{\\lg{n}} - 1}{(3/2) - 1} + \\Theta(n^{\\lg3}) \\\\\\\\\n        &= n\\Theta(n^{\\lg3 - 1}) + \\Theta(n^{\\lg3}) \\\\\\\\\n        &= \\Theta(n^{\\lg3})\n   \\end{aligned} $$\n\nLet's use substitution. We guess $T(n) \\le cn^{\\lg3} + 2n$ (and drop the floor):\n\n$$ \\begin{aligned}\n   T(n) & \\le 3c(n/2)^{\\lg3} + 2n/2 + n \\\\\\\\\n        & \\le cn^{\\lg3} + 2n \\\\\\\\\n        & = \\Theta(n^{\\lg3})\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/04/04/02.dot",
    "content": "digraph tree {\n  node[shape=none];\n  edge[dir=none];\n\n  a1[label=\"n²\"];\n  b1[label=\"n²/4\"];\n  c1[label=\"n²/16\"];\n\n  { rank=same\n    z1[label=\"T(1)\"];\n    zs[label=\"n²/4ⁱ\"];\n  }\n\n  a1 -> b1 -> c1;\n  { edge[style=dotted] c1 -> z1; }\n}\n"
  },
  {
    "path": "other/clrs/04/04/02.markdown",
    "content": "> Use a reccursion tree to determine a good asymptotic upper bound on the\n> recurrence $T(n) = T(n/2) + n^2$. Use the substitution method to verify your\n> answer.\n\nEach level of the tree is $n^2/4^i$, there are $\\lg{n}$ levels and 1 leaf. Thus:\n\n$$ T(n) = \\sum_{i=0}^{\\lg{n}-1}\\Big(\\frac{1}{4}\\Big)^i n^2 + 1\n        < n^2 \\sum_{i=0}^{\\infty}\\Big(\\frac{1}{4}\\Big)^i + 1\n        = n^2 \\frac{1}{1-1/4} + 1\n        = \\Theta(n^2)\n$$\n\nWe guess $T(n) \\le cn^2$\n$$ \\begin{aligned}\n   T(n) & \\le c(n/2)^2 + n^2 \\\\\\\\\n        & \\le cn^2/4 + n^2 \\\\\\\\\n        & \\le (c/4 + 1)n^2 \\qquad (c > 4/3) \\\\\\\\\n        & \\le cn^2\n   \\end{aligned}\n$$\n"
  },
  {
    "path": "other/clrs/04/04/03.dot",
    "content": "digraph tree {\n  node[shape=none, margin=0.0001];\n  edge[dir=none];\n\n  { rank=same;\n    a1[label=\"n\"]\n    as[label=\"n\"]\n  }\n\n  { rank=same;\n    b1[label=\"n/2 + 2\"];\n    b2[label=\"n/2 + 2\"];\n    b3[label=\"n/2 + 2\"];\n    b4[label=\"n/2 + 2\"];\n    bs[label=\"2n\"];\n  }\n\n  { rank=same;\n    c1[label=\"n/4 + 1\"];\n    c2[label=\"n/4 + 1\"];\n    c3[label=\"n/4 + 1\"];\n    c4[label=\"n/4 + 1\"];\n    c5[label=\"n/4 + 1\"];\n    c6[label=\"n/4 + 1\"];\n    c7[label=\"n/4 + 1\"];\n    c8[label=\"n/4 + 1\"];\n    c9[label=\"n/4 + 1\"];\n    c10[label=\"n/4 + 1\"];\n    c11[label=\"n/4 + 1\"];\n    c12[label=\"n/4 + 1\"];\n    c13[label=\"n/4 + 1\"];\n    c14[label=\"n/4 + 1\"];\n    c15[label=\"n/4 + 1\"];\n    c16[label=\"n/4 + 1\"];\n    cs[label=\"4n\"];\n  }\n\n  { rank=same;\n    z1[label=\"T(1)\"];\n    z2[label=\"T(1)\"];\n    z3[label=\"T(1)\"];\n    z4[label=\"T(1)\"];\n    z5[label=\"T(1)\"];\n    z6[label=\"T(1)\"];\n    z7[label=\"T(1)\"];\n    z8[label=\"T(1)\"];\n    z9[label=\"T(1)\"];\n    z10[label=\"T(1)\"];\n    z11[label=\"T(1)\"];\n    z12[label=\"T(1)\"];\n    z13[label=\"T(1)\"];\n    z14[label=\"T(1)\"];\n    z15[label=\"T(1)\"];\n    z16[label=\"T(1)\"];\n    zs[label=\"2ⁱn + 2¹⁻ⁱ\"];\n  }\n\n  a1 -> b1; a1 -> b2; a1 -> b3; a1 -> b4;\n\n  b1 -> c1;  b1 -> c2;  b1 -> c3;  b1 -> c4;\n  b2 -> c5;  b2 -> c6;  b2 -> c7;  b2 -> c8;\n  b3 -> c9;  b3 -> c10; b3 -> c11; b3 -> c12\n  b4 -> c13; b4 -> c14; b4 -> c15; b4 -> c16\n\n  { edge[style=dotted]\n    c1 -> z1;   c2 -> z2;   c3 -> z3;   c4 -> z4;\n    c5 -> z5;   c6 -> z6;   c7 -> z7;   c8 -> z8;\n    c9 -> z9;   c10 -> z10; c11 -> z11; c12 -> z12;\n    c13 -> z13; c14 -> z14; c15 -> z15; c16 -> z16;\n  }\n  { edge[style=invis]\n    as -> bs -> cs -> zs;\n  }\n}\n"
  },
  {
    "path": "other/clrs/04/04/03.markdown",
    "content": "> Use a reccursion tree to determine a good asymptotic upper bound on the\n> recurrence $T(n) = 4T(n/2 + 2) + n$. Use the substitution method to verify\n> your answer.\n\nWith some simplification, the height of the tree is $\\lg{n}$, each level adds\nup to $2^i n + 2^{1-i}$ and there are $4^{\\lg{n}} = n^2$ leaves. We get:\n\n$$ \\begin{aligned}\n   T(n) &= \\sum_{i=0}^{\\lg{n}-1}\\Big(2^i n + 2^{1-i}) + \\Theta(n^2) \\\\\\\\\n        &= \\sum_{i=0}^{\\lg{n}-1}2^i n + \\sum_{i=0}^{\\lg{n}-1}2^{1-i} + \\Theta(n^2) \\\\\\\\\n        &= \\frac{2^{\\lg{n}} - 1}{2 - 1} + 2\\sum_{i=0}^{\\lg{n}-1}\\Big(\\frac{1}{2}\\Big)^i + \\Theta(n^2) \\\\\\\\\n        &\\le n - 1 + 2\\sum_{i=0}^{\\infty}\\Big(\\frac{1}{2}\\Big)^i + \\Theta(n^2) \\\\\\\\\n        &= n - 1 + 2\\frac{1}{1-1/2} + \\Theta(n^2) \\\\\\\\\n        &= \\Theta(n^2) + n + 3 \\\\\\\\\n        &= \\Theta(n^2)\n   \\end{aligned} $$\n\nLet's substitute. We guess $T(n) \\le cn^2 + 2n$:\n$$ \\begin{aligned}\n   T(n) & \\le 4c(n/2)^2 + 2n/2 + n \\\\\\\\\n        & \\le cn^2 + 2n \\\\\\\\\n        & = \\Theta(n^2)\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/04/04/04.dot",
    "content": "digraph tree {\n  node[shape=none, margin=0.0001];\n  edge[dir=none];\n\n  { rank=same;\n    a1[label=\"1\"]\n    as[label=\"1\"]\n  }\n\n  { rank=same;\n    b1[label=\"1\"]\n    b2[label=\"1\"]\n    bs[label=\"2\"]\n  }\n\n  { rank=same;\n    c1[label=\"1\"]\n    c2[label=\"1\"]\n    c3[label=\"1\"]\n    c4[label=\"1\"]\n    cs[label=\"4\"]\n  }\n\n  { rank=same;\n    z1[label=\"T(1)\"]\n    z2[label=\"T(1)\"]\n    z3[label=\"T(1)\"]\n    z4[label=\"T(1)\"]\n    zs[label=\"2ⁱ\"]\n  }\n\n  a1 -> b1; a1 -> b2;\n\n  b1 -> c1; b1 -> c2;\n  b2 -> c3; b2 -> c4;\n\n  { edge[style=dotted];\n    c1 -> z1; c2 -> z2;\n    c3 -> z3; c4 -> z4;\n  }\n\n  { edge[style=invis];\n    as -> bs -> cs -> zs;\n  }\n}\n"
  },
  {
    "path": "other/clrs/04/04/04.markdown",
    "content": "> Use a reccursion tree to determine a good asymptotic upper bound on the\n> recurrence $T(n) = 2T(n - 1) + 1$. Use the substitution method to verify your\n> answer.\n\nThe depth is $n$, each level is $2^i$ and there are $2^n$ leaves. Thus:\n\n$$ T(n) = \\sum_{i=0}^{n-1}2^i + \\Theta(2^n)\n        = \\frac{2^n - 1}{2 - 1} + \\Theta(2^n)\n        = \\Theta(2^n) + 2^n - 1\n        = \\Theta(2^n) $$\n\nWe guess $T(n) \\le c2^n + n$. Thus:\n\n$$ \\begin{aligned}\n     T(n) & \\le 2c2^{n-1} + (n - 1) + 1 \\\\\\\\\n          & \\le c2^n + n \\\\\\\\\n          & = O(2^n)\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/04/04/05.markdown",
    "content": "> Use a reccursion tree to determine a good asymptotic upper bound on the\n> recurrence $T(n) = T(n-1) + T(n/2) + n$. Use the substitution method to\n> verify your answer.\n\nThis is a curious one. The tree makes it look like it is exponential in the\nworst case. The tree is not full (not a complete binary tree of height $n$), but\nit is not polynomial either. It's easy to show $\\Omega(n^2)$ and $O(2^n)$:\n\nWe guess $T(n) \\le c2^n - 4n$:\n\n$$ \\begin{aligned}\n   T(n) & \\le c2^{n-1} - 4(n-1) + c2^{n/2} - 4n/2 + n \\\\\\\\\n        & \\le c(2^{n-1} + 2^{n/2}) - 5n + 1 & (n > 1/4) \\\\\\\\\n        & \\le c(2^{n-1} + 2^{n/2}) - 4n & (n > 2)\\\\\\\\\n        & \\le c(2^{n-1} + 2^{n-1}) - 4n \\\\\\\\\n        & \\le c2^n - 4n \\\\\\\\\n        & = O(2^n)\n   \\end{aligned} $$\n\nWe guess $T(n) \\ge cn^2$:\n\n$$ \\begin{aligned}\n   T(n) & \\ge c(n - 1)^2 + c(n/2)^2 + n \\\\\\\\\n        & \\ge cn^2 - 2cn + 1 + cn^2/4 + n \\\\\\\\\n        & \\ge (5/4)cn^2 + (1 - 2c)n + 1 \\\\\\\\\n        & \\ge cn^2 + (1 - 2c)n + 1 & (c < 1/2)\\\\\\\\\n        & \\ge cn^2 \\\\\\\\\n        & = O(n^2)\n   \\end{aligned} $$\n\nAs to more details - I am lost.\n"
  },
  {
    "path": "other/clrs/04/04/06.markdown",
    "content": "> Argue that the solution to the recurrence $T(n) = T(n/3) + T(2n/3) + cn$,\n> where $c$ is a constant, is $\\Omega(n\\lg{n})$ by appealing to the recurrsion\n> tree.\n\nThe shortest path to a leaf has $\\log_3{n}$ levels. The cost at each level is\n$cn$.  If we cut the tree right below the first leaf, we are left with\ncomplexity of $cn\\log_3{n}$, which is $\\Omega(n\\lg{n})$.\n"
  },
  {
    "path": "other/clrs/04/04/07.dot",
    "content": "digraph tree {\n  node[shape=none, margin=0.0001];\n  edge[dir=none];\n\n  { rank=same;\n    a1[label=\"cn\"];\n    as[label=\"cn\"]\n  }\n\n  { rank=same;\n    b1[label=\"cn/2\"];\n    b2[label=\"cn/2\"];\n    b3[label=\"cn/2\"];\n    b4[label=\"cn/2\"];\n    bs[label=\"2cn\"]\n  }\n\n  { rank=same;\n    c1[label=\"cn/4\"];\n    c2[label=\"cn/4\"];\n    c3[label=\"cn/4\"];\n    c4[label=\"cn/4\"];\n    c5[label=\"cn/4\"];\n    c6[label=\"cn/4\"];\n    c7[label=\"cn/4\"];\n    c8[label=\"cn/4\"];\n    c9[label=\"cn/4\"];\n    c10[label=\"cn/4\"];\n    c11[label=\"cn/4\"];\n    c12[label=\"cn/4\"];\n    c13[label=\"cn/4\"];\n    c14[label=\"cn/4\"];\n    c15[label=\"cn/4\"];\n    c16[label=\"cn/4\"];\n    cs[label=\"4cn\"]\n  }\n\n  { rank=same;\n    z1[label=\"T(1)\"];\n    z2[label=\"T(1)\"];\n    z3[label=\"T(1)\"];\n    z4[label=\"T(1)\"];\n    z5[label=\"T(1)\"];\n    z6[label=\"T(1)\"];\n    z7[label=\"T(1)\"];\n    z8[label=\"T(1)\"];\n    z9[label=\"T(1)\"];\n    z10[label=\"T(1)\"];\n    z11[label=\"T(1)\"];\n    z12[label=\"T(1)\"];\n    z13[label=\"T(1)\"];\n    z14[label=\"T(1)\"];\n    z15[label=\"T(1)\"];\n    z16[label=\"T(1)\"];\n    zs[label=\"2ⁱcn\"]\n  }\n\n  a1 -> b1; a1 -> b2; a1 -> b3; a1 -> b4;\n\n  b1 -> c1;  b1 -> c2;  b1 -> c3;  b1 -> c4;\n  b2 -> c5;  b2 -> c6;  b2 -> c7;  b2 -> c8;\n  b3 -> c9;  b3 -> c10; b3 -> c11; b3 -> c12;\n  b4 -> c13; b4 -> c14; b4 -> c15; b4 -> c16;\n\n  { edge[style=dotted];\n    c1 -> z1;   c2 -> z2;   c3 -> z3;   c4 -> z4;\n    c5 -> z5;   c6 -> z6;   c7 -> z7;   c8 -> z8;\n    c9 -> z9;   c10 -> z10; c11 -> z11; c12 -> z12;\n    c13 -> z13; c14 -> z14; c15 -> z15; c16 -> z16;\n  }\n\n  { edge[style=invis];\n    as -> bs -> cs -> zs;\n  }\n}\n"
  },
  {
    "path": "other/clrs/04/04/07.markdown",
    "content": "> Draw the recursion tree for $T(n) = 4T(\\lfloor n/2 \\rfloor) + cn$, where $c$\n> is a constant, and provide a tight asymptotic bound on its solution. Verify\n> your answer with the substitution method.\n\nLet's ignore the floor. Previous exercises illustrate how this can be handled.\n\nThe depth of the tree is $\\lg{n}$, each level is $2^icn$ and there are\n$4^\\{\\lg{n}} = n^2$ leaves.\n\nThus:\n\n$$ T(n) = \\sum_{i=0}^{\\lg{n}- 1}2^icn + \\Theta(n^2)\n        = cn \\sum_{i=0}^{\\lg{n}-1}2^i + \\Theta(n^2)\n        = cn \\frac{2^{\\lg{n}} - 1}{2 - 1} + \\Theta(n^2)\n        = \\Theta(n^2) $$\n\nLet's guess $T(n) \\le cn^2 + 2cn$:\n\n$$ T(n) \\le 4c(n/2)^2 + 2cn/2 + cn\n        \\le cn^2 + 2cn $$\n\nLet's guess $T(n) \\ge cn^2 + 2cn$:\n\n$$ T(n) \\ge 4c(n/2)^2 + 2cn/2 + cn\n        \\ge cn^2 + 2cn $$\n"
  },
  {
    "path": "other/clrs/04/04/08.dot",
    "content": "digraph tree {\n  node[shape=none, margin=0.0001];\n  edge[dir=none];\n\n  { rank=same;\n    a1[label=\"cn\"];\n    as[label=\"cn\"];\n  }\n\n  { rank=same;\n    b1[label=\"c(n - a)\"];\n    b2[label=\"ca\"];\n    bs[label=\"cn\"];\n  }\n\n  { rank=same;\n    c1[label=\"c(n - 2a)\"];\n    c2[label=\"ca\"];\n    cs[label=\"c(n - a)\"];\n  }\n\n  { rank=same;\n    d1[label=\"c(n - 3a)\"];\n    d2[label=\"ca\"];\n    ds[label=\"c(n - 2a)\"];\n  }\n\n  { rank=same;\n    z1[label=\"c(n - ia)\"];\n    z2[label=\"ca\"];\n    zs[label=\"c(n - (i - 1)a)\"];\n  }\n\n  a1 -> b1; a1 -> b2;\n  b1 -> c1; b1 -> c2;\n  c1 -> d1; c1 -> d2;\n\n  { edge[style=dotted]; d1 -> z1; d1 -> z2; }\n  { edge[style=invis]; as -> bs -> cs -> ds -> zs; }\n}\n"
  },
  {
    "path": "other/clrs/04/04/08.markdown",
    "content": "> Use a recursion tree to give an asymptotically tight solution to the\n> recurrence $T(n) = T(n-a) + T(a) + cn$, where $a \\ge 1$ and $c > 0$ are\n> constants.\n\nThe tree height is $n/a$ and each level is $c(n-ia)$. Thus:\n\n$$ T(n) = \\sum_{i=0}^{n/a}c(n-ia) + (n/a)ca\n        = \\sum_{i=0}^{n/a}cn - \\sum_{i=0}^{n/a}cia + (n/a)ca\n        = cn^2/a - \\Theta(n) + \\Theta(n)\n        = \\Theta(n^2) $$\n\nAnother approach is:\n\n$$ \\begin{aligned}\n   T(n) &= cn + T(a) + T(n - a) + T(a) \\\\\\\\\n        &= cn + ca + c(n-a) + T(a) + T(n - 2a) \\\\\\\\\n        &= cn + c(n-a) + 2ca + c(n - 2a) + T(a) + T(n - 3a) \\\\\\\\\n        &= cn + c(n-a) + c(n - 2a) + c(n - 3a) + T(n - 4a) + 3ca + T(a) \\\\\\\\\n        &= \\frac{n(n+1)}{2a} + cn \\\\\\\\\n        &= \\Theta(n^2)\n   \\end{aligned} $$\n\nWe can guess $T(n) \\le cn^2$:\n\n$$ \\begin{aligned}\n   T(n) & \\le c(n-a)^2 + ca + cn \\\\\\\\\n        & \\le cn^2 - 2acn + ca + cn \\\\\\\\\n        & \\le cn^2 - c(2an - a - n) & (a > 1/2, n > 2a) \\\\\\\\\n        & \\le cn^2 - cn \\\\\\\\\n        & \\le cn^2 \\\\\\\\\n        & = \\Theta(n^2)\n   \\end{aligned} $$\n\nWe can guess $T(n) \\ge cn^2$:\n\n$$ \\begin{aligned}\n   T(n) & \\ge c(n-a)^2 + ca + cn \\\\\\\\\n        & \\ge cn^2 - 2acn + ca + cn \\\\\\\\\n        & \\ge cn^2 - c(2an - a - n) & (a < 1/2, n > 2a) \\\\\\\\\n        & \\ge cn^2 + cn \\\\\\\\\n        & \\ge cn^2 \\\\\\\\\n        & = \\Theta(n^2)\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/04/04/09.dot",
    "content": "digraph tree {\n  node[shape=none, margin=0.0001];\n  edge[dir=none];\n\n  { rank=same;\n    a1[label=\"cn\"];\n    as[label=\"cn\"];\n  }\n\n  { rank=same;\n    b1[label=\"cαn\"];\n    b2[label=\"c(1-α)n\"];\n    bs[label=\"cn\"];\n  }\n\n  { rank=same;\n    c1[label=\"cα²n\"];\n    c2[label=\"c(α-1)αn\"];\n    c3[label=\"cα(α-1)n\"];\n    c4[label=\"c(1-α)²n\"];\n    cs[label=\"cn\"];\n  }\n\n  { rank=same;\n    z1[label=\"T(1)\"];\n    z2[label=\"T(1)\"];\n    z3[label=\"T(1)\"];\n    z4[label=\"T(1)\"];\n    zs[label=\"cn\"];\n  }\n\n  a1 -> b1; a1 -> b2;\n\n  b1 -> c1; b1 -> c2;\n  b2 -> c3; b2 -> c4;\n\n  { edge[style=dotted]; c1 -> z1; c2 -> z2; c3 -> z3; c4 -> z4; }\n  { edge[style=invis]; as -> bs -> cs -> zs; }\n}\n"
  },
  {
    "path": "other/clrs/04/04/09.markdown",
    "content": "> Use a recursion tree to give an asymptotically tight solution to the\n> recurrence $T(n) = T(\\alpha{n}) + T((1-\\alpha)n) + cn$, where $\\alpha$ is a\n> constant in the range $0 < \\alpha < 1$, and $c > 0$ is also a constant.\n\nWe can assume that $\\alpha \\le 1/2$, since otherwise we can let $\\beta = 1 - \\alpha$\nand solve it for $\\beta$.\n\nThus, the depnth of the tree is $\\log_{1/\\alpha}n$ and each level is $cn$. The leaves\nar not obvious, but let's guess they are $\\Theta(n)$.\n\n$$ T(n) = \\sum_{i=0}^{\\log_{1/\\alpha}n}cn + \\Theta(n)\n        = cn\\log_{1/\\alpha}n + \\Theta(n)\n        = \\Theta(n\\lg{n}) $$\n\nThere is another way to show it. Let $\\beta = 1 - \\alpha$. Thus:\n\n$$ \\begin{aligned}\n   T(n) = & T(\\alpha n) + T(\\beta n) + cn \\\\\\\\\n        = & T(\\alpha^2 n) + 2T(\\alpha \\beta n) + T(\\beta^2 n) + cn + c \\alpha n  + c \\beta n \\\\\\\\\n         = & T(\\alpha^2 n) + 2T(\\alpha \\beta n) + T(\\beta^2 n) + 2cn \\\\\\\\\n         = & T(\\alpha^3 n) + T(\\alpha^2 \\beta n) + c\\alpha^2 n +\n             2T(\\alpha^2 \\beta n) + 2T(\\alpha \\beta^2 n) + 2c\\alpha\\beta n +\n             T(\\alpha \\beta^2 n) + T(\\beta ^ 3 n) + c\\beta ^ 2 n +\n             2cn\\\\\\\\\n         = & T(\\alpha^3 n) + 3T(\\alpha^2 \\beta n) + 3T(\\alpha \\beta^2 n) + T(\\beta^3 n) +\n             c \\alpha^2 n + 2c \\alpha \\beta n + c \\beta ^ 2 n + 2cn \\\\\\\\\n         = & T(\\alpha^3 n) + 3T(\\alpha^2 \\beta n) + 3T(\\alpha \\beta^2 n) + T(\\beta^3 n) + 3cn \\\\\\\\\n         = & \\ldots\n   \\end{aligned} $$\n\nThis goes until $\\alpha^kn \\le 1$, after which we have $T(n) = \\mathcal{O}(1) + ckn$.\nWell:\n\n$$ \\alpha^k = \\frac{1}{n} \\Rightarrow\n   \\log{\\alpha^k} = \\log\\frac{1}{n} \\Rightarrow\n   k\\log\\alpha = - \\log{n} \\Rightarrow\n   k = \\frac{-\\log{n}}{\\log\\alpha} = \\frac{\\log{n}}{\\log(1/\\alpha)} = \\log_{1/\\alpha}n$$\n\nLet's verify with substitution. We guess $T(n) \\le dn\\lg{n}$:\n\n$$ \\begin{aligned}\n   T(n) & \\le d \\alpha n \\lg(\\alpha n) + c \\beta n \\lg(\\beta n) + cn \\\\\\\\\n        & \\le d \\alpha n \\lg{n} + d \\beta n \\lg{n} + d \\alpha n \\lg\\alpha + d \\beta n \\lg\\beta + cn \\\\\\\\\n        & \\le d n \\lg{n} + \\big(d (\\alpha \\lg\\alpha + \\beta \\lg\\beta) + c\\big)n & (d(\\alpha\\lg\\alpha + \\beta\\lg\\beta) + c \\le 0)\\\\\\\\\n        & \\le d n \\lg{n}\n   \\end{aligned} $$\n\nIn this case:\n\n$$ d \\le -\\frac{c}{\\alpha\\lg\\alpha + (1-\\alpha)\\lg(1-\\alpha)}$$\n\nI can't proove it, but $-1 \\le \\alpha\\lg\\alpha + \\beta\\lg\\beta\\big < 0 $.\n\nAnd the other way around. We guess $T(n) \\ge dn\\lg{n}$:\n\n$$ \\begin{aligned}\n   T(n) & \\ge d \\alpha n \\lg(\\alpha n) + c \\beta n \\lg(\\beta n) + cn \\\\\\\\\n        & \\ge d \\alpha n \\lg{n} + d \\beta n \\lg{n} + d \\alpha n \\lg\\alpha + d \\beta n \\lg\\beta + cn \\\\\\\\\n        & \\ge d n \\lg{n} + \\big(d (\\alpha \\lg\\alpha + \\beta \\lg\\beta) + c\\big)n & (d(\\alpha\\lg\\alpha + \\beta\\lg\\beta) + c \\ge 0)\\\\\\\\\n        & \\ge d n \\lg{n}\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/04/05/01.markdown",
    "content": "> Use the master method to give tight asymptotic bounds for the following\n> recurrences:\n\n> 1. $T(n) = 2T(n/4) + 1$\n> 2. $T(n) = 2T(n/4) + \\sqrt{n}$\n> 3. $T(n) = 2T(n/4) + n$\n> 4. $T(n) = 2T(n/4) + n^2$\n\n1. $\\Theta(n^{\\log_4{2}}) = \\Theta(\\sqrt{n})$\n1. $\\Theta(n^{\\log_4{2}}\\lg{n}) = \\Theta(\\sqrt{n}\\lg{n})$\n1. $\\Theta(n)$\n1. $\\Theta(n^2)$\n"
  },
  {
    "path": "other/clrs/04/05/02.markdown",
    "content": "> Professor Caesar wishes to develop a matrix-multiplication algorithm that is\n> asymptotically faster than Strassen's algorithm. His algorithm will use the\n> divide-and-conquer method, dividing each matrix into pieces of size\n> $n/4 \\times n/4$, and the divide and combine steps together will take\n> $\\Theta(n^2)$ time. He needs to determine how many subproblems his algorithm\n> has to create in order to beat Strassen's algorithm. If his algorithm creates\n> $a$ subproblems, then the recurrence for the running time $T(n)$ becomes\n> $T(n) = aT(n/4) + \\Theta(n^2)$. What is the largest integer value of $a$ for\n> which Professor Caesar's algorithm would be asymptotically faster than\n> Strassen's algorithm?\n\nTo fall in third case of the master theorem, we need to have $a < 16$. In that case,\nthe algorithm will be $T(n) = \\Theta(n^2)$. For the second case, with $a = 16$, $T(n) = \\Theta(n^2 \\log n)$. In the first case of the master theorem, to be faster than Strassen, we need\n$\\log_4{a} < \\log_{2}7$, which is $a < 7^2 = 49$. Thus, the largest integer value will\nbe $48$.\n"
  },
  {
    "path": "other/clrs/04/05/03.markdown",
    "content": "> Use the master method to show that the solution to the binary-search\n> recurrence $T(n) = T(n/2) + \\Theta(1)$ is $T(n) = \\Theta(\\lg{n})$. (See\n> exercise 2.3-5 for a description of binary search).\n\n$$ a = 1, b = 2 \\\\\\\\\n   f(n) = \\Theta(n^{\\log_2{1}}) = \\Theta(1) \\\\\\\\\n   T(n) = \\Theta(\\lg{n}) $$\n"
  },
  {
    "path": "other/clrs/04/05/04.markdown",
    "content": "> Can the master method be applied to the recurrence $T(n) = 4T(n/2) + n^2\\lg{n}$?\n> Why or why not? Give an asymptotic upper bound for this recurrence.\n\nWith $a = 4, b = 2$, we have $f(n) = n^2\\lg{n} \\ne \\mathcal{O}(n^{2-\\epsilon}) \\ne \\Omega(n^{2-\\epsilon})$, so no - we cannot apply the master method.\n\nLet's guess $\\Theta(n^2\\lg^2{n})$:\n\n$$ \\begin{aligned}\n   T(n) & \\le 4T(n/2) + n^2\\lg{n} \\\\\\\\\n        & \\le 4c(n/2)^2\\lg^2(n/2) + n^2\\lg{n} \\\\\\\\\n        & \\le cn^2\\lg(n/2)\\lg{n} - cn^2\\lg(n/2)\\lg{2} + n^2\\lg{n} \\\\\\\\\n        & \\le cn^2\\lg^2{n} - cn^2\\lg{n}\\lg{2} - cn^2\\lg(n/2) + n^2\\lg{n} \\\\\\\\\n        & \\le cn^2\\lg^2{n} + (1 - c)n^2\\lg{n} - cn^2\\lg(n/2) & (c > 1) \\\\\\\\\n        & \\le cn^2\\lg^2{n} - cn^2\\lg(n/2) \\\\\\\\\n        & \\le cn^2\\lg^2{n}\n   \\end{aligned} $$\n\nExercise 4.6-2 is the general case for this.\n"
  },
  {
    "path": "other/clrs/04/05/05.markdown",
    "content": "> $\\star$ Consider the regularity condition $af(n/b) \\ge cf(n)$ for some\n> constant $c < 1$, which is part of case 3 of the master theorem. Give an\n> example of constants $a \\ge 1$ and $b > 1$ and a function $f(n)$ that\n> satisfies all the conditions in case 3 of the master theorem, except the\n> regularity condition.\n\n$$ a = 1 \\\\\\\\ b = 2 \\\\\\\\ f(n) = n(2-\\cos{n}) $$\n\nThus, if we try to proove it:\n\n$$ \\frac{n}{2}(2 - \\cos\\frac{n}{2}) < cn \\\\\\\\\n   \\frac{1 - cos(n/2)}{2} < c \\\\\\\\\n   c \\ge 1 - \\frac{cos(n/2)}{2} $$\n\nSince $\\min\\cos(n/2) = -1$, this implies that $c \\ge 3/2$. But $c < 1$.\n"
  },
  {
    "path": "other/clrs/04/06/01.markdown",
    "content": "> $\\star$ Give a simple and exact expression for $n_j$ in equation (4.27) for\n> the case in which $b$ is a positive integer instead of an arbitrary real\n> number.\n\nSome experimentation leas me to:\n\n$$ n_j = \\lceil n / b^j \\rceil $$\n\nAn [elaboration][elaboration] can be found on StackExchange.\n\n[elaboration]: http://math.stackexchange.com/questions/509862/simple-and-exact-expression-for-n-j-in-the-following-formula\n"
  },
  {
    "path": "other/clrs/04/06/02.markdown",
    "content": "> $\\star$ Show that if $f(n) = \\Theta(n^{\\log_b{a}}\\lg^k{n})$, where $k \\ge 0$,\n> then the master recurrence has solution $T(n) = \\Theta(n^{\\log_b{a}}\\lg^{k+1}n)$.\n> For simplicity, confine your analysis to exact powers of $b$.\n\n$$ g(n) = \\sum_{j=0}^{\\log_b{n}-1}a^jf(n/b^j) \\\\\\\\\n   f(n/b^j) = \\Theta\\Big((n/b^j)^{\\log_b{a}}\\lg^k(n/b^j)\\Big) \\\\\\\\\n   g(n) = \\Theta\\Big(\\sum_{j=0}^{\\log_b{n}-1}a^j\\big(\\frac{n}{b^j}\\big)^{\\log_b{a}}\\lg^k\\big(\\frac{n}{b^j}\\big)\\Big) = \\Theta(A) \\\\\\\\\n   A = \\sum_{j=0}^{\\log_b{n}-1}a^j\\big(\\frac{n}{b^j}\\big)^{\\log_b{a}}\\lg^k\\frac{n}{b^j}\n   = n^{\\log_b{a}}\\sum_{j=0}^{\\log_b{n}-1}\\Big(\\frac{a}{b^{\\log_b{a}}}\\Big)^j\\lg^k\\frac{n}{b^j}\n   = n^{\\log_b{a}}\\sum_{j=0}^{\\log_b{n}-1}\\lg^k\\frac{n}{b^j} \n   = n^{\\log_b{a}}B\\\\\\\\\n   \\lg^k\\frac{n}{d} = (\\lg{n} - \\lg{d})^k = \\lg^k{n} + o(\\lg^k{n}) \\\\\\\\\n   B = \\sum_{j=0}^{\\log_b{n}-1}\\lg^k\\frac{n}{b^j}\n     = \\sum_{j=0}^{\\log_b{n}-1}\\Big(\\lg^k{n} - o(\\lg^k{n})\\Big)\n     = \\log_b{n}\\lg^k{n} + \\log_b{n} \\cdot o(\\lg^k{n})\n     = \\Theta(\\log_b{n}\\lg^k{n})\n     = \\Theta(\\lg^{k+1}{n}) \\\\\\\\\n   g(n) = \\Theta(A) = \\Theta(n^{\\log_b{a}}B) = \\Theta(n^{\\log_b{a}}\\lg^{k+1}{n})\n   $$\n"
  },
  {
    "path": "other/clrs/04/06/03.markdown",
    "content": "> $\\star$ Show that case 3 of the master method is overstated, in the sense\n> that the regularity condition $af(n/b) \\le cf(n)$ for some constant $c < 1$\n> implies that there exists a constant $\\epsilon > 0$ such that\n> $f(n) = \\Omega(n^{\\log_b{a}+\\epsilon})$.\n\n$$ af(n/b) \\le cf(n) \\\\\\\\\n   \\alpha f(n/b) \\le f(n), \\quad \\alpha = a/c \\\\\\\\\n   \\alpha f(n) \\le f(nb) \\\\\\\\\n   \\alpha^i f(1) \\le f(b^i) \\\\\\\\\n   n = b^i \\Rightarrow i = \\log_{b}n \\Rightarrow f(n) \\ge \\alpha^{\\log_b{n}}f(1) = n^{\\log_{b}\\alpha} \\\\\\\\\n   \\alpha > a \\Rightarrow \\alpha = a + d \\quad (c < 1, d > 0) \\\\\\\\\n   \\Rightarrow f(n) = n^{\\log_b{a} + log_b{d}} = n^{\\log_b{a}+\\epsilon} \\quad (\\epsilon = \\log_{b}d) $$\n\nI did not think this up. I had [some help][help] at StackExchange.\n\n[help]: http://math.stackexchange.com/questions/510897/why-does-afn-b-cfn-for-c-1-imply-that-fn-omegan-log-ba-ep\n"
  },
  {
    "path": "other/clrs/04/problems/01.markdown",
    "content": "## Recurrence examples\n\n> Give asymptotic upper and lower bound for $T(n)$ in each of the following\n> recurrences. Assume that $T(n)$ is constant for $n \\le 2$. Make your bounds\n> as tight as possible, and justify your answers.\n>\n> 1. $T(n) = 2T(n/2) + n^4$\n> 2. $T(n) = T(7n/10) + n$\n> 3. $T(n) = 16T(n/4) + n^2$\n> 4. $T(n) = 7T(n/3) + n^2$\n> 5. $T(n) = 7T(n/2) + n^2$\n> 6. $T(n) = 2T(n/4) + \\sqrt{n}$\n> 7. $T(n) = T(n - 2) + n^2$\n\n1. $\\Theta(n^4)$ (master method)\n2. $\\Theta(n)$ (master method, $\\log_{10/7}1 = 0$)\n3. $\\Theta(n^2\\lg{n})$ (master method)\n4. $\\Theta(n^2)$ (master method)\n5. $\\Theta(n^{\\log_2{7}})$ (master method)\n6. $\\Theta(\\sqrt{n}\\lg_{n})$ (master method)\n7. $\\Theta(n^3)$ by the following:\n\n$$ \\begin{aligned}\n   T(n) &= n^2 + T(n - 2) \\\\\\\\\n   &= n^2 + (n - 2)^2 + T(n - 4) \\\\\\\\\n   &= \\sum_{i=0}^{n/2}(n -2i)^2 \\\\\\\\\n   &= n^2 \\sum_{i=0}^{n/2} 1 + 4 \\sum_{i=0}^{n/2} i^2 - 4n \\sum_{i=0}^{n/2} i \\\\\\\\\n\\end{aligned}$$\n\nFor the three sums above:\n\n$$n^2 \\sum_{i=0}^{n/2} 1 = \\frac{n^3}{2}$$\n\n$$4 \\sum_{i=0}^{n/2} i^2 = \\frac{4}{6} \\left[\\frac{n}{2}\\left(\\frac{n+2}{2}(n+1)\\right)\\right] = \\frac{1}{3}(2n^3 + 6n^2 + 4n)$$\n\n$$4n \\sum_{i=0}^{n/2} i = 4n\\left[\\frac{1}{2}\\frac{n}{2}\\left(\\frac{n+2}{2}\\right)\\right] = \\frac{1}{2}(n^3 + 2n^2)$$\n\nNow substitute back in these 3 simplifications:\n\n$$ \\begin{aligned}\n   T(n) &= n^2 \\sum_{i=0}^{n/2} 1 + 4 \\sum_{i=0}^{n/2} i^2 - 4n \\sum_{i=0}^{n/2} i \\\\\\\\\n   &= \\frac{n^3}{2} + \\frac{1}{3}(2n^3 + 6n^2 + 4n) - \\frac{1}{2}(n^3 + 2n^2) \\\\\\\\\n   &= \\frac{2}{3}n^3 + n^2 + \\frac{4}{3}n \\\\\\\\\n   &= \\Theta(n^3)\n\\end{aligned}$$\n"
  },
  {
    "path": "other/clrs/04/problems/02.markdown",
    "content": "## Parameter-passing costs\n\n> Throughout this book, we assume that parameter passing during procedure calls\n> takes constant time, even if an N-element array is being passed. This assumption\n> is valid in most systems because a pointer to the array is passed, not the array\n> itself. This problem examines the implications of three parameter-passing strategies:\n>\n> 1. An array is passed by pointer. Time $= \\Theta(1)$\n> 2. An array is passed by copying. Time $= \\Theta(N)$, where $N$ is the size of the array.\n> 3. An array is passed by copying only the subrage that might be accessed by the called\n>    procedure. Time $= \\Theta(q - p + 1)$ if the subarray $A[p \\ldots q]$ is passed.\n>\n> So:\n>\n> 1. Consider the recursive binary search algorithm for finding a number in a sorted\n>    array (see Exercise 2.3-5). Give recurrences for the worst-case running times\n>    of binary search when arrays are passed using each of the three methods above,\n>    and give good upper bounds on the solutions of the recurrences. Let $N$ be the\n>    size of the original problems and $n$ be the size of a subproblem.\n> 2. Redo part (a) for the MERGE-SORT algorithm from Section 2.3.1.\n\n### Binary search\n\n1. $T(n) = T(n/2) + c = \\Theta(\\lg{n})$ (master method)\n2. $T(n) = T(n/2) + cN = 2cN + T(n/4) = 3cN + T(n/8) = \\sum_{i=0}^{\\lg{n}-1}(2^icN/2^i) = cN\\lg{n} = \\Theta(n\\lg{n})$\n3. $T(n) = T(n/2) + cn = \\Theta(n)$ (master method)\n\n### Merge sort\n\n1. $T(n) = 2T(n/2) + cn = \\Theta(n\\lg{n})$ (master method, duh)\n2. $T(n) = 2T(n/2) + cn + 2N = 4N + cn + 2c(n/2) + 4T(n/4) = 8N + 2cn + 4c(n/4) + 8T(n/8) = \\\\\\\\ \\qquad\n         = \\sum_{i=0}^{\\lg{n}-1}(cn + 2^iN)\n         = \\sum_{i=0}^{\\lg{n}-1}cn + N\\sum_{i=0}^{\\lg{n}-1}2^i\n         = cn\\lg{n} + N\\frac{2^{\\lg{n}} - 1}{2-1}\n         = cn\\lg{n} + nN - N\n         = \\Theta(nN) \\\\\\\\ \\qquad\n         = \\Theta(n^2) $\n3. $T(n) = 2T(n/2) + cn + 2n/2 = 2T(n/2) + (c+1)n = \\Theta(n\\lg{n})$ (master method)\n"
  },
  {
    "path": "other/clrs/04/problems/03.markdown",
    "content": "## More recurrence examples\n\n> Give asymptotic upper and lower bounds for $T(n)$ in each of the following\n> recurrences. Assume that $T(n)$ is constant for sufficiently small $n$. Make\n> your bounds as tight as possible, and justify your answers.\n>\n> 1. $T(n) = 4T(n/3) + n\\lg{n}$\n> 2. $T(n) = 3T(n/3) + n/\\lg{n}$\n> 3. $T(n) = 4T(n/2) + n^2\\sqrt{n}$\n> 4. $T(n) = 3T(n/3 - 2) + n/2$\n> 5. $T(n) = 2T(n/2) + n/\\lg{n}$\n> 6. $T(n) = T(n/2) + T(n/4) + T(n/8) + n$\n> 7. $T(n) = T(n - 1) + 1/n$\n> 8. $T(n) = T(n - 1) + \\lg{n}$\n> 9. $T(n) = T(n - 2) + 1/\\lg{n}$\n> 10. $T(n) = \\sqrt{n}T(\\sqrt{n}) + n$\n\n### 1. $T(n) = 4T(n/3) + n\\lg{n}$\n\n$\\Theta(n^{\\log_3{4}})$ by the master method.\n\n### 2. $T(n) = 3T(n/3) + n/\\lg{n}$\n\nIt's $\\Theta(n\\lg\\lg{n})$. Check subtask 5 for the reasoning.\n\n### 3. $T(n) = 4T(n/2) + n^2\\sqrt{n}$\n\n$\\Theta(n^2\\sqrt{n}) = \\Theta(n^{2.5})$ by the master method ($\\log_2{4} = 2 < 2.5$).\n\n### 4. $T(n) = 3T(n/3 - 2) + n/2$\n\nWe can ignore the $-2$ and using the master method, we arrive at $\\Theta(n\\lg{n})$.\n\n### 5. $T(n) = 2T(n/2) + n/\\lg{n}$\n\n$$ \\begin{aligned}\n   T(n) & = 2T(n/2) + \\frac{n}{\\lg{n}} = 4(n/4) + 2\\frac{n/2}{\\lg(n/2)} + \\frac{n}{\\lg{n}}\n          = 4T(n/4) + \\frac{n}{\\lg{n} - 1} + \\frac{n}{\\lg{n}} \\\\\\\\\n        & = nT(1) + \\sum_{i=0}^{\\lg{n} - 1}\\frac{n}{\\lg{n}-i}\n          = nT(1) + n\\sum_{i=1}^{\\lg{n}}\\frac{1}{\\lg{n}} \\\\\\\\\n        & = \\Theta(n\\lg\\lg{n})\n   \\end{aligned} $$\n\n### 6. $T(n) = T(n/2) + T(n/4) + T(n/8) + n$\n\nWe guess $\\Theta(n)$:\n\n$$ \\begin{aligned}\n   T(n) & = cn/2 + cn/4 + cn/8 + n \\le (7/8)cn + n \\le cn = O(n) \\quad (c \\ge 8) \\\\\\\\\n   T(n) & = cn/2 + cn/4 + cn/8 + n \\ge (7/8)cn + n \\ge cn = \\Omega(n) \\quad (c \\le 8)\n   \\end{aligned} $$\n\n### 7. $T(n) = T(n - 1) + 1/n$\n\n$$ \\begin{aligned}\n   T(n) &= T(n-1) + 1/n = \\frac{1}{n} + \\frac{1}{n-1} + T(n-2) \\\\\\\\\n        &= \\frac{1}{n} + \\frac{1}{n-1} + \\frac{1}{n-2} + T(n-3) \\\\\\\\\n        &= \\sum_{i=0}^{n-1}\\frac{1}{n-i} = \\sum_{i=1}^n\\frac{1}{i} = \\\\\\\\\n        &= \\Theta(\\lg{n})\n   \\end{aligned} $$\n\n### 8. $T(n) = T(n - 1) + \\lg{n}$\n\n$$ \\begin{aligned}\n   T(n) &= \\lg{n} + T(n-1) = \\lg{n} + \\lg{n-1} + T(n-2) = \\\\\\\\\n        &= \\sum_{i=0}^{n-1}\\lg(n - i) = \\sum_{i=1}^{n}\\lg{i} = \\lg(n!) \\le \\lg{n^n} = n\\lg{n} \\\\\\\\\n        &= \\Theta(n\\lg{n})\n   \\end{aligned} $$\n\n### 9. $T(n) = T(n - 2) + 1/\\lg{n}$\n\n$$ \\begin{aligned}\n   T(n) &= \\frac{1}{\\lg{n}} + \\frac{1}{\\lg{n-2}} + \\ldots \\\\\\\\\n        &= \\sum_{i=1}^{n/2}\\frac{1}{\\lg(2i)} \\\\\\\\\n        &= \\sum_{i=1}^{\\infty}\\frac{1}{\\lg{i}} \\\\\\\\\n        &= \\Theta(\\lg\\lg{n})\n   \\end{aligned} $$\n\n### 10. $T(n) = \\sqrt{n}T(\\sqrt{n}) + n$\n\nLet $n = 2^m$, or $m = \\lg{n}$. We use this to get another recurrence in hopes of being able to use the master theorem on it:\n\n$$ \\begin{aligned}\n   T(2^m) &= \\sqrt{2^m}T(\\sqrt{2^m}) + 2^m \\\\\\\\\n        &= 2^{m/2}T(2^{m/2}) + 2^m \\\\\\\\\n   Q(m) &= 2^{m/2} Q(m/2) + 2^m\n\\end{aligned} $$\n\nWe still cannot use the master theorem. Now multiply $Q(m)$ by $\\frac{1}{2^m}$ to get: $R(m) = R(m/2) + 1$. Now we can use the master theorem to compare $f(n) = 1$ and $n^{log_b a} = n^{log_2 1} = n^0 = 1$. Since $n^{log_b a} = f(n)$:\n\n$$ \\begin{aligned}\n   R(m) &= \\Theta(1 \\times \\lg{m}) \\\\\\\\\n   Q(m) &= \\Theta(2^m \\lg{m}) \\\\\\\\\n   T(m) &= \\Theta(2^{\\lg{n}} \\lg{\\lg{n}}) \\\\\\\\\n        & = \\Theta(n \\lg{\\lg{n}})\n\\end{aligned}$$\n\nWe verify $T(n) \\le cn\\lg\\lg{n}$:\n\n$$ \\begin{aligned}\n   T(n) &\\le \\sqrt{n}c\\sqrt{n}\\lg\\lg\\sqrt{n} + n \\\\\\\\\n        & = cn\\lg\\lg\\sqrt{n} + n \\\\\\\\\n        & = cn\\lg\\frac{\\lg{n}}{2} + n \\\\\\\\\n        & = cn\\lg\\lg{n} - cn\\lg{2} + n \\\\\\\\\n        & = cn\\lg\\lg{n} + (1 - c)n & (c > 1) \\\\\\\\\n        &\\le cn\\lg\\lg{n}\n        & = \\Theta(n\\lg\\lg{n})\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/04/problems/04.markdown",
    "content": "## Fibonacci numbers\n\n> This problem develops properties of the Fibonacci numbers, which are defined\n> by recurrence (3.22). We shall use the technique of generating functions to\n> solve the Fibonacci recurrence. Define the generating function (or formal\n> power series) $\\mathcal{F}$ as\n>\n> $$ \\begin{aligned}\n>    \\mathcal{F}(z) &= \\sum_{i=0}^{\\infty}F_iz^i \\\\\\\\\n>                   &= 0 + z + z^2 + 2z^3 + 3z^4 + 5z^5 + 8z^6 + 13z^7 + 21z^8 + \\ldots,\n>    \\end{aligned} $$\n>\n> where $F_i$ is the $i$th Fibonacci number.\n>\n> 1. Show that $\\mathcal{F}(z) = z + z\\mathcal{F}(z) + z^2\\mathcal{F}$.\n> 2. Show that\n>    $$ \\begin{aligned}\n>       \\mathcal{F}(z) &= \\frac{z}{1 - z - z^2} \\\\\\\\\n>                      &= \\frac{z}{(1 - \\phi z)(1 - \\hat\\phi z)} \\\\\\\\\n>                      &= \\frac{1}{\\sqrt5}\\Big(\\frac{1}{1 - \\phi z} - \\frac{1}{1 - \\hat{\\phi} z}\\Big)\n>       \\end{aligned} $$\n>    where\n>    $$ \\phi = \\frac{1 + \\sqrt5}{2} = 1.61803\\ldots \\\\\\\\\n>       \\hat\\phi = \\frac{1 - \\sqrt5}{2} = -0.61803\\ldots $$\n> 3. Show that\n>    $$ \\mathcal{F}(z) = \\sum_{i=0}^{\\infty}\\frac{1}{\\sqrt5}(\\phi^i - \\hat{\\phi}^i)z^i $$\n> 4. Use part (c) to prove that $F_i = \\phi^i / \\sqrt5$ for $i > 0$, rounded to the nearest\n>    integer. (_Hint:_ Observe that <nobr>$|\\hat{\\phi}| < 1$)</nobr>\n\n### Part 1\n\n$$ \\begin{aligned}\n   & z + z\\mathcal{F}(z) + z^2\\mathcal{F}(Z) = \\\\\\\\\n   & = z + z\\sum_{i=0}^{\\infty}F_iz^i + z^2\\sum_{i=0}^{\\infty}F_iz^i \\\\\\\\\n   & = z + \\sum_{i=1}^{\\infty}F_{i-1}z^i + \\sum_{i=2}^{\\infty}F_{i-2}z^i \\\\\\\\\n   & = z + F_1z + \\sum_{i=2}^{\\infty}(F_{i-1} + F_{i-2})z^i \\\\\\\\\n   & = z + F_1z + \\sum_{i=2}^{\\infty}F_iz^i \\\\\\\\\n   & = \\mathcal{F}(z)\n   \\end{aligned} $$\n\n### Part 2\n\nLet's just note that $\\phi - \\hat\\phi = \\sqrt5$,  $\\phi + \\hat\\phi = 1$ and $\\phi\\hat\\phi = - 1$ (just calculate them):\n\n$$ \\begin{aligned}\n   \\mathcal{F}(z) &= \\frac{\\mathcal{F}(z)(1 - z - z^2)}{1 - z - z^2} \\\\\\\\\n        &= \\frac{\\mathcal{F}(z) - z\\mathcal{F}(z) - z^2\\mathcal{F}(z) - z + z}{1 - z - z^2} \\\\\\\\\n        &= \\frac{\\mathcal{F}(z) - \\mathcal{F}(z) + z}{1 - z - z^2} \\\\\\\\\n        &= \\frac{z}{1 - z - z^2} \\\\\\\\\n        &= \\frac{z}{1 - (\\phi + \\hat\\phi)z + \\phi\\hat\\phi z^2} \\\\\\\\\n        &= \\frac{z}{(1 - \\phi z)(1 - \\hat\\phi z)} \\\\\\\\\n        &= \\frac{\\sqrt5 z}{\\sqrt5 (1 - \\phi z)(1 - \\hat\\phi z)} \\\\\\\\\n        &= \\frac{(\\phi - \\hat\\phi)z + 1 - 1}{\\sqrt5 (1 - \\phi z)(1 - \\hat\\phi z)} \\\\\\\\\n        &= \\frac{(1 - \\hat\\phi z) - (1 - \\phi z)}{\\sqrt5 (1 - \\phi z)(1 - \\hat\\phi z)} \\\\\\\\\n        &= \\frac{1}{\\sqrt5}\\Big(\\frac{1}{1 - \\phi z} - \\frac{1}{1 - \\hat\\phi z}\\Big) \\\\\\\\\n   \\end{aligned} $$\n\n### Part 3\n\nWe have that:\n\n$$ \\frac{1}{1 - x} = \\sum_{k=0}^{\\infty}x^k \\quad\\text{when } |x| < 1 $$\n\nThus:\n\n$$ \\begin{aligned}\n   \\mathcal{F}(n) &= \\frac{1}{\\sqrt5}\\Big(\\frac{1}{1 - \\phi z} - \\frac{1}{1 - \\hat\\phi z}\\Big) \\\\\\\\\n                  &= \\frac{1}{\\sqrt5}\\Big(\\sum_{i=0}^{\\infty}\\phi^i z^i - \\sum_{i=0}^{\\infty}\\hat{\\phi}^i z^i\\Big) \\\\\\\\\n                  &= \\sum_{i=0}^{\\infty}\\frac{1}{\\sqrt5}(\\phi^i - \\hat{\\phi}^i) z^i\n   \\end{aligned} $$\n\n### Part 4\n\n$$ \\mathcal{F}(z) = \\sum_{i=0}^{\\infty}\\alpha_iz^i \\quad\\text{ where } \\alpha_i = \\frac{\\phi^i - \\hat{\\phi}^i}{\\sqrt5} $$\n\nFrom this follows that $\\alpha_i = F_i$, that is:\n\n$$ F_i = \\frac{\\phi^i - \\hat{\\phi}^i}{\\sqrt5}  = \\frac{\\phi^i}{\\sqrt5} - \\frac{\\hat{\\phi}^i}{\\sqrt5} $$\n\nFor $i = 0$, $\\phi/\\sqrt5 = (\\sqrt5 + 5)/10 > 0.5$. For $i > 2$, $|\\hat{\\phi}^i| < 0.5$.\n"
  },
  {
    "path": "other/clrs/04/problems/05.markdown",
    "content": "## Chip testing\n\n> Professor Diogenes has $n$ supposedly identical integrated-circuit chips that\n> in principle are capable of testing each other. The professor's test jig\n> accomodates two chips at a time. When the jig is loaded, each chip tests the\n> other and reports whether it is good or bad. A good chip always reports\n> accurately whether the other chip is good or bad, but the professor cannot\n> trust the answer of a bad chip. Thus, the four possible outcomes of a test\n> are as follows.\n>\n> | Chip A says | Chip B says | Conclusion                     |\n> |:------------|:------------|:-------------------------------|\n> | B is good   | A is good   | both are good, or both are bad |\n> | B is good   | A is bad    | at least one is bad            |\n> | B is bad    | A is good   | at least one is bad            |\n> | B is bad    | A is bad    | at least one is bad            |\n>\n> 1. Show that if more than $n/2$ chips are bad, the professor cannot\n>    necessarily determine which chips are good using any strategy based on\n>    this kind of pairwise test. Assume that the bad chips can conspire to fool\n>    the professor.\n> 2. Consider the problem of finding a single good chip from among $n$ chips,\n>    assuming that more than $n/2$ of the chips are good. Show that $\\lfloor\n>    n/2 \\rfloor$ pairwise tests are sufficient to reduce the problem to one of\n>    nearly half the size.\n> 3. Show that the good chips can be identified with $\\Theta(n)$ pairwise\n>    tests, assuming that more than $n/2$ chips are good. Give and solve the\n>    recurrence that describes the number of tests.\n\n### If more than half are bad\n\nLets say that there are $g < n/2$ good chips. The same amount of the remaining\nbad chips can choose to act similar to good chips. That is, they can identify\neach other as good and all other as faulty. Since this is what the good chips\nwould do, both groups are symmetric in regards to the operation of parwise\ncomparison. No strategy can distinguish between the two groups.\n\n### Finding a single good chip in logarithmic time\n\nWe split the chips in groups of two and compare them. We can take one of the\nchips if the outcome is the first one (both are good or both are bad) and but\nboth away otherwise. When putting away, we're removing at least one bad chip\nfor every good one we remove. Out of the pairs we've chosen a chip from, there\nwould be more good chips than bad chips (there would be more good pairs,\nbecause the good chips are more than the half). Now we have at most $n/2$\nchips, where at least half of them are good.\n\n### Finding the good chips\n\nThe recurrence for finding at least one good chip is:\n\n$$ T(n) = T(n/2) + n/2 $$\n\nBy the master method, this is $\\Theta(n)$. After we've found one, we can\ncompare it will all others, which is a $\\Theta(n)$ operation.\n"
  },
  {
    "path": "other/clrs/04/problems/05.py",
    "content": "import random\n\nclass GoodChip:\n    def good(self):\n        return True\n\n    def check(self, other):\n        return other.good()\n\nclass BadChip:\n    def good(self):\n        return False\n\n    def check(self, other):\n        return [True, False][random.randint(0, 1)]\n\ndef jig(a, b):\n    return [a.check(b), b.check(a)]\n\ndef diogenes(chips, verbose = False):\n    def find_single(chips):\n        if len(chips) <= 2:\n            return chips[0]\n        else:\n            halfpoint = len(chips) // 2\n            pairs     = zip(chips[0:halfpoint], chips[halfpoint:halfpoint * 2])\n            kept      = [a for (a, b) in pairs if jig(a, b) == [True, True]]\n\n            if len(chips) % 2 == 1:\n                kept.append(chips[-1])\n\n            return find_single(kept)\n\n    good = find_single(chips)\n    return [chip for chip in chips if jig(good, chip) == [True, True]]\n"
  },
  {
    "path": "other/clrs/04/problems/05.test.py",
    "content": "import unittest\nimport random\nimport os.path as path\nimport random\nimport time\n\nfilename = path.join(path.dirname(__file__), '05.py')\nexec(open(filename).read())\n\nrandom.seed(1)\n\ndef generate_chips(count):\n    good = [GoodChip() for _ in range(random.randint(count // 2 + 1, 3 * count // 4 + 1))]\n    bad  = [BadChip() for _ in range(count - len(good))]\n    chips = good + bad\n    random.shuffle(chips)\n\n    return chips\n\nclass DiogenesTest(unittest.TestCase):\n    def test_correctness(self):\n        for n in range(100):\n            chips = generate_chips(random.randint(1, 1000))\n            good = diogenes(chips, n == 155)\n            good_count = sum(1 for chip in chips if chip.good())\n            self.assertTrue(good_count == len(good))\n            self.assertTrue(all(chip.good for chip in good))\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/04/problems/06.c",
    "content": "typedef struct array {\n    int m;\n    int n;\n    int step;\n    int *data;\n} array;\n\nint get(array A, int i, int j) {\n    return A.data[((i + 1) * A.step - 1) * A.n + j];\n}\n\narray half(array a) {\n    array result = { a.m, a.n, a.step * 2, a.data };\n    return result;\n}\n\nint height(array array) {\n    return array.m / array.step;\n}\n\nint min_index(array A, int row, int left, int right) {\n    int min = left;\n\n    for (int i = left; i < right; i++) {\n        if (get(A, row, i) < get(A, row, min)) {\n            min = i;\n        }\n    }\n\n    return min;\n}\n\nvoid find_minimums(array A, int *mins) {\n    if (height(A) == 1) {\n        mins[0] = min_index(A, 0, 0, A.n);\n    } else {\n        array evens = half(A);\n        int even_minimums[height(evens)];\n\n        find_minimums(evens, even_minimums);\n\n        int leftmost = 0;\n\n        for (int i = 0; i < height(evens); i++) {\n            leftmost = min_index(A, 2 * i, leftmost, even_minimums[i] + 1);\n\n            mins[2 * i]     = leftmost;\n            mins[2 * i + 1] = even_minimums[i];\n        }\n\n        if (height(A) % 2) {\n            mins[height(A) - 1] = min_index(A, height(A) - 1, leftmost, A.n);\n        }\n    }\n}\n"
  },
  {
    "path": "other/clrs/04/problems/06.markdown",
    "content": "## Monge arrays\n\n> An $m \\times n$ array $A$ of real numbers is a ***Monge array*** if for all\n> $i$, $j$, $k$, and $l$ such that $1 \\le i < k \\le m$ and $1 \\le j < l \\le n$,\n> we have\n>\n> $$ A[i, j] + a[k, l] \\le A[i, l] + A[k, j] $$\n>\n> In other words, whenever we pick two rows and two columns of a Monge array\n> and consider the four elements at the intersections of the rows and columns,\n> the sum of the upper-left and lower-right elements is less than or equal to\n> the sum of the lower-left and upper-right elements. For example, the\n> following array is Monge:\n>\n> $$ \\begin{matrix}\n>    10 & 17 & 13 & 28 & 23 \\\\\\\\\n>    17 & 22 & 16 & 29 & 23 \\\\\\\\\n>    24 & 28 & 22 & 34 & 24 \\\\\\\\\n>    11 & 13 &  6 & 17 &  7 \\\\\\\\\n>    45 & 44 & 32 & 37 & 23 \\\\\\\\\n>    36 & 33 & 19 & 21 &  6 \\\\\\\\\n>    75 & 66 & 51 & 53 & 34\n>    \\end{matrix} $$\n>\n> 1. Prove that an array is Monge if and only i for all $i = 1,2,\\ldots, m-1$,\n>    and $j = 1,2,\\ldots,n-1$ we have\n>    $$ A[i,j] + A[i+1,j+1] \\le A[i,j+1] + A[i+1,j] $$\n>    (Hint: For the \"if\" part, use induction seperately on rows and columns)\n>\n> 2. The following array is not Monge. Change one element in order to make it\n>    Monge. (Hint: Use part (a).)\n>    $$ \\begin{matrix}\n>       37 & 23 & 22 & 32 \\\\\\\\\n>       21 &  6 &  7 & 10 \\\\\\\\\n>       53 & 34 & 30 & 31 \\\\\\\\\n>       32 & 13 &  9 &  6 \\\\\\\\\n>       43 & 21 & 15 &  8 \\\\\\\\\n>       \\end{matrix} $$\n>\n> 3. Let $f(i)$ be the index of the column containing the leftmost minimum\n>    element of the row $i$. Prove that $f(1) \\le f(2) \\le \\dots f(m)$ for\n>    any $m \\times n$ Monge array.\n>\n> 4. Here is a description of a divide-and-conquer algorithm that computes the\n>    leftmost minimum element in each row of an $m \\times n$ Monge array $A$:\n>\n>    > Construct a submatrix $A'$ of $A$ consisting of the even-numbered rows\n>    > of $A$. Recursively determine the leftmost minimum for each row in $A'$.\n>    > Then compute the leftmost minimum in the odd-numbered rows of $A$.\n>\n>    Explain how to compute the leftmost minimum in the odd-numbered rows of\n>    $A$ (given that the leftmost minimum of the even-numbered rows is known)\n>    in $O(m+n)$ time.\n>\n> 5. Write the recurrence describing the running time of the algorithm described\n>    in part (d). Show that its solution is $O(m + n\\log{m})$.\n\n### Part one\n\nThe \"only if\" part is trivial -- it follows form the definition of Monge array.\n\nAs for the \"if\" part, let's first prove that:\n\n$$ A[i,j] + A[i+1, j+1] \\le A[i,j+1] + A[i+1, j] \\\\\\\\\n   \\Downarrow \\\\\\\\\n   A[i,j] + A[k, j+1] \\le A[i, j+1] + A[k,j] $$\n\nWhere $i < k$.\n\nLet's prove it by induction. The base case of $k = i + 1$ is given. As for the\ninductive step, we assume it holds for $k = i + n$ and we want to prove it for\n$k + 1= i + n + 1$. If we add the given to the assumption, we get:\n\n$$\n   A[i, j] + A[k, j+1] \\le A[i, j+1] + A[k, j] \\quad (assumption) \\\\\\\\\n   A[k, j] + A[k+1, j+1] \\le A[k, j+1] + A[k+1, j] \\quad (given) \\\\\\\\\n   \\Downarrow \\\\\\\\\n   A[i, j] + A[k, j+1] + A[k, j] + A[k+1, j+1] \\le\n   A[i, j+1] + A[k, j] + A[k, j+1] + A[k+1, j] \\\\\\\\\n   \\Downarrow \\\\\\\\\n   A[i, j] + A[k+1, j+1] \\le A[i, j+1] + A[k+1, j]\n   $$\n\n### Part two\n\n$$ \\begin{matrix}\n   37 & 23 & \\mathbf{24} & 32 \\\\\\\\\n   21 &  6 &  7 & 10 \\\\\\\\\n   53 & 34 & 30 & 31 \\\\\\\\\n   32 & 13 &  9 &  6 \\\\\\\\\n   43 & 21 & 15 &  8 \\\\\\\\\n   \\end{matrix} $$\n\n### Part three\n\nLet $a_i$ and $b_j$ be the leftmost minimal elements on rows $a$ and $b$ and\nlet's assume that $i > j$. Then we have:\n\n$$ A[j, a] + A[i, b] \\le A[i, a] + A[j, b] $$\n\nBut:\n\n$$ \\begin{aligned}\n   & A[j, a] \\ge A[i, a] & (a_i \\text{ is minimal}) \\\\\\\\\n   & A[i, b] \\ge A[j, b] & (b_j \\text{ is minimal}) \\\\\\\\\n   \\end{aligned} $$\n\nWhich implies that:\n\n$$ A[j, a] + A[i, b] \\ge A[i, a] + A[j, b] \\\\\\\\\n   \\Downarrow \\\\\\\\\n   A[j, a] + A[i, b] = A[i, a] + A[j, b] $$\n\nWhich in turn implies that either:\n\n$$ \\begin{aligned}\n   &A[j, b] < A[i, b] \\Rightarrow A[i, a] > A[j, a] && \\Rightarrow a_i \\text{ is not minimal} \\\\\\\\\n   &A[j, b] = A[i, b] && \\Rightarrow b_j \\text{ is not the leftmost minimal}\n   \\end{aligned} $$\n\n### Part four\n\nIf $\\mu_i$ is the index of the $i$-th row's leftmost minimum, then we have:\n\n$$ \\mu_{i-1} \\le \\mu_i \\le \\mu_{i+1} $$\n\nFor $i = 2k + 1$, $k \\ge 0$, finding $\\mu_i$ takes $\\mu_{i+1}-\\mu_{i-1} + 1$\nsteps at most, since we only need to compare with those numbers. Thus:\n\n$$ \\begin{aligned}\n   T(m, n) &= \\sum_{i=0}^{m/2-1}\\Big(\\mu_{2i + 2} - \\mu_{2i} + 1\\Big) \\\\\\\\\n           &= \\sum_{i=0}^{m/2-1}\\mu_{2i+2} - \\sum_{i=0}^{m/2-1}\\mu_{2i} + m/2 \\\\\\\\\n           &= \\sum_{i=1}^{m/2}\\mu{2i} - \\sum_{i=0}^{m/2-1}\\mu{2i} + m/2 \\\\\\\\\n           &= \\mu_m - \\mu_0 + m/2 \\\\\\\\\n           &= n + m/2 \\\\\\\\\n           &= O(m + n)\n   \\end{aligned} $$\n\n### Part five\n\nThe divide time is $O(1)$, the conquer part is $T(m/2)$ and the merge part is\n$O(m+n)$. Thus:\n\n$$ \\begin{aligned}\n   T(m) &= T(m/2) + cn + dm \\\\\\\\\n        &= cn + dm + cn + dm/2 + cn + dm/4 + \\ldots \\\\\\\\\n        &= \\sum_{i=0}^{\\lg{m}-1}cn + \\sum_{i=0}^{\\lg{m}-1}\\frac{dm}{2^i} \\\\\\\\\n        &= cn\\lg{m} + dm\\sum_{i=0}^{\\lg{m} - 1} \\\\\\\\\n        &< cn\\lg{m} + 2dm \\\\\\\\\n        &= O(n\\lg{m} + m)\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/04/problems/06.test.c",
    "content": "#include \"06.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(large_example) {\n    int data[] = {10, 17, 13, 28, 23,\n                  17, 22, 16, 29, 23,\n                  24, 28, 22, 34, 24,\n                  11, 13,  6, 17,  7,\n                  45, 44, 32, 37, 23,\n                  36, 33, 19, 21,  6,\n                  75, 66, 51, 53, 34},\n        expected[7] = {0, 2, 2, 2, 4, 4, 4},\n        actual[7];\n    array A = { 7, 5, 1, data };\n\n    find_minimums(A, actual);\n    ASSERT_SAME_ARRAYS(actual, expected);\n}\n\nTEST(small_example) {\n    int data[] = {37, 23, 24, 32,\n                  21,  6,  7, 10,\n                  53, 34, 30, 31,\n                  32, 13,  9,  6,\n                  43, 21, 15,  8},\n        expected[5] = {1, 1, 2, 3, 3},\n        actual[5];\n    array A = { 5, 4, 1, data };\n\n    find_minimums(A, actual);\n    ASSERT_SAME_ARRAYS(actual, expected);\n}\n\n"
  },
  {
    "path": "other/clrs/05/01/01.markdown",
    "content": "> Show that the assumption that we are always able to determine which candidate\n> is best, in line 4 of procedure `HIRE-ASSISTANT`, implies that we know a\n> total order of the ranks of the candidates.\n\nA total order is a partial order that is a total relation ($\\forall a,b \\in A:\na R b \\text{ or } b R a$). A relation is a partial order if it is reflexive,\nantisymmetric and transitive.\n\nLet's assume that the relation is \"is as good or better\".\n\n* _Reflexive_: This is a bit trivial, but everybody is as good or better as\n  themselves.\n* _Transitive_: If A is better than B and B is better than C, then A is better\n  than C - that's also obvious.\n* _Antisymmetric_: If A is better than B, then B is not better than A.\n\nSo far we have a partial order.\n\nSince we assume we can compare any two candidates, then comparison must be a\ntotal relation and thus we have a total order.\n"
  },
  {
    "path": "other/clrs/05/01/02.markdown",
    "content": "> $\\star$ Describe an implementation of the procedure `RANDOM(a,b)` that only\n> makes calls to `RANDOM(0,1)`. What is the expected running time of your\n> procedure as a function of $a$ and $b$?\n\nLet $n = b - a$. The algorithm is as follows:\n\n1. We find the smallest integer $c$ such that $2^c \\ge n$ ($c = \\lceil \\ln{n} \\rceil$)\n2. We call `RANDOM(0, 1)` $c$ times to and get a $c$-digit binary number $r$\n3. If $r > n$ we go back to the previous step\n4. Otherwise we return $a + r$\n\nThis produces a uniformly random number in that range. However, there is a\npossibility to have to repeat step 2. There is $p = n/2^c$ chance of not having\nto repeat step two. The geometric distribution suggests that on average it\ntakes $1/p$ trials before we get such a number, that is $2^c/n$ trials. Since\nwe perform $c$ calls to `RANDOM(0, 1)` on each trial, the expected running time\nis\n\n$$ \\O\\bigg(\\frac{2^c}{n} c\\bigg) = \\O\\bigg(\\frac{\\ln(b-a)2^{\\ln(b-a)}}{b-a}\\bigg)\n                                 = \\O(\\ln(b-a)) $$\n"
  },
  {
    "path": "other/clrs/05/01/03.markdown",
    "content": "> $\\star$ Suppose that you want to output $0$ with probability $1/2$ and 1 with\n> probability $1/2$. At your disposal is a procedure `BIASED-RANDOM` that\n> outputs either $0$ or $1$. It outputs $1$ with some probability $p$ and $0$\n> with probability $1 - p$, where $0 < p < 1$, but you don't now what $p$ is.\n> Give an algorithm that uses `BIASED-RANDOM` as a subroutine, and returns an\n> unbiased answer, returning $0$ with probability $1/2$ and $1$ with\n> probability $1/2$. What is the expected running time of your algorithm as a\n> function of $p$?\n\nSimple!\n\n1. Generate two random numbers $x$ and $y$\n2. If they are not the same, return $x$\n3. Otherwise, repeat from step 1\n\nThe change of getting [0, 1] is the same as getting [1, 0].\n\nThe likelyhood of that happening is $2pq$. Thus, the expected number of trials\nis $1/(2pq)$ making the running time $\\O\\Big(\\frac{1}{p(1-p)}\\Big)$.\n"
  },
  {
    "path": "other/clrs/05/02/01.markdown",
    "content": "> In `HIRE-ASSISTANT`, assuming that the candidates are presented in a random\n> order, what is the probability that you hire exactly one time? What is the\n> probability you hire exactly $n$ times?\n\nYou hire once when the best candidate is first. There is $1/n$ chance of that\nhappening ($n!$ positions in $(n-1)!$ of which they are first).\n\nYou hire $n$ times when the candidates come in increasing order, which is\n$1/n!$.\n"
  },
  {
    "path": "other/clrs/05/02/02.markdown",
    "content": "> In `HIRE-ASSISTANT`, assuming that the candidates are presented in a random\n> order, what is the probability that you hire exactly twice?\n\nYou hire twice when you first hire is the candidate with rank $i$ and all the\ncandidates with rank $k > i$ come after the candidate with rank $n$. There\nare $n - i$ better suited candidates and the probability of the best one\ncoming first is $1/(n-i)$ (we can ignore the other candidates and they don't\naffect the probability). Thus, the probability for hiring twice if your first\ncandidate has rank $i$ is:\n\n$$ \\Pr\\\\{T_i\\\\} = \\frac{1}{n}\\frac{1}{n-i} $$\n\nThe first part reflects the probability of picking that particular candidate\nout of $n$.\n\nThe probability to hire twice is:\n\n$$ \\Pr\\\\{T\\\\} = \\sum_{i=1}^{n-1}\\Pr\\\\{T_i\\\\}\n              = \\sum_{i=1}^{n-1}\\frac{1}{n}\\frac{1}{n-i}\n              = \\frac{1}{n} \\sum_{i=1}^{n-1}\\frac{1}{i}\n              = \\frac{1}{n} \\Big(\\lg(n-1) + \\O(1)\\Big) $$\n"
  },
  {
    "path": "other/clrs/05/02/03.markdown",
    "content": "> Use indicator random variables to compute the expected value of the sum of\n> $n$ dice\n\nExpectation of a single die $X_i$, is unsurprisingly:\n\n$$ \\E[X_k] = \\sum_{i=0}^6 i \\Pr\\\\{X_k = i\\\\}\n           = \\frac{1 + 2 + 3 + 4 + 5 + 6}{6}\n           = \\frac{21}{6}\n           = 3.5 $$\n\nAs for multiple dice:\n\n$$ \\E[X] = \\E\\Big[\\sum_{i=1}^nX_i\\Big]\n         = \\sum_{i=1}^n \\E[X_i]\n         = \\sum_{i=1}^n 3.5\n         = 3.5 \\cdot n $$\n"
  },
  {
    "path": "other/clrs/05/02/04.markdown",
    "content": "> Use indicator random variables to solve the following problem, which is\n> known as the **hat-check problem**. Each of $n$ customer gives a hat to a\n> hat-check person at a restaurant. The hat-check person gives the hats back\n> to the customers in a random order. What is the expected number of\n> customers who get back their hat?\n\nThe probability that each person gets their hat back is $1/n$. Let $X_i$ be the\nevent that the $i$th person gets their hat back. Thus:\n\n$$ \\E[X] = \\E[X_1 + X_2 + \\ldots + X_n]\n         = \\sum_{i=1}^n \\E[X_i]\n         = \\sum_{i=1}^n \\frac{1}{n}\n         = 1 $$\n\nYup.\n\nOne person will get their hat back. I'm surprised too.\n"
  },
  {
    "path": "other/clrs/05/02/05.markdown",
    "content": "> Let $A[1 \\ldots n]$ be an array of $n$ distinct numbers. If $i < j$ and\n> $A[i] > A[j]$, then the pair $(i, j)$ is called an **inversion** of $A$.\n> (See Problem 2-4 for more on inversions.) Suppose that the elements of $A$\n> form a uniform random permutation of $\\langle 1, 2, \\ldots, n \\rangle$. Use\n> indicator random variables to compute the expected number of inversions.\n\nLet $X_{ij}$ be the event that there is an inversion between $i$ and $j$. The\nprobability of an inversion for each pair is $1/2$ because there are\n$\\binom{n}{2}$ possible pairs and the probability of having the larger number\nfirst is $\\frac{1}{n(n-1)}$. Dividing the two yields $1/2$. Thus we get that\n$\\E[X_{ij}] = 1/2$.\n\n$$ \\E[X] = \\sum_{i=1}^{n-1} \\sum_{j=i+1}^n \\E[X_{ij}]\n         = \\sum_{i=1}^{n-1} \\sum_{j=i+1}^n \\frac{1}{2}\n         = \\frac{1}{2} \\sum_{i=1}^{n-1} \\sum_{j=i+1}^n 1\n         = \\frac{1}{2} \\sum_{i=1}^{n-1} (n-i)\n         = \\frac{1}{2} \\sum_{i=1}^{n-1} i\n         = \\frac{n(n-1)}{4}\n         = \\binom{n}{2}/2\n$$\n"
  },
  {
    "path": "other/clrs/05/03/01.markdown",
    "content": "> Professor Marceau objects to the loop invariant used in the proof of Lemma\n> 5.5. He questions whether it is true prior to the first iteration. He\n> reasons that we could just as easily declare that an empty subarray\n> contains no 0-permutations. Therefore, the probability that an empty\n> subarray contains a 0-permutation should be 0, thus invalidating the loop\n> invariant prior to the first iteration. Rewrite the procedure\n> `RANDOMIZE-IN-PLACE` so that its associated loop invariant applies to a\n> nonempty subarray prior to the first iteration, and modify the proof of\n> Lemma 5.5 for your procedure.\n\nI'm not going to write any code since this is trivial.\n\nWe can pick up an element at random before entering the loop and replace it\nwith the first one. Now our invariant holds initially for a 1-permutation.\n"
  },
  {
    "path": "other/clrs/05/03/02.markdown",
    "content": "> Professor Kelp decides to write a procedure that produces at random any\n> permutation besides the identity permutation. He proposes the following\n> procedure:\n>\n>     PERMUTE-WITHOUT-IDENTITY(A)\n>     n = A.length\n>     for i = 1 to n - 1\n>         swap A[i] with A[RANDOM(i + 1, n)]\n>\n> Does this code do what Professor Kelp intends?\n\nIt does not. It always changes the position of each element. We cannot get the\nidentity permutation, but we also can't get any permutation where an element is\nat the same place.\n"
  },
  {
    "path": "other/clrs/05/03/03.markdown",
    "content": "> Suppose that instead of swapping element $A[i]$ with a random element from\n> the subarray $A[i \\ldots n]$, we swapped it with a random element from\n> anywhere in the array:\n>\n>     PERMUTE-WITH-ALL(A)\n>     n = A.length\n>     for i = 1 to n\n>         swap A[i] with A[RANDOM(1,n)]\n>\n> Does this code produce a uniform random permutation? Why or why not?\n\nIt does not. Intuitivelly, this one can go in $n^n$ different ways while there\nare $n!$ combinations. Since $n!$ does not divide $n^n$, there is no way that\nthis can be a uniform distribution. (Why doesn't it divide $n^n$? That's the\nintuitive part. $n!$ is divisable by $n-1$, but $n^n$ can't be for $n > 2$).\n\nOf course, this is a popular problem and there are tons of posts and papers\nwritten on it. Here's [one from Coding Horror](http://www.codinghorror.com/blog/2007/12/the-danger-of-naivete.html)\n"
  },
  {
    "path": "other/clrs/05/03/04.markdown",
    "content": "> Professor Armstrong suggests the following procedure for generating a uniform\n> random permutation:\n>\n>     n = A.length\n>     let B[1..n] be a new array\n>     offset = RANDOM(1, n)\n>     for i = 1 to n\n>         dest = i + offset\n>         if dest > n\n>             dest = dest - n\n>         B[dest] = A[i]\n>     return B\n>\n> Show that each element $A[i]$ has a $1/n$ probability of winding up in any\n> particular position in $B$. Then show that Professor Armstrong is mistaken by\n> showing that the resulting permutation is not uniformly random.\n\nBoth are trivial.\n\n$A[i]$ will go to $B[j]$ if $j \\equiv \\text{offset} + i \\pmod{n}$. There is\n$1/n$ probability of that happening.\n\nIt does not generate all permutations - it only generates permutations that can\nbe obtained from the initial input by cycling.\n\nBTW, \"Armstrong\" and \"cycling\". Nice pun.\n"
  },
  {
    "path": "other/clrs/05/03/05.markdown",
    "content": "> $\\star$ Prove that in the array $P$ in procedure `PERMUTE-BY-SORTING`, the\n> probability that all elements are unique is at least $1 - 1/n$.\n\nLet $\\Pr\\\\{j\\\\}$ be the probability that the element with index $j$ is unique.\nIf there are $n^3$ elements, then the $\\Pr\\\\{j\\\\} = 1 - \\frac{j-1}{n^3}$.\n\n$$ \\begin{aligned}\n   \\Pr\\\\{1 \\cap 2 \\cap 3 \\cap \\ldots\\\\}\n       &= \\Pr\\\\{1\\\\} \\cdot \\Pr\\\\{2 | 1\\\\} \\cdot \\Pr\\\\{3 | 1 \\cap 2\\\\} \\cdots \\\\\\\\\n       &= 1 \\bigg(1 - \\frac{1}{n^3}\\bigg)\n            \\bigg(1 - \\frac{2}{n^3}\\bigg)\n            \\bigg(1 - \\frac{3}{n^3}\\bigg)\n            \\cdots \\\\\\\\\n     &\\ge 1 \\bigg(1 - \\frac{n}{n^3}\\bigg)\n            \\bigg(1 - \\frac{n}{n^3}\\bigg)\n            \\bigg(1 - \\frac{n}{n^3}\\bigg)\n            \\cdots \\\\\\\\\n     &\\ge \\bigg(1 - \\frac{1}{n^2}\\bigg)^n \\\\\\\\\n     &\\ge 1 - \\frac{1}{n} \\\\\\\\\n   \\end{aligned} $$\n\nWhy does the last derivation work, you ask? Well, $(1-x)^n \\ge 1 - nx$.\n"
  },
  {
    "path": "other/clrs/05/03/06.markdown",
    "content": "> Explain how to implement the algorithm `PERMUTE-BY-SORTING` to handle the\n> case in which two or more priorities are identical. That is, your algorithm\n> should produce a uniform random permutation, even if two or more priorities\n> are identical.\n\nThis is a stupid algorithm and requires a stupid solution. Just generate new\npriorities and try again.\n"
  },
  {
    "path": "other/clrs/05/03/07.markdown",
    "content": "> Suppose we want to create a **random sample** of the set $\\\\{1, 2, 3, \\ldots,\n> n\\\\}$, that is, an $m$-element subset $S$, where $0 \\le m \\le n$, such that\n> each $m$-subset is equally likely to be created. One way would be to set\n> $A[i] = i$ for $i = 1, 2, 3, \\ldots, n$, call `RANDOMIZE-IN-PLACE(A)`, and\n> then take just the first $m$ array elements. This method would make $n$ calls\n> to the `RANDOM` procedure. If $n$ is much larger than $m$, we can create a\n> random sample with fewer calls to `RANDOM`. Show that the following recursive\n> procedure returns a random $m$-subset $S$ of $\\\\{1, 2, \\ldots, n\\\\}$, in\n> which each $m$-subset is equally likely, while making only $m$ calls to\n> `RANDOM`:\n>\n>     RANDOM-SAMPLE(m,n)\n>     if m == 0\n>         return ∅\n>     else\n>         S = RANDOM-SAMPLE(m-1, n-1)\n>         i = RANDOM(1,n)\n>         if i ∈ S\n>             S = S ∪ {n}\n>         else\n>             S = S ∪ {i}\n>         return S\n\nEach combination should have a $1/\\binom{n}{m}$ chance of showing up. Let's\nestablish an invariant for `RANDOM-SAMPLE(m,n)`. We are going to go with:\n\n> `RANDOM-SAMPLE(m,n)` returns a uniformly distributed combination.\n\nWe shall do induction on $m$. It's trivially so when $m$ is 1 (or 0). Let's\nassume the invariant holds for $m-1$. Let's see what happens when we pass $m$.\n\nThe recursive call returns an $m-1$ sample with uniform probability. There are\ntwo options - either the new $m$-subset includes $n$ or not.\n\nIf that happens (probability: $m/n$), the probability for each combination\nincluding $n$ is:\n\n$$ \\frac{m}{n}\\bigg(1/\\binom{n-1}{m-1}\\bigg) = 1/\\binom{n}{m} $$\n\nIf it does not (probability: $(n-m)/n$), it includes one of the $(n-m)$ numbers\nnot present. The chance for each is:\n\n$$ \\frac{n-m}{n}\\bigg(1/\\binom{n-1}{m}\\bigg) = 1/\\binom{n}{m} $$\n"
  },
  {
    "path": "other/clrs/05/04/01.markdown",
    "content": "> How many people must there be in a room before the probability that someone\n> has the same birthday as you do is at least $1/2$? How many people must there\n> be before the probability that at least two people have a birthday on July 4\n> is greater than $1/2$?\n\nThe probability of a person not having the same birthday as me is $(n-1)/n$.\nThe probability of $k$ people not having the same birthday as me is that,\nsquared. We apply the same approach as the text - we take the complementary\nevent and solve it for $k$:\n\n$$ 1 - \\bigg(\\frac{n-1}{k}\\bigg)^k \\ge \\frac{1}{2} \\\\\\\\\n   \\bigg(\\frac{n-1}{k}\\bigg)^k \\le \\frac{1}{2} \\\\\\\\\n   k\\lg\\bigg(\\frac{n-1}{n}\\bigg) \\ge \\lg\\frac{1}{2} \\\\\\\\\n   k = \\frac{\\log(1/2)}{\\log(364/365)} \\approx 263 $$\n\nAs for the other question:\n\n$$ \\begin{aligned}\n   \\Pr\\\\{\\text{2 born on Jul 4}\\\\} &=\n        1 - \\Pr\\\\{\\text{1 born on Jul 4}\\\\} - Pr\\\\{\\text{0 born on Jul4}\\\\} \\\\\\\\\n     &= 1 - \\frac{k}{n}\\bigg(\\frac{n-1}{n}\\bigg)^{k-1} - \\bigg(\\frac{n-1}{n}\\bigg)^k \\\\\\\\\n     &= 1 - \\bigg(\\frac{n-1}{n}\\bigg)^{k-1}\\bigg(\\frac{n+k-1}{n}\\bigg)\n   \\end{aligned} $$\n\nWriting a Ruby programme to find the closest integer, we get 115.\n"
  },
  {
    "path": "other/clrs/05/04/02.markdown",
    "content": "> Suppose that we toss balls into $b$ bins until some bin contains two balls.\n> Each toss is independent, and each ball is equally likely to end up in any\n> bin. What is the expected number of ball tosses?\n\nThis is just a restatement of the birthday problem. I consider this all that\nneeds to be said on this subject.\n\n[More analysis can be found on wikipedia](http://en.wikipedia.org/wiki/Birthday_problem#Average_number_of_people)\n"
  },
  {
    "path": "other/clrs/05/04/03.markdown",
    "content": "> $\\star$ For the analysis of the birthday paradox, is it important that the\n> birthdays be mutually independent, or is pairwise independence sufficient?\n> Justify your answer.\n\nPairwise independence is enough. It's sufficient for the derivation after (5.6).\n"
  },
  {
    "path": "other/clrs/05/04/04.markdown",
    "content": "> $\\star$ How many people should be invited to a party in order to make it\n> likely that there are *three* people with the same birthday?\n\nThe answer is $88$. I reached it by trial and error. But let's analyze it with\nindicator random variables.\n\nLet $X_{ijk}$ be the indicator random variable for the event of the people with\nindices $i$, $j$ and $k$ have the same birthday. The probability is $1/n^2$.\nThen:\n\n$$ \\begin{aligned}\n   \\E[X] &= \\sum_{i=1}^n\\sum_{j=i+1}^n\\sum_{k=j+1}^nX_{ijk} \\\\\\\\\n         &= \\sum_{i=1}^n\\sum_{j=i+1}^n\\sum_{k=j+1}^n\\frac{1}{n^2} \\\\\\\\\n         &= \\binom{n}{3}\\frac{1}{n^2} \\\\\\\\\n         &= \\frac{k(k-1)(k-2)}{6n^2}\n   \\end{aligned} $$\n\nSolving this yields $94$. It's a bit more, but again, indicator random\nvariables are approximate.\n\nFinding more commentary online is tricky.\n"
  },
  {
    "path": "other/clrs/05/04/05.markdown",
    "content": "> $\\star$ What is the probability that a $k$-string over a set of size $n$\n> forms a $k$-permutation? How does this question relate to the birthday\n> paradox?\n\n$$ \\Pr\\\\{k\\text{-perm in }n\\\\} = 1 \\cdot\n                                 \\frac{n-1}{n} \\cdot\n                                 \\frac{n-2}{n} \\cdots\n                                 \\frac{n-k+1}{n}\n      = \\frac{(n-1)!}{(n-k)!n^k} $$\n\nThis is the complementary event to the birthday problem, that is, the chance of\n$k$ people have distinct birthdays.\n"
  },
  {
    "path": "other/clrs/05/04/06.markdown",
    "content": "> $\\star$ Suppose that $n$ balls are tossed into $n$ bins, where each toss is\n> independent and the ball is equally likely to end up in any bin. What is the\n> expected number of empty bins? What is the expected number of bins with\n> exactly one ball?\n\nBoth of them are $n/e$ or at least are approximatelly close to it when $n$ is\nlarge enough. Let's do empty bins first.\n\nLet $X_i$ be the event that all the balls fall in bins, other than the $i$th.\n\n$$ \\Pr\\\\{X_i\\\\} = \\bigg(\\frac{n-1}{n}\\bigg)^n\n                = \\bigg(1 - \\frac{1}{n}\\bigg)^n\n                \\approx \\frac{1}{e} $$\n\nThe expectation:\n\n$$ \\E[X] = \\sum_{i=1}^n\\E[X_i] = \\frac{n}{e} $$\n\nIt's quite similar with exactly one ball. The probability is:\n\n$$ \\Pr\\\\{Y_i\\\\} = n\\frac{1}{n}\\bigg(\\frac{n-1}{n}\\bigg)^{n-1}\n                = \\bigg(\\frac{n-1}{n}\\bigg)^{n-1} \\approx \\frac{1}{e} $$\n\nThe expectation is the same.\n\nHere's a [Math/StackExchange][question] question that clarifies it.\n\n[question]: http://math.stackexchange.com/questions/545920/expactation-of-throwing-n-balls-into-n-bins\n"
  },
  {
    "path": "other/clrs/05/04/07.markdown",
    "content": "> $\\star$ Sharpen the lower bound on streak length by showing that in $n$ flips\n> of a fair coin, the probability is less than $1/n$ that no streak longer than\n> $\\lg{n} - 2\\lg\\lg{n}$ consecutive heads occurs.\n\n**(UNSOLVED)** Too much work, too little connection to reality.\n"
  },
  {
    "path": "other/clrs/05/problems/01.markdown",
    "content": "## Probabilstic counting\n\n> With a $b$-bit counter, we can ordinarily only count up to $2^b - 1$. With R.\n> Morris's **probabilistic counting**, we can count up to a much larger value\n> at the expense of some loss of precision.\n>\n> We let a counter value of $i$ represent that a count of $n_i$ for\n> $i = 0, 1, \\ldots, 2^b-1$, where the $n_i$ form an increasing sequence of\n> nonnegative values. We assume that the initial value of the counter is 0,\n> representing a count of $n_0 = 0$. The `INCREMENT` operation works on a\n> counter containing the value $i$ in a probabilistic manner. If $i = 2^b - 1$,\n> then the operation reports an overflow error. Otherwise, the `INCREMENT`\n> operation increases the counter by 1 with probability $1/(n_{i+1} - n_i)$,\n> and it leaves the counter unchanged with probability $1-1/(n_{i+1} - n_i)$.\n>\n> If we select $n_i = i$ for all $i \\ge 0$, then the counter is an ordinary\n> one. More interesting situations arise if we select, say, $n_i = 2^{i-1}$ for\n> $i > 0$ or $n_i = F_i$ (the $i$th Fibonacci number - see Section 3.2).\n>\n> For this problem, assume that $n_{2^b-1}$ is large enough that the\n> probability of an overflow error is negligible.\n>\n> 1. Show that the expected value represented by the counter after $n$\n>    `INCREMENT` operations have been performed is exactly $n$.\n> 2. The analysis of the variance of the count represented by the counter\n>    depends on the sequence of the $n_i$. Let us consider a simple case: $n_i\n>    = 100i$ for all $i \\ge 0$. Estimate the variance in the value represented\n>    by the register after $n$ `INCREMENT` operations have been performed.\n\n### Expected value\n\nSuppose at the start of the $j$th increment, the counter holds $i$, which\nrepresents $n_i$. If the counter increases, then the value it will increase by\n$n_{i+1} - n_i$. It happens with probability $1/(n_{i+1} - n_i)$, and so:\n\n$$ \\begin{aligned}\n     \\E[X_j] &= 0 \\cdot \\Pr\\\\{\\text{stays same}\\\\} + 1 \\cdot \\Pr\\\\{\\text{increases}\\\\} \\\\\\\\\n             &= 0 \\cdot \\bigg(1 - \\frac{1}{n_{i+1} - n_i}\\bigg) +\n                1 \\cdot \\bigg((n_{i+1} - n_i) \\cdot \\frac{1}{n_{i+1} - n_i}\\bigg) \\\\\\\\\n             &= 1\n   \\end{aligned} $$\n\nThis is the expectation any increment. Since there are $n$ increments, the\nexecpted value will be $n$.\n\n### Variance\n\nThe variance of a single increment.\n\n$$ \\begin{aligned}\n   \\Var[X_j] &= \\E[X_j^2] - \\E^2[X_j] \\\\\\\\\n             &= \\bigg(0^2 \\cdot \\frac{99}{100} + 100^2 \\frac{1}{100}\\bigg) - 1 \\\\\\\\\n             &= 99\n   \\end{aligned} $$\n\nAs for the variance of the total value:\n\n$$ \\Var[X] = \\Var[X_1 + X_2 + \\ldots + X_n] = \\sum_{i=1}^n\\Var[X_i] = 99n $$\n"
  },
  {
    "path": "other/clrs/05/problems/02.markdown",
    "content": "## Searching an unsorted array\n\n> The problem examines three algorithms for searching for a value $x$ in an\n> unsorted array $A$ consisting for $n$ elements.\n>\n> Consider the following randomized strategy: pick a random index $i$ into $A$.\n> If $A[i] = x$, then we terminate; otherwise, we continue the search by\n> picking a new random index into $A$. We continue picking random indices into\n> $A$ until we find an index $j$ such that $A[j] = x$ or until we have checked\n> every element of $A$. Note that we pick from the whole set of indices each\n> time, so that we may examine a given element more than once.\n>\n> 1. Write pseudocode for a procedure `RANDOM-SEARCH` to implement the strategy\n>    above. Be sure that your algorithm terminates when all indices into $A$\n>    have been picked.\n> 2. Suppose that there is exactly one index $i$ such that $A[i] = x$. What is\n>    the expected number of indices into $A$ that we must pick before we find\n>    $x$ and `RANDOM-SEARCH` terminates?\n> 3. Generalizing your solution to part (b), suppose that there are $k \\ge 1$\n>    indices $i$ such that $A[i] = x$. What is the expected number of indices\n>    into $A$ that we must pick before we find $x$ and `RANDOM-SEARCH`\n>    terminates? Your answer should be a function of $n$ and $k$.\n> 4. Suppose that there are no indices $i$ such that $A[i] = x$. What is the\n>    expected number of indices into $A$ that we must pick before we have\n>    checked all elements of $A$ and `RANDOM-SEARCH` terminates?\n>\n> Now consider a deterministic linear search algorithm, which we refer to as\n> `DETERMINISTIC-SEARCH`. Specifically, the algorithm searches $A$ for $x$ in\n> order, considering $A[1], A[2], A[3], \\ldots, A[n]$ until either it finds\n> $A[i] = x$ or it reaches the end of the array. Assume that possible\n> permutations of the input array are equally likely.\n>\n> 5. Suppose that there is exactly one index $i$ such that $A[i] = x$. What is\n>    the average-case running time of `DETERMINISTIC-SEARCH`? What is the\n>    worst-case running time of `DETERMINISTIC-SEARCH`?\n> 6. Generalizing your solution to part (e), suppose that there are $k \\ge 1$\n>    indices $i$ such that $A[i] = x$. What is the average-case running time of\n>    `DETERMINISTIC-SEARCH`? What is the worst-case running time of\n>    `DETERMINISTIC-SEARCH`? Your answer should be a function of $n$ and $k$.\n> 7. Suppose that there are no indices $i$ such that $A[i] = x$. What is the\n>    average-case running time of `DETERMINISTIC-SEARCH`? What is the\n>    worst-case running time of `DETERMINISTIC-SEARCH`?\n>\n> Finally, consider a randomized algorithm `SCRAMBLE-SEARCH` that works by\n> first randomly permuting the input array and then running the deterministic\n> linear search given above on the resulting permuting array.\n>\n> 8. Letting $k$ be the number of indices $i$ such that $A[i] = x$, give the\n>    worst-case and expected running time of `SCRAMBLE-SEARCH` for the cases in\n>    which $k = 0$ and $k = 1$. Generalizing your solution to handle the case\n>    in which $k \\ge 1$.\n> 9. Which of the three searching algorithms would you use? Explain your\n>    answer.\n\n### RANDOM-SEARCH pseudocode\n\n    RANDOM-SEARCH(x, A, n):\n      v = ∅\n      while |∅| ≠ n\n          i = RANDOM(1, n)\n          if A[i] = x\n              return i\n          else:\n              v = v ∩ i\n      return ␀\n\n`v` can be implemented in multiple ways - a hash table, a tree or a bitmap. The\nlast one would probabily perform best and consume the least space.\n\n### RANDOM-SEARCH with one match\n\n`RANDOM-SEARCH` is well-modelled by Bernoulli trials. The expected number of\npicks is $n$.\n\n### RANDOM-SEARCH with multiple matches\n\nIn similar fashion, the expected number of picks is $n/k$.\n\n### RANDOM-SEARCH with no matches\n\nThis is modelled by the balls and bins problem, explored in section 5.4.2. The\nanswer is $n(\\ln{n} + \\O(1))$.\n\n### DETERMINISTIC-SEARCH with one match\n\nThe worst-case running time is $n$. The average-case is $(n+1)/2$ (obviously).\n\n### DETERMINISTIC-SEARCH with multiple matches\n\nThe worst-case running time is $n-k+1$. The average-case running time is\n$(n+1)/(k+1)$. Let $X_i$ be an indicator random variable that the $i$th element\nis a match. $\\Pr\\\\{X_i\\\\} = 1/(k+1)$. Let $Y$ be an indicator random variable\nthat we have found a match after the first $n-k+1$ elements ($\\Pr\\\\{Y\\\\} = 1$).\nThus:\n\n$$ \\E[X] = \\E[X_1 + X_2 + \\ldots + X_{n-k} + Y]\n         = 1 + \\sum_{i=1}^{n-k}\\E[X_i]\n         = 1 + \\frac{n-k}{k+1}\n         = \\frac{n+1}{k+1} $$\n\n### DETERMINISTIC-SEARCH with no matches\n\nBoth the worst-case and average case is $n$.\n\n### SCRAMBLE-SEARCH matches\n\nIt's the same as `DETERMINISTIC-SEARCH`, only we replace \"average-case\" with \"expected\".\n\n### Best algorithm\n\nDefinitelly `DETERMINISTIC-SEARCH`. `SCRAMBLE-SEARCH` gives better expected\nresults, but for the cost of randomly permuting the array, which is a linear\noperation. In the same time we could have scanned the full array and reported a\nresult.\n"
  },
  {
    "path": "other/clrs/06/01/01.markdown",
    "content": "> What are the minimum and maximum numbers of elements in a heap of height $h$?\n\nIt is between $2^n$ and $2^{n+1} - 1$. For example, a heap with $2$ ($2^1$) or\n$3$ ($2^2 - 1$) will have height $1$. If there are four elements, however, the\nheap height will be $2$.\n"
  },
  {
    "path": "other/clrs/06/01/02.markdown",
    "content": "> Show that an $n$-element heap has height $\\lfloor \\lg{n} \\rfloor$\n\nThis is way too obvious, that it is hard to prove it.\n\nThe number of internal nodes a complete binary tree has is $2^h - 1$ where $h$\nis the height of the tree. A heap of height $h$ has at least one additional\nnode (otherwise it would be a heap of length $h-1$) and at most $2^h$\nadditional nodes (otherwise it would be a heap of length $h+1$), which is\nsimilar to the answer in exercise 6.1-1.\n\nThus, if $n \\in (2^h, 2^{h+1} - 1)$, then the height will be $\\lfloor \\lg{n}\n\\rfloor$.\n"
  },
  {
    "path": "other/clrs/06/01/03.markdown",
    "content": "> Show that in any subtree of a max-heap, the root of the subtree contains the\n> largest value occuring anywhere in the subtree.\n\nThis follows from the max-heap property.\n\nIf the $i$th element is the root of the subtree, then both its children would\nbe less or equal to it. Since this properties holds for their children too and\nit is transitive, all of the descendents will be less or equal to the root,\nmaking it the largest value.\n"
  },
  {
    "path": "other/clrs/06/01/04.markdown",
    "content": "> Where in a max-heap might the smallest element reside, assuming that all\n> elements are distinct?\n\nIn any of the leaves, that is, elements with index $\\lfloor n/2 \\rfloor + 1$\n(see exercise 6.1-7), that is, in the second half of the heap array.\n"
  },
  {
    "path": "other/clrs/06/01/05.markdown",
    "content": "> Is an array that is in sorted order a min-heap?\n\nYes. For any index $i$, both `LEFT(i)` and `RIGHT(i)` are larger and thus the\nelements indexed by them are greater or equal to $A[i]$ (because the array is\nsorted).\n"
  },
  {
    "path": "other/clrs/06/01/06.dot",
    "content": "graph Heap {\n  23 -- 17;\n  23 -- 14;\n\n  17 -- 6;\n  17 -- 13;\n  14 -- 10;\n  14 -- 1;\n\n  6 -- 5;\n  6 -- 7 [color=red];\n  13 -- 12;\n\n}\n"
  },
  {
    "path": "other/clrs/06/01/06.markdown",
    "content": "> Is the array with values $\\langle 23, 17, 14, 6, 13, 10, 1, 5, 7, 12 \\rangle$\n> a max-heap?\n\nNo. The property is violated by the next-to-last leaf (illustrated below in\nred).\n"
  },
  {
    "path": "other/clrs/06/01/07.markdown",
    "content": "> Show that, with the array representation for sorting an $n$-element heap, the\n> leaves are the nodes indexed by $\\lfloor n/2 \\rfloor + 1,\\lfloor n/2 \\rfloor\n> + 2, \\ldots, n$.\n\nAnother very obvious one.\n\nLet's take the left child of the node indexed by $\\lfloor n/2 \\rfloor + 1$.\n\n$$ \\text{LEFT}(\\lfloor n/2 \\rfloor + 1) = 2(\\lfloor n/2 \\rfloor + 1)\n                                        > 2(n/2 - 1) + 2\n                                        = n - 2 + 2\n                                        = n $$\n\nSince the index of the left child is larger than the number of elements in the\nheap, the node doesn't have childrens and thus is a leaf. Same goes for all\nnodes with larger indices.\n\nNote that if we take element indexed by $\\lfloor n/2 \\rfloor$, it will not be a\nleaf. In case of even number of nodes, it will have a left child with index $n$\nand in the case of odd number of nodes, it will have a left child with index\n$n-1$ and a right child with index $n$.\n\nThis makes the number of leaves in a heap of size $n$ equal to $\\lceil n/2\n\\rceil$.\n"
  },
  {
    "path": "other/clrs/06/02/01.dot",
    "content": "graph Illustration {\n  subgraph A {\n    node[shape=circle, fixedsize=true];\n    a1[label=27];\n    a2[label=17];\n    a3[label=3, style=filled];\n    a4[label=16];\n    a5[label=13];\n    a6[label=10];\n    a7[label=1];\n    a8[label=5];\n    a9[label=7];\n    a10[label=12];\n    a11[label=4];\n    a12[label=8];\n    a13[label=9];\n    a14[label=0];\n\n    a1 -- a2; a1 -- a3;\n    a2 -- a4; a2 -- a5; a3 -- a6;  a3 -- a7;\n    a4 -- a8; a4 -- a9; a5 -- a10; a5 -- a11; a6 -- a12; a6 -- a13; a7 -- a14;\n  }\n\n  subgraph B {\n    node[shape=circle, fixedsize=true];\n    b1[label=27];\n    b2[label=17];\n    b3[label=10]\n    b4[label=16];\n    b5[label=13];\n    b6[label=3, style=filled];\n    b7[label=1];\n    b8[label=5];\n    b9[label=7];\n    b10[label=12];\n    b11[label=4];\n    b12[label=8];\n    b13[label=9];\n    b14[label=0];\n\n    b1 -- b2; b1 -- b3;\n    b2 -- b4; b2 -- b5; b3 -- b6;  b3 -- b7;\n    b4 -- b8; b4 -- b9; b5 -- b10; b5 -- b11; b6 -- b12; b6 -- b13; b7 -- b14;\n  }\n  subgraph C {\n    node[shape=circle, fixedsize=true];\n    c1[label=27];\n    c2[label=17];\n    c3[label=10];\n    c4[label=16];\n    c5[label=13];\n    c6[label=9];\n    c7[label=1];\n    c8[label=5];\n    c9[label=7];\n    c10[label=12];\n    c11[label=4];\n    c12[label=8];\n    c13[label=3, style=filled];\n    c14[label=0];\n\n    c1 -- c2; c1 -- c3;\n    c2 -- c4; c2 -- c5; c3 -- c6;  c3 -- c7;\n    c4 -- c8; c4 -- c9; c5 -- c10; c5 -- c11; c6 -- c12; c6 -- c13; c7 -- c14;\n  }\n}\n"
  },
  {
    "path": "other/clrs/06/02/01.markdown",
    "content": "> Using figure 6.2 as a model, illustrate the operation of `MAX-HEAPIFY(A, 3)`\n> on the array $A = \\langle 27, 17, 3, 16, 13, 10, 1, 5, 7, 12, 4, 8, 9, 0\n> \\rangle$.\n"
  },
  {
    "path": "other/clrs/06/02/02.markdown",
    "content": "> Starting with the procedure `MAX-HEAPIFY`, write pseudocode for the procedure\n> `MIN-HEAPIFY(A, i)`, which performs the corresponding manipulation on a\n> min-heap. How does the running time of `MIN-HEAPIFY` compare to that of\n> `MAX-HEAPIFY`?\n\n    MIN-HEAPIFY(A, i)\n      l = LEFT(i)\n      r = RIGHT(i)\n      if l ≤ A.heap-size and A[l] < A[i]\n          smallest = l\n      else\n          smallest = i\n      if r ≤ A.heap-size and A[r] < A[i]\n          smallest = r\n      if smallest ≠ i\n          exchange A[i] with A[smallest]\n          MIN-HEAPIFY(A, smallest)\n\nThe running time is the same. Actually, the algorithm is the same with the\nexceptions of two comparisons and some names.\n"
  },
  {
    "path": "other/clrs/06/02/03.markdown",
    "content": "> What is the effect of calling `MAX-HEAPIFY(A, i)` when th element $A[i]$ is\n> larger than its children?\n\nNo effect. The comparisons are carried out, $A[i]$ is found to be largest and\nthe procedure just returns.\n"
  },
  {
    "path": "other/clrs/06/02/04.markdown",
    "content": "> What is the effect of calling `MAX-HEAPIFY(A, i)` for $i > A.heap-size / 2$?\n\nNo effect. In that case, it is a leaf. Both `LEFT` and `RIGHT` return values\nthat fail the comparison with the heap size and `i` is stored in `largest`.\nAfterwards the procedure just returns\n"
  },
  {
    "path": "other/clrs/06/02/05.c",
    "content": "#define PARENT(i) ((i - 1) / 2)\n#define LEFT(i)   (2 * i + 1)\n#define RIGHT(i)  (2 * i + 2)\n\ntypedef struct {\n    int *nodes;\n    int length;\n    int heap_size;\n} heap;\n\nvoid max_heapify(heap A, int i) {\n    int left, right, largest, temp;\n\n    while(1) {\n        left  = LEFT(i);\n        right = RIGHT(i);\n\n        if (left < A.heap_size && A.nodes[left] > A.nodes[i])\n            largest = left;\n        else\n            largest = i;\n\n        if (right < A.heap_size && A.nodes[right] > A.nodes[largest])\n            largest = right;\n\n        if (largest == i)\n            return;\n\n        temp = A.nodes[i];\n        A.nodes[i] = A.nodes[largest];\n        A.nodes[largest] = temp;\n\n        i = largest;\n    }\n}\n"
  },
  {
    "path": "other/clrs/06/02/05.markdown",
    "content": "> The code for `MAX-HEAPIFY` is quite efficient in terms of constant factors,\n> except possibly for the recursive call in line 10, which might cause some\n> compilers to produce inefficient code. Write an efficient `MAX-HEAPIFY` that\n> uses an iterative control construct (a loop) instead of recursion.\n\nAs always, the most fun was converting from 1- to 0-based indexing.\n"
  },
  {
    "path": "other/clrs/06/02/05.test.c",
    "content": "#include \"05.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(chapter_example) {\n    int expected[] = {16, 14, 10, 8,  7, 9, 3, 2, 4, 1},\n        actual[]   = {16,  4, 10, 14, 7, 9, 3, 2, 8, 1};\n\n    heap A = {actual, 10, 10};\n\n    max_heapify(A, 1);\n\n    ASSERT_SAME_ARRAYS(actual, expected);\n}\n\nTEST(exercise_6_2_1_example) {\n    int expected[] = {27, 17, 10, 16, 13,  9, 1, 5, 7, 12, 4, 8, 3, 0},\n        actual[]   = {27, 17,  3, 16, 13, 10, 1, 5, 7, 12, 4, 8, 9, 0};\n\n    heap A = {actual, 14, 14};\n\n    max_heapify(A, 2);\n\n    ASSERT_SAME_ARRAYS(actual, expected);\n}\n"
  },
  {
    "path": "other/clrs/06/02/06.markdown",
    "content": "> Show that the worst-case running time of `MAX-HEAPIFY` on a heap of size $n$\n> is $\\Omega(\\lg{n})$. (Hint: For a heap with $n$ nodes, give node values that\n> cause `MAX-HEAPIFY` to be called recursively at every node on a simple path\n> from the root down to a leaf.)\n\nThis is another obvious one.\n\nLet's take the leftmost path in the given heap. If we put the largest elements\nin the heap on that path and the smallest one at the root, `MAX-HEAPIFY` will\nneed to be invoked once for each level in the heap in order to push the minimum\nelement to the leftmost leaf. Since the heap height (and thus the leftmost\npath's length) is $\\lfloor \\lg{n} \\rfloor$ (exercise 6.1-2), the worst-case\nrunning time of the procedure is $\\Omega(\\lg{n})$.\n"
  },
  {
    "path": "other/clrs/06/03/01.dot",
    "content": "graph Illustration {\n  node[shape=circle, fixedsize=true]\n\n  subgraph A {\n    a1[label=5];\n    a2[label=3];\n    a3[label=17];\n    a4[label=10, style=filled];\n    a5[label=84];\n    a6[label=19];\n    a7[label=6];\n    a8[label=22];\n    a9[label=9];\n\n    a1 -- a2; a1 -- a3;\n    a2 -- a4; a2 -- a5; a3 -- a6; a3 -- a7;\n    a4 -- a8; a4 -- a9;\n  }\n\n  subgraph B {\n    b1[label=5];\n    b2[label=3];\n    b3[label=17 style=filled];\n    b4[label=22];\n    b5[label=84];\n    b6[label=19];\n    b7[label=6];\n    b8[label=10];\n    b9[label=9];\n\n    b1 -- b2; b1 -- b3;\n    b2 -- b4; b2 -- b5; b3 -- b6; b3 -- b7;\n    b4 -- b8; b4 -- b9;\n  }\n\n  subgraph C {\n    c1[label=5];\n    c2[label=3 style=filled];\n    c3[label=19];\n    c4[label=22];\n    c5[label=84];\n    c6[label=17];\n    c7[label=6];\n    c8[label=10];\n    c9[label=9];\n\n    c1 -- c2; c1 -- c3;\n    c2 -- c4; c2 -- c5; c3 -- c6; c3 -- c7;\n    c4 -- c8; c4 -- c9;\n  }\n\n  subgraph D {\n    d1[label=5 style=filled];\n    d2[label=84];\n    d3[label=19];\n    d4[label=22];\n    d5[label=3];\n    d6[label=17];\n    d7[label=6];\n    d8[label=10];\n    d9[label=9];\n\n    d1 -- d2; d1 -- d3;\n    d2 -- d4; d2 -- d5; d3 -- d6; d3 -- d7;\n    d4 -- d8; d4 -- d9;\n  }\n\n  subgraph E {\n    e1[label=84];\n    e2[label=22];\n    e3[label=19];\n    e4[label=10];\n    e5[label=3];\n    e6[label=17];\n    e7[label=6];\n    e8[label=5];\n    e9[label=9];\n\n    e1 -- e2; e1 -- e3;\n    e2 -- e4; e2 -- e5; e3 -- e6; e3 -- e7;\n    e4 -- e8; e4 -- e9;\n  }\n}\n"
  },
  {
    "path": "other/clrs/06/03/01.markdown",
    "content": "> Using figure 6.3 as a model, illustrate the operation of `BUILD-MAX-HEAP` on\n> the array $A = \\langle 5, 3, 17, 10, 84, 19, 6, 22, 9 \\rangle$.\n\nOh boy.\n"
  },
  {
    "path": "other/clrs/06/03/02.markdown",
    "content": "> Why do we want the loop index $i$ in line 2 of `BUILD-MAX-HEAP` to decrease\n> from $\\lfloor A.length / 2 \\rfloor$ to $1$ rather than increase from $1$ to\n> $\\lfloor A.length/2 \\rfloor$?\n\nOtherwise we won't be allowed to call `MAX-HEAPIFY`, since it will fail the\ncondition of having the subtrees be max-heaps. That is, if we start with $1$,\nthere is no guarantee that $A[2]$ and $A[3]$ are roots of max-heaps.\n"
  },
  {
    "path": "other/clrs/06/03/03.markdown",
    "content": "> Show that there are at most $\\lceil n/2^{h+1} \\rceil$ nodes of height $h$ in\n> any $n$-element heap.\n\nFirst, let's observe that the number of leaves in a heap is $\\lceil n/2 \\rceil$\n(exercise 6.1-7). Let's prove it by induction on $h$.\n\n**Base**: $h = 0$. The number of leaves is $\\lceil n/2 \\rceil = \\lceil n/2^{0+1} \\rceil$.\n\n**Step**: Let's assume it holds for nodes of height $h-1$. Let's take a tree\nand remove all it's leaves. We get a new tree with $n - \\lceil n/2 \\rceil =\n\\lfloor n/2 \\rfloor$ elements. Note that the nodes with height $h$ in the old\ntree have height $h-1$ in the new one.\n\nWe will calculate the number of such nodes in the new tree.  By the inductive\nassumption we have that $T$, the number of nodes with height $h-1$ in the new\ntree, is:\n\n$$ T = \\bigg\\lceil \\lfloor n/2 \\rfloor / 2^{h-1+1} \\bigg\\rceil\n     < \\bigg\\lceil (n/2)/2^h \\bigg\\rceil\n     = \\bigg\\lceil \\frac{n}{2^{h+1}} \\bigg\\rceil $$\n\nAs mentioned, this is also the number of nodes with height $h$ in the old tree.\n"
  },
  {
    "path": "other/clrs/06/04/01.dot",
    "content": "graph Heapsort {\n  node[shape=circle, fixedsize=true];\n\n  subgraph A {\n    a1[label=25];\n    a2[label=13];\n    a3[label=20];\n    a4[label=8];\n    a5[label=7];\n    a6[label=17];\n    a7[label=2];\n    a8[label=5];\n    a9[label=4];\n\n    a1 -- a2; a1 -- a3;\n    a2 -- a4; a2 -- a5; a3 -- a6; a3 -- a7;\n    a4 -- a8; a4 -- a9;\n  }\n\n  subgraph B {\n    b1[label=20];\n    b2[label=13];\n    b3[label=17];\n    b4[label=8];\n    b5[label=7];\n    b6[label=4];\n    b7[label=2];\n    b8[label=5];\n    b9[label=25 style=filled];\n\n    b1 -- b2; b1 -- b3;\n    b2 -- b4; b2 -- b5; b3 -- b6; b3 -- b7;\n    b4 -- b8;\n    { edge[color=gray]\n      b4 -- b9;\n    }\n  }\n\n  subgraph C {\n    c1[label=17];\n    c2[label=13];\n    c3[label=5];\n    c4[label=8];\n    c5[label=7];\n    c6[label=4];\n    c7[label=2];\n    c8[label=20 style=filled];\n    c9[label=25 style=filled];\n\n    c1 -- c2; c1 -- c3;\n    c2 -- c4; c2 -- c5; c3 -- c6; c3 -- c7;\n    { edge[color=gray]\n      c4 -- c8; c4 -- c9;\n    }\n  }\n\n  subgraph D {\n    d1[label=13];\n    d2[label=8];\n    d3[label=5];\n    d4[label=2];\n    d5[label=7];\n    d6[label=4];\n    d7[label=17 style=filled];\n    d8[label=20 style=filled];\n    d9[label=25 style=filled];\n\n    d1 -- d2; d1 -- d3;\n    d2 -- d4; d2 -- d5; d3 -- d6;\n    { edge[color=gray]\n      d3 -- d7; d4 -- d8; d4 -- d9;\n    }\n  }\n\n  subgraph E {\n    e1[label=8];\n    e2[label=7];\n    e3[label=5];\n    e4[label=2];\n    e5[label=4];\n    e6[label=13 style=filled];\n    e7[label=17 style=filled];\n    e8[label=20 style=filled];\n    e9[label=25 style=filled];\n\n    e1 -- e2; e1 -- e3;\n    e2 -- e4; e2 -- e5;\n    { edge[color=gray]\n      e3 -- e6; e3 -- e7; e4 -- e8; e4 -- e9;\n    }\n  }\n\n  subgraph F {\n    f1[label=7];\n    f2[label=4];\n    f3[label=5];\n    f4[label=2];\n    f5[label=8  style=filled];\n    f6[label=13 style=filled];\n    f7[label=17 style=filled];\n    f8[label=20 style=filled];\n    f9[label=25 style=filled];\n\n    f1 -- f2; f1 -- f3;\n    f2 -- f4;\n    { edge[color=gray]\n      f2 -- f5; f3 -- f6; f3 -- f7; f4 -- f8; f4 -- f9;\n    }\n  }\n\n  subgraph G {\n    g1[label=5];\n    g2[label=4];\n    g3[label=2];\n    g4[label=7  style=filled];\n    g5[label=8  style=filled];\n    g6[label=13 style=filled];\n    g7[label=17 style=filled];\n    g8[label=20 style=filled];\n    g9[label=25 style=filled];\n\n    g1 -- g2; g1 -- g3;\n    { edge[color=gray]\n      g2 -- g4; g2 -- g5; g3 -- g6; g3 -- g7; g4 -- g8; g4 -- g9;\n    }\n  }\n\n  subgraph H {\n    h1[label=4];\n    h2[label=2];\n    h3[label=5  style=filled];\n    h4[label=7  style=filled];\n    h5[label=8  style=filled];\n    h6[label=13 style=filled];\n    h7[label=17 style=filled];\n    h8[label=20 style=filled];\n    h9[label=25 style=filled];\n\n    h1 -- h2;\n    { edge[color=gray]\n      h1 -- h3; h2 -- h4; h2 -- h5; h3 -- h6; h3 -- h7; h4 -- h8; h4 -- h9;\n    }\n  }\n\n  subgraph I {\n    i1[label=4];\n    i2[label=2  style=filled];\n    i3[label=5  style=filled];\n    i4[label=7  style=filled];\n    i5[label=8  style=filled];\n    i6[label=13 style=filled];\n    i7[label=17 style=filled];\n    i8[label=20 style=filled];\n    i9[label=25 style=filled];\n\n    i1 -- i2;\n    { edge[color=gray]\n      i1 -- i3; i2 -- i4; i2 -- i5; i3 -- i6; i3 -- i7; i4 -- i8; i4 -- i9;\n    }\n  }\n}\n"
  },
  {
    "path": "other/clrs/06/04/01.markdown",
    "content": "> Using figure 6.4 as a model, illustrate the operation of `HEAPSORT` on the\n> array $A = \\langle 5, 13, 2, 25, 7, 17, 20, 8, 4 \\rangle$.\n"
  },
  {
    "path": "other/clrs/06/04/02.markdown",
    "content": "> Argue the correctness of `HEAPSORT` using the following loop invariant:\n>\n> > At the start of each iteration of the **for** loop of lines 2-5, the\n> > subarray $A[1 \\ldots i]$ is a max-heap containing the $i$ smallest elements\n> > of $A[1 \\ldots n]$, and the subarray $A[i + 1 \\ldots n]$ contains the $n -\n> > i$ largest elements of $A[1 \\ldots n]$, sorted.\n\n**Initialization**. The subarray $A[i + 1 \\ldots n]$ is empty, thus the\ninvariant holds.\n\n**Maintenance**. $A[1]$ is the largest element in $A[1 \\ldots i]$ and it is\nsmaller than the elements in $A[i + 1 \\ldots n]$. When we put it in the $i$th\nposition, then $A[i \\ldots n]$ contains the largest elements, sorted.\nDecreasing the heap size and calling `MAX-HEAPIFY` turns $A[1 \\ldots i-1]$ into\na max-heap. Decrementing $i$ sets up the invariant for the next iteration.\n\n**Termination**. After the loop $i = 1$. This means that $A[2 \\ldots n]$ is\nsorted and $A[1]$ is the smallest element in the array, which makes the array\nsorted.\n"
  },
  {
    "path": "other/clrs/06/04/03.markdown",
    "content": "> What is the running time of `HEAPSORT` on an array $A$ of length $n$ that is\n> already sorted in increasing order? What about decreasing order?\n\nBoth of them are $\\Theta(n\\lg{n})$.\n\nIf the array is sorted in increasing order, the algorithm will need to convert\nit to a heep that will take $\\O(n)$. Afterwards, however, there are $n-1$ calls\nto `MAX-HEAPIFY` and each one will perform the full $\\lg{k}$ operations. Since:\n\n$$ \\sum_{i=1}^{n-1}\\lg{k} = \\lg\\Big((n-1)!\\Big) = \\Theta(n\\lg{n}) $$\n\nSame goes for decreasing order. `BUILD-MAX-HEAP` will be faster (by a constant\nfactor), but the computation time will be dominated by the loop in `HEAPSORT`,\nwhich is $\\Theta(n\\lg{n})$.\n"
  },
  {
    "path": "other/clrs/06/04/04.markdown",
    "content": "> Show that the worst-case running time of `HEAPSORT` is $\\Omega(n\\lg{n})$.\n\nThis is essentially the first part of exercise 6.4-3. Whenever we have an array\nthat is already sorted, we take linear time to convert it to a max-heap and\nthen $n\\lg{n}$ time to sort it.\n"
  },
  {
    "path": "other/clrs/06/04/05.markdown",
    "content": "> $\\star$ Show that when all elements are distinct, the best-case running time\n> of `HEAPSORT` is $\\Omega(n\\lg{n})$.\n\nThis proved to be quite tricky. My initial solution was wrong. Also, heapsort\nappeared in 1964, but the lower bound was proved by Schaffer and Sedgewick\nin 1992. It's evil to put this an exercise.\n\nLet's assume that the heap is a full binary tree with $n = 2^k - 1$. There are\n$2^{k-1}$ leaves and $2^{k-1} - 1$ inner nodes.\n\nLet's look at sorting the first $2^{k-1}$ elements of the heap. Let's consider\ntheir arrangement in the heap and color the leaves to be red and the inner\nnodes to be blue. The colored nodes are a subtree of the heap (otherwise there\nwould be a contradiction). Since there are $2^{k-1}$ colored nodes, at most\n$2^{k-2}$ are red, which means that at least $2^{k-2} - 1$ are blue.\n\nWhile the red nodes can jump directly to the root, the blue nodes need to\ntravel up before they get removed. Let's count the number of swaps to move the\nblue nodes to the root. The minimal case of swaps is when (1) there are\n$2^{k-2} - 1$ blue nodes and (2) they are arranged in a binary tree. If there\nare $d$ such blue nodes, then there would be $i = \\lg{d}$ levels, each\ncontaining $2^i$ nodes with length $i$. Thus the number of swaps is:\n\n$$ \\sum_{i=0}^{\\lg{d}}i2^i = 2 + (\\lg{d} - 2)2^{\\lg{d}} = \\Omega(d\\lg{d}) $$\n\nAnd now for a lazy (but cute) trick. We've figured out a tight bound on sorting\nhalf of the heap. We have the following recurrence:\n\n$$ T(n) = T(n/2) + \\Omega(n\\lg{n}) $$\n\nApplying the master method, we get that $T(n) = \\Omega(n\\lg{n}) $.\n"
  },
  {
    "path": "other/clrs/06/05/01.dot",
    "content": "graph HeapExtractMax {\n  node[shape=circle, fixedsize=true];\n\n  subgraph A {\n    a1[label=15 style=filled];\n    a2[label=13];\n    a3[label=9];\n    a4[label=5];\n    a5[label=12];\n    a6[label=8];\n    a7[label=7];\n    a8[label=4];\n    a9[label=0];\n    a10[label=6];\n    a11[label=2];\n    a12[label=1];\n\n    a1 -- a2; a1 -- a3;\n    a2 -- a4; a2 -- a5; a3 -- a6;  a3 -- a7;\n    a4 -- a8; a4 -- a9; a5 -- a10; a5 -- a11; a6 -- a12;\n\n    { node[style=invis]; edge[style=invis];\n      a6 -- a13; a7 -- a14; a7 -- a15;\n    }\n  }\n\n  subgraph B {\n    b1[label=1 style=filled];\n    b2[label=13];\n    b3[label=9];\n    b4[label=5];\n    b5[label=12];\n    b6[label=8];\n    b7[label=7];\n    b8[label=4];\n    b9[label=0];\n    b10[label=6];\n    b11[label=2];\n\n    b1 -- b2; b1 -- b3;\n    b2 -- b4; b2 -- b5; b3 -- b6;  b3 -- b7;\n    b4 -- b8; b4 -- b9; b5 -- b10; b5 -- b11;\n\n    { node[style=invis]; edge[style=invis];\n      b6 -- b12; b6 -- b13; b7 -- b14; b7 -- b15;\n    }\n  }\n\n  subgraph C {\n    c1[label=13];\n    c2[label=12];\n    c3[label=9];\n    c4[label=5];\n    c5[label=6];\n    c6[label=8];\n    c7[label=7];\n    c8[label=4];\n    c9[label=0];\n    c10[label=1 style=filled];\n    c11[label=2];\n\n    c1 -- c2; c1 -- c3;\n    c2 -- c4; c2 -- c5; c3 -- c6;  c3 -- c7;\n    c4 -- c8; c4 -- c9; c5 -- c10; c5 -- c11;\n\n    { node[style=invis]; edge[style=invis];\n      c6 -- c12; c6 -- c13; c7 -- c14; c7 -- c15;\n    }\n  }\n}\n"
  },
  {
    "path": "other/clrs/06/05/01.markdown",
    "content": "> Illustrate the operation `HEAP-EXTRACT-MAX` on the heap $A =\n> \\langle 15, 13, 9, 5, 12, 8, 7, 4, 0, 6, 2, 1 \\rangle$.\n"
  },
  {
    "path": "other/clrs/06/05/02.dot",
    "content": "graph MaxHeapInsert {\n  node[shape=circle, fixedsize=true];\n\n  subgraph A {\n    a1[label=15];\n    a2[label=13];\n    a3[label=9];\n    a4[label=5];\n    a5[label=12];\n    a6[label=8];\n    a7[label=7];\n    a8[label=4];\n    a9[label=0];\n    a10[label=6];\n    a11[label=2];\n    a12[label=1];\n    a13[label=10 style=filled];\n\n    a1 -- a2; a1 -- a3;\n    a2 -- a4; a2 -- a5; a3 -- a6;  a3 -- a7;\n    a4 -- a8; a4 -- a9; a5 -- a10; a5 -- a11; a6 -- a12; a6 -- a13;\n\n    { node[style=invis]; edge[style=invis];\n      a7 -- a14; a7 -- a15;\n    }\n  }\n\n  subgraph B {\n    b1[label=15];\n    b2[label=13];\n    b3[label=9];\n    b4[label=5];\n    b5[label=12];\n    b6[label=10 style=filled];\n    b7[label=7];\n    b8[label=4];\n    b9[label=0];\n    b10[label=6];\n    b11[label=2];\n    b12[label=1];\n    b13[label=8];\n\n    b1 -- b2; b1 -- b3;\n    b2 -- b4; b2 -- b5; b3 -- b6;  b3 -- b7;\n    b4 -- b8; b4 -- b9; b5 -- b10; b5 -- b11; b6 -- b12; b6 -- b13;\n\n    { node[style=invis]; edge[style=invis];\n      b7 -- b14; b7 -- b15;\n    }\n  }\n\n  subgraph C {\n    c1[label=15];\n    c2[label=13];\n    c3[label=10 style=filled];\n    c4[label=5];\n    c5[label=12];\n    c6[label=9];\n    c7[label=7];\n    c8[label=4];\n    c9[label=0];\n    c10[label=6];\n    c11[label=2];\n    c12[label=1];\n    c13[label=8];\n\n    c1 -- c2; c1 -- c3;\n    c2 -- c4; c2 -- c5; c3 -- c6;  c3 -- c7;\n    c4 -- c8; c4 -- c9; c5 -- c10; c5 -- c11; c6 -- c12; c6 -- c13;\n\n    { node[style=invis]; edge[style=invis];\n      c7 -- c14; c7 -- c15;\n    }\n  }\n}\n"
  },
  {
    "path": "other/clrs/06/05/02.markdown",
    "content": "> Illustrate the operation of `MAX-HEAP-INSERT(A, 10)` on the heap $A = \\langle\n> 15, 13, 9, 5, 12, 8, 7, 4, 0, 6, 2, 1 \\rangle$.\n"
  },
  {
    "path": "other/clrs/06/05/03.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <limits.h>\n\n#define PARENT(i) ((i - 1) / 2)\n#define LEFT(i)   (2 * i + 1)\n#define RIGHT(i)  (2 * i + 2)\n\ntypedef struct {\n    int *elements;\n    int length;\n    int heap_size;\n} heap_t;\n\nint heap_minimum(heap_t *heap) {\n    return heap->elements[0];\n}\n\nvoid min_heapify(heap_t *heap, int i) {\n    int left  = LEFT(i),\n        right = RIGHT(i),\n        smallest;\n\n    if (left < heap->heap_size && heap->elements[left] < heap->elements[i]) {\n        smallest = left;\n    } else {\n        smallest = i;\n    }\n\n    if (right < heap->heap_size && heap->elements[right] < heap->elements[smallest]) {\n        smallest = right;\n    }\n\n    if (smallest != i) {\n        int tmp = heap->elements[i];\n        heap->elements[i] = heap->elements[smallest];\n        heap->elements[smallest] = tmp;\n\n        min_heapify(heap, smallest);\n    }\n}\n\nint heap_extract_min(heap_t *heap) {\n    if (heap->heap_size == 0) {\n        fprintf(stderr, \"heap underflow\");\n        exit(0);\n    }\n\n    int min = heap->elements[0];\n    heap->elements[0] = heap->elements[heap->heap_size - 1];\n    heap->heap_size--;\n    min_heapify(heap, 0);\n\n    return min;\n}\n\nvoid heap_decrease_key(heap_t *heap, int i, int key) {\n    if (key > heap->elements[i]) {\n        fprintf(stderr, \"new key is larger than current key\");\n        exit(0);\n    }\n\n    heap->elements[i] = key;\n    while (i > 0 && heap->elements[PARENT(i)] > heap->elements[i]) {\n        int tmp = heap->elements[PARENT(i)];\n        heap->elements[PARENT(i)] = heap->elements[i];\n        heap->elements[i] = tmp;\n        i = PARENT(i);\n    }\n}\n\nvoid min_heap_insert(heap_t *heap, int key) {\n    if (heap->length == heap->heap_size) {\n        fprintf(stderr, \"heap overflow\");\n        exit(0);\n    }\n\n    heap->elements[heap->heap_size] = INT_MAX;\n    heap->heap_size++;\n    heap_decrease_key(heap, heap->heap_size - 1, key);\n}\n"
  },
  {
    "path": "other/clrs/06/05/03.markdown",
    "content": "> Write pseudocode for the procedures `HEAP-MINIMUM`, `HEAP-EXTRACT-MIN`,\n> `HEAP-DECREASE-KEY`, and `MIN-HEAP-INSERT` that implement a min-priority\n> queue with a min-heap.\n\nPseudocode? Why, let's do some real code!\n"
  },
  {
    "path": "other/clrs/06/05/03.test.c",
    "content": "#include \"03.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(heap_minumum) {\n    int numbers[] = {1, 2, 4};\n    heap_t heap = {numbers, 3, 3};\n\n    ASSERT_EQUALS(heap_minimum(&heap), 1);\n}\n\nTEST(heap_extract_min) {\n    int actual[]   = {1, 2, 4, 3, 5, 7},\n        expected[] = {2, 3, 4, 7, 5};\n\n    heap_t heap = {actual, 6, 6};\n\n    int min = heap_extract_min(&heap);\n\n    ASSERT_EQUALS(min, 1);\n    ASSERT_EQUALS(heap.heap_size, 5);\n    ASSERT_SAME_ARRAYS_S(heap.elements, expected, 5);\n}\n\nTEST(heap_decrease_key) {\n    int actual[]   = {1, 2, 4, 3, 5},\n        expected[] = {0, 1, 4, 3, 2};\n\n    heap_t heap = {actual, 5, 5};\n    heap_decrease_key(&heap, 4, 0);\n\n    ASSERT_SAME_ARRAYS(actual, expected);\n}\n\nTEST(min_heap_insert) {\n    int actual[]   = {1, 3, 4, 6, 5, -1},\n        expected[] = {1, 3, 2, 6, 5, 4};\n\n    heap_t heap = {actual, 6, 5};\n    min_heap_insert(&heap, 2);\n\n    ASSERT_SAME_ARRAYS(actual, expected);\n}\n"
  },
  {
    "path": "other/clrs/06/05/04.markdown",
    "content": "> Why do we bother setting the key of the inserted node to $-\\infty$ in line 2\n> of `MAX-HEAP-INSERT` when the next thing we do is increase its key to the\n> desired value?\n\nIn order to pass the guard clause. Otherwise we have to drop the check if $key\n< A[i]$.\n"
  },
  {
    "path": "other/clrs/06/05/05.markdown",
    "content": "> Argue the correctness of `HEAP-INCREASE-KEY` using the following loop\n> invariant:\n>\n> > At the start of each iteration of the **while** loop of lines 4-6, the\n> > subarray $A[1 \\ldots A.heap\\text{-}size]$ satisfies the max-heap property,\n> > except that there may be one violation: $A[i]$ may be larger than\n> > $A[\\text{PARENT}(i)]$.\n>\n> You may assume that the subarray $A[1 \\ldots A.heap\\text{-}size]$ satisfies\n> the max-heap property at the time `HEAP-INCREASE-KEY` is called.\n\n**Initialization**. $A$ is a heap except that $A[i]$ might be larger that it's\nparent, because it has been modified. $A[i]$ is larger than its children,\nbecause otherwise the guard clause would fail and the loop will not be entered\n(the new value is larger than the old value and the old value is larger than\nthe children).\n\n**Maintenance**. When we exchange $A[i]$ with its parent, the max-heap property\nis satisfied except that now $A[\\text{PARENT}(i)]$ might be larger than its\nparent. Changing $i$ to its parent maintains the invariant.\n\n**Termination**. The loop terminates whenever the heap is exhausted or the\nmax-heap property for $A[i]$ and its parent is preserved. At the loop\ntermination, $A$ is a max-heap.\n"
  },
  {
    "path": "other/clrs/06/05/06.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <limits.h>\n\n#define PARENT(i) ((i - 1) / 2)\n#define LEFT(i)   (2 * i + 1)\n#define RIGHT(i)  (2 * i + 2)\n\ntypedef struct {\n    int *elements;\n    int length;\n    int heap_size;\n} heap_t;\n\nvoid heap_increase_key(heap_t *heap, int i, int key) {\n    if (key < heap->elements[i]) {\n        fprintf(stderr, \"new key is larger than current key\");\n        exit(0);\n    }\n\n    while (i > 0 && heap->elements[PARENT(i)] < key) {\n        heap->elements[i] = heap->elements[PARENT(i)];\n        i = PARENT(i);\n    }\n    heap->elements[i] = key;\n}\n"
  },
  {
    "path": "other/clrs/06/05/06.markdown",
    "content": "> Each exchange operation on line 5 of `HEAP-INCREASE-KEY` typically requires\n> three assignments. Show how to use the idea of the inner loop of\n> `INSERTION-SORT` to reduce the three assignments down to just one assignment.\n\nHere we really need the set to $- \\infty$.\n"
  },
  {
    "path": "other/clrs/06/05/06.test.c",
    "content": "#include \"06.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(heap_increase_key) {\n    int actual[]   = {16, 14, 10,  8, 7, 9, 3, 2, 4, 1},\n        expected[] = {16, 15, 10, 14, 7, 9, 3, 2, 8, 1};\n\n    heap_t heap = {actual, 10, 10};\n    heap_increase_key(&heap, 8, 15);\n\n    ASSERT_SAME_ARRAYS(actual, expected);\n}\n"
  },
  {
    "path": "other/clrs/06/05/07.markdown",
    "content": "> Show how to implement a first-in, first-out queue with a priority queue. Show\n> how to implement a stack with a priority queue. (Queues and stacks are\n> defined in section 10.1).\n\nBoth are simple. For a stack we keep adding elements in increasing priority,\nwhile in a queue we add them in decreasing priority. For the stack we can set\nthe new priority to `HEAP-MAXIMUM(A) + 1`. For the queue we need to keep track\nof it and decrease it on every insertion.\n\nBoth are not very efficient. Furthermore, if the priority can overflow or\nunderflow, so will eventually need to reassign priorities.\n"
  },
  {
    "path": "other/clrs/06/05/08.markdown",
    "content": "> The operation `HEAP-DELETE(A,i)` deletes the item in node $i$ from heap $A$.\n> Give an implementation of `HEAP-DELETE` that runs in $\\O(\\lg{n})$ time for an\n> $n$-element max-heap.\n\nThis is the pseudocode is as follows:\n\n    HEAP-DELETE(A, i):\n      A[i] = A[A.heap-size]\n      A.heap-size -= 1\n      MAX-HEAPIFY(A, i)\n\nWe just move the last element of the heap to the deleated position and then\ncall `MAX-HEAPIFY` on it. This works, because the element is already smaller\nthan its parent (because it was already under it on the heap), but might be\nlarger than its children. `MAX-HEAPIFY` restored the heap property.\n"
  },
  {
    "path": "other/clrs/06/05/09.markdown",
    "content": "> Give an $\\O(n\\lg{k})$-time algorithm to merge $k$ sorted lists into one\n> sorted list, where $n$ is the total number of elements in all the input\n> lists. (Hint: Use a min-heap for $k$-way merging).\n\nWe take one element of each list and put it in a min-heap. Along with each\nelement we have to track which list we took it from. When merging, we take the\nminimum element from the heap and insert another element off the list it came\nfrom (unless the list is empty). We continue until we empty the heap.\n\nWe have $n$ steps and at each step we're doing an insertion into the heap,\nwhich is $\\lg{k}$.\n"
  },
  {
    "path": "other/clrs/06/problems/01.markdown",
    "content": "## Building a heap using insertion\n\n> We can build a heap by repeatedly calling `MAX-HEAP-INSERT` to insert the\n> elements into the heap. Consider the following variation of the\n> `BUILD-MAX-HEAP` procedure.\n>\n>     BUILD-MAX-HEAP'(A)\n>       A.heap-size = 1\n>       for i = 2 to A.length\n>           MAX-HEAP-INSERT(A, A[i])\n>\n> 1. Do the procedures `BUILD-MAX-HEAP` and `BUILD-MAX-HEAP'` always create the\n>    same heap when run on the same input array? Prove that they do, or provide\n>    a counterexample.\n> 2. Show that in the worst case, `BUILD-MAX-HEAP'` requires $\\Theta(n\\lg{n})$\n>    time to build a $n$-element heap.\n\n### Same heaps?\n\nNo. They produce different heaps. This is illustrated with $\\langle 1, 2, 3, 4,\n5, 6 \\rangle$. Results are shown below.\n\n### Complexity\n\n`MAX-HEAP-INSERT` is a $\\Theta(\\lg{n})$ operation in the worst case and it gets\ncalled $n - 1$ times. `MAX-HEAP-INSERT` might need to pull each element up to\nthe beginning of the heap, that is, $\\lg{k}$ operations whatever $k$ currently\nis. The worst case happens when the array is sorted. Thus the complexity is:\n\n$$ \\sum_{i=2}^{n}\\lg{i} = \\lg(n!) = \\Theta(n\\lg{n})$$\n\nThe above is due to exercise 3.2.3.\n"
  },
  {
    "path": "other/clrs/06/problems/01.py",
    "content": "##############################################################################\n# DATA STRUCTURES\n##############################################################################\n\nclass heap:\n    def __init__(self, items, size = None):\n        self.items = items\n        self.heap_size = size or len(items)\n\n    def __getitem__(self, key):\n        return self.items[key]\n\n    def __setitem__(self, key, value):\n        self.items[key] = value\n\n    def __len__(self):\n        return len(self.items)\n\ndef left(i):\n    return 2 * i + 1\n\ndef right(i):\n    return 2 * i + 2\n\ndef parent(i):\n    return (i - 1) // 2\n\n##############################################################################\n# Standard BUILD-MAX-HEAP\n##############################################################################\n\ndef max_heapify(A, i):\n    l = left(i)\n    r = right(i)\n    if l < A.heap_size and A[l] > A[i]:\n        largest = l\n    else:\n        largest = i\n    if r < A.heap_size and A[r] > A[largest]:\n        largest = r\n\n    if largest != i:\n        A[i], A[largest] = A[largest], A[i]\n        max_heapify(A, largest)\n\ndef build_max_heap(A):\n    A.heap_size = len(A)\n    for i in range(len(A) // 2, -1, -1):\n        max_heapify(A, i)\n\n##############################################################################\n# Exercise BUILD-MAX-HEAP'\n##############################################################################\n\ndef heap_increase_key(A, i, key):\n    if key < A[i]:\n        raise Exception(\"new key is smaller than current key\")\n    A[i] = key\n    while i > 0 and A[parent(i)] < A[i]:\n        A[i], A[parent(i)] = A[parent(i)], A[i]\n        i = parent(i)\n\ndef max_heap_insert(A, key):\n    A.heap_size += 1\n    A[A.heap_size - 1] = float(\"-inf\")\n    heap_increase_key(A, A.heap_size - 1, key)\n\ndef build_max_heap2(A):\n    A.heap_size = 1\n    for i in range(1, len(A)):\n        max_heap_insert(A, A[i])\n"
  },
  {
    "path": "other/clrs/06/problems/01.run.py",
    "content": "import os.path as path\nimport random\nimport time\n\nfilename = path.join(path.dirname(__file__), '01.py')\nexec(open(filename).read())\n\ndata  = [1, 2, 3, 4, 5, 6]\nfuncs = [(\"BUILD-MAX-HEAP: \", build_max_heap), (\"BUILD-MAX-HEAP':\", build_max_heap2)]\n\nprint('Heap builds for: {}'.format(', '.join(map(str, data))))\nprint('---------------------------------')\n\nfor (label, func) in funcs:\n    h = heap(data[:])\n    func(h)\n    print('{} {}'.format(label, ', '.join(str(item) for item in h.items)))\n"
  },
  {
    "path": "other/clrs/06/problems/02.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <limits.h>\n\n#define PARENT(i,d) ((i - 1) / d)\n#define CHILD(i,c,d) (3 * i + c + 1)\n\ntypedef struct {\n    int *elements;\n    int d;\n    int heap_size;\n    int length;\n} heap_t;\n\nvoid max_heapify(heap_t *heap, int i) {\n    int largest = i;\n\n    for (int k = 0; k < heap->d; k++) {\n        int child = CHILD(i, k, heap->d);\n        if (child < heap->heap_size && heap->elements[child] > heap->elements[largest])\n            largest = child;\n    }\n\n    if (largest != i) {\n        int tmp = heap->elements[i];\n        heap->elements[i] = heap->elements[largest];\n        heap->elements[largest] = tmp;\n\n        max_heapify(heap, largest);\n    }\n}\n\nint extract_max(heap_t *heap) {\n    int max = heap->elements[0];\n    heap->elements[0] = heap->elements[heap->heap_size - 1];\n    heap->heap_size--;\n    max_heapify(heap, 0);\n    return max;\n};\n\nvoid increase_key(heap_t *heap, int i, int key) {\n    if (key < heap->elements[i]) {\n        exit(0);\n        fprintf(stderr, \"new key is smaller than current key\\n\");\n    }\n\n    while (i > 0 && heap->elements[PARENT(i,heap->d)] < key) {\n        heap->elements[i] = heap->elements[PARENT(i,heap->d)];\n        i = PARENT(i,heap->d);\n    }\n\n    heap->elements[i] = key;\n}\n\nvoid insert(heap_t *heap, int key) {\n    heap->heap_size++;\n    heap->elements[heap->heap_size - 1] = INT_MIN;\n    increase_key(heap, heap->heap_size - 1, key);\n}\n"
  },
  {
    "path": "other/clrs/06/problems/02.markdown",
    "content": "## Analysis of d-ary heaps\n\n> A **d-ary heap** is like a binary heap, but (with one possible exception)\n> non-leaf nodes have $d$ children instead of 2 children.\n>\n> 1. How would you represent a $d$-ary heap in an array?\n> 2. What is the height of a $d$-ary heap of $n$ elements in terms of $n$ and\n>    $d$?\n> 3. Give an efficient implementation of `EXTRACT-MAX` in a $d$-ary max-heap.\n>    Analyze its running time in terms of $d$ and $n$.\n> 4. Give an efficient implementation of `INSERT` in $d$-ary max-heap. Analyze\n>    its running time in terms of $d$ and $n$.\n> 5. Give an efficient implementation of `INCREASE-KEY(A, i, k)`, which flags\n>    an error if $k < A[i]$, but otherwise sets $A[i] = k$ and then updates the\n>    $d$-ary max-heap structure appropriately. Analyze its running time in\n>    terms of $d$ and $n$.\n\n### Representation\n\nWe just modify `LEFT`, `RIGHT` and `PARENT`. We can get the $k$-th child of the\n$i$th node with $d i + k - 1$ and the parent with $\\lfloor i/d \\rfloor$ (when\nindexing is 1-based).\n\n### Height\n\nOf course it's $\\log_dn$.\n\n### Implementation\n\nThe implementation is below. The complexity of `EXTRACT-MAX` is\n$\\O(d\\log_dn)$, while the other two are $\\O(\\log_dn)$.\n"
  },
  {
    "path": "other/clrs/06/problems/02.test.c",
    "content": "#include \"02.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(extract_min) {\n    int actual[]   = {13,   12, 10, 11,   5, 9, 8,   1, 7, 2,   4, 6, 3},\n        expected[] = {12,    9, 10, 11,   5, 3, 8,   1, 7, 2,   4, 6};\n\n    heap_t heap = {actual, 3, 13, 13};\n\n    int max = extract_max(&heap);\n    ASSERT_EQUALS(max, 13);\n    ASSERT_EQUALS(heap.heap_size, 12);\n    ASSERT_SAME_ARRAYS_S(heap.elements, expected, 12);\n}\n\nTEST(insert) {\n    int actual[]   = {14,   12, 10, 11,   5, 9, 8,   1, 7, 2,   4, 6, -1},\n        expected[] = {14,   12, 10, 13,   5, 9, 8,   1, 7, 2,   4, 6, 11};\n\n    heap_t heap = {actual, 3, 12, 13};\n\n    insert(&heap, 13);\n    ASSERT_EQUALS(heap.heap_size, 13);\n    ASSERT_SAME_ARRAYS_S(heap.elements, expected, 13);\n}\n"
  },
  {
    "path": "other/clrs/06/problems/03.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <stdbool.h>\n#include <limits.h>\n\ntypedef struct {\n    int i;\n    int j;\n} cell;\n\ntypedef struct {\n    int *elements;\n    int m;\n    int n;\n} tableau_t;\n\ncell up(cell c) {\n    cell result = {c.i - 1, c.j};\n    return result;\n}\n\ncell down(cell c) {\n    cell result = {c.i + 1, c.j};\n    return result;\n}\n\ncell left(cell c) {\n    cell result = {c.i, c.j - 1};\n    return result;\n}\n\ncell right(cell c) {\n    cell result = {c.i, c.j + 1};\n    return result;\n}\n\ncell make_cell(int i, int j) {\n    cell result = {i, j};\n    return result;\n}\n\nbool within(tableau_t *tableau, cell c) {\n    return (c.i >= 0 && c.j >= 0 && c.i < tableau->m && c.j < tableau->n);\n}\n\nint get(tableau_t *tableau, cell c) {\n    int index = c.i * tableau->n + c.j;\n    return tableau->elements[index];\n}\n\nvoid set(tableau_t *tableau, cell c, int value) {\n    int index = c.i * tableau->n + c.j;\n    tableau->elements[index] = value;\n}\n\nvoid init_empty_tableau(tableau_t *tableau) {\n    for (int i = 0; i < tableau->m * tableau-> n; i++) {\n        tableau->elements[i] = INT_MAX;\n    }\n}\n\nint extract_min(tableau_t *tableau) {\n    int min, new;\n    cell current = {0, 0},\n         next;\n\n    new = INT_MAX;\n    min = get(tableau, current);\n\n    set(tableau, current, INT_MAX);\n\n    while (true) {\n        int smallest;\n        cell d = down(current);\n        cell r = right(current);\n\n        if (within(tableau, d) && get(tableau, d) < new) {\n            next = d;\n            smallest = get(tableau, next);\n        } else {\n            smallest = new;\n        }\n\n        if (within(tableau, r) && get(tableau, r) < smallest) {\n            next = r;\n            smallest = get(tableau, next);\n        }\n\n        if (new == smallest) {\n            set(tableau, current, new);\n            break;\n        }\n\n        set(tableau, current, smallest);\n        current = next;\n    }\n\n    return min;\n}\n\nvoid insert(tableau_t *tableau, int key) {\n    cell current = make_cell(tableau->m - 1, tableau->n - 1),\n         next;\n\n    if (get(tableau, current) != INT_MAX) {\n        fprintf(stderr, \"tableau is full\\n\");\n        exit(0);\n    }\n\n    while (true) {\n        int largest;\n        cell u = up(current);\n        cell l = left(current);\n\n        if (within(tableau, u) && get(tableau, u) > key) {\n            next = u;\n            largest = get(tableau, next);\n        } else {\n            largest = key;\n        }\n\n        if (within(tableau, l) && get(tableau, l) > largest) {\n            next = l;\n            largest = get(tableau, next);\n        }\n\n        if (key == largest) {\n            set(tableau, current, key);\n            break;\n        }\n\n        set(tableau, current, largest);\n        current = next;\n    }\n}\n\nvoid sort(int *array, int size_sqrt) {\n    int elements[size_sqrt * size_sqrt];\n    tableau_t tableau = {elements, size_sqrt, size_sqrt};\n\n    init_empty_tableau(&tableau);\n\n    for (int i = 0; i < size_sqrt * size_sqrt; i++) {\n        insert(&tableau, array[i]);\n    }\n\n    for (int i = 0; i < size_sqrt * size_sqrt; i++) {\n        int next = extract_min(&tableau);\n        array[i] = next;\n    }\n}\n\nbool find(tableau_t *tableau, int key) {\n    cell c = {tableau->m - 1, 0};\n\n    while (within(tableau, c)) {\n        int value = get(tableau, c);\n\n        if (value == key) {\n            return true;\n        } else if (value > key) {\n            c = up(c);\n        } else {\n            c = right(c);\n        }\n    }\n\n    return false;\n}\n"
  },
  {
    "path": "other/clrs/06/problems/03.markdown",
    "content": "## Young tableaus\n\n> An $m \\times n$ **Young tableau** is an $m \\times n$ matrix such that the\n> entries of each row are in sorted order from left to right and the entries of\n> each column are in sorted order from top to bottom. Some of the entries of a\n> Young tableau may be $\\infty$, which we treat as nonexistent elements. Thus,\n> a Young tableau can be used to hold $r \\le mn$ finite numbers.\n>\n> 1. Draw $4 \\times 4$ tableau containing the elements $\\\\{9, 16, 3, 2, 4, 8,\n>    5, 14, 12\\\\}$\n> 2. Argue that an $m \\times n$ Young tableau $Y$ is empty if $Y[1, 1] =\n>    \\infty$. Argue that $Y$ is full (contains $mn$ elements) if $Y[m, n] <\n>    \\infty$.\n> 3. Give an algorithm to implement `EXTRACT-MIN` on a nonempty $m \\times n$\n>    Young tableau that runs in $\\O(m + n)$ time. Your algorithm should use a\n>    recursive subroutine that solves an $m \\times n$ problem by recursively\n>    solving either an $(m - 1) \\times n$ or an $m \\times (n - 1)$ subproblem.\n>    (Hint: Think about `MAX-HEAPIFY`.) Define $T(p)$ where $p = m + n$, to be\n>    the maximum running time of `EXTRACT-MIN` on any $m \\times n$ Young\n>    tableau. Give and solve a recurrence relation for $T(p)$ that yields the\n>    $\\O(m + n)$ time bound.\n> 4. Show how to insert a new element into a nonfull $m \\times n$ Young tableau\n>    in $\\O(m + n)$ time\n> 5. Using no other sorting method as a subroutine, show how to use an $n\n>    \\times n$ Young tableau to sort $n^2$ numbers in $\\O(n^3)$ time.\n> 6. Give an $\\O(m + n)$-time algorithm to determine whether a given number is\n>    stored in a given $m \\times n$ Young tableau.\n\n### Draw a tableau\n\n$$ \\begin{matrix}\n        2 &      3 &     12 &     14 \\\\\\\\\n        4 &      8 &     16 & \\infty \\\\\\\\\n        5 &      9 & \\infty & \\infty \\\\\\\\\n   \\infty & \\infty & \\infty & \\infty \\\\\\\\\n   \\end{matrix} $$\n\n### Empty and full\n\nIf the top left element is $\\infty$, then all the elements on the first row\nneed to be $\\infty$. But if this is the case, all other elements need to be\n$\\infty$ because they are larger than the first element on their column.\n\nIf the bottom right element is smaller than $\\infty$, all the elements on the\nbottom row need to be smaller than $\\infty$. But so are the other elements in\nthe tableau, because each is smaller than the bottom element of its column.\n\n### Extracting a minimum element\n\nThe $A[1, 1]$ is the smallest elemnt. We store it, so we can return it later\nand then replace is with $\\infty$. This breaks the Young tableau property and\nwe need to perform a procedure, similar to `MAX-HEAPIFY` to restore it.\n\nWe compare $A[i, j]$ with each of its neighbours and exchange it with the\nsmallest. This restores the property for $A[i, j]$ but reduces the problem to\neither $A[i, j+1]$ or $A[i+1, j]$. We terminate when $A[i,j]$ is smaller than\nits neighbours.\n\nThe relation in question is:\n\n$$ T(p) = T(p - 1) + \\O(1) = T(p-2) + \\O(1) + \\O(1) = \\ldots = \\O(p) $$\n\n### Inserting a new element\n\nThe algorithm is very similar to the previous, except that we start with the\nbottom right element of the tableau and move it upwards and leftwards to the\ncorrect position. The asymptotic analysis is the same.\n\n### Sorting\n\nWe can sort by starting with an empty tableau and inserting all the $n^2$\nelements in it. Each insertion is $\\O(n + n) = \\O(n)$. The complexity is\n$n^2\\O(n) = \\O(n^3)$. Afterwards we can take them one by one and put them back\nin the original array which has the same complexity. In total, its $\\O(n^3)$.\n\nWe can also do it in place if we allow for \"partial\" tableaus where only a\nportion of the top rows (and a portion of the last of them) is in the tableau.\nThen we can build the tableau in place and then start putting each minimal\nelement to the end. This would be asymptotically equal, but use constant\nmemory. It would also sort the array in reverse.\n\n### Finding\n\nWe from the lower-left corner. We check the current element $current$ with the\none we're looking for $key$ and move up if $current > key$ and right if\n$current < key$. We declare success if $current = key$ and otherwise terminate\nif we walk off the tableau.\n"
  },
  {
    "path": "other/clrs/06/problems/03.test.c",
    "content": "#include \"03.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(extract_min) {\n    int actual[]   = {  1,   3,   7,   8,\n                        2,   5,   9, 100,\n                        4, 100, 100, 100},\n        expected[] = {  2,   3,   7,   8,\n                        4,   5,   9, 100,\n                      100, 100, 100, INT_MAX};\n\n    tableau_t tableau = {actual, 3, 4};\n\n    int min = extract_min(&tableau);\n\n    ASSERT_EQUALS(min, 1);\n    ASSERT_SAME_ARRAYS_S(tableau.elements, expected, 12);\n}\n\nTEST(insert) {\n    int actual[]   = {  1,   3,   7,   8,\n                        2,   5,  10, 100,\n                        4, 100, 100, INT_MAX},\n        expected[] = {  1,   3,   7,   8,\n                        2,   5,   9,  10,\n                        4, 100, 100, 100};\n\n    tableau_t tableau = {actual, 3, 4};\n\n    insert(&tableau, 9);\n\n    ASSERT_SAME_ARRAYS_S(tableau.elements, expected, 12);\n}\n\nTEST(sort) {\n    int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},\n        actual[]   = {9, 6, 13, 8, 16, 2, 14, 5, 4, 11, 3, 1, 12, 7, 10, 15};\n\n    sort(actual, 4);\n\n    ASSERT_SAME_ARRAYS(expected, actual);\n}\n\nTEST(find) {\n    int numbers[] = {  1,   3,   7,   8,\n                       2,   5,  10, 100,\n                       4, 100, 100, INT_MAX};\n\n    tableau_t tableau = {numbers, 3, 4};\n\n    ASSERT_TRUE(find(&tableau, 1));\n    ASSERT_TRUE(find(&tableau, 2));\n    ASSERT_TRUE(find(&tableau, 3));\n    ASSERT_TRUE(find(&tableau, 4));\n    ASSERT_TRUE(find(&tableau, 5));\n    ASSERT_TRUE(find(&tableau, 7));\n    ASSERT_TRUE(find(&tableau, 8));\n    ASSERT_TRUE(find(&tableau, 10));\n\n    ASSERT_FALSE(find(&tableau, 0));\n    ASSERT_FALSE(find(&tableau, 6));\n    ASSERT_FALSE(find(&tableau, 9));\n    ASSERT_FALSE(find(&tableau, 11));\n}\n"
  },
  {
    "path": "other/clrs/07/01/01.dot",
    "content": "graph Partition {\n  node [shape=box style=filled fillcolor=white];\n\n  subgraph cluster_A {\n    a1[label=13];\n    a2[label=19];\n    a3[label=3];\n    a4[label=5];\n    a5[label=12];\n    a6[label=8];\n    a7[label=7];\n    a8[label=4];\n    a9[label=21];\n    a10[label=2];\n    a11[label=6];\n    a12[label=11 fillcolor=black fontcolor=white];\n\n    { rank=same; a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12; }\n    { edge[style=invis];\n      a1 -- a2 -- a3 -- a4 -- a5 -- a6 -- a7 -- a8 -- a9 -- a10 -- a11 -- a12;\n    }\n  }\n\n  subgraph cluster_B {\n    b1[label=13 fillcolor=\"#dddddd\"];\n    b2[label=19];\n    b3[label=3];\n    b4[label=5];\n    b5[label=12];\n    b6[label=8];\n    b7[label=7];\n    b8[label=4];\n    b9[label=21];\n    b10[label=2];\n    b11[label=6];\n    b12[label=11 fillcolor=black fontcolor=white];\n\n    { rank=same; b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12; }\n    { edge[style=invis];\n      b1 -- b2 -- b3 -- b4 -- b5 -- b6 -- b7 -- b8 -- b9 -- b10 -- b11 -- b12;\n    }\n  }\n\n  subgraph cluster_C {\n    c1[label=13 fillcolor=\"#dddddd\"];\n    c2[label=19 fillcolor=\"#dddddd\"];\n    c3[label=3];\n    c4[label=5];\n    c5[label=12];\n    c6[label=8];\n    c7[label=7];\n    c8[label=4];\n    c9[label=21];\n    c10[label=2];\n    c11[label=6];\n    c12[label=11 fillcolor=black fontcolor=white];\n\n    { rank=same; c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12; }\n    { edge[style=invis];\n      c1 -- c2 -- c3 -- c4 -- c5 -- c6 -- c7 -- c8 -- c9 -- c10 -- c11 -- c12;\n    }\n  }\n\n  subgraph cluster_D {\n    d1[label=3 fillcolor=\"#999999\"];\n    d2[label=19 fillcolor=\"#dddddd\"];\n    d3[label=13 fillcolor=\"#dddddd\"];\n    d4[label=5];\n    d5[label=12];\n    d6[label=8];\n    d7[label=7];\n    d8[label=4];\n    d9[label=21];\n    d10[label=2];\n    d11[label=6];\n    d12[label=11 fillcolor=black fontcolor=white];\n\n    { rank=same; d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12; }\n    { edge[style=invis];\n      d1 -- d2 -- d3 -- d4 -- d5 -- d6 -- d7 -- d8 -- d9 -- d10 -- d11 -- d12;\n    }\n  }\n\n  subgraph cluster_E {\n    e1[label=3 fillcolor=\"#999999\"];\n    e2[label=5 fillcolor=\"#999999\"];\n    e3[label=13 fillcolor=\"#dddddd\"];\n    e4[label=19 fillcolor=\"#dddddd\"];\n    e5[label=12];\n    e6[label=8];\n    e7[label=7];\n    e8[label=4];\n    e9[label=21];\n    e10[label=2];\n    e11[label=6];\n    e12[label=11 fillcolor=black fontcolor=white];\n\n    { rank=same; e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12; }\n    { edge[style=invis];\n      e1 -- e2 -- e3 -- e4 -- e5 -- e6 -- e7 -- e8 -- e9 -- e10 -- e11 -- e12;\n    }\n  }\n\n  subgraph cluster_F {\n    f1[label=3 fillcolor=\"#999999\"];\n    f2[label=5 fillcolor=\"#999999\"];\n    f3[label=13 fillcolor=\"#dddddd\"];\n    f4[label=19 fillcolor=\"#dddddd\"];\n    f5[label=12 fillcolor=\"#dddddd\"];\n    f6[label=8];\n    f7[label=7];\n    f8[label=4];\n    f9[label=21];\n    f10[label=2];\n    f11[label=6];\n    f12[label=11 fillcolor=black fontcolor=white];\n\n    { rank=same; f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12; }\n    { edge[style=invis];\n      f1 -- f2 -- f3 -- f4 -- f5 -- f6 -- f7 -- f8 -- f9 -- f10 -- f11 -- f12;\n    }\n  }\n\n  subgraph cluster_G {\n    g1[label=3 fillcolor=\"#999999\"];\n    g2[label=5 fillcolor=\"#999999\"];\n    g3[label=8 fillcolor=\"#999999\"];\n    g4[label=19 fillcolor=\"#dddddd\"];\n    g5[label=12 fillcolor=\"#dddddd\"];\n    g6[label=13 fillcolor=\"#dddddd\"];\n    g7[label=7];\n    g8[label=4];\n    g9[label=21];\n    g10[label=2];\n    g11[label=6];\n    g12[label=11 fillcolor=black fontcolor=white];\n\n    { rank=same; g1, g2, g3, g4, g5, g6, g7, g8, g9, g10, g11, g12; }\n    { edge[style=invis];\n      g1 -- g2 -- g3 -- g4 -- g5 -- g6 -- g7 -- g8 -- g9 -- g10 -- g11 -- g12;\n    }\n  }\n\n  subgraph cluster_H {\n    h1[label=3 fillcolor=\"#999999\"];\n    h2[label=5 fillcolor=\"#999999\"];\n    h3[label=8 fillcolor=\"#999999\"];\n    h4[label=7 fillcolor=\"#999999\"];\n    h5[label=12 fillcolor=\"#dddddd\"];\n    h6[label=13 fillcolor=\"#dddddd\"];\n    h7[label=19 fillcolor=\"#dddddd\"];\n    h8[label=4];\n    h9[label=21];\n    h10[label=2];\n    h11[label=6];\n    h12[label=11 fillcolor=black fontcolor=white];\n\n    { rank=same; h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11, h12; }\n    { edge[style=invis];\n      h1 -- h2 -- h3 -- h4 -- h5 -- h6 -- h7 -- h8 -- h9 -- h10 -- h11 -- h12;\n    }\n  }\n\n  subgraph cluster_I {\n    i1[label=3 fillcolor=\"#999999\"];\n    i2[label=5 fillcolor=\"#999999\"];\n    i3[label=8 fillcolor=\"#999999\"];\n    i4[label=7 fillcolor=\"#999999\"];\n    i5[label=4 fillcolor=\"#999999\"];\n    i6[label=13 fillcolor=\"#dddddd\"];\n    i7[label=19 fillcolor=\"#dddddd\"];\n    i8[label=12 fillcolor=\"#dddddd\"];\n    i9[label=21];\n    i10[label=2];\n    i11[label=6];\n    i12[label=11 fillcolor=black fontcolor=white];\n\n    { rank=same; i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12; }\n    { edge[style=invis];\n      i1 -- i2 -- i3 -- i4 -- i5 -- i6 -- i7 -- i8 -- i9 -- i10 -- i11 -- i12;\n    }\n  }\n\n  subgraph cluster_J {\n    j1[label=3 fillcolor=\"#999999\"];\n    j2[label=5 fillcolor=\"#999999\"];\n    j3[label=8 fillcolor=\"#999999\"];\n    j4[label=7 fillcolor=\"#999999\"];\n    j5[label=4 fillcolor=\"#999999\"];\n    j6[label=13 fillcolor=\"#dddddd\"];\n    j7[label=19 fillcolor=\"#dddddd\"];\n    j8[label=12 fillcolor=\"#dddddd\"];\n    j9[label=21 fillcolor=\"#dddddd\"];\n    j10[label=2];\n    j11[label=6];\n    j12[label=11 fillcolor=black fontcolor=white];\n\n    { rank=same; j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12; }\n    { edge[style=invis];\n      j1 -- j2 -- j3 -- j4 -- j5 -- j6 -- j7 -- j8 -- j9 -- j10 -- j11 -- j12;\n    }\n  }\n\n  subgraph cluster_K {\n    k1[label=3 fillcolor=\"#999999\"];\n    k2[label=5 fillcolor=\"#999999\"];\n    k3[label=8 fillcolor=\"#999999\"];\n    k4[label=7 fillcolor=\"#999999\"];\n    k5[label=4 fillcolor=\"#999999\"];\n    k6[label=2 fillcolor=\"#999999\"];\n    k7[label=19 fillcolor=\"#dddddd\"];\n    k8[label=12 fillcolor=\"#dddddd\"];\n    k9[label=21 fillcolor=\"#dddddd\"];\n    k10[label=13 fillcolor=\"#dddddd\"];\n    k11[label=6];\n    k12[label=11 fillcolor=black fontcolor=white];\n\n    { rank=same; k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12; }\n    { edge[style=invis];\n      k1 -- k2 -- k3 -- k4 -- k5 -- k6 -- k7 -- k8 -- k9 -- k10 -- k11 -- k12;\n    }\n  }\n\n  subgraph cluster_L {\n    l1[label=3 fillcolor=\"#999999\"];\n    l2[label=5 fillcolor=\"#999999\"];\n    l3[label=8 fillcolor=\"#999999\"];\n    l4[label=7 fillcolor=\"#999999\"];\n    l5[label=4 fillcolor=\"#999999\"];\n    l6[label=2 fillcolor=\"#999999\"];\n    l7[label=6 fillcolor=\"#999999\"];\n    l8[label=12 fillcolor=\"#dddddd\"];\n    l9[label=21 fillcolor=\"#dddddd\"];\n    l10[label=13 fillcolor=\"#dddddd\"];\n    l11[label=19 fillcolor=\"#dddddd\"];\n    l12[label=11 fillcolor=black fontcolor=white];\n\n    { rank=same; l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12; }\n    { edge[style=invis];\n      l1 -- l2 -- l3 -- l4 -- l5 -- l6 -- l7 -- l8 -- l9 -- l10 -- l11 -- l12;\n    }\n  }\n\n  subgraph cluster_M {\n    m1[label=3 fillcolor=\"#999999\"];\n    m2[label=5 fillcolor=\"#999999\"];\n    m3[label=8 fillcolor=\"#999999\"];\n    m4[label=7 fillcolor=\"#999999\"];\n    m5[label=4 fillcolor=\"#999999\"];\n    m6[label=2 fillcolor=\"#999999\"];\n    m7[label=6 fillcolor=\"#999999\"];\n    m8[label=11 fillcolor=black fontcolor=white];\n    m9[label=21 fillcolor=\"#dddddd\"];\n    m10[label=13 fillcolor=\"#dddddd\"];\n    m11[label=19 fillcolor=\"#dddddd\"];\n    m12[label=12 fillcolor=\"#dddddd\"];\n\n    { rank=same; m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12; }\n    { edge[style=invis];\n      m1 -- m2 -- m3 -- m4 -- m5 -- m6 -- m7 -- m8 -- m9 -- m10 -- m11 -- m12;\n    }\n  }\n\n\n  { edge[style=invis];\n    a1 -- b1 -- c1 -- d1 -- e1 -- f1 -- g1 -- h1 -- i1 -- j1 -- k1 -- l1 -- m1;\n  }\n}\n"
  },
  {
    "path": "other/clrs/07/01/01.markdown",
    "content": "> Using figure 7.1 as a model, illustrate the operation of `PARTITION` on the\n> array $A = \\langle 13, 19, 9, 5, 12, 8, 7, 4, 21, 2, 6, 11 \\rangle$.\n"
  },
  {
    "path": "other/clrs/07/01/02.markdown",
    "content": "> What value of $q$ does `PARTITION` return when all elements in the array $A[p\n> \\ldots r]$ have the same value? Modify `PARTITION` so that $q = \\lfloor\n> (p+r)/2 \\rfloor$ when all elements in the array $A[p \\ldots r]$ have the same\n> value.\n\nIt returns $r$.\n\nWe can modify `PARTITION` by counting the number of comparisons in which $A[j]\n= A[r]$ and then subtracting half that number from the pivot index.\n"
  },
  {
    "path": "other/clrs/07/01/02.py",
    "content": "def partition(numbers, start = 0, end = None):\n    last = end - 1 if end else len(numbers) - 1\n\n    pivot_value = numbers[last]\n    pivot       = start\n    repetitions = 0\n\n    for i in range(start, last):\n        value = numbers[i]\n\n        if value == pivot_value:\n            repetitions += 1\n\n        if value <= pivot_value:\n            numbers[pivot], numbers[i] = numbers[i], numbers[pivot]\n            pivot += 1\n\n    numbers[pivot], numbers[last] = numbers[last], numbers[pivot]\n    return pivot - repetitions // 2\n\ndef quicksort(numbers, start = 0, end = None):\n    end = end if end else len(numbers)\n\n    if start < end - 1:\n        pivot = partition(numbers, start, end)\n        quicksort(numbers, start, pivot)\n        quicksort(numbers, pivot + 1, end)\n"
  },
  {
    "path": "other/clrs/07/01/02.test.py",
    "content": "import unittest\nimport random\nimport os.path as path\nimport random\nimport time\n\nfilename = path.join(path.dirname(__file__), '02.py')\nexec(open(filename).read())\n\nclass PartitionTest(unittest.TestCase):\n    def test_normal_partition(self):\n      numbers = [13, 19, 3, 5, 12, 8, 7, 4, 21, 2, 6, 11]\n      pivot = partition(numbers)\n      self.assertEqual(pivot, 7)\n      self.assertEqual(numbers, [3, 5, 8, 7, 4, 2, 6, 11, 21, 13, 19, 12])\n\n    def test_partition_with_repetition(self):\n      self.assertEqual(partition([2, 2, 2, 2, 2, 2]), 3)\n      self.assertEqual(partition([1, 2, 2, 2, 3, 2]), 3)\n\n    def test_quicksort(self):\n      numbers  = [13, 19, 3, 5, 12, 8, 7, 4, 21, 2, 6, 11]\n      expected = sorted(numbers)\n      quicksort(numbers)\n      self.assertEqual(numbers, expected)\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/07/01/03.markdown",
    "content": "> Give a brief argument that the running time of `PARTITION` on a subarray of\n> size $n$ is $\\Theta(n)$\n\nThere is a **for** statement whose body executes $r - 1 - p = \\Theta(n)$ times.\nIn the worst case every time the body of the **if** is executed, but it takes\nconstant time and so does the code outside of the loop. Thus the running time\nis $\\Theta(n)$.\n"
  },
  {
    "path": "other/clrs/07/01/04.markdown",
    "content": "> How would you modify `QUICKSORT` to sort into nonincreasing order?\n\nWe only need to flip the condition on line 4.\n"
  },
  {
    "path": "other/clrs/07/02/01.markdown",
    "content": "> Use the substitution method to prove that the recurrence $T(n) = T(n-1) +\n> \\Theta(n)$ has the solution $T(n) = \\Theta(n^2)$, as claimed at the beginning\n> of section 7.2\n\nWe represent $\\Theta(n)$ as $c_2n$ and we guess that $T(n) \\le c_1n^2$\n\n$$ \\begin{aligned}\n   T(n) &=   T(n-1) + c_2n \\\\\\\\\n        &\\le c_1(n-1)^2 + c_2n \\\\\\\\\n        &=   c_1n^2 - 2c_1n + c_1 + c_2n & (2c_1 > c_2, n \\ge c_1/(2c_1 - c_2))\\\\\\\\\n        &\\le c_1n^2\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/07/02/02.markdown",
    "content": "> What is the running time of `QUICKSORT` when all elements of the array $A$\n> have the same value?\n\nIt is $\\Theta(n^2)$, since one of the partitions is always empty (see exercise\n7.1.2).\n"
  },
  {
    "path": "other/clrs/07/02/03.markdown",
    "content": "> Show that the running time of `QUICKSORT` is $\\Theta(n^2)$ when the array $A$\n> contains distict elements and is sorted in decreasing order.\n\nIn this case `PARTITION` always returns $p$ because all the elements are\ngreater than the pivot. While the **if** will never be executed, we still get\none empty partition and the recurrence is $T(n) = T(n-1) + \\Theta(n)$ (even if\nits body is not executed, the **for** is still $\\Theta(n)$).\n"
  },
  {
    "path": "other/clrs/07/02/04.markdown",
    "content": "> Banks often record transactions on an account in order of the times of the\n> transactions, but many people like to receive their bank statements with\n> checks listed in order by check numbers. People usually write checks in order\n> by check number, and merchants usually cash them with reasonable dispatch. The\n> problem of converting time-of-transaction ordering to check-number ordering\n> is therefore the problem of sorting almost-sorted input. Argue that the\n> procedure `INSERTION-SORT` would tend to beat the procedure `QUICKSORT` on\n> this problem.\n\nA simple intuitive argument will suffice here.\n\nThe more sorted the array is, the less work insertion sort will do. Namely,\n`INSERTION-SORT` is $\\Theta(n + d)$, where $d$ is the number of inversions in\nthe array. In the example above the number of inversions tends to be small so\ninsertion sort will be close to linear.\n\nOn the other hand, if `PARTITION` does pick a pivot that does not participate\nin an inversion, it will produce an empty partition. Since there is a small\nnumber of inversions, `QUICKSORT` is very likely to produce empty partitions.\n"
  },
  {
    "path": "other/clrs/07/02/05.markdown",
    "content": "> Suppose that the splits at every level of quicksort are in proportion $1 -\n> \\alpha$ to $\\alpha$, where $0 < \\alpha \\le 1/2$ is a constant. Show that the\n> minumum depth of a leaf in the recursion tree is approximately\n> $-\\lg{n}/lg{\\alpha}$ and the maximum depth is approximately\n> $-\\lg{n}/\\lg(1-\\alpha)$. (Don't worry about integer round-off)\n\nThe minimum depth of the tree is the solution of $n\\alpha^x \\le 1$:\n\n$$ n\\alpha^x \\le 1 \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\alpha^x \\le \\frac 1 n \\\\\\\\\n   \\Downarrow \\\\\\\\\n   x \\ge \\log_{\\alpha}\\frac{1}{n} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\log_{\\alpha}\\frac{1}{n} = \\log_{1/\\alpha}\n                            = \\frac{\\lg{n}}{\\lg(1/\\alpha)}\n                            = - \\frac{\\lg{n}}{\\lg{\\alpha}}\n$$\n\nIn the same way, the maximum depth is $\\log_{1/(1-\\alpha)}n = - \\frac{\\lg{n}}{\\lg(1-\\alpha)}$\n"
  },
  {
    "path": "other/clrs/07/02/06.markdown",
    "content": "> $\\star$ Argue that for any constant $0 < \\alpha \\le 1/2$, the probability is\n> approximately $1 - 2\\alpha$ that on a random input array, `PARTITION`\n> produces a split more balanced than $1 - \\alpha$ to $\\alpha$.\n\nOh, this is nice!\n\nIn order to produce a worse split than $\\alpha$ to $1 - \\alpha$, `PARTITION`\nmust pick a pivot that will be either within the smallest $\\alpha n$ elements\nor the largest $\\alpha n$ elements. The probability of either is\n(approximately) $\\alpha n / n = \\alpha$ and the probability of both is\n$2\\alpha$. Thus, the probability of having a better partition is the complement,\n$1 - 2\\alpha$.\n\nSweet!\n"
  },
  {
    "path": "other/clrs/07/03/01.markdown",
    "content": "> Why do we analyze the expected running time of a randomized algorithm and not\n> its worst-case running time?\n\nThe worst-case running time is not triggered by a specific output, but occurs\nrandomly. We're not interested in it, since we cannot reproduce it reliably.\nInstead, it is factored in the analysis of the expected running time.\n"
  },
  {
    "path": "other/clrs/07/03/02.markdown",
    "content": "> When `RANDOMIZED-QUICKSORT` runs, how many calls are made to the random\n> number generator `RANDOM` in the worst case? How about in the best case? Give\n> your answer in terms of $\\Theta$-notation.\n\nIn the worst case, the number of calls to `RANDOM` is:\n\n$$ T(n) = T(n-1) + 1 = n = \\Theta(n) $$\n\nAs for the best case:\n\n$$ T(n) = 2T(n/2) + 1 = \\Theta(n) $$\n\nThis is not too surprising, because each third element (at least) gets picked\nas pivot.\n"
  },
  {
    "path": "other/clrs/07/04/01.markdown",
    "content": "> Show that in the recurrence\n>\n> $$ T(n) = \\max_{0 \\le q \\le n-1} (T(q) + T(n-q-1)) + \\Theta(n) $$\n>\n> $$ T(n) = \\Omega(n^2) $$\n\nWe guess $T(n) \\ge cn^2 - 2n$:\n\n$$ \\begin{aligned}\n   T(n) &=   \\max_{0 \\le q \\le n-1} (T(q) + T(n-q-1)) + \\Theta(n) \\\\\\\\\n        &\\ge \\max_{0 \\le q \\le n-1} (cq^2 - 2q + c(n-q-1)^2 - 2n - 2q -1) + \\Theta(n) \\\\\\\\\n        &\\ge c\\max_{0 \\le q \\le n-1} (q^2 + (n-q-1)^2 - (2n + 4q + 1)/c) + \\Theta(n) \\\\\\\\\n        &\\ge cn^2 - c(2n-1) + \\Theta(n) \\\\\\\\\n        &\\ge cn^2 - 2cn + 2c & (c \\le 1) \\\\\\\\\n        &\\ge cn^2 - 2n\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/07/04/02.markdown",
    "content": "> Show that quicksort's best-case running time is $\\Omega(n\\lg{n})$.\n\nThe best case happens when the partition is even, that is:\n\n$$ T(n) = 2T(n/2) + \\Theta(n) $$\n\nUsing the master method, we get the solution $\\Theta(n\\lg{n})$.\n"
  },
  {
    "path": "other/clrs/07/04/03.markdown",
    "content": "> Show that the expression $q^2 + (n - q - 1)^2$ achieves a maximum over $q =\n> 0, 1, \\ldots, n-1$ when $q = 0$ and $q = n - 1$.\n\n$$ \\begin{aligned}\n   f(q)   &= q^2 + (n - q - 1)^2 \\\\\\\\\n   f'(q)  &= 2q - 2(n - q - 1) = 4q - 2n + 2 \\\\\\\\\n   f''(q) &= 4 \\\\\\\\\n   \\end{aligned} $$\n\n$f'(q) = 0$ when $q = \\frac{1}{2}n - \\frac{1}{4}$. $f'(q)$ is also continious.\n$\\forall q : f''(q) > 0$, which means that $f'(q)$ is negative left of $f'(q) =\n0$ and positive right of it, which means that this is a local minima. In this\ncase, $f(q)$ is decreasing in the beginning of the interval and increasing in\nthe end, which means that those two points are the only candidates for a\nmaximum in the interval.\n\n$$ f(0) = (n - 1)^2 \\\\\\\\\n   f(n-1) = (n - 1)^2 + 0^2 $$\n"
  },
  {
    "path": "other/clrs/07/04/04.markdown",
    "content": "> Show that `RANDOMIZED-QUICKSORT`'s expected running time is\n> $\\Omega(n\\lg{n})$.\n\nWe use the same reasoning for the expected number of comparisons, we just take\nin in a different direction.\n\n$$ \\begin{aligned}\n   \\E[X] &=   \\sum_{i=1}^{n-1} \\sum_{j=i+1}^n \\frac{2}{j-i+1} \\\\\\\\\n         &=   \\sum_{i=1}^{n-1} \\sum_{k=1}^{n-i} \\frac{2}{k + 1} & (k \\ge 1) \\\\\\\\\n         &\\ge \\sum_{i=1}^{n-1} \\sum_{k=1}^{n-i} \\frac{2}{2k} \\\\\\\\\n         &\\ge \\sum_{i=1}^{n-1} \\Omega(\\lg{n}) \\\\\\\\\n         &=   \\Omega(n\\lg{n})\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/07/04/05.c",
    "content": "#define K 550\n\nint partition(int[], int, int);\nvoid limited_quicksort(int[], int, int, int);\nvoid insertion_sort(int[], int, int);\n\nvoid quicksort(int A[], int p, int r) {\n    if (p < r - 1) {\n        int q = partition(A, p, r);\n        quicksort(A, p, q);\n        quicksort(A, q + 1, r);\n    }\n}\n\nvoid modified_quicksort(int A[], int p, int r) {\n    limited_quicksort(A, p, r, K);\n    insertion_sort(A, p, r);\n}\n\nvoid limited_quicksort(int A[], int p, int r, int treshold) {\n    if (r - p > treshold) {\n        int q = partition(A, p, r);\n        limited_quicksort(A, p, q, treshold);\n        limited_quicksort(A, q + 1, r, treshold);\n    }\n}\n\nint partition(int A[], int p, int r) {\n    int x, i, j, tmp;\n\n    x = A[r - 1];\n    i = p;\n\n    for (j = p; j < r - 1; j++) {\n        if (A[j] <= x) {\n            tmp = A[i];\n            A[i] = A[j];\n            A[j] = tmp;\n            i++;\n        }\n    }\n\n    tmp = A[i];\n    A[i] = A[r - 1];\n    A[r - 1] = tmp;\n\n    return i;\n}\n\nvoid insertion_sort(int A[], int p, int r) {\n    int i, j, key;\n\n    for (j = p + 1; j < r; j++) {\n        key = A[j];\n        for (i = j - 1; i >= p && A[i] > key; i--) {\n            A[i + 1] = A[i];\n        }\n        A[i + 1] = key;\n    }\n}\n"
  },
  {
    "path": "other/clrs/07/04/05.markdown",
    "content": "> We can improve the running time of quicksort in practice by taking advantage\n> of the fast running time of insertion sort when its input is \"nearly\" sorted.\n> Upon calling quicksort on a subarray with fewer than $k$ elements, let it\n> simply return without sorting the subarray. After the top-level call to\n> quicksort returns, run insertion sort on the entire array to finish the\n> sorting process. Argue that this sorting algorithm runs in $\\O(nk + n\\lg(n/k))$\n> expected time. How should we pick $k$, both in theory and practice?\n\nIn the quicksort part of the proposed algorithm, the recursion stops at level\n$\\lg(n/k)$, which makes the expected running time $\\O(n\\lg(n/k))$. However,\nthis leaves $n/k$ non-sorted, non-intersecting subarrays of (maximum) length\n$k$.\n\nBecause of the nature of the insertion sort algorithm, it will first sort fully\none such subarray before consider the next one. Thus, it has the same\ncomplexity as sorting each of those arrays, that is $\\frac{n}{k}\\O(k^2) = \\O(nk).$\n\nIn theory, if we ignore the constant factors, we need to solve:\n\n$$ n\\lg{n} \\ge nk + n\\lg{n/k} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\lg{n} \\ge k + \\lg{n} - \\lg{k} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\lg{k} \\ge k $$\n\nWhich is not possible.\n\nIf we add the constant factors, we get:\n\n$$ c_qn\\lg{n} \\ge c_ink + c_qn\\lg(n/k) \\\\\\\\\n   \\Downarrow \\\\\\\\\n   c_q\\lg{n} \\ge c_ik + c_q\\lg{n} - c_q\\lg{k} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\lg{k} \\ge \\frac{c_i}{c_q}k $$\n\nWhich indicates that there might be a good candidate. Furthermore, the\nlower-order terms should be taken into consideration too.\n\nIn practice, $k$ should be chosed by experiment.\n"
  },
  {
    "path": "other/clrs/07/04/05.run.c",
    "content": "#include <stdlib.h>\n#include <stdio.h>\n#include <time.h>\n\n#define SIZE 400000\n#define SEED 300\n\n#include \"05.c\"\n\n#define TIME(message, sort) \\\n    randomize_array(array, SIZE, SEED); \\\n    timer_start_time = clock(); \\\n    sort(array, 0, SIZE); \\\n    printf(message \" = %f\\n\", (double) (clock() - timer_start_time) / CLOCKS_PER_SEC); \\\n    check_sorted(array, SIZE);\n\nstatic clock_t timer_start_time;\n\nvoid randomize_array(int array[], unsigned length, unsigned int seed) {\n    srand(seed);\n    for (unsigned i = 0; i < length; i++) {\n        array[i] = rand() % 1000 + 1;\n    }\n}\n\nvoid check_sorted(int array[], int length) {\n    for (int i = 1; i < length; i++) {\n        if (array[i - 1] > array[i]) {\n            printf(\"%d %d %d %d\\n\", i - 1, i, array[i - 1], array[i]);\n            fprintf(stderr, \"...but the array is not sorted!\");\n            exit(1);\n        }\n    }\n}\n\nint main() {\n    int *array = calloc(SIZE, sizeof(int));\n\n    printf(\"n = %d, k = %d\\n\", SIZE, K);\n    printf(\"-----------------------------\\n\");\n    TIME(\"quicksort         \", quicksort);\n    TIME(\"modified-quicksort\", modified_quicksort);\n\n    return 0;\n}\n"
  },
  {
    "path": "other/clrs/07/04/05.test.c",
    "content": "#include \"05.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(trivial_case) {\n    int array[] = {13, 19, 3, 5, 12, 8, 7, 4, 21, 2, 6, 11},\n        expected[] = {2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 19, 21};\n\n    modified_quicksort(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_SAME_ARRAYS(array, expected);\n}\n"
  },
  {
    "path": "other/clrs/07/04/06.markdown",
    "content": "> $\\star$ Consider modifying the `PARTITION` procedure by randomly picking\n> three elements from array $A$ and partitioning about their median (the middle\n> value of the three elements). Approximate the probability of getting at worst\n> an $\\alpha$-to-$(1-\\alpha)$ split, as a function of $\\alpha$ in the range\n> $0 < \\alpha < 1$.\n\nFirst, for simplicity's sake, let's assume that we can pick the same element\ntwice. Let's also assume that $0 < \\alpha \\le 1/2$.\n\nIn order to get such a split, two out of three elements need need to be in the\nsmallest $\\alpha n$ elements. The probability of having one is $\\alpha n / n =\n\\alpha$. The probability of having exactly two is $\\alpha^2 - \\alpha^3$. There\nare three ways in which two elements can be in the smallest $\\alpha n$ and one\nway in which all three can be in the smallest $\\alpha n$ so the probability of\ngetting such a median is $3\\alpha^2 - 2\\alpha^3$. We will get the same split if\nthe median is in the largest $\\alpha n$. Since the two events are mutually\nexclusive, the probability is:\n\n$$ \\Pr\\\\{\\text{OK split}\\\\} = 6\\alpha^2 - 4\\alpha^3 = 2\\alpha^2(3 - 2\\alpha) $$\n"
  },
  {
    "path": "other/clrs/07/problems/01.c",
    "content": "#include <stdbool.h>\n\nint hoare_partition(int A[], int p, int r) {\n    int x = A[p],\n        i = p - 1,\n        j = r,\n        tmp;\n\n    while(true) {\n        do { j--; } while (!(A[j] <= x));\n        do { i++; } while (!(A[i] >= x));\n\n        if (i < j) {\n            tmp = A[i]; A[i] = A[j]; A[j] = tmp;\n        } else {\n            return j;\n        }\n    }\n}\n\nvoid quicksort(int A[], int p, int r) {\n    if (p < r - 1) {\n        int q = hoare_partition(A, p, r);\n        quicksort(A, p, q + 1);\n        quicksort(A, q + 1, r);\n    }\n}\n"
  },
  {
    "path": "other/clrs/07/problems/01.dot",
    "content": "graph Partition {\n  node[shape=box style=filled fillcolor=white];\n\n  subgraph cluster_A {\n    a1[label=13 fillcolor=black fontcolor=white];\n    a2[label=19];\n    a3[label=9];\n    a4[label=5];\n    a5[label=12];\n    a6[label=8];\n    a7[label=7];\n    a8[label=4];\n    a9[label=11];\n    a10[label=2];\n    a11[label=6];\n    a12[label=21];\n\n    { rank=same; a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12; }\n    { edge[style=invis];\n      a1 -- a2 -- a3 -- a4 -- a5 -- a6 -- a7 -- a8 -- a9 -- a10 -- a11 -- a12;\n    }\n  }\n\n  subgraph cluster_B {\n    b1[label=6 fillcolor=lightgray];\n    b2[label=19];\n    b3[label=9];\n    b4[label=5];\n    b5[label=12];\n    b6[label=8];\n    b7[label=7];\n    b8[label=4];\n    b9[label=11];\n    b10[label=2];\n    b11[label=13 fillcolor=black fontcolor=white];\n    b12[label=21 fillcolor=lightgray];\n\n    { rank=same; b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12; }\n    { edge[style=invis];\n      b1 -- b2 -- b3 -- b4 -- b5 -- b6 -- b7 -- b8 -- b9 -- b10 -- b11 -- b12;\n    }\n  }\n\n  subgraph cluster_C {\n    c1[label=6 fillcolor=lightgray];\n    c2[label=2 fillcolor=lightgray];\n    c3[label=9];\n    c4[label=5];\n    c5[label=12];\n    c6[label=8];\n    c7[label=7];\n    c8[label=4];\n    c9[label=11];\n    c10[label=19 fillcolor=lightgray];\n    c11[label=13 fillcolor=black fontcolor=white];\n    c12[label=21 fillcolor=lightgray];\n\n    { rank=same; c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12; }\n    { edge[style=invis];\n      c1 -- c2 -- c3 -- c4 -- c5 -- c6 -- c7 -- c8 -- c9 -- c10 -- c11 -- c12;\n    }\n  }\n\n  subgraph cluster_D {\n    d1[label=6 fillcolor=lightgray];\n    d2[label=2 fillcolor=lightgray];\n    d3[label=9 fillcolor=lightgray];\n    d4[label=5 fillcolor=lightgray];\n    d5[label=12 fillcolor=lightgray];\n    d6[label=8 fillcolor=lightgray];\n    d7[label=7 fillcolor=lightgray];\n    d8[label=4 fillcolor=lightgray];\n    d9[label=11 fillcolor=lightgray];\n    d10[label=19 fillcolor=black fontcolor=white];\n    d11[label=13 fillcolor=lightgray];\n    d12[label=21 fillcolor=lightgray];\n\n    { rank=same; d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12; }\n    { edge[style=invis];\n      d1 -- d2 -- d3 -- d4 -- d5 -- d6 -- d7 -- d8 -- d9 -- d10 -- d11 -- d12;\n    }\n  }\n\n  { edge[style=invis];\n    a1 -- b1 -- c1 -- d1;\n  }\n}\n"
  },
  {
    "path": "other/clrs/07/problems/01.markdown",
    "content": "## Hoare partition correctness\n\n> The version of `PARTITION` given in this chapter is not the original\n> partitioning algorithm. Here is the original partition algorithm, which is\n> due to C.A.R. Hoare:\n>\n>     HOARE-PARTITION(A, p, r)\n>       x = A[p]\n>       i = p - 1\n>       j = r + 1\n>       while TRUE\n>           repeat\n>               j = j - 1\n>           until A[j] ≤ x\n>           repeat\n>               i = i + 1\n>           until A[i] ≥ x\n>           if i < j\n>               exchange A[i] with A[j]\n>           else return j\n>\n> 1. Demonstrate the operation of `HOARE-PARTITION` on the array $A = \\langle\n>    13, 19, 9, 5, 12, 8, 7, 4, 11, 2, 6, 21 \\rangle$, showing the values of\n>    the array and auxiliary values after each iteration of the **while** loop\n>    in lines 4-13.\n>\n> The next three questions ask you to give a careful argument that the\n> procedure `HOARE-PARTITION` is correct. Assuming that the subarray $A[p..r]$\n> contains at least two elements, prove the following:\n>\n> 2. The indices $i$ and $j$ are such that we never access an element of $A$\n>    outside the subarray $A[p..r]$.\n> 3. When `HOARE-PARTITION` terminates, it returns a value $j$ such that $p \\le\n>    j < r$.\n> 4. Every element of $A[p..j]$ is less than or equal to every element of\n>    $A[j + 1..r]$ when `HOARE-PARTITION` terminates.\n>\n> The `PARTITION` procedure in section 7.1 separates the pivot value\n> (originally in $A[r]$) from the two partitions it forms. The\n> `HOARE-PARTITION` procedure, on the other hand, always places the pivot value\n> (originally in $A[p]$) into one of the two parititions $A[p..j]$ and\n> $A[j + 1..r]$. Since $p \\le j < r$, this split is always nontrivial.\n>\n> 5. Rewrite the `QUICKSORT` procedure to use `HOARE-PARTITION`.\n\n### Demonstration\n\nAt the end of the loop, the variables have the following values:\n\n    x = 13\n    j = 9\n    i = 10\n\n### Correctness\n\nThe indices will not walk of the array. At the first check $i < j$, $i = p$ and\n$j \\ge p$ (because $A[p] = x$). If $i = j$, the algorithm will terminate\nwithout accessing \"invalid\" elements. If $i < j$, the next loop will also have\nindices $i$ and $j$ within the array, (because $i \\le r$ and $j \\ge p$). Note\nthat if one of the indices gets to the end of the array, then $i$ won't be less\nor equal to $j$ any more.\n\nAs for the return value, it will be at least one less than $j$. At the first\niteration, either (1) $A[p]$ is the maximum element and then $i = p$ and $j = p\n< r$ or (2) it is not and $A[p]$ gets swapped with $A[j]$ where $j \\le r$. The\nloop will not terminate and on the next iteration, $j$ gets decremented (before\neventually getting returned). Combining those two cases we get $p \\le j < r$.\n\nFinally, it's easy to observe the following invariant:\n\n> Before the condition comparing $i$ to $j$, all elements $A[p..i-1] \\le x$ and\n> all elements $A[j+1..r] \\ge x$.\n\n**Initialization**. The two **repeat** blocks establish just this condition.\n\n**Maintenance**. By exchanging $A[i]$ and $A[j]$ we make the $A[p..i] \\le x$\nand $A[j..r] \\ge x$. Incrementing $i$ and decrementing $j$ maintain this\ninvariant.\n\n**Termination**. The loop terminates when $i \\ge j$. The invariant still holds\nat termination.\n\nThe third bit follows directly from this invariant.\n\n### Implementation\n\nThere's some C code below.\n"
  },
  {
    "path": "other/clrs/07/problems/01.test.c",
    "content": "#include \"01.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(partitioning) {\n    int array[]    = {13, 19,  9,  5, 12,  8,  7,  4, 11,  2,  6, 21},\n        expected[] = { 6,  2,  9,  5, 12,  8,  7,  4, 11, 19, 13, 21};\n\n    int index = hoare_partition(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_EQUALS(index, 8);\n    ASSERT_SAME_ARRAYS(array, expected);\n}\n\nTEST(sorting) {\n    int array[]    = {13, 19,  9,  5, 12,  8,  7,  4, 11,  2,  6, 21},\n        expected[] = { 2,  4,  5,  6,  7,  8,  9, 11, 12, 13, 19, 21};\n\n    quicksort(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_SAME_ARRAYS(array, expected);\n}\n"
  },
  {
    "path": "other/clrs/07/problems/02.c",
    "content": "#include <stdlib.h>\n\n#define EXCHANGE(a, b) tmp = a; a = b; b = tmp;\n\ntypedef struct {\n    int q;\n    int t;\n} pivot_t;\n\npivot_t partition(int[], int, int);\npivot_t randomized_partition(int[], int, int);\n\nvoid quicksort(int A[], int p, int r) {\n    if (p < r - 1) {\n        pivot_t pivot = randomized_partition(A, p, r);\n        quicksort(A, p, pivot.q);\n        quicksort(A, pivot.t, r);\n    }\n}\n\npivot_t randomized_partition(int A[], int p, int r) {\n    int i = rand() % (r - p) + p,\n        tmp;\n\n    EXCHANGE(A[i], A[r-1]);\n\n    return partition(A, p, r);\n}\n\npivot_t partition(int A[], int p, int r) {\n    int x = A[r - 1],\n        q = p,\n        t,\n        tmp;\n\n    for (int i = p; i < r - 1; i++) {\n        if (A[i] < x) {\n            EXCHANGE(A[q], A[i]);\n            q++;\n        }\n    }\n\n    for (t = q; t < r && A[t] == x; t++);\n\n    for (int i = r - 1; i >= t; i--) {\n        if (A[i] == x) {\n            EXCHANGE(A[t], A[i]);\n            t++;\n        }\n    }\n\n    pivot_t result = {q, t};\n    return result;\n}\n"
  },
  {
    "path": "other/clrs/07/problems/02.markdown",
    "content": "## Quicksort with equal element values\n\n> The analysis of the expected running time of randomized quicksort in section\n> 7.4.2 assumes that all element values are distinct. In this problem. we\n> examine what happens when they are not.\n>\n> 1. Suppose that all element values are equal. What would be randomized\n>    quick-sort's running time in this case?\n> 2. The `PARTITION` procedure returns an index $q$ such that each element of\n>    $A[p \\ldots q - 1]$ is less than or equal to $A[q]$ and each element of\n>    $A[q + 1 \\ldots r]$ is greater than $A[q]$. Modify the `PARTITION`\n>    procedure to produce a procedure `PARTITION'(A, p, r)` which permutes the\n>    elements of $A[p \\ldots r]$ and returns two indices $q$ and $t$ where $p\n>    \\le q \\le t \\le r$, such that:\n>    <ul>\n>      <li>all elements of $A[q \\ldots t]$ are equal,</li>\n>      <li>each element of $A[p \\ldots q - 1]$ is less than $A[q]$, and</li>\n>      <li>each element of $A[t + 1 \\ldots r]$ is greater than $A[q]$.</li>\n>    </ul>\n>    Like `PARTITION`, your `PARTITION'` procedure should take $\\Theta(r - p)$\n>    time.\n> 3. Modify the `RANDOMIZED-QUICKSORT` procedure to call `PARTITION'`, and name\n>    the new procedure `RANDOMIZED-QUICKSORT'`. Then modify the `QUICKSORT`\n>    procedure to produce a procedure `QUICKSORT'(p, r)` that calls\n>    `RANDOMIZED-PARTITION'` and recurses only on partitions of elements not\n>    know to be equal to each other.\n> 4. Using `QUICKSORT'`, how would you adjust the analysis of section 7.4.2 to\n>    avoid the assumption that all elements are distinct?\n\n### Running time\n\nIt will be $\\Theta(n^2)$, because each split will be (n-1)-to-1 (see exercise\n7.1-2).\n\n### Implementation\n\nThe code is below.\n\n`PARTITION'` is very similar to `PARTITION`, except that after it completes\narranging the elements around a pivot $q$, it moves all elements $t > q: A[t] =\nx$ right after $q$. That way we get a chuck of equal elements after the pivot.\n\nThe procedure makes another pass at the array, which is at most $n$ more time\nand becuse $\\Theta(n) + \\Theta(n) = \\Theta(n) = \\Theta(r - p)$ we fulfill the\ncondition.\n\n### Analysis\n\nThe analysis does not change much. Section 7.4.2 uses the knowledge that the\nelements are distinct in order to determine when two elements cannot be\ncompared. It will still be true that in any interval $Z_{ij}$, two elements\nwill get compared only if $z_i$ or $z_j$ gets picked as a pivot first. This\nwould not hold with `PARTITION'` if there are repeated elements.\n\nNote that with this implementation, the number of comparisons increases, but\nonly by a constant factor. The results from the analysis are the same.\n"
  },
  {
    "path": "other/clrs/07/problems/02.test.c",
    "content": "#include \"02.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n#include <stdbool.h>\n\nvoid randomize_array(int array[], unsigned length, unsigned int seed);\nbool is_sorted(int array[], int length);\n\nTEST(partitioning) {\n    int array[]    = {10, 19,  3,  5, 10,  8, 17,  4, 10,  2, 16, 10},\n        expected[] = { 3,  5,  8,  4,  2, 10, 10, 10, 10, 19, 16, 17};\n\n    pivot_t pivot = partition(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_EQUALS(pivot.q, 5);\n    ASSERT_EQUALS(pivot.t, 9);\n    ASSERT_SAME_ARRAYS(array, expected);\n}\n\nTEST(sorting) {\n    int array[]    = {10, 19,  3,  5, 10,  8, 17,  4, 10,  2, 16, 10},\n        expected[] = { 2,  3,  4,  5,  8, 10, 10, 10, 10, 16, 17, 19};\n\n    quicksort(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_SAME_ARRAYS(array, expected);\n}\n\nTEST(large_array) {\n    int size = 100000,\n        seed = 300,\n        array[size];\n\n    randomize_array(array, size, seed);\n\n    quicksort(array, 0, size);\n\n    ASSERT_TRUE(is_sorted(array, size));\n}\n\nvoid randomize_array(int array[], unsigned length, unsigned int seed) {\n    srand(seed);\n    for (unsigned i = 0; i < length; i++) {\n        array[i] = rand() % 100 + 1;\n    }\n}\n\nbool is_sorted(int array[], int length) {\n    for (int i = 1; i < length; i++) {\n        if (array[i - 1] > array[i]) {\n            return false;\n        }\n    }\n    return true;\n}\n"
  },
  {
    "path": "other/clrs/07/problems/03.markdown",
    "content": "## Alternative quicksort analysis\n\n> An alternative analysis of the running time of randomized quicksort focuses\n> on the expected running time of each individual recursive call to\n> `RANDOMIZED-QUICKSORT`, rather than on the number of comparisons performed.\n>\n> 1. Argue that, given an array of size $n$, the probability that any\n>    particular element is chosen as the pivot is $1/n$. Use this to define\n>    indicator random variables $X_i = I\\\\{i\\text{th smallest element is chosen\n>    as the pivot}\\\\}$. What is $\\E[X_i]$?\n> 2. Let $T(n)$ be a random variable denoting the running time of quicksort on\n>    an array of size $n$. Argue that\n>    $$ \\E[T(n)] = \\E\\bigg[\\sum_{q=1}^nX_q(T(q-1) + T(n-q) + \\Theta(n))\\bigg] \\tag{7.5} $$\n> 3. Show that we can rewrite equation (7.5) as\n>    $$ \\E[T(n)] = \\frac{2}{n}\\sum_{q=2}^{n-1}\\E[T(q)] + \\Theta(n) \\tag{7.6} $$\n> 4. Show that\n>    $$ \\sum_{k=2}^{n-1}k\\lg{k} \\le \\frac{1}{2}n^2\\lg{n} - \\frac{1}{8}n^2 \\tag{7.7} $$\n>    (<i>Hint</i>: Split the summation into two parts, one for $k = 2, 3,\n>    \\ldots, \\lceil n/2 \\rceil - 1$ and one for $k = \\lceil n/2 \\rceil, \\ldots,\n>    n - 1$.\n> 5. Using the bound from equation (7.7), show that the recurrence in equation\n>    (7.6) has the solution $\\E[T(n)] = \\Theta(n\\lg{n})$. (<i>Hint</i>: Show,\n>    by substitution, that $\\E[T(n)] \\le an\\lg{n}$ for sufficiently large $n$\n>    and for some positive constant $a$.)\n\n### Choosing a pivot\n\n`PARTITION` is equally likely to pick any element as a pivot. Since there are\n$n$ elements, the probability of one being picked is $1/n$. For the same\nreason, $\\E[X_i] = 1/n$.\n\n### Running time of quicksort\n\nLet the $q$th smallest element be the pivot. There are $n$ possible choices for\nit, each with chance $X_q$. Each will solve the problem by breaking it down in\ntwo parts of size $q - 1$ and $n - q$ and adding a linear factor. The formula\nin (7.5) follows by the definition of expectation.\n\n### The rewrite\n\n$$ \\begin{aligned}\n   \\E[T(n)] &= \\E\\bigg[\\sum_{q=1}^nX_q(T(q-1) + T(n-q) + \\Theta(n))\\bigg] \\\\\\\\\n            &= \\sum_{q=1}^n\\frac{1}{n}(\\E[T(q-1)] + \\E[T(n-q)] + \\Theta(n))\\bigg] \\\\\\\\\n            &= \\frac{1}{n}\\sum_{q=1}^n\\E[T(q-1)]\n             + \\frac{1}{n}\\sum_{q=1}^n\\E[T(n - q)]\n             + \\frac{1}{n}\\sum_{q=1}^n\\Theta(n) \\\\\\\\\n            &= \\frac{1}{n}\\sum_{q=0}^{n-1}\\E[T(q)]\n             + \\frac{1}{n}\\sum_{q=0}^{n-1}\\E[T(n - q + 1)]\n             + \\Theta(n) \\\\\\\\\n            &= \\frac{1}{n}\\sum_{q=0}^{n-1}\\E[T(q)]\n             + \\frac{1}{n}\\sum_{q=0}^{n-1}\\E[T(q)]\n             + \\Theta(n) \\\\\\\\\n            &= \\frac{2}{n}\\sum_{q=0}^{n-1}\\E[T(q)] + \\Theta(n) \\\\\\\\\n            &= \\frac{2}{n}\\sum_{q=2}^{n-1}\\E[T(q)]\n             + \\frac{2\\E[T(0)]}{n}\n             + \\frac{2\\E[T(1)]}{n}\n             + \\Theta(n) \\\\\\\\\n            &= \\frac{2}{n}\\sum_{q=2}^{n-1}\\E[T(q)] + \\Theta(n)\n   \\end{aligned} $$\n\n### The bound\n\n$$ \\begin{aligned}\n   \\sum_{k=2}^{n-1}k\\lg{k}\n   &=   \\sum_{k=2}^{\\lceil n/2 \\rceil - 1}k\\lg{k} + \\sum_{k=\\lceil n/2 \\rceil}^{n - 1}k\\lg{k} \\\\\\\\\n   &\\le \\sum_{k=2}^{n/2}k\\lg{k} + \\sum_{k=n/2 + 1}^{n}k\\lg{k} \\\\\\\\\n   &\\le \\sum_{k=2}^{n/2}k\\lg(n/2) + \\sum_{k=n/2 + 1}^{n}k\\lg{n} \\\\\\\\\n   &=   \\lg(n/2)\\sum_{k=2}^{n/2}k\\ + \\lg{n}\\sum_{k=n/2 + 1}^{n}k \\\\\\\\\n   &=   (\\lg{n} - \\lg{2})\\bigg(\\frac{(n/2)(n/2 + 1)}{2}\\bigg) +\n          \\lg{n}\\bigg(\\frac{n(n+1)}{2} - \\frac{(n/2)(n/2 + 1)}{2}\\bigg) \\\\\\\\\n   &=   \\lg{n}\\frac{n(n+1)}{2} - \\frac{(n/2)(n/2 + 1)}{2} \\\\\\\\\n   &=   \\frac{1}{2}\\lg{n}(n^2 + 2n + 1) - \\frac{1}{8}(n^2 + 2n + 1/8) \\\\\\\\\n   &=   \\frac{1}{2}n^2\\lg{n} - \\frac{1}{8}n^2 - \\frac{8n\\lg{n} + 4\\lg{n} - 2n - 1/8}{8} \\\\\\\\\n   &\\le \\frac{1}{2}n^2\\lg{n} - \\frac{1}{8}n^2\n   \\end{aligned} $$\n\n### The solution\n\nWe guess $\\E[T(n)] \\le an\\lg{n}$:\n\n$$ \\begin{aligned}\n   \\E[T(n)] &=   \\frac{2}{n}\\sum_{q=2}^{n-1}\\E[T(q)] + \\Theta(n) \\\\\\\\\n            &\\le \\frac{2}{n}\\sum_{q=2}^{n-1}an\\lg{n} + \\Theta(n) & \\text{(by the guess)} \\\\\\\\\n            &\\le \\frac{2a}{n}\\bigg(\\frac{1}{2}n^2\\lg{n} - \\frac{1}{8}n^2\\bigg)\n                 + \\Theta(n) & \\text{(by 7.7)} \\\\\\\\\n            &=   an\\lg{n} - \\frac{a}{4}n + \\Theta(n) & \\text{(by }\\Theta\\text{-notation)} \\\\\\\\\n            &\\le an\\lg{n}\n   \\end{aligned} $$\n\nNote that $\\Theta$-notation allows us to pick $a$ and $n$ such that the last\nderivation is possible.\n"
  },
  {
    "path": "other/clrs/07/problems/04.c",
    "content": "#include <stdio.h>\n\nint partition(int[], int, int);\n\nstatic int stack_depth = 0;\nstatic int max_stack_depth = 0;\n\nvoid reset_stack_depth_counter();\nvoid increment_stack_depth();\nvoid decrement_stack_depth();\n\nvoid tail_recursive_quicksort(int A[], int p, int r) {\n    increment_stack_depth();\n\n    while (p < r - 1) {\n        int q = partition(A, p, r);\n\n        if (q < (p + r) / 2) {\n            tail_recursive_quicksort(A, p, q);\n            p = q;\n        } else {\n            tail_recursive_quicksort(A, q + 1, r);\n            r = q;\n        }\n    }\n\n    decrement_stack_depth();\n}\n\nint partition(int A[], int p, int r) {\n    int x, i, j, tmp;\n\n    x = A[r - 1];\n    i = p;\n\n    for (j = p; j < r - 1; j++) {\n        if (A[j] <= x) {\n            tmp = A[i]; A[i] = A[j]; A[j] = tmp;\n            i++;\n        }\n    }\n\n    tmp = A[i]; A[i] = A[r - 1]; A[r - 1] = tmp;\n\n    return i;\n}\n\nvoid increment_stack_depth() {\n    stack_depth++;\n    if (max_stack_depth < stack_depth) {\n        max_stack_depth = stack_depth;\n    }\n}\n\nvoid decrement_stack_depth() {\n    stack_depth--;\n}\n\nvoid reset_stack_depth_counter() {\n    max_stack_depth = 0;\n    stack_depth = 0;\n}\n"
  },
  {
    "path": "other/clrs/07/problems/04.markdown",
    "content": "## Stack depth for quicksort\n\n> The `QUICKSORT` algorithm of Section 7.1 contains two recursive calls to\n> itself. After `QUICKSORT` calls `PARTITION`, it recursively sorts the left\n> subarray and then it recursively sorts the right subarray. The second\n> recursive call in `QUICKSORT` is not really necessary; we can avoid it by\n> using an iterative control structure. This technique, called **tail\n> recursion**, is provided automatically by good compilers. Consider the\n> following version of quicksort, which simulates tail recursion:\n>\n>     TAIL-RECURSIVE-QUICKSORT(A, p, r)\n>       while p < r\n>           // Partition and sort left subarray\n>           q = PARTITION(A, p, r)\n>           TAIL-RECURSIVE-QUICKSORT(A, p, q - 1)\n>           p = q + 1\n>\n> 1. Argue that `TAIL-RECURSIVE-QUICKSORT(A, 1, A.length)` correctly sorts the\n>    array $A$.\n>\n> Compilers usually execute recursive procedures by using a **stack** that\n> contains pertinent information, including the parameter values, for each\n> recursive call. The information for the most recent call is at the top of the\n> stack, and the information for the initial call is at the bottom. Upon\n> calling a procedure, its information is **pushed** onto the stack; when it\n> terminates, its information is **popped**. Since we assume that array\n> parameters are represented by pointers, the information for each procedure\n> call on the stack requires $\\O(1)$ stack space. The **stack depth** is the\n> maximum amount of stack space used at any time during a computation.\n>\n> 2. Describe a scenario in which `TAIL-RECURSIVE-QUICKSORT`'s stack depth is\n>    $\\Theta(n)$ on an $n$-element input array.\n> 3. Modify the code for `TAIL-RECURSIVE-QUICKSORT` so that the worst-case\n>    stack depth is $\\Theta(\\lg{n})$. Maintain the $\\O(n\\lg{n})$ expected\n>    running time of the algorithm.\n\n### Argue correctness\n\nThe original version partitions the array and then calls `QUICKSORT` one on\neach side. This version does the same, although in a different fashion -\ninstead of calling `TAIL-RECURSIVE-QUICKSORT`, it just changes `p` and restarts\nthe loop. It amounts to the same.\n\nThis is a straightforward tail-call unrolling.\n\n### Linear stack depth\n\nThis will happen whenever partition returns $r$. That is, whenever the array is\nsorted.\n\n### Modified algorithm\n\nWe are always doing a tail-recursive call on the second partition. We can\nmodify the algorithm to do the tail recursion on the larger partition. That\nway, we'll consume less stack.\n"
  },
  {
    "path": "other/clrs/07/problems/04.test.c",
    "content": "#include \"04.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n#include <stdbool.h>\n#include <math.h>\n\nvoid randomize_array(int array[], unsigned length, unsigned int seed);\nbool is_sorted(int array[], int length);\n\nTEST(sorting) {\n    int array[]    = {10, 19,  3,  5, 10,  8, 17,  4, 10,  2, 16, 10},\n        expected[] = { 2,  3,  4,  5,  8, 10, 10, 10, 10, 16, 17, 19};\n\n    tail_recursive_quicksort(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_SAME_ARRAYS(array, expected);\n}\n\nTEST(stack_depth) {\n    int array[]    = {2, 1, 3, 4, 5, 6, 7, 8, 9, 10},\n        expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n\n    reset_stack_depth_counter();\n\n    tail_recursive_quicksort(array, 0, sizeof(array) / sizeof(int));\n\n    ASSERT_SAME_ARRAYS(array, expected);\n    ASSERT_TRUE(max_stack_depth < 4);\n}\n\nTEST(large_array) {\n    int size = 100000,\n        seed = 300,\n        array[size];\n\n    reset_stack_depth_counter();\n    randomize_array(array, size, seed);\n\n    tail_recursive_quicksort(array, 0, size);\n\n    ASSERT_TRUE(is_sorted(array, size));\n    ASSERT_TRUE(max_stack_depth <= log2(size));\n}\n\nvoid randomize_array(int array[], unsigned length, unsigned int seed) {\n    srand(seed);\n    for (unsigned i = 0; i < length; i++) {\n        array[i] = rand() % 100 + 1;\n    }\n}\n\nbool is_sorted(int array[], int length) {\n    for (int i = 1; i < length; i++) {\n        if (array[i - 1] > array[i]) {\n            return false;\n        }\n    }\n    return true;\n}\n"
  },
  {
    "path": "other/clrs/07/problems/05.markdown",
    "content": "## Median-of-3 partition\n\n> One way to improve the `RANDOMIZED-QUICKSORT` procedure is to partition\n> around a pivot that is chosen more carefully than by picking a random element\n> from the subarray. One common approach is the **median-of-3** method: choose\n> the pivot as the median (middle element) of a set of 3 elements randomly\n> selected from the subarray. (See exercise 7.4-6.) For this problem, let us\n> assume that the elements of the input array $A[1 \\ldots n]$ are distinct and\n> that $n \\ge 3$. We denote the sorted output array by $A'[1 \\ldots n]$. Using\n> the median-of-3 method to choose the pivot element $x$, define $p_i = \\Pr\\\\{x\n> = A'[i]\\\\}$.\n>\n> 1. Give an exact formula for $p_i$ as a function of $n$ and $i$ for $i = 2,\n>    3, \\ldots, n - 1$. (Note that $p_1 = p_n = 0$.)\n> 2. By what amount have we increased the likelihood of choosing the pivot as\n>    $x = A'[\\lfloor(n+1)/2\\rfloor]$, the median of $A[1 \\ldots n]$, compared with\n>    the ordinary implementation? Assume that $n \\to \\infty$, and give the\n>    limiting ratio of these probabilities.\n> 3. If we define a \"good\" split to mean choosing the pivot as $x = A'[i]$,\n>    where $n/3 \\le i \\le 2n/3$, by what amount have we increased the\n>    likelihood of getting a good split compared with the ordinary\n>    implementation? (<i>Hint</i>: Approximate the sum by an integral.)\n> 4. Argue that in the $\\Omega(n\\lg{n})$ running time of quicksort, the\n>    median-of-3 method affects only the constant factor.\n\n### Probability\n\nThere are $n!/(n-3)!$ 3-permutations of all possible picks. In order to have\nthe $i$th element, we need to pick one smaller, the $i$th element and one\nlarger. There are $i - 1$ ways to pick a smaller one and $n-i$ ways to pick the\nlarger. There are $3! ways to arrange how the three elements are picked. Thus:\n\n$$ p_i = \\frac{6(i-1)(n-i)}{n(n-1)(n-2)} $$\n\n### Improvement\n\n$$ \\lim_{n \\to \\infty}\\frac{6(i-1)(n-i)}{n(n-1)(n-2)}/\\frac{1}{n}\n = \\lim_{n \\to \\infty}\\frac{6n(n/2 - 1)(n/2)}{(n-1)(n-2)}\n = \\lim_{n \\to \\infty}\\frac{6(n^2 - 2n)}{4(n^2 - 3n + 2)}\n = \\frac{6}{4} $$\n\nWe get a $1.5$ improvement, which does not seem that much.\n\n### Improvement\n\nFrom exercise 7.2-6 we know that we get a \"good\" split with probability $1 -\n2(1/3) = 1/3$. As for the probability of getting a good split with median-of-3:\n\n$$ \\begin{aligned}\n   \\lim_{n \\to \\infty}\\sum_{i=n/3}^{2n/3}\\frac{6(i-1)(n-i)}{n(n-1)(n-2)} &=\n     \\lim_{n \\to \\infty}\\frac{6}{n(n-1)(n-2)}\\sum_{i=n/3}^{2n/3}(i-1)(n-i) \\\\\\\\\n     &= \\lim_{n \\to \\infty}\\binom{n}{3}\\int_{n/3}^{2n/3}(i-1)(n-1)\\mathrm{d}i \\\\\\\\\n        & \\quad \\Bigg( \\int(i-1)(n-1)\\mathrm{d}i = \\frac{1}{6}(3ni^2 - 6ni - 2i^3 + 3i^2) \\Bigg) \\\\\\\\\n     &= \\lim_{n \\to \\infty}\\binom{n}{3}\\frac{1}{6}\\bigg[\n          \\frac{36}{27}n^3 - \\frac{16}{27}n^3 + o(n^3) -\n          \\frac{9}{27}n^3 + \\frac{2}{27}n^3 + o(n^3)\n        \\bigg] \\\\\\\\\n    &= \\lim_{n \\to \\infty}\\frac{1}{n(n-1)(n-2)} \\frac{13}{27}(n^3 + o(n^3)) \\\\\\\\\n    &= \\lim_{n \\to \\infty}\\frac{13}{27}\\frac{n^3 + o(n^3)}{n^3 + o(n^3)} \\\\\\\\\n    &= \\frac{13}{27}\n   \\end{aligned} $$\n\nThus, as $n$ grows, the chance of getting a \"good\" split converges to $13/27$. The improvement is:\n\n$$ \\frac{13}{27} \\div \\frac{1}{3} = \\frac{39}{27} \\approx 1.444(4) $$\n\n### Improvement\n\nThe running time would improve if the new approach can always pick a good\nsplit. Unfortunatelly, it can't. It makes it impossible for one of the splits\nto be empty, but it can still pick a $1$-to-$n-2$ split. It improves the\nprobability of a good split and adds some overhead to picking the pivot, but it\nmakes no hard guarantees on the quality of the split. Thus, the algorithm\nremains $\\Omega(n\\lg{n})$ and $\\O(n^2)$.\n"
  },
  {
    "path": "other/clrs/07/problems/06.c",
    "content": "#include <stdbool.h>\n#include <stdlib.h>\n\ntypedef struct {\n    int left;\n    int right;\n} interval;\n\nbool intersects(interval a, interval b) { return a.left <= b.right && b.left <= a.right; }\nbool before(interval a, interval b)     { return a.right < b.left; }\nbool after(interval a, interval b)      { return a.left > b.right; }\n\n#define EXCHANGE(a, b) tmp = a; a = b; b = tmp;\n\ninterval partition(interval A[], int p, int r) {\n    int pick, s, t, i;\n    interval intersection, tmp;\n\n    // Pick a random interval as a pivot\n    pick = p + rand() % (r - p);\n    EXCHANGE(A[pick], A[r-1]);\n    intersection = A[r-1];\n\n    // Find an intersection of the pivot and other intervals\n    for (i = p; i < r - 1; i++) {\n        if (intersects(intersection, A[i])) {\n            if (A[i].left > intersection.left)\n                intersection.left = A[i].left;\n            if (A[i].right < intersection.right)\n                intersection.right = A[i].right;\n        }\n    }\n\n    // Classic partition around the intersection\n    for (i = s = p; i < r - 1; i++) {\n        if (before(A[i], intersection)) {\n            EXCHANGE(A[i], A[s]);\n            s++;\n        }\n    }\n    EXCHANGE(A[r-1], A[s]);\n\n    // Group intervals including the intersection\n    for (t = s + 1, i = r - 1; t <= i;) {\n        if (intersects(A[i], intersection)) {\n            EXCHANGE(A[t], A[i]);\n            t++;\n        } else {\n            i--;\n        }\n    }\n\n    return (interval) {s, t};\n}\n\nvoid fuzzy_sort(interval array[], int p, int r) {\n    if (p < r - 1) {\n        interval pivot = partition(array, p, r);\n        fuzzy_sort(array, p, pivot.left);\n        fuzzy_sort(array, pivot.right, r);\n    }\n}\n\n"
  },
  {
    "path": "other/clrs/07/problems/06.markdown",
    "content": "## Fuzzy sorting of intervals\n\n> Consider the problem in which we do not know the numbers exactly. Instead,\n> for each number, we know an interval on the real line to which it belongs.\n> That is, we are given $n$ closed intervals of the form $[a_i, b_i]$, where\n> $a_i \\le b_i$. We wish to **fuzzy-sort** these intervals, i.e., to produce a\n> permutation $\\langle i_1, i_2, \\ldots, i_n \\rangle$ of the intervals such\n> that for $j = 1, 2, \\ldots, n$, there exists $c_j \\in [a_{i_j}, b_{i_j}]$\n> satisfying $c_1 \\le c_2 \\le \\cdots \\le c_n$.\n>\n> 1. Design a randomized algorithm for fuzzy-sorting $n$ intervals. Your\n>    algorithm should have the general structure of an algorithm that\n>    quicksorts the left endpoints (the $a_i$ values), but it should take\n>    advantage of overlapping intervals to improve the running time. (As the\n>    intervals overlap more and more, the problem of fuzzy-sorting the\n>    intervals becoes progressively easier. Your algorithm should take\n>    advantage of such overlapping, to the extend that it exists).\n> 2. Argue that your algorithm runs in expected time $\\Theta(n\\lg{n})$ in\n>    general, but runs in expected time $\\Theta(n)$ when all of the intervals\n>    overlap (i.e., when there exists a value $x$ such that $x \\in [a_i, b_i]$\n>    for all $i$). Your algorithm should not be checking for this case\n>    explicitly; rather, its performance should naturally improve as the amount\n>    of overlap increases.\n\n### The algorithm\n\nThe approach is very similar to problem 7.2. After we (randomly) choose a pivot\ninterval, we check if it intersects with the other intervals. More precisely,\nwe accumulate an intersection of the pivot and the other intervals. Afterwards\nwe use this interval for comparison instead of the pivot.\n\nWhen comparing, we can treat intervals containing the intersection as equal to\neach other. Thus after we have arranged all the smaller intervals on the left\nof the pivot, we can put all the equal ones immediatelly to the right of the\npivot. Like in problem 7.2, we return two points (an interval) to use as a for\nrecursive calls.\n\nEven if partition does (worst-case) three passes over the array, it is still\nlinear.\n\n### Expected time\n\nIf we assume that no two intervals have intersections, the analysis is\nidentical to quicksort. If, however, all the intervals share a common point,\nthe partitioning function would solve it in one go.\n"
  },
  {
    "path": "other/clrs/07/problems/06.test.c",
    "content": "#include \"06.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(intersects) {\n    ASSERT_TRUE(intersects((interval) {1, 3}, (interval) {0, 2}));\n    ASSERT_TRUE(intersects((interval) {2, 4}, (interval) {1, 3}));\n    ASSERT_TRUE(intersects((interval) {0, 4}, (interval) {1, 3}));\n    ASSERT_TRUE(intersects((interval) {1, 3}, (interval) {0, 4}));\n\n    ASSERT_FALSE(intersects((interval) {1, 2}, (interval) {3, 4}));\n    ASSERT_FALSE(intersects((interval) {2, 3}, (interval) {0, 1}));\n}\n\nvoid randomize_array(interval[], unsigned, unsigned int);\nbool is_sorted(interval[], int);\n\nTEST(sorting) {\n    int seed = 300,\n        size = 100000;\n    interval array[size];\n\n    randomize_array(array, size, seed);\n    fuzzy_sort(array, 0, size);\n\n    ASSERT_TRUE(is_sorted(array, size));\n}\n\nvoid randomize_array(interval array[], unsigned length, unsigned int seed) {\n    srand(seed);\n    for (unsigned i = 0; i < length; i++) {\n        array[i].left  = rand() % 10000 + 1;\n        array[i].right = array[i].left + rand() % 5000;\n    }\n}\n\nbool is_sorted(interval array[], int length) {\n    for (int i = 1; i < length; i++) {\n        if (!(before(array[i - 1], array[i]) || intersects(array[i - 1], array[i]))) {\n            return false;\n        }\n    }\n    return true;\n}\n"
  },
  {
    "path": "other/clrs/08/01/01.markdown",
    "content": "> What is the smallest possible depth of a leaf in a decision tree for a\n> comparison sort?\n\nIt's $\\Theta(n)$, or more precisely, $n-1$. This is the minimal number of\ncomparisons we need to perform in order to check if an array is sorted and\nreturn it. It's what insertion sort does.\n"
  },
  {
    "path": "other/clrs/08/01/02.markdown",
    "content": "> Obtain asymptotically tight bounds on $\\lg(n!)$ without using Stirling's\n> approximation. Instead, evaluate the summation $\\sum_{k=1}^n\\lg{k}$ using\n> techniques from section A.2.\n\nFirst we show that it is $\\O(n\\lg{n})$:\n\n$$ \\sum_{k=1}^n\\lg{k} \\le \\sum_{k=1}^n\\lg{n} = n\\lg{n} = \\O(n\\lg{n})$$\n\nNext we show that it is $\\Omega(n\\lg{n})$:\n\n$$ \\begin{aligned}\n   \\sum_{k=1}^n\\lg{k} &=   \\sum_{k=1}^{\\lfloor n/2 \\rfloor}\\lg{k} +\n                           \\sum_{k=\\lfloor n/2 \\rfloor + 1}^n\\lg{k} \\\\\\\\\n                      &\\ge \\sum_{k=\\lfloor n/2 \\rfloor + 1}^n\\lg{k} \\\\\\\\\n                      &\\ge \\sum_{k=n/2}^n\\lg{k} \\\\\\\\\n                      &\\ge \\sum_{k=n/2}^n\\lg{n/2} \\\\\\\\\n                      &\\ge (n/2)\\lg(n/2) \\\\\\\\\n                      &=   \\frac{1}{2}n\\lg{n} - \\frac{1}{2}n \\\\\\\\\n                      &=   \\Omega(n\\lg{n})\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/08/01/03.markdown",
    "content": "> Show that there is no comparison sort whose running time is linear for at\n> least half of the $n!$ inputs of length $n$. What about a fraction $1/n$ of\n> the inputs of length $n$? What about a fraction $1/2^n$?\n\nIf it is linear for at least half of the inputs, then using the same reasoning\nas in the text, it must hold that:\n\n$$ \\frac{n!}{2} \\le 2^n $$\n\nThis holds only for small values for $n$. Same goes for the other:\n\n$$ \\frac{n!}{n} \\le 2^n $$\n\nAnd:\n\n$$ \\frac{n!}{2^n} \\le 2^n \\Leftrightarrow n! \\le 4^n $$\n\nAll those have solutions for small $n < n_0$, but don't hold for larger values.\n\nIn contrast, insertion sort gets its work done in $\\Theta(n)$ time in the best\ncase. But this is a $1/n!$ fraction of the inputs, which is smaller than $1/2^n$.\n"
  },
  {
    "path": "other/clrs/08/01/04.markdown",
    "content": "> Suppose that you are given a sequence of $n$ elements to sort. The input\n> sequence consists of $n/k$ subsequences, each containing $k$ elements. The\n> elements in a given subsequence are all smaller than the elements in the\n> succeeding subsequence and larger than the elements in the preceding\n> subsequence. Thus, all that is needed to sort the whole sequence of length\n> $n$ is to sort the $k$ elements in each of the $n/k$ subsequences. Show an\n> $\\Omega(n\\lg{k})$ lower bound on the number of comparisons needed to solve\n> this variant of the sorting problem. (<i>Hint:</i> It is not rigorous to\n> simply combine the lower bounds for the individual subsequences.)\n\nThis is somehow tricky. There are $n/k$ subsequences and each can be ordered in\n$k!$ ways. This makes a $(k!)^{n/k}$ outputs. We use the same reasoning:\n\n$$ (k!)^{n/k} \\le 2^h $$\n\nTaking the logarithm of both sides, we get:\n\n$$ \\begin{aligned}\n   h &\\ge \\lg(k!)^{n/k} \\\\\\\\\n     &=   (n/k)\\lg(k!) \\\\\\\\\n     &\\ge (n/k)(k/2)\\lg(k/2) & \\text{(ex 8.1.2)}\\\\\\\\\n     &=   \\frac{1}{2}n\\lg{k} - \\frac{1}{2}n \\\\\\\\\n     &=   \\Omega(n\\lg{k})\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/08/02/01.markdown",
    "content": "> Using figure 8.2 as a model, illustrate the operation of `COUNTING-SORT` on\n> the array $A = \\langle 6, 0, 2, 0, 1, 3, 4, 6, 1, 3, 2 \\rangle$\n\nThis is tricky to do with graphviz, so I'm going to resort to ASCII art.\n\n    This is the array we sort\n\n       +---+---+---+---+---+---+---+---+---+---+---+\n    A: | 6 | 0 | 2 | 0 | 1 | 3 | 4 | 6 | 1 | 3 | 2 |\n       +---+---+---+---+---+---+---+---+---+---+---+\n\n    We build an array of counts:\n\n         0   1   2   3   4   5   6\n       +---+---+---+---+---+---+---+\n    C: | 2 | 2 | 2 | 2 | 1 | 0 | 2 |\n       +---+---+---+---+---+---+---+\n\n    The number of elements before each\n\n         0   1   2   3   4   5   6\n       +---+---+---+---+---+---+----+\n    C: | 2 | 4 | 6 | 8 | 9 | 9 | 11 |\n       +---+---+---+---+---+---+----+\n\n    Then we start iterating:\n\n         1   2   3   4   5   6   7   8   9   10  11         0   1   2   3   4   5   6\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n    A: |   |   |   |   |   | 2 |   |   |   |   |   |   C: | 2 | 4 | 5 | 8 | 9 | 9 | 11 |\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n\n         1   2   3   4   5   6   7   8   9   10  11         0   1   2   3   4   5   6\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n    A: |   |   |   |   |   | 2 |   | 3 |   |   |   |   C: | 2 | 4 | 5 | 7 | 9 | 9 | 11 |\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n\n         1   2   3   4   5   6   7   8   9   10  11         0   1   2   3   4   5   6\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n    A: |   |   |   | 1 |   | 2 |   | 3 |   |   |   |   C: | 2 | 3 | 5 | 7 | 9 | 9 | 11 |\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n\n         1   2   3   4   5   6   7   8   9   10  11         0   1   2   3   4   5   6\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n    A: |   |   |   | 1 |   | 2 |   | 3 |   |   | 6 |   C: | 2 | 3 | 5 | 7 | 9 | 9 | 10 |\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n\n         1   2   3   4   5   6   7   8   9   10  11         0   1   2   3   4   5   6\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n    A: |   |   |   | 1 |   | 2 |   | 3 | 4 |   | 6 |   C: | 2 | 3 | 5 | 7 | 8 | 9 | 10 |\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n\n         1   2   3   4   5   6   7   8   9   10  11         0   1   2   3   4   5   6\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n    A: |   |   |   | 1 |   | 2 | 3 | 3 | 4 |   | 6 |   C: | 2 | 3 | 5 | 6 | 8 | 9 | 10 |\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n\n         1   2   3   4   5   6   7   8   9   10  11         0   1   2   3   4   5   6\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n    A: |   |   | 1 | 1 |   | 2 | 3 | 3 | 4 |   | 6 |   C: | 2 | 2 | 5 | 6 | 8 | 9 | 10 |\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n\n         1   2   3   4   5   6   7   8   9   10  11         0   1   2   3   4   5   6\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n    A: |   | 0 | 1 | 1 |   | 2 | 3 | 3 | 4 |   | 6 |   C: | 1 | 2 | 5 | 6 | 8 | 9 | 10 |\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n\n         1   2   3   4   5   6   7   8   9   10  11         0   1   2   3   4   5   6\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n    A: |   | 0 | 1 | 1 | 2 | 2 | 3 | 3 | 4 |   | 6 |   C: | 1 | 2 | 4 | 6 | 8 | 9 | 10 |\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n\n         1   2   3   4   5   6   7   8   9   10  11         0   1   2   3   4   5   6\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n    A: | 0 | 0 | 1 | 1 | 2 | 2 | 3 | 3 | 4 |   | 6 |   C: | 0 | 2 | 4 | 6 | 8 | 9 | 10 |\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+----+\n\n         1   2   3   4   5   6   7   8   9   10  11         0   1   2   3   4   5   6\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+---+\n    A: | 0 | 0 | 1 | 1 | 2 | 2 | 3 | 3 | 4 | 6 | 6 |   C: | 0 | 2 | 4 | 6 | 8 | 9 | 9 |\n       +---+---+---+---+---+---+---+---+---+---+---+      +---+---+---+---+---+---+---+\n"
  },
  {
    "path": "other/clrs/08/02/02.markdown",
    "content": "> Prove that `COUNTING-SORT` is stable.\n\nAn informal argument will suffice.\n\nLet's say that two elements at indices $i_1 < i_2$ are equal to each other. In\nthe sorted array, they take place at indices $j_1 + 1 = j_2$. Since the\n`COUNTING-SORT` processes the input array in reverse order, $A[i_2]$ is put in\n$B[j_2]$ first and then $A[i_1]$ is put in $A[j_2]$. Since the two elements\npreserve their order, the algorithm is stable.\n"
  },
  {
    "path": "other/clrs/08/02/03.markdown",
    "content": "> Suppose that we were to rewrite the for loop header in line 10 of the\n> `COUNTING-SORT` as\n>\n>     for j = 1 to A.length\n>\n> Show that the algorithm still works properly. Is the modified algorithm\n> stable?\n\nIt will work properly, but they are not stable. Equal elements will appear in\nreverse order in the sorted array.\n"
  },
  {
    "path": "other/clrs/08/02/04.markdown",
    "content": "> Describe an algorithm that, given $n$ integers in the range $0$ to $k$,\n> preprocesses its input and then answers any query about how many of the $n$\n> integers fall into a range $[a..b]$ in $\\O(1)$ time. Your algorithm should\n> use $\\Theta(n+k)$ preprocessing time.\n\nThis is not even challenging.\n\nWe just take the part of `COUNTING-SORT` that builds up the array `C`. Whenever\nwe want to count the number of integers in $[a..b]$, we take `C[b] - C[a-1]`\n(where `C[-1] = 0`). This yields the number of integers in the given range.\n"
  },
  {
    "path": "other/clrs/08/03/01.markdown",
    "content": "> Using figure 8.3 as a model, illustrate the operation of `RADIX-SORT` on the\n> following list of English words: `COW`, `DOG`, `SEA`, `RUG`, `ROW`, `MOB`,\n> `BOX`, `TAB`, `BAR`, `EAR`, `TAR`, `DIG`, `BIG`, `TEA`, `NOW`, `FOX`.\n\nAgain, ASCII is way simpler for this. I miss solving all my problems with ASCII :/\n\n    COW        SEA        TAB        BAR\n    DOG   =>   TEA   =>   BAR   =>   BIG\n    SEA        MOB        EAR        BOX\n    RUG        TAB        TAR        COW\n    ROW        DOG        SEA        DIG\n    MOB        RUG        TEA        DOG\n    BOX        DIG        DIG        EAR\n    TAB        BIG        BIG        FOX\n    BAR        BAR        MOB        MOB\n    EAR        EAR        DOG        NOW\n    TAR        TAR        COW        ROW\n    DIG        COW        ROW        RUG\n    BIG        ROW        NOW        SEA\n    TEA        NOW        BOX        TAB\n    NOW   =>   BOX   =>   FOX   =>   TAR\n    FOX        FOX        RUG        TEA\n"
  },
  {
    "path": "other/clrs/08/03/02.markdown",
    "content": "> Which of the following sorting algorithms are stable: insertion sort, merge\n> sort, heapsort, and quicksort? Give a simple scheme that makes any sorting\n> algorithm stable. How much additional time and space does your scheme entail?\n\n**Stable**: Insertion sort, merge sort\n\n**Not stable**: Heapsort, quicksort\n\nWe can make any algorithm stable by mapping the array to an array of pairs,\nwhere the first element in each pair is the original element and the second is\nits index. Then we sort lexicographically. This scheme takes additional\n$\\Theta(n)$ space.\n"
  },
  {
    "path": "other/clrs/08/03/03.markdown",
    "content": "> Use induction to prove that radix sort works. Where does your proof need the\n> assumption that the intermediate sort is stable?\n\nWe can take the following invariant:\n\n> At the beginning of the **for** loop, the array is sorted on the last $i - 1$\n> digits.\n\n**Initialization**. The array is trivially sorted on the last 0 digits.\n\n**Maintenance**. Let's assume that the array is sorted on the last $i - 1$\ndigits. After we sort on the $i$th digit, the array will be sorted on the last\n$i$ digits. It is obvious that elements with different digit in the $i$th\nposition are ordered accordingly; in the case of the same $i$th digit, we still\nget a correct order, because we're using a stable sort and the elements were\nalready sorted on the last $i - 1$ digits.\n\n**Termination**. The loop terminates when $i = d + 1$. Since the invariant\nholds, we have the numbers sorted on $d$ digits.\n\nWe use the assumption in the maintenance explanation.\n"
  },
  {
    "path": "other/clrs/08/03/04.markdown",
    "content": "> Show how to sort $n$ integers in the range $0$ to $n^3 - 1$ in $\\O(n)$ time.\n\nWe use radix sort. In this case, we have 2-digit numbers in base $n$. This\nmakes `RADIX-SORT` to be $\\Theta(2(n + n)) = \\Theta(4n) = \\Theta(n)$.\n"
  },
  {
    "path": "other/clrs/08/03/05.markdown",
    "content": "> $\\star$ In the first card-sorting algorithm in this section, exactly how many\n> sorting passes are needed to sort $d$-digit decimal numbers in the worst\n> case? How many piles of cards would an operator need to keep track of in the\n> worst case?\n\nThe algorithm becomes exponential. Here's a simple breakdown for sorting\nn-digits numbers in base 3.\n\n    - sort all on first digit into 3 piles\n      - sort pile with first digit = 0 into 3 piles on second digit\n        - sort pile with second digit = 0 on third digit\n          ...\n        - sort pile with second digit = 1 on third digit\n          ...\n        - sort pile with third digit = 1 on third digit\n          ...\n      - sort pile with first digit = 1 into 3 piles on second digit\n        ..\n      ...\n\nThis is exponential. We need to perform $\\Theta(k^d)$ passes. Furthermore, we\nneed to keep track of $\\Theta(nk)$ piles.\n\nThose correspond to space and time.\n"
  },
  {
    "path": "other/clrs/08/04/01.markdown",
    "content": "> Using figure 8.4 as a model, illustrate the operation of `BUCKET-SORT` on the\n> array $A = \\langle .79, .13, .16, .64, .39, .20, .89, .53, .71, .42 \\rangle$.\n\n          A           B\n       +-----+      +---+\n     1 | .79 |    0 | / |\n       +-----+      +---+\n     2 | .13 |    1 | o-----> (.13 .16)\n       +-----+      +---+\n     3 | .16 |    2 | o-----> (.20)\n       +-----+      +---+\n     4 | .64 |    3 | o-----> (.39)\n       +-----+      +---+\n     5 | .39 |    4 | o-----> (.42)\n       +-----+      +---+\n     6 | .20 |    5 | o-----> (.53)\n       +-----+      +---+\n     7 | .89 |    6 | o-----> (.64)\n       +-----+      +---+\n     8 | .53 |    7 | o-----> (.71 .79)\n       +-----+      +---+\n     9 | .71 |    8 | o-----> (.89)\n       +-----+      +---+\n    10 | .42 |    9 | / |\n       +-----+      +---+\n"
  },
  {
    "path": "other/clrs/08/04/02.markdown",
    "content": "> Explain why the worst-case running time for bucket sort is $\\Theta(n^2)$.\n> What simple change to the algorithm preserves its linear average-case running\n> time and makes its worst-case running time $\\O(n\\lg{n})$.\n\nIf all the keys fall in the same bucket and they happen to be in reverse order,\nwe have to sort a single bucket with $n$ items in reversed order with insertion\nsort. This is $\\Theta(n^2)$.\n\nWe can use merge sort or heapsort to improve the worst-case running time.\nInsertion sort was chosen, because it operates well on linked lists. If we use\nanother sorting algorithm, we have to convert each list to an array, which\nmight slow down the algorithm in practice.\n"
  },
  {
    "path": "other/clrs/08/04/03.markdown",
    "content": "> Let $X$ be a random variable that is equal to the number of heads in two\n> flips of a fair coin. What is $\\E[X^2]$? What is $\\E^2[X]$.\n\nFirst let's see what $\\E[X]$ is:\n\n$$ \\E[X] = 2 \\cdot \\frac{1}{4} + 1 \\cdot \\frac{1}{2} + 0 \\cdot \\frac{1}{4} = 1 $$\n\nNext we take $\\E[X^2]$:\n\n$$ \\E[X^2] = \\E[X] \\cdot \\E[X] = 1 $$\n\nFinally $\\E^2[X]$:\n\n$$ \\E^2[X] = \\E[X] \\cdot \\E[X] = 1 $$\n"
  },
  {
    "path": "other/clrs/08/04/04.markdown",
    "content": "> $\\star$ We are given $n$ points in the unit circle, $p_i = (x_i, y_i)$, such\n> that $0 < x_i^2 + y_i^2 \\le 1$ for $i = 1, 2, \\ldots, n$. Suppose that the\n> points are uniformly distributed; that is, the probability of finding a point\n> in any region of the circle is proportional to the area of that region.\n> Design an algorithm with an average-case running time of $\\Theta(n)$ to sort\n> the $n$ points by their distances $d_i = \\sqrt{x_i^2 + y_i^2}$ from the\n> origin. (<i>Hint:</i> Design the bucket sizes in `BUCKET-SORT` to reflect the\n> uniform distribution of the points in the unit circle.)\n\nThe unit circle has area $\\pi 1^2 = \\pi$. We need to split it in $n$ discs,\neach having area $\\pi / n$. The radius of such a disc is $\\pi(b^2 - a^2)$,\nwhere $b$ is the radius of the outer edge and $a$ is the radius of the inner\nedge of the disc.\n\nLet the points $a_0, a_1, a_2, \\ldots a_n$ divide the circle in n dics, the\n$i$th disc having radiuses $a_i$ and $a_{i-1}$. We know that $a_0 = 0$ and $a_n\n= 1$. For any two discs we have:\n\n$$ \\pi^2 \\pi(a_i^2 - a_{i-1}^2) = \\pi(a_j^2 - a_{j-1}^2) = \\frac{\\pi}{n} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   a_i^2 - a_{i-1}^2 = a_j^2 - a_{j-1}^2 = \\frac{1}{n} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   a_i^2 = \\frac{1}{n} + a_{i-1}^2 $$\n\nWe get the following recurrence:\n\n$$ \\begin{aligned}\n   a_0 &= 0 \\\\\\\\\n   a_i &= \\sqrt{1/n + a_{i-1}^2}\n   \\end{aligned} $$\n\nIf we check some small values, we see the following pattern:\n\n$$ \\pi n^2 $$\n\n$$ \\begin{aligned}\n   a_0 & = 0 = \\frac{1}{\\sqrt n} \\\\\\\\\n   a_1 & = \\sqrt{\\frac{1}{n} + \\frac{1}{n}} = \\frac{\\sqrt 2}{\\sqrt n} \\\\\\\\\n   a_2 & = \\sqrt{\\frac{1}{n} + \\frac{2}{n}} = \\frac{\\sqrt 2}{\\sqrt n} \\\\\\\\\n   & \\ldots \\\\\\\\\n   a_i & = \\frac{\\sqrt i}{\\sqrt n}\n   \\end{aligned} $$\n\nThe last step is easy to prove by induction. If we assume it for $i \\le k$, then:\n\n$$ a_{k+1} = \\sqrt{\\frac{1}{n} + a_k^2}\n           = \\sqrt{\\frac{1}{n} + \\frac{k}{n}}\n           = \\frac{\\sqrt{k+1}}{\\sqrt n} $$\n\nThus, we create buckets for the following intervals:\n\n$$ \\bigg[0, \\frac{1}{\\sqrt n} \\bigg),\n   \\bigg[\\frac{1}{\\sqrt n}, \\frac{\\sqrt 2}{\\sqrt n}\\bigg) \\cdots\n   \\bigg[\\frac{\\sqrt{n-1}}{\\sqrt n}, 1 \\bigg] $$\n\nAnd distribute elements according to their distance. To calculate the bucket\n$k$ for a distance $d$ in constant time, just take:\n\n$$ k = \\begin{cases}\n    \\lfloor d^2n \\rfloor + 1 & \\text{if } d < 1, \\\\\\\\\n    n & \\text{id } d = 1\n  \\end{cases} $$\n\n...for 1-based buckets.\n"
  },
  {
    "path": "other/clrs/08/04/05.markdown",
    "content": "> $\\star$ A **probability distribution function** $P(x)$ for a random variable\n> $X$ is defined by $P(x) = \\Pr\\\\{X \\le x\\\\}$. Suppose that we draw a list of\n> $n$ random variables $X_1, X_2, \\ldots, X_n$ from a continuous probability\n> distribution function $P$ that is computable in $\\O(1)$ time. Give an\n> algorithm that sorts these numbers in linear average-case time.\n\n**(UNSOLVED)** I don't really understand the math. But the approach is similar\nto exercise 8.4.4 - we pick a way to partition the buckets so each one is\nequally likely.\n"
  },
  {
    "path": "other/clrs/08/problems/01.markdown",
    "content": "## Probabilistic lower bounds on comparison sorting\n\n> In this problem, we prove a probabilistic $\\Omega(n\\lg{n})$ on the running\n> time of any deterministic or randomized comparison sort on $n$ distinct input\n> elements. We begin by examining a deterministic comparison sort $A$ with\n> decision tree $T_A$. We assume that every permutation of $A$'s inputs is\n> equally likely.\n>\n> 1. Suppose that each leaf of $T_A$ is labeled with the probability that it is\n>    reached given a random input. Prove that exactly $n!$ leaves are labeled\n>    $1/n!$ and the rest are labeled $0$.\n> 2. Let $D(T)$ denote the external path length of a decision tree $T$; that\n>    is, $D(T)$ is the sum of the depths of all the leaves of $T$. Let $T$ be a\n>    decision tree with $k > 1$ leaves, and let $LT$ and $RT$ be the left and\n>    right subtrees of $T$. Show that $D(T) = D(LT) + D(RT) + k$\n> 3. Let $d(k)$ be the minimum value of $D(T)$ over all decision trees $T$ with\n>    $k > 1$ leaves. Show that $d(k) = \\min_{1 \\le i \\le k - 1} \\\\{d(i) +\n>    d(k-i) + k\\\\}$. (<i>Hint</i>: Consider a decision tree $T$ with $k$\n>    leaves that achieves the minimum. Let $i_0$ be the number of leaves in\n>    $LT$ and $k - i_0$ the number of leaves in $RT$.)\n> 4. Prove that for a given value of $k > 1$ and $i$ in the range $i \\le i \\le\n>    k - 1$, the function $i\\lg{i} + (k-i)\\lg(k-i)$ is minimized at $i = k/2$.\n>    Conclude that $d(k) = \\Omega(k\\lg{k})$.\n> 5. Prove that $D(T_A) = \\Omega(n!\\lg(n!))$, and conclude that the\n>    average-case time to sort $n$ elements is $\\Omega(n\\lg{n})$.\n>\n> Now consider a *randomized* comparison sort $B$. We can extend the\n> decision-tree model to handle randomization by incorporating two kinds of\n> nodes: ordinary comparison nodes and \"randomization\" nodes. A randomization\n> node models a random choice of the form `RANDOM(1,r)` made by algorithm $B$;\n> the node has $r$ children, each of which is equally likely to be chosen\n> during an execution of the algorithm.\n>\n> 6. Show that for any randomized comparison sort $B$, there exists a deterministic\n>    comparison sort $A$ whose expected number of comparisons is no more than\n>    those made by $B$.\n\n### Probability labels\n\nThere are $n!$ permutations that the algorithm can perform and each\ncorresponds to one of the $n!$ possible inputs. Each permutation will be a\nleaf in this tree and since the inputs are equally likely, the probability of\nreaching one will be $1/n!$. If the decision tree has more leaves, they will\nbe unreachable.\n\nThis is an intuitive argument. It's easy to see that it is so if you think\nabout it, but a formal proof seems tricky to me.\n\n### External path length\n\nIf we take a node in the tree, all paths go either through the left or the\nright child. Both children have the same paths as the node itself, except that\nthey are shorter by one. Thus, $D(T) = D(LT) + D(RT) +\n\\mathrm{LEAVES}(LT) + \\mathrm{LEAVES}(RT) = D(LT) + D(RT) + k$.\n\n### Minimal external path length\n\nIf we take a tree with $k$ leaves that achieves the minimal external path,\nwe know from the previous point that:\n\n$$ D(T) = D(LT) + D(RT) + k $$\n\nThere are $k - 1$ possible pairs of left-right children and one of them is the\nminimum. That is:\n\n$$ d(k) = D(T) = D(LT) + D(RT) + k = \\min_{1 \\le i \\le k-1}\\\\{d(i) + d(k-i) + k\\\\} $$\n\n### Minimal value\n\nLet:\n\n$$ \\begin{aligned}\n      f(i) &= i\\lg{i} + (k-i)\\lg(k-i) \\\\\\\\\n     f'(i) &= \\lg{i} + 1 - \\lg(k-i) - 1 = \\lg\\frac{i}{k-i} \\\\\\\\\n     f'(i) = 0 & \\Leftrightarrow \\lg\\frac{i}{k-i} = 0 \\Rightarrow i/(k-i) = 1 \\Rightarrow i = \\frac k 2\n   \\end{aligned} $$\n\nSince $f'(i)$ is monotonously increasing, $i = k/2$ is a local minimum.\n\nIntuitively said, the minimum is reached when the tree is balanced (as in the\nway merge sort halves is decision-tree on each step.\n\n### Average-case time\n\nIn $T_A$ there are $n!$ leaves, thus $D(n) > d(k) = \\Omega(n!\\lg(n!))$. Each\npermutation has an equal probability of $1/n!$, thus the expected time to sort\nit is:\n\n$$ \\frac{\\Omega(n!\\lg(n!))}{n!} = \\Omega(n\\lg(n!)) = \\Omega(n\\lg{n}) $$\n\n### The randomized algorithm\n\nA deterministic algorithm $A$ corresponding to $B$ would be one that has made\nits \"random\" choices in advance. To construct it we just remove the randomized\nnodes by replacing them by a child we pick. The new result is a subtree (in\nrespect to the non-randomized nodes) and its number of choices is less than or\nequal to the one of the randomized algorithm. Since any subtree we pick is\n$\\Omega(n\\lg{n})$, this implies that $B$ is $\\Omega(n\\lg{n})$.\n"
  },
  {
    "path": "other/clrs/08/problems/02.c",
    "content": "#include <stdbool.h>\n\ntypedef struct {\n    int key;\n    int value;\n} item;\n\nstatic item tmp;\n\n#define EXCHANGE(a, b) tmp = a; a = b; b = tmp;\n\nvoid stable_linear_sort(item *A, int size) {\n    int zero = 0,\n        one  = 0;\n    item copy[size];\n\n    for (int i = 0; i < size; i++) {\n        if (A[i].key == 0) {\n            one++;\n        }\n    }\n\n    for (int i = 0; i < size; i++) {\n        if (A[i].key == 0) {\n            copy[zero] = A[i];\n            zero++;\n        } else {\n            copy[one] = A[i];\n            one++;\n        }\n    }\n\n    for (int i = 0; i < size; i++) {\n        A[i] = copy[i];\n    }\n}\n\nvoid linear_in_place_sort(item *A, int size) {\n    int left = -1,\n        right = size;\n\n    while (true) {\n        do { left++;  } while (A[left].key  == 0);\n        do { right--; } while (A[right].key == 1);\n\n        if (left > right) {\n            return;\n        }\n\n        EXCHANGE(A[left], A[right]);\n    }\n}\n\nvoid stable_in_place_sort(item *A, int size) {\n    for (int i = size; i > 0; i--) {\n        for (int j = 0; j < i; j++) {\n            if (A[j].key > A[j + 1].key) {\n                EXCHANGE(A[j], A[j+1]);\n            }\n        }\n    }\n}\n\nvoid in_place_counting_sort(item *A, int size, int range) {\n    int counts[range + 1];\n    int positions[range + 1];\n\n    for (int i = 0; i <= range; i++) {\n        counts[i] = 0;\n    }\n\n    for (int i = 0; i < size; i++) {\n        counts[A[i].key]++;\n    }\n\n    for (int i = 2; i <= range; i++) {\n        counts[i] += counts[i-1];\n    }\n\n    for (int i = 0; i <= range; i++) {\n        positions[i] = counts[i];\n    }\n\n    int i = 0;\n    while (i < size) {\n        int key = A[i].key;\n        bool placed = (positions[key - 1] <= i && i < positions[key]);\n\n        if (placed) {\n            i++;\n        } else {\n            EXCHANGE(A[i], A[counts[key] - 1]);\n            counts[key]--;\n        }\n    }\n}\n"
  },
  {
    "path": "other/clrs/08/problems/02.markdown",
    "content": "## Sorting in place in linear time\n\n> Suppose that we have an array of $n$ data records and that the key of each\n> record has the value 0 or 1. An algorithm for sorting such a set of records\n> might posses some subset of the following three desirable characteristics:\n>\n> 1. The algorithm runs in $\\O(n)$ time\n> 2. The algorithm is stable.\n> 3. The algorithm sorts in place, using no more than a constant amount of\n>    storage space in addition to the original array.\n>\n> Do the following:\n>\n> 1. Give an algorithm that satisfies criteria 1 and 2 above\n> 2. Give an algorithm that satisfies criteria 1 and 3 above\n> 3. Give an algorithm that satisfies criteria 2 and 3 above\n> 4. Can you use any of your algorithms from parts (a)-(c) as the sorting\n>    method used in line 2 of `RADIX-SORT`, so that `RADIX-SORT` sorts $n$\n>    records with $b$-bit keys in $\\O(bn)$ time? Explain how or why not.\n> 5. Suppose that the $n$ records have keys in the range $1$ to $k$. Show how\n>    to modify counting sort so that it sorts the records in place in\n>    $\\O(n+k)$ time. You may use $\\O(k)$ storage outside the input array. Is\n>    your algorithm stable? (<i>Hint</i>: How would you do it for $k = 3$?)\n\n### Algorithms\n\n1. This can be done with counting sort. We need two variables to track the\n   numbers/indices of ones and zeroes and $\\Theta(n)$ space to make a copy.\n2. This can be done with approach similar to Hoare partition in problem 7.1\n3. I can't think of a stable in-place algorithm so bubble-sort will do\n\n### Usage in radix sort\n\nOnly the first one (the counting sort variant) can be used. The second is not\nstable, which is a requirement for radix sort, and the third takes\n$\\Theta(n^2)$ time, which will turn the compound sorting algorithm\n$\\Theta(bn^2)$.\n\n### In place counting sort\n\nWe build an array of counts as in `COUNTING-SORT`, but we perform the sorting\ndifferently. We start with `i = 0` and then.\n\n    while i ≤ A.length\n        if A[i] is correctly placed\n            i = i + 1\n        else\n            put A[i] in place, exchanging with the element there\n\nOn each step we're either (1) incrementing `i` or (2) putting an element in\nits place. The algorithm terminates because eventually we run out of misplaced\nelements and have to increment `i`.\n\nThere are some details about checking whether `A[i]` is correctly placed that\nare in the C code.\n"
  },
  {
    "path": "other/clrs/08/problems/02.test.c",
    "content": "#include \"02.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n\n#define SEED 300\n#define SIZE 10000\n#define RANGE 200\n\nvoid generate_binary_array(item *A, int size, int from, int to);\nvoid assert_sorted(item *A, int size);\nvoid assert_stable(item *A, int size);\n\nTEST(stable_linear) {\n    item items[SIZE];\n    generate_binary_array(items, SIZE, 0, 1);\n\n    stable_linear_sort(items, SIZE);\n\n    assert_sorted(items, SIZE);\n    assert_stable(items, SIZE);\n}\n\nTEST(linear_in_place) {\n    item items[SIZE];\n    generate_binary_array(items, SIZE, 0, 1);\n\n    linear_in_place_sort(items, SIZE);\n\n    assert_sorted(items, SIZE);\n}\n\nTEST(stable_in_place) {\n    item items[SIZE];\n    generate_binary_array(items, SIZE, 0, 1);\n\n    stable_in_place_sort(items, SIZE);\n\n    assert_sorted(items, SIZE);\n    assert_stable(items, SIZE);\n}\n\nTEST(in_place_counting_sort) {\n    item items[SIZE];\n    generate_binary_array(items, SIZE, 1, RANGE);\n\n    in_place_counting_sort(items, SIZE, RANGE);\n\n    assert_sorted(items, SIZE);\n}\n\nint next_id();\n\nvoid generate_binary_array(item *A, int size, int from, int to) {\n    srand(SEED);\n    for (int i = 0; i < size; i++) {\n        A[i].key = rand() % (to - from + 1) + from;\n        A[i].value = next_id();\n    }\n}\n\nvoid assert_sorted(item *A, int size) {\n    for (int i = 0; i < size - 1; i++) {\n        if (A[i].key > A[i+1].key) {\n            FAIL(\"Not sorted at index %d: %d > %d\", i, A[i].key, A[i+1].key);\n        }\n    }\n}\n\nvoid assert_stable(item *A, int size) {\n    for (int i = 0; i < size - 1; i++) {\n        if (A[i].key == A[i + 1].key && A[i].value > A[i+1].value) {\n            FAIL(\"Not stable at index %d: %d > %d\", i, A[i].value, A[i+1].value);\n        }\n    }\n}\n\nint next_id() {\n    static int id = 1;\n    return id++;\n}\n"
  },
  {
    "path": "other/clrs/08/problems/03.c",
    "content": "#include <math.h>\n#include <string.h>\n\n#define MAX_LENGTH 10\n\n// --- Structs and typedefs ---------------------------------------------------\n\n// In order to simplify everything, both numbers and strings are meshed in a\n// single union called key_t. The key does not know whether it is a number or a\n// string - the handling code already knows it instead.\n\nunion key_t {\n    int number;\n    char string[MAX_LENGTH + 1];\n};\n\ntypedef struct {\n    union key_t key;\n    int value;\n} item;\n\ntypedef int (*key_f)(item, int);\ntypedef int (*dimension_f)(item);\ntypedef int (*compare_f)(item, item);\n\n// --- Prototypes -------------------------------------------------------------\n\n// Various sorting functinos\n\nvoid partition(item *A, int size, int digits, int *groups, dimension_f dimension);\nvoid radix_sort(item *A, int left, int right, int digits, key_f key);\nvoid counting_sort(item *A, int left, int right, int dimension, key_f key, int key_index);\n\n// Functions to work on numbers\n\nint item_nth_digit(item i, int d);\nint item_digits(item i);\n\n// Functions to work on strings\n\nint item_string_length(item i);\nint item_nth_char(item i, int d);\n\n// --- The solutions ----------------------------------------------------------\n\nvoid sort_numbers(item *A, int size, int max_digits) {\n    int groups[max_digits + 1];\n\n    partition(A, size, max_digits, groups, item_digits);\n\n    for (int i = 1; i < max_digits + 1; i++) {\n        radix_sort(A, groups[i - 1], groups[i], i, item_nth_digit);\n    }\n}\n\nvoid sort_strings(item *A, int size, int max_length) {\n    int groups[max_length + 1];\n\n    partition(A, size, max_length, groups, item_string_length);\n\n    for (int len = max_length; len > 0; len--) {\n        counting_sort(A, groups[len - 1], size, 26, item_nth_char, len - 1);\n    }\n}\n\n// --- Auxiliary sorting functions --------------------------------------------\n\n// Performs counting sort on a dimension (number of digits or string length)\n// and populates a table (groups) with the position of each dimension.\n\nvoid partition(item *A, int size, int max_dimension, int *groups, dimension_f dimension) {\n    int counts[max_dimension + 1];\n    item temp[size];\n\n    for (int i = 0; i < max_dimension + 1; i++) { groups[i] = 0; }\n    for (int i = 0; i < size;              i++) { groups[dimension(A[i])]++; }\n    for (int i = 1; i < max_dimension + 1; i++) { groups[i] += groups[i - 1]; }\n    for (int i = 0; i < max_dimension + 1; i++) { counts[i] = groups[i]; }\n    for (int i = 0; i < size;              i++) { temp[i] = A[i]; }\n\n    for (int i = size - 1; i >= 0; i--) {\n        int d = dimension(temp[i]);\n        int count = counts[d];\n\n        A[count - 1] = temp[i];\n        counts[d]--;\n    }\n}\n\n// A simple radix sort\n\nvoid radix_sort(item *A, int left, int right, int digits, key_f key) {\n    for (int i = 0; i < digits; i++) {\n        counting_sort(A, left, right, 10, key, i);\n    }\n}\n\n// A slightly generalized counting sort\n\nvoid counting_sort(item *A, int left, int right, int dimension, key_f key, int key_index) {\n    int size = right - left;\n    int counts[dimension];\n    item temp[size];\n\n    for (int i = 0;    i < dimension; i++) { counts[i] = 0; }\n    for (int i = left; i < right;     i++) { counts[key(A[i], key_index)]++; }\n    for (int i = 1;    i < dimension; i++) { counts[i] += counts[i - 1]; }\n    for (int i = 0;    i < size;      i++) { temp[i] = A[left + i]; }\n\n    for (int i = size - 1; i >= 0; i--) {\n        int n = key(temp[i], key_index);\n        int count = counts[n];\n\n        A[left + count - 1] = temp[i];\n        counts[n]--;\n    }\n}\n\n// --- Key handling -----------------------------------------------------------\n\nint count_digits(int n) {\n    if (n == 0) {\n        return 1;\n    } else {\n        return (int) log10(n) + 1;\n    }\n}\n\nint nth_digit(int n, int d) {\n    int magnitude = (int) pow(10, d);\n\n    return (n / magnitude) % 10;\n}\n\nint item_nth_digit(item i, int d) {\n    return nth_digit(i.key.number, d);\n}\n\nint item_digits(item i) {\n    return count_digits(i.key.number);\n}\n\nint item_string_length(item a) {\n    return strlen(a.key.string);\n}\n\nint item_nth_char(item a, int n) {\n    return a.key.string[n] - 'a';\n}\n"
  },
  {
    "path": "other/clrs/08/problems/03.markdown",
    "content": "## Sorting variable-length items\n\n> 1. You are given an array of integers, where different integers may have\n>    different number of digits, but the total number of digits over *all* the\n>    integers in the array is $n$. Show how to sort the array in $\\O(n)$ time.\n> 2. You are given an array of strings, where different strings may have\n>    different numbers of characters, but the total number of characters over\n>    all the strings is $n$. Show how to sort the strings in $\\O(n)$ time.<br>\n>    (Note that the desired order here is the standard alphabetical order; for\n>    example; $\\mathrm{a} < \\mathrm{ab} < \\mathrm{b}$.)\n\n### The numbers\n\nFor the numbers, we can do this:\n\n1. Group the numbers by number of digits and order the groups\n2. Radix sort each group\n\nLet's analyze the number of steps. Let $G_i$ be the group of numbers with $i$\ndigits and $c_i = |G_i|$. Thus:\n\n$$ T(n) = \\sum_{i=1}{n}c_i \\cdot i = n $$\n\n### The strings\n\nFor the strings, we can do this:\n\n1. Groups the strings by length and order the groups\n2. Starting $i$ on the maximum length and going down to 1, perform counting\n   sort on the $i$th character. Make sure to include only groups that have an\n   $i$th character.\n\nIf the groups are subsequent subarrays in the original array, we're performing\ncounting sort on a subarray ending on the last index of the original array.\n\n### The implementation\n\nThe C code is a bit clever, but this is an exercise, not a production system.\n"
  },
  {
    "path": "other/clrs/08/problems/03.test.c",
    "content": "#include \"03.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n\n#define SEED 300\n#define N 400000\n#define MAX_DIGITS 10\n\nint generate_random_numbers(item *items);\nint generate_random_strings(item *items);\nvoid assert_sorted(item *A, int size, compare_f compare);\nvoid assert_stable(item *A, int size, compare_f compare);\n\nint compare_strings(item a, item b);\nint compare_numbers(item a, item b);\n\nTEST(sort_numbers) {\n    item numbers[N];\n    int size = generate_random_numbers(numbers);\n\n    sort_numbers(numbers, size, MAX_DIGITS);\n\n    assert_sorted(numbers, size, compare_numbers);\n    assert_stable(numbers, size, compare_numbers);\n}\n\nTEST(sort_strings) {\n    item strings[N];\n    int size = generate_random_strings(strings);\n\n    sort_strings(strings, size, MAX_LENGTH);\n\n    assert_sorted(strings, size, compare_strings);\n    assert_stable(strings, size, compare_strings);\n}\n\nint compare_strings(item a, item b) {\n    return strcmp(a.key.string, b.key.string);\n}\n\nint compare_numbers(item a, item b) {\n    return a.key.number - b.key.number;\n}\n\nvoid assert_sorted(item *A, int size, compare_f compare) {\n    for (int i = 0; i < size - 1; i++) {\n        if (compare(A[i], A[i + 1]) > 0) {\n            FAIL(\"Not sorted at index %d\", i);\n        }\n    }\n}\n\nvoid assert_stable(item *A, int size, compare_f compare) {\n    for (int i = 0; i < size - 1; i++) {\n        if (compare(A[i], A[i + 1]) == 0 && A[i].value > A[i+1].value) {\n            FAIL(\"Not stable at index %d: %d > %d\", i, A[i].value, A[i+1].value);\n        }\n    }\n}\n\nint next_id() {\n    static int id = 1;\n    return id++;\n}\n\nint generate_random_numbers(item *numbers) {\n    srand(SEED);\n    int i = 0,\n        digits = 0;\n\n    while (digits < N) {\n        int magnitude = rand() % MAX_DIGITS + 1;\n\n        if (magnitude > N - digits) {\n            magnitude = N - digits;\n        }\n\n        int base   = (int) pow(10, magnitude - 1);\n        int number = rand() % ((int) pow(10, magnitude) - base) + base;\n\n        numbers[i].key.number = number;\n        numbers[i].value = next_id();\n\n        i++;\n        digits += magnitude;\n    }\n\n    return i;\n}\n\nint generate_random_strings(item *strings) {\n    srand(SEED);\n    int i = 0,\n        chars = 0;\n\n    while (chars < N) {\n        int length = rand() % MAX_LENGTH + 1;\n\n        if (length > N - chars) {\n            length = N - chars;\n        }\n\n        int j;\n        for (j = 0; j < length; j++) {\n            strings[i].key.string[j] = 'a' + rand() % 26;\n        }\n        strings[i].key.string[j] = '\\0';\n\n        strings[i].value = next_id();\n\n        i++;\n        chars += length;\n    }\n\n    return i;\n}\n"
  },
  {
    "path": "other/clrs/08/problems/04.c",
    "content": "#include <stdlib.h>\n\ntypedef int jug;\n\nstatic int tmp;\n#define EXCHANGE(a, b) {tmp = a; a = b; b = tmp;}\n\nint cmp(jug red, jug blue);\n\nvoid quadratic_pair(jug *red, jug *blue, int size) {\n    for (int i = 0; i < size; i++) {\n        for (int j = i; j < size; j++) {\n            if (cmp(red[i], blue[j]) == 0) {\n                EXCHANGE(blue[i], blue[j]);\n                break;\n            }\n        }\n    }\n}\n\nint partition(jug *red, jug *blue, int p, int q);\n\nvoid quick_pair(jug *red, jug *blue, int p, int r) {\n    if (p < r - 1) {\n        int q = partition(red, blue, p, r);\n        quick_pair(red, blue, p, q);\n        quick_pair(red, blue, q + 1, r);\n    }\n}\n\nint partition(jug *red, jug *blue, int p, int q) {\n    int pivot, i;\n    jug red_pivot, blue_pivot;\n\n    // Pick a red pivot\n    i = rand() % (q - p) + p;\n    EXCHANGE(red[i], red[q - 1]);\n    red_pivot = red[q - 1];\n\n    // Find the blue pivot and put it in final position\n    // NOTE: This look can be folded in the next one to minimize the number of\n    // comparisons, but I will keep it here for clarity\n    for (int i = p; i < q; i++) {\n        if (cmp(red_pivot, blue[i]) == 0) {\n            EXCHANGE(blue[i], blue[q - 1]);\n            break;\n        }\n    }\n\n    // Partition the blue jugs around the red pivot\n    pivot = p;\n    for (int i = p; i < q - 1; i++) {\n        if (cmp(red_pivot, blue[i]) > 0) {\n            EXCHANGE(blue[pivot], blue[i]);\n            pivot++;\n        }\n    }\n\n    // Put the blue pivot in place\n    EXCHANGE(blue[pivot], blue[q-1]);\n    blue_pivot = blue[pivot];\n\n    // Partition the red jugs around the blue pivot\n    int j = p;\n    for (int i = p; i < q - 1; i++) {\n        if (cmp(red[i], blue_pivot) < 0) {\n            EXCHANGE(red[j], red[i]);\n            j++;\n        }\n    }\n\n    // Put the red pivot in place\n    EXCHANGE(red[q - 1], red[j]);\n\n    // Return the pivot index\n    return pivot;\n}\n\nint cmp(jug red, jug blue) {\n    return red - blue;\n}\n"
  },
  {
    "path": "other/clrs/08/problems/04.markdown",
    "content": "## Water jugs\n\n> Suppose that you are given $n$ red and $n$ blue water jugs, all of different\n> shapes and sizes. All red jugs hold different amounts of water, as do the\n> blue ones. Moreover, for every red jug, there is a blue jug that holds the\n> same amount of water, and vice versa.\n>\n> Your task is to find a grouping of the jugs into pairs of red and blue jugs\n> that hold the same amount of water. To do so, you may perform the following\n> operation: pick a pair of jugs in which one is red and one is blue, fill the\n> red jug with water, and then pour the water into the blue jug. This\n> operation will tell you whether the red or the blue jug can hold more water,\n> or that they have the same volume. Assume that such a comparison takes one\n> time unit. Your goal is to find an algorithm that makes a minimum number of\n> comparisons to determine the grouping. Remember that you man not directly\n> compare two red jugs or two blue jugs.\n>\n> 1. Describe a deterministic algorithm that user a $\\Theta(n^2)$ comparisons\n>    to group the jugs into pairs.\n> 2. Prove a lower bound of $\\Omega(n\\lg{n})$ for the number of comparisons\n>    that an algorithm solving this problem must make.\n> 3. Give a randomized algorithm whose expected number of comparisons is\n>    $\\O(n\\lg{n})$, and prove that this bound is correct. What is the\n>    worst-case number of comparisons for your algorithm?\n\n### Deterministic algorithm\n\nWe compare each red jug with each blue jug and pair them on the first match.\n\n### Lower bound\n\nWe approach it in a similar fashion as section 8.1. The difference is that the\nnodes in this decision tree have three children, instead of two (it's a\n3-tree!). If both sets of jugs are ordered, then a pairing is a\n$n$-permutation that maps each red jug to a blue one. Since there are $n!$\npossible outputs, they should be present as leaves in the decision tree. If\nthe length of the tree is $l$ we get a similar inequality:\n\n$$ n! \\le l \\le 3^h$$\n\nAgain, taking the logarithms, we get:\n\n$$ h \\ge lg(n!) = \\Omega(n\\lg{n}) $$\n\n### Randomized algorithm\n\nWe can use an approach similar to quicksort. The partition function should\nwork as follows:\n\n1. Choose, at random, a red jug for a pivot ($\\O(1)$)\n2. Pick a corresponding blue jug ($\\O(n)$)\n3. Partition the blue jugs around the red pivot and put the blue pivot in\n   place ($\\O(n)$)\n4. Partition the red jugs around the blue pivot and but the red pivot in place\n   ($\\O(n)$).\n\nWe're only comparing red and blue jugs.\n\nThe analysis is similar to the one of quicksort in section 7.4. There is some\neffort to translate the argument to having two arrays and additional\ncomparisons, but the work is not hard. I will not present it here, since I\nthink the applicability of the same argument is obvious.\n"
  },
  {
    "path": "other/clrs/08/problems/04.test.c",
    "content": "#include \"04.c\"\n#include \"../../build/ext/test.h\"\n\n#define SIZE 10000\n#define RANGE 1000000\n#define SEED 300\n\nvoid generate_jugs(int *red, int *blue);\nvoid assert_paired(int *red, int *blue);\n\nTEST(quadratic_pairing) {\n    int red_jugs[SIZE];\n    int blue_jugs[SIZE];\n\n    generate_jugs(red_jugs, blue_jugs);\n\n    quadratic_pair(red_jugs, blue_jugs, SIZE);\n\n    assert_paired(red_jugs, blue_jugs);\n}\n\nTEST(quick_pairing) {\n    int red_jugs[SIZE];\n    int blue_jugs[SIZE];\n\n    generate_jugs(red_jugs, blue_jugs);\n\n    quick_pair(red_jugs, blue_jugs, 0, SIZE);\n\n    assert_paired(red_jugs, blue_jugs);\n}\n\nvoid generate_jugs(int *red, int *blue) {\n    srand(SEED);\n    for (int i = 0; i < SIZE; i++) {\n        red[i] = rand() % RANGE;\n    }\n\n    for (int i = 0; i < SIZE; i++) {\n        blue[i] = red[i];\n    }\n\n    for (int i = SIZE; i >= 1; i--) {\n        int pos = rand() % i;\n        EXCHANGE(blue[i - 1], blue[pos]);\n    }\n}\n\nvoid assert_paired(int *red, int *blue) {\n    for (int i = 0; i < SIZE; i++) {\n        if (red[i] != blue[i]) {\n            FAIL(\"Not paired at index %d: %d != %d\", i, red[i], blue[i]);\n        }\n    }\n}\n"
  },
  {
    "path": "other/clrs/08/problems/05.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <limits.h>\n#include <string.h>\n\ntypedef struct {\n    int value;\n    int s;\n} item;\n\ntypedef struct {\n    item *elements;\n    int length;\n    int heap_size;\n} heap_t;\n\ntypedef struct {\n    int size;\n    int k;\n    int exhausted;\n    int *next_indices;\n} sort_state_t;\n\nvoid merge_sort(int A[], int p, int r, int k, int s);\nvoid min_heap_insert(heap_t *heap, item key);\nint state_took_column(sort_state_t *state, int index);\nitem min_heap_push_pop(heap_t *heap, item new);\nitem heap_minimum(heap_t *heap);\nitem heap_extract_min(heap_t *heap);\n\n/*\n * Average soting is performed by just merge-sorting each column. That was\n * easy. Modifying merge sort was hard.\n */\n\nvoid k_sort(int *numbers, int size, int k) {\n    for (int i = 0; i < k; i++) {\n        merge_sort(numbers, 0, size, k, i);\n    }\n}\n\n/*\n * Sorting a k-sorted array. We need to keep track of which column produced\n * the minumum element in the heap and this resulted in quite the tricky C\n * code. I don't think this is a good practice, but still, that's the best I'm\n * willing to make it right now.\n */\n\nvoid merge_k_sorted(int *numbers, int size, int k) {\n    int copy[size];\n\n    item heap_elements[k];\n    heap_t heap = {heap_elements, k, 0};\n\n    int next_indices[k];\n    sort_state_t state = {size, k, 0, next_indices};\n\n    memcpy(copy, numbers, size * sizeof(int));\n\n    for (int i = 0; i < k; i++) {\n        item new = {copy[i], i};\n        min_heap_insert(&heap, new);\n        next_indices[i] = i + k;\n    }\n\n    for (int i = 0; i < size; i++) {\n        item min = heap_minimum(&heap);\n        numbers[i] = min.value;\n\n        int next = state_took_column(&state, min.s);\n\n        if (next != -1) {\n            min_heap_push_pop(&heap, (item) {copy[next], next % k});\n        } else {\n            heap_extract_min(&heap);\n        }\n    }\n}\n\nint state_took_column(sort_state_t *state, int index) {\n    int size = state->size,\n        k = state->k,\n        s = index,\n        *next_indices = state->next_indices;\n\n    if (next_indices[s] >= size) {\n        while (state->exhausted < k && next_indices[state->exhausted] >= state->size) {\n            state->exhausted++;\n        }\n\n        if (state->exhausted == k) {\n            return -1;\n        }\n\n        int next = next_indices[state->exhausted];\n        next_indices[state->exhausted] += k;\n        return next;\n    } else {\n        next_indices[s] += k;\n        return s;\n    }\n}\n\n/*\n * This is the merge sort from Chapter 2, modified to look only at indices\n * congruent to k modulo s. There are two very ugly and long macroses that\n * perform this unpleasant job. There's probably a nicer way to do the\n * calculation, but modular arithmetic has always been my Achilles' heel.\n */\n\n#define FIRST(index, k, s) ((index) + (s) - (index) % (k) + ((index) % (k) <= (s) ? 0 : (k)))\n#define COUNT(a, b, k, s) (((b) - (a)) / (k) + ((((s) - (a) % (k)) + (k)) % (k) < ((b) - (a)) % (k) ? 1 : 0))\n\nvoid merge(int A[], int p, int q, int r, int k, int s) {\n    int i, j, l;\n\n    int n1 = COUNT(p, q, k, s);\n    int n2 = COUNT(q, r, k, s);\n\n    int L[n1];\n    int R[n2];\n\n    for (i = FIRST(p, k, s), j = 0; i < q; j++, i += k) L[j] = A[i];\n    for (i = FIRST(q, k, s), j = 0; i < r; j++, i += k) R[j] = A[i];\n\n    for(i = 0, j = 0, l = FIRST(p, k, s); l < r; l += k) {\n        if (i == n1) {\n            A[l] = R[j++];\n        } else if (j == n2) {\n            A[l] = L[i++];\n        } else if (L[i] <= R[j]) {\n            A[l] = L[i++];\n        } else {\n            A[l] = R[j++];\n        }\n    }\n}\n\nvoid merge_sort(int A[], int p, int r, int k, int s) {\n    if (COUNT(p, r, k, s) > 1) {\n        int q = (p + r) / 2;\n        merge_sort(A, p, q, k, s);\n        merge_sort(A, q, r, k, s);\n        merge(A, p, q, r, k, s);\n    }\n}\n\n/*\n * Finally, the min heap from exercise 6.5-3, modified to store items instead\n * of ints. When I first wrote it, I made an error in the implementation and\n * that sent me in a hour-long debugging session. C is fun.\n *\n * Also, there is a new heap operation (min_heap_push_pop) that is a faster\n * than heap_extract_min and then min_heap_insert.\n */\n\n#define PARENT(i) ((i - 1) / 2)\n#define LEFT(i)   (2 * i + 1)\n#define RIGHT(i)  (2 * i + 2)\n\nitem heap_minimum(heap_t *heap) {\n    return heap->elements[0];\n}\n\nvoid min_heapify(heap_t *heap, int i) {\n    int left  = LEFT(i),\n        right = RIGHT(i),\n        smallest;\n\n    if (left < heap->heap_size && heap->elements[left].value < heap->elements[i].value) {\n        smallest = left;\n    } else {\n        smallest = i;\n    }\n\n    if (right < heap->heap_size && heap->elements[right].value < heap->elements[smallest].value) {\n        smallest = right;\n    }\n\n    if (smallest != i) {\n        item tmp = heap->elements[i];\n        heap->elements[i] = heap->elements[smallest];\n        heap->elements[smallest] = tmp;\n\n        min_heapify(heap, smallest);\n    }\n}\n\nitem heap_extract_min(heap_t *heap) {\n    if (heap->heap_size == 0) {\n        fprintf(stderr, \"heap underflow\");\n        exit(0);\n    }\n\n    item min = heap->elements[0];\n    heap->elements[0] = heap->elements[heap->heap_size - 1];\n    heap->heap_size--;\n    min_heapify(heap, 0);\n\n    return min;\n}\n\nvoid heap_decrease_key(heap_t *heap, int i, item key) {\n    if (key.value > heap->elements[i].value) {\n        fprintf(stderr, \"new key is larger than current key\");\n        exit(0);\n    }\n\n    heap->elements[i].value = key.value;\n    while (i > 0 && heap->elements[PARENT(i)].value > heap->elements[i].value) {\n        item tmp = heap->elements[PARENT(i)];\n        heap->elements[PARENT(i)] = heap->elements[i];\n        heap->elements[i] = tmp;\n        i = PARENT(i);\n    }\n}\n\nvoid min_heap_insert(heap_t *heap, item key) {\n    if (heap->length == heap->heap_size) {\n        fprintf(stderr, \"heap overflow\");\n        exit(0);\n    }\n\n    heap->elements[heap->heap_size].value = INT_MAX;\n    heap->elements[heap->heap_size].s = key.s;\n    heap->heap_size++;\n    heap_decrease_key(heap, heap->heap_size - 1, key);\n}\n\nitem min_heap_push_pop(heap_t *heap, item new) {\n    item result = heap->elements[0];\n    heap->elements[0] = new;\n    min_heapify(heap, 0);\n    return result;\n}\n"
  },
  {
    "path": "other/clrs/08/problems/05.markdown",
    "content": "## Average sorting\n\n> Suppose that instead of sorting an array, we just require that the elements\n> increase on average. More precisely, we call an $n$-element array\n> **k-sorted** if, for all $i = 1, 2, \\ldots, n - k$, the following holds:\n>\n> $$ \\frac{\\sum_{j=i}^{i+k-1}A[j]}{k} \\le\n>    \\frac{\\sum_{j=i + 1}^{i+k}A[j]}{k} $$\n>\n> <ol type=\"a\">\n>   <li>What does it mean for an array to be 1-sorted?\n>   <li>Give a permutation of the numbers $1, 2, \\ldots, 10$ that is 2-sorted,\n>       but not sorted\n>   <li>Prove that an $n$-element array is k-sorted if and only if $A[i] \\le\n>       A[i+k]$ for all $i = 1, 2, \\ldots, n-k$.\n>   <li>Give an algorithm that $k$-sorts an $n$-element array in\n>       $\\O(n\\lg(n/k))$ time.\n> </ol>\n>\n> We can also show a lower bound on the time to produce a $k$-sorted array,\n> when $k$ is a constant.\n>\n> <ol type=\"a\" start=\"5\">\n>   <li>Show that we can sort a $k$-sorted array of length $n$ in\n>       $\\O(n\\lg{k})$ time. (<i>Hint:</i> Use the solution to exercise 6.5-9.)\n>   <li>Show that when $k$ is a constant, $k$-sorting an $n$-element array\n>       requires $\\Omega(n\\lg{n})$ time. (<i>Hint:</i> Use the solution to the\n>       previous part along with the lower bound on comparison sorts.)\n> </ol>\n\n### Intuitive description\n\nI'm going to state an unintuitive description of what does it mean for an\narray to be $k$-sorted. It will be presented without proof. It will become\nevident later in the text.\n\nIf we write out $k$-sorted array in a grid with $k$ columns, each column will\nbe sorted from top to bottom. This is essentially what (c) means.\n\n### Various notions\n\nFor an array to be 1-sorted it means that it is sorted in the traditional\nsense of the word, that is, $A[i] \\le A[i+1]$ for each index $i$.\n\nHere's a 2-sorted permutation that is not sorted: $2, 1, 4, 3, 6, 5, 8, 7, 10,\n9$.\n\n### Alternative condition\n\nLet's assume that an array is $k$-sorted. Then:\n\n$$ \\frac{\\sum_{j=i}^{i+k-1}A[j]}{k} \\le \\frac{\\sum_{j=i + 1}^{i+k}A[j]}{k} \\\\\\\\\n   \\Updownarrow \\\\\\\\\n   \\frac{A[i] + \\sum_{j=i+1}^{i+k-1}A[j]}{k} \\le\n     \\frac{\\sum_{j=i+1}^{i+k-1}A[j] + A[i+k]}{k} \\\\\\\\\n   \\Updownarrow \\\\\\\\\n   \\frac{A[i]}{k} \\le \\frac{A[i+k]}{k} \\\\\\\\\n   \\Updownarrow \\\\\\\\\n   A[i] \\le A[i+k] $$\n\nNote that this derivation works backwards for proving the **if** part.\n\n### The algorithms\n\nTo $k$-sort the array, we need to sort the $k$ columns, that is, $k$ arrays of\n$n/k$ elements. This is a $(n/k)\\lg(n/k)$ algorithm, performed $k$ times. We\ncan use merge-sort. We don't even need to copy the array - we can calculate\nthe indices on the fly, although that turned less fun than expected.\n\nTo sort a $k$-sorted array, we just do what we suggested in exercise 6.5-9 -\nwe build a min heap and every time we take an element from it, we pick another\nelement from the column the minimal element was in. Keeping track of that in C\nis a bit hairy, so the implementation is gruesome. There is a new operation,\n`MIN-HEAP-PUSH-POP`, that is an improvement over first extracting the element\nand then inserting another one.\n\n### Lower bound on comparisons\n\nThe problem can be reduced to $k$ problems of size $(n/k)$, each with minimal\nnumber of comparisons $\\Omega((n/k)\\lg(n/k))$. The total is\n$\\Omega(n\\lg(n/k))$ and if $k$ is a constant, we get a very familiar\n$\\Omega(n\\lg{n})$. Really not that surprising.\n"
  },
  {
    "path": "other/clrs/08/problems/05.test.c",
    "content": "#include \"05.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n\n#define N 1000000\n#define K 100\n#define SEED 300\n#define RANGE 1000000\n\nvoid generate_random_array(int *numbers);\nvoid assert_k_sorted(int *numbers, int k);\n\nTEST(k_sorting) {\n    int numbers[N];\n\n    generate_random_array(numbers);\n    k_sort(numbers, N, K);\n    assert_k_sorted(numbers, K);\n}\n\nTEST(merging_k_sorted) {\n    int numbers[N];\n\n    generate_random_array(numbers);\n    k_sort(numbers, N, K);\n    merge_k_sorted(numbers, N, K);\n    assert_k_sorted(numbers, 1);\n}\n\nvoid assert_k_sorted(int *numbers, int k) {\n    for (int i = 0; i < N - k; i++) {\n        if (numbers[i] > numbers[i + k]) {\n            FAIL(\"Array not k-sorted at %d/%d: %d > %d:\",\n                    i, i + k, numbers[i], numbers[i + k]);\n        }\n    }\n}\n\nvoid generate_random_array(int *numbers) {\n    srand(SEED);\n\n    for (int i = 0; i < N; i++) {\n        numbers[i] = rand() % RANGE;\n    }\n}\n"
  },
  {
    "path": "other/clrs/08/problems/06.markdown",
    "content": "## Lower bound on merging sorted lists\n\n> The problem of merging two sorted lists arises frequently. We have seen a\n> procedure for it as the subroutine `MERGE` in Section 2.3.1. In this\n> problem, we will prove a lower bound of $2n - 1$ on the worst-case number of\n> comparisons required to merge two sorted lists, each containing $n$ items.\n>\n> First we will show a lower bound of $2n - o(n)$ comparisons by using a\n> decision tree.\n>\n> <ol type=\"a\">\n>   <li>Given $2n$ numbers, compute the number of possible ways to divide them\n>       into two sorted lists, each with $n$ numbers.\n>   <li>Using a decision tree and your answer to part (a), show that any\n>       algorithm that correctly merges two sorted lists must perform $2n -\n>       o(n)$ comparisons.\n> </ol>\n>\n> Now we will show a slightly tighter $2n - 1$ bound.\n>\n> <ol type=\"a\" start=\"3\">\n>   <li>Show that if two elements are consecutive in the sorted order and from\n>   different lists, then they must be compared.\n>   <li>Use your answers to the previous part to show a lower bound of $2n -\n>       1$ comparisons for merging two sorted lists.\n> </ol>\n\n### The first bound\n\nThis can be reduced to a counting problem: in how many ways can we pick $n$\nitems out of $2n$ items? That way we pick the first sorted list and each such\npick determines a single, unique second list. In exercise C.1-13 we already\nproved that:\n\n$$ \\binom{2n}{n} = \\frac{2^{2n}}{\\sqrt{\\pi n}}(1 + \\O(1/n)) $$\n\nUsing the familiar reasoning, if there are $l$ leaves in the decision tree and\nits height is $h$, the following inequality must hold:\n\n$$ \\frac{2^{2n}}{\\sqrt{\\pi n}}(1 + \\O(1/n)) \\le l \\le 2^h $$\n\nTaking the logarithm of the leftmost and rightmost parts (and inverting their\npositions) we get;\n\n$$ \\begin{aligned}\n   h & \\ge \\lg\\bigg(\\frac{2^{2n}}{\\sqrt{\\pi n}}(1 + \\O(1/n))\\bigg) \\\\\\\\\n     & = \\lg{2^{2n}} - \\lg\\sqrt{\\pi n} + \\lg(1 + O(1/n)) \\\\\\\\\n     & = 2n - \\o(n)\n   \\end{aligned} $$\n\n### The tighter bound\n\nIf we don't compare two consecutive elements, we don't know which one comes\nfirst. They are completely indistinguishable when comparing to the other\nelements. We have no way in determining which one should come first. (Note\nthat if they were in the same sorted list, we don't need to compare them,\nsince we already have that information).\n\nIf the sorted order of the elements is $\\langle a_1, b_2, a_2, b_2, \\ldots,\na_n, b_n \\rangle$ and we have the two lists $\\langle a_1, a_2, \\ldots, a_n\n\\rangle$ and $\\langle b_1, b_2, \\ldots, b_n \\rangle$, then there are $2n - 1$\npairs of elements that need to be compared. Any algorithm that handles this\ncase must perform $2n - 1$ comparisons in the worst case.\n"
  },
  {
    "path": "other/clrs/08/problems/07.c",
    "content": "#include <pthread.h>\n#include <math.h>\n#include <stdlib.h>\n#include <stdio.h>\n\n#define STDLIB_SORT qsort\n\ntypedef unsigned int number;\n\ntypedef struct {\n    size_t start;\n    size_t size;\n} column_t;\n\ntypedef void column_sorter(number *, column_t *, int);\n\nvoid check_dimensions(size_t r, size_t s);\n\n/**\n * The basic column sort implementation. It does a copy of the array for steps\n * 3 and 5. It also does not sort the half-columns in the beginning and the\n * end, since that is not necessary for the correctness of the algorithm.\n */\n\nvoid columnsort(number *A, size_t r, size_t s, column_sorter sort_columns) {\n    size_t size = r * s;\n    number *copy;\n    column_t columns[s];\n\n    check_dimensions(r, s);\n\n    copy = calloc(size, sizeof(number));\n\n    for (size_t i = 0; i < s; i++) {\n        columns[i] = (column_t) {i * r, r};\n    }\n\n    sort_columns(A, columns, s);\n\n    for (size_t i = 0; i < size; i++) {\n        copy[(i % s) * r + i / s] = A[i];\n    }\n\n    sort_columns(copy, columns, s);\n\n    for (size_t i = 0; i < size; i++) {\n        A[i] = copy[(i % s) * r + i / s];\n    }\n\n    sort_columns(A, columns, s);\n\n    for (size_t i = 0; i < s - 1; i++) {\n        columns[i] = (column_t) {i * r + r / 2, r};\n    }\n\n    sort_columns(A, columns, s - 1);\n\n    free(copy);\n}\n\n/*\n * A function that compares numbers, to be passed to the stdlib sort.\n */\n\nint compare(const void *a, const void *b) {\n    number *first  = (number *) a;\n    number *second = (number *) b;\n\n    if (*first == *second) {\n        return 0;\n    } else if (*first > *second) {\n        return 1;\n    } else {\n        return -1;\n    }\n}\n\n/*\n * Verified the dimensions of the passed array.\n */\n\nvoid check_dimensions(size_t r, size_t s) {\n    if (r % 2) {\n        fprintf(stderr, \"r must be even\\n\");\n        exit(0);\n    }\n\n    if (r % s) {\n        fprintf(stderr, \"s must divide r\\n\");\n        exit(0);\n    }\n\n    if (r < 2 * s * s) {\n        fprintf(stderr, \"r must be grater than 2s²\\n\");\n        exit(0);\n    }\n}\n\n/*\n * A utility function to call with the array and a column.\n */\n\nvoid sort(number *A, column_t column) {\n    STDLIB_SORT(A + column.start, column.size, sizeof(number), compare);\n}\n\n/*\n * Sequential sorting of columns\n */\n\nvoid sequential_sort_columns(number *numbers, column_t *columns, int size) {\n    for (int i = 0; i < size; i++) {\n        sort(numbers, columns[i]);\n    }\n}\n\n/*\n * Parallel sorting of columns. This implementation is a bit naïve - it can\n * reuse existing threads instead of spawning new ones every time. Furthermore,\n * I never explored using locking mechanisms instead of joining the threads.\n */\n\ntypedef struct {\n    number *numbers;\n    column_t column;\n} job_t;\n\nvoid *sort_job(void *pjob) {\n    job_t *job = (job_t *) pjob;\n    sort(job->numbers, job->column);\n    return NULL;\n}\n\nvoid threaded_sort_columns(number *numbers, column_t *columns, int size) {\n    void *status;\n    pthread_t threads[size];\n    job_t jobs[size];\n    pthread_attr_t attr;\n\n    pthread_attr_init(&attr);\n    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);\n\n    for (int i = 0; i < size; i++) {\n        jobs[i] = (job_t) {numbers, columns[i]};\n        pthread_create(&threads[i], &attr, sort_job, &jobs[i]);\n    }\n\n    for (int i = 0; i < size; i++) {\n        pthread_join(threads[i], &status);\n    }\n}\n"
  },
  {
    "path": "other/clrs/08/problems/07.markdown",
    "content": "## The 0-1 sorting lemma and columnsort\n\n> A **compare-exchange** operation on two array elements $A[i]$ and $A[j]$,\n> where $i < j$ has the form:\n>\n>     COMPARE-EXCHANGE(A, i, j)\n>       if A[i] > A[j]\n>           exchange A[i] with A[j]\n>\n> After the compare-exchange operation, we know that $A[i] \\le A[j]$.\n>\n> An **oblivious compare-exchange algorithm** operates solely by a sequence\n> of prespecified compare-exchange operations. The indices of the positions\n> compared in the sequence must be determined in advance, and although they\n> can depend on the number of elements being sorted, they cannot depend on the\n> values being sorted, nor can they depend on the result of any prior\n> compare-exchange operation. For example, here is insertion sort expressed as\n> an oblivious compare-exchange algorithm:\n>\n>     INSERTION-SORT(A)\n>       for j = 2 to A.length\n>           for i = j - 1 downto 1\n>               COMPARE-EXCHANGE(A, i, i + 1)\n>\n> The **0-1 sorting lemma** provides a powerful way to prove that an oblivious\n> compare-exchange algorithm produces a sorted result. It states that if an\n> oblivious compare-exchange algorithm correctly sorts all input sequences\n> consisting of only 0s and 1s, then it correctly sorts all inputs containing\n> arbitrary values.\n>\n> You will prove the 0-1 sorting lemma by proving its contrapositive: if an\n> oblivious compare-exchange algorithm fails to sort an input containing\n> arbitrary values, then it fails to sort some 0-1 input. Assume that an\n> oblivious compare-exchange algorithm X fails to correctly sort the array\n> $A[1..n]$. Let $A[p]$ be the smallest value in $A$ that algorithm X puts\n> into the wrong location, and let $A[q]$ be the value that algorithm X moves\n> to the location into which $A[p]$ should have gone. Define an array\n> $B[1..n]$ of 0s and 1s as follows:\n>\n> $$ B[i] = \\begin{cases}\n>             0 & \\text{ if } A[i] \\le A[p] \\\\\\\\\n>             1 & \\text{ if } A[i] > A[p]\n>           \\end{cases} $$\n>\n> <ol type=\"a\">\n>   <li>Argue that $A[q] > A[p]$, so that $B[p] = 0$ and $B[q] = 1$.\n>   <li>To complete the proof 0-1 sorting lemma, provide that algorithm X\n>   fails to sort array $B$ correctly.\n> </ol>\n>\n> Now you will use the 0-1 sorting lemma to prove that a particular sorting\n> algorithm works correctly. The algorithm, **columnsort**, works on a\n> rectangular array of $n$ elements. The array has $r$ rows and $s$ columns\n> (so that $n = rs$), subject to three restrictions:\n>\n> * $r$ must be even,\n> * $s$ must be a divisor of r, and\n> * $r \\ge 2s^2$.\n>\n> When columnsort completes, the array is sorted in **column-major order**:\n> reading down the columns, from left to right, the elements monotonically\n> increase.\n>\n> Columnsort operates in eight steps, regardless of the value of $n$. The odd\n> steps are all the same: sort each column individually. Each even step is a\n> fixed permutation. Here are the steps:\n>\n> 1. Sort each column.\n> 2. Transpose the array, but reshape it back to $r$ rows and $s$ columns. In\n>    other words, turn the leftmost column into the top $r/s$ rows, in order;\n>    turn the next column into the next $r/s$ rows, in order; and so on.\n> 3. Sort each column.\n> 4. Perform the inverse of the permutation performed in step 2.\n> 5. Sort each column.\n> 6. Shift the top half of each column into the bottom half of the same\n>    column, and shift the bottom half of each column into the top half of the\n>    next column to the right. Leave the top half of the leftmost column\n>    empty. Shift the bottom half of the last column into the top last column\n>    into the top half of a new rightmost column, and leave the bottom half of\n>    this new column empty.\n> 7. Sort each column\n> 8. Perform the inverse of the permutation performed in step 6.\n>\n> Figure 8.5 shows an example of the steps of columnsort with $r = 6$ and $s =\n> 3$. (Even though this example violated the requirement that $r \\ge 2s^2$, it\n> happens to work.)\n>\n> <ol type=\"a\" start=\"3\">\n>   <li>Argue that we can treat columnsort as an oblivious compare-exchange\n>   algorithm, even if we do not know what sorting method the odd steps are.\n> </ol>\n>\n> Although it might seem hard to believe that columnsort actually sorts, you\n> will use the 0-1 sorting lemma to prove that it does. The 0-1 dorting lemma\n> applies because we can treat columnsort as an oblivious compare-exchange\n> algorithm. A couple of definitions will help you apply the 0-1 sorting\n> lemma. We say that an area of an array is **clean** if we know that it\n> contains either all 0s or all 1s. Otherwise, the area might contain mixed 0s\n> and 1s, and it is dirty. From here on, assume that the input array contains\n> only 0s and 1s, and that we can treat it as an array with $r$ rows and $s$\n> columns.\n>\n> <ol type=\"a\" start=\"4\">\n>   <li>Prove that after steps 1-3, the array consists of some clean rows of\n>   0s at the top, some clean rows of 1s at the bottom, and at most $s$ dirty\n>   rows between them\n>   <li>Prove that after step 4, the array, read in column-major order, starts\n>   with a clean area of 0s, ends with a clean area of 1s, and has a dirty\n>   area of at most $s^2$ elements in the middle.\n>   <li>Prove that steps 5-8 produce a fully sorted 0-1 output. Conclude that\n>   columnsort correctly sorts all inputs containing arbitrary values.\n>   <li>Now suppose that $s$ does not divide $r$. Prove that after steps 1-3,\n>   the array consists of some clean rows of 0s at the top, some clean rows of\n>   1s at the bottom, and at most $2s - 1$ dirty rows between them. How large\n>   must $r$ be, compared with $s$, for columnsort to correctly sort when $s$\n>   does not divide $r$?\n>   <li>Suggest a simple change to step 1 that allow us to maintain the\n>   requirement that $r \\ge 2s^2$ when $s$ does not divide $r$, and prove that\n>   with your change, columnsort correctly sorts.\n> </ol>\n\nThis one is tricky. I would not have been able to solve it by myself. I had\nhelp from those two:\n\n* [The 0-1 sorting principle][0-1-lemma]\n* [Stupid Column Sort Tricks][csort-tricks]\n\n### Proof of the 0-1 sorting lemma\n\nWe know that $A[q] > A[p]$ by definition ($A[q]$ is misplaced, but it cannot\nbe smaller than $A[p]$, since $A[p]$ is the smallest misplaced element). From\nthis it follows that $B[p] = 0$ and $B[q] = 1$.\n\nTo prove the rest, we need to establish that a monotonous mapping and a\ncompare-exchange operation commutate, that is, they can be applied in any\norder. This makes sense, since if the mapping is applied first, the order of\nthe elements would not change (because the mapping is monotonic) and the\ncompare-exchange would have the same result.\n\nAn oblivious compare-exchange algorithm can be regarded as a sequence of\ncompare-exchange operations. Thus, it doesn't matter if the monotonous mapping\nis applied before the fist or after the last compare-exchange operation.\n\nApplying that to $A$ and $B$, we conclude that $B[q] = 1$ and $B[p] = 0$. We\nknow that $q < p$, otherwise $A[q]$ there would have been a smaller misplaced\nelement. From this we gather that $B[q] > B[p]$ and $q < p$, which means that\nthe array is unsorted.\n\nThere is a more formal proof in [the first link][0-1-lemma].\n\n### Applicability\n\nSince the even-numbered steps perform things _blindly_, we can suspect that\nthe algorithm has some elements of obliviousness in it.\n\nIf we perform the odd numbered steps with an oblivious compare-exchange\nalgorithm, then columnsort is obviously oblivious and we can apply the 0-1\nsorting lemma. Since we can treat those steps as \"black boxes\", we can replace\nthe sorting algorithm with any other algorithm that produces the same result\n(that is, any sorting algorithm) and the resulting columnsort would still\nsort.\n\n### Correctness\n\nAfter the first step, each column becomes a sequences of 0s followed by a\nsequence of 1s. In this sense, there is only one `0 → 1` transition in each\ncolumn. Since $s$ divides $r$, each column will map to $r/s$ rows. One of\nthose rows will contain the `0 → 1` transition. The others will contain only\n0s or 1s. That is, each column will map to at most one dirty row and the rest\nwill be clean.\n\nAfter the transposition, and second sorting, the clean rows of 0s will move to\nthe top and the clean rows of 1s will move to the bottom. We're left with at\nmost $s$ dirty rows in the middle.\n\nAfter the reversal of the permutation, the $s$ dirty rows will map to a\nsequence of $s^2$. All the other elements are clean.\n\nThe dirty sequence is at least half a column long now. It either fits in one\ncolumn or crosses over in the next one. All columns left of it contain only 0s\nand all columns right of it contain only 1s.\n\nIf the result is contained in a single column, step 5 will result in a sorting\nin column major mode and the subsequent steps will not interfere with it.\n\nIf not, step 6 arranges the columns in a way that the dirty subsequence will\nfill a single column. Sorting all column cleans it and we have a sorted array.\n\nNote that sorting the half-columns is unnecessary - step 5 already sorted\nthem.\n\n### When s does not divide r\n\nIf $s$ does not divide $r$, a row can contain not only a `0 → 1` transition,\nbut also a `1 → 0` transitions. There would be at most $s - 1$ of those,\nresulting to a dirty region of $2s - 1$.\n\nWe can make $r$ to be at least $2(2s - 1)^2$. As for the change to step one,\nwe can either pad the array with $+ \\infty$ until $s$ divides $r$, or we can\nchop off a small part of the array and sort it separately. The latter will be\nmore efficient, since it does not require moving the array.\n\nFinally, all of that turns to be unnecessary - columnsort works without the\ndivisibility restriction. Details can be found in [the paper][csort-tricks].\n\n### Implementation\n\nSurprising as it is, columnsort smokes the stdlib implementation of quicksort.\nI thought the overhead was to much, but it appears that it is not. Of course,\nthe crossover point will vary.\n\n[0-1-lemma]: http://www.iti.fh-flensburg.de/lang/algorithmen/sortieren/networks/nulleinsen.htm\n[csort-tricks]: http://www.cs.dartmouth.edu/reports/TR2003-444.pdf\n"
  },
  {
    "path": "other/clrs/08/problems/07.run.c",
    "content": "#include \"07.test.c\"\n\n#include <sys/time.h>\n#ifdef __MACH__\n#include <mach/clock.h>\n#include <mach/mach.h>\n#endif\n\nvoid current_utc_time(struct timespec *ts) {\n#ifdef __MACH__\n  clock_serv_t cclock;\n  mach_timespec_t mts;\n  host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);\n  clock_get_time(cclock, &mts);\n  mach_port_deallocate(mach_task_self(), cclock);\n  ts->tv_sec = mts.tv_sec;\n  ts->tv_nsec = mts.tv_nsec;\n#else\n  clock_gettime(CLOCK_REALTIME, ts);\n#endif\n}\n\ndouble elapsed;\nstruct timespec start, finish;\n\n#define TIME(message, sorting) \\\n    randomize(array, NUMBERS); \\\n    current_utc_time(&start); \\\n    sorting; \\\n    current_utc_time(&finish); \\\n    elapsed = (finish.tv_sec - start.tv_sec); \\\n    elapsed += (finish.tv_nsec - start.tv_nsec) / 1000000000.0;\\\n    printf(message \" = %f\\n\", (double) elapsed); \\\n    assert_sorted(array, NUMBERS);\n\nconst size_t COLUMNS = 180;\nconst size_t ROWS = 2 * COLUMNS * COLUMNS;\nconst size_t NUMBERS = ROWS * COLUMNS;\n\nint main() {\n    number *array = calloc(NUMBERS, sizeof(number));\n\n    TIME(\"stdlib sort\", { sort(array, (column_t) {0, NUMBERS}); });\n    TIME(\"columnsort \", { columnsort(array, ROWS, COLUMNS, threaded_sort_columns); });\n\n    return 0;\n}\n"
  },
  {
    "path": "other/clrs/08/problems/07.test.c",
    "content": "#include \"07.c\"\n#include \"../../build/ext/test.h\"\n\n#include <limits.h>\n#include <fcntl.h>\n#include <unistd.h>\n\n#define S 8\n#define R (2 * S * S)\n#define SIZE (R * S)\n#define SEED 301\n\nvoid assert_sorted(number *A, size_t size);\nvoid randomize(number *A, size_t size);\n\nTEST(single_process_columnsort) {\n    number numbers[SIZE];\n    randomize(numbers, SIZE);\n    columnsort(numbers, R, S, threaded_sort_columns);\n    assert_sorted(numbers, SIZE);\n}\n\nTEST(paralel_sort) {\n    number numbers[SIZE];\n    randomize(numbers, SIZE);\n    columnsort(numbers, R, S, threaded_sort_columns);\n    assert_sorted(numbers, SIZE);\n}\n\nvoid assert_sorted(number *A, size_t size) {\n    for (size_t i = 0; i < size - 1; i++) {\n        if (A[i] > A[i + 1]) {\n            FAIL(\"Not sorted at index %lu\", i);\n        }\n    }\n}\n\nvoid randomize(number *A, size_t size) {\n    srand(SEED);\n    for (size_t i = 0; i < size; i++) {\n        A[i] = 0;\n        for (size_t j = 0; j < sizeof(number); j += sizeof(int)) {\n            A[i] <<= sizeof(number);\n            A[i] += rand();\n        }\n    }\n}\n\nvoid print_mesh(number *A, size_t r, size_t s) {\n    size_t size = r * s;\n    number max = 0;\n\n    for (size_t i = 0; i < size; i++) {\n        if (A[i] > max) {\n            max = A[i];\n        }\n    }\n\n    char format[10];\n    sprintf(format, \"%%%dd\", (int) (log10(max) + 3));\n\n    for (size_t i = 0; i < r; i++) {\n        for (size_t j = 0; j < s; j++) {\n            printf(format, A[i + j * r]);\n        }\n        puts(\"\");\n    }\n}\n"
  },
  {
    "path": "other/clrs/09/01/01.markdown",
    "content": "> Show that the second smallest of $n$ elements can be found with $n + \\lceil\n> \\lg{n} \\rceil - 2$ comparisons in the worst case. (<i>Hint:</i> Also find\n> the smallest element.)\n\nWe can compare the elements in a tournament fashion - we split them into\npairs, compare each pair and then proceed to compare the winners in the same\nfashion. We need to keep track of each \"match\" the potential winners have\nparticipated in.\n\nWe select a winner in $n - 1$ matches. At this point, we know that the second\nsmallest element is one of the $\\lg{n}$ elements that lost to the smallest ­\neach of them is smaller than the ones it has been compared to, prior to\nlosing. In another $\\lceil \\lg{n} \\rceil - 1$ comparisons we can find the\nsmallest element out of those. This is the answer we are looking for.\n"
  },
  {
    "path": "other/clrs/09/01/02.markdown",
    "content": "> $\\star$ Prove the lower bound of $\\lceil 3n/2 \\rceil - 2$ comparisons in the\n> worst case to find both the maximum and minimum of $n$ numbers.\n> (<i>Hint:</i> Consider how many numbers are potentially either the maximum\n> or minimum, and investigate how a comparison affects these counts.)\n\nEach comparison can reduce both the potential minimums and maximums by one.\nNote that this is now always the case if we make two comparisons to infer that\n$a < b$ and $a < c$, we have excluded two elements from the potential minimums\n($b$ and $c$), but only one from the potential maximums ($a$).\n\nWe can optimize by splitting the input in pairs and comparing each pair. After\n$n/2$ comparisons, we have reduced the potential minimums and potential\nmaximums to $n/2$ each. Furthermore, those two sets are disjoint so now we\nhave two problems, one minimum and one maximum, each of size $n/2$. The total\nnumber of comparisons is:\n\n$$ n/2 + 2(n/2 - 1) = n/2 + n - 2 = 3n/2 - 2 $$\n\nThis assumes that $n$ is even. If $n$ is odd we need one additional comparison\nin order to determine whether the last element is a potential minimum or\nmaximum. Hence the ceiling.\n"
  },
  {
    "path": "other/clrs/09/02/01.markdown",
    "content": "> Show that `RANDOMIZED-SELECT` never makes a recursive call to a 0-length\n> array.\n\nThe are two cases where it appears that `RANDOMIZED-SELECT` can make a call to\na 0-length array:\n\n1. Line 8 with $k = 1$. But for this to happen, $i$ needs to be 0. And that\n   cannot happen since the initial call is supposed to pass a nonzero $i$ and\n   the recursive calls either pass $i$ unmodified or pass $i - k$ where $i >\n   k$.\n2. Line 9 with $q = r$. But for this to happen, $i$ must be greater than $k$,\n   that is $i > q - p + 1 = r - p + 1$, that is, $i$ needs to be greater than\n   the number of elements in the array. Initially that is not true and both\n   recursive calls maintain an invariant that $i$ is less or equal to the\n   number of elements in $A[p..q]$.\n"
  },
  {
    "path": "other/clrs/09/02/02.markdown",
    "content": "> Argue that the indicator random variable $X_k$ and the value\n> $T(\\max(k-1,n-k))$ are independent.\n\nPicking the pivot in one partitioning does not affect the probabilities of the\nsubproblem. That is, the call to `RANDOM` in `RANDOMIZED-PARTITION` produces a\nresult, independent from the call in the next iteration.\n"
  },
  {
    "path": "other/clrs/09/02/03.c",
    "content": "#include <stdlib.h>\n\nstatic int tmp;\n#define EXCHANGE(a, b) { tmp = a; a = b; b = tmp; }\n\nint randomized_partition(int *A, int p, int r);\n\nint randomized_select(int *A, int p, int r, int i) {\n    while (p < r - 1) {\n        int q = randomized_partition(A, p, r);\n        int k = q - p;\n\n        if (i == k) {\n            return A[q];\n        } else if (i < k) {\n            r = q;\n        } else {\n            p = q + 1;\n            i = i - k - 1;\n        }\n    }\n\n    return A[p];\n}\n\nint partition(int *A, int p, int r) {\n    int x, i, j;\n\n    x = A[r - 1];\n    i = p;\n\n    for (j = p; j < r - 1; j++) {\n        if (A[j] < x) {\n            EXCHANGE(A[i], A[j]);\n            i++;\n        }\n    }\n\n    EXCHANGE(A[i], A[r - 1]);\n\n    return i;\n}\n\nint randomized_partition(int *A, int p, int r) {\n    int pivot = rand() % (r - p) + p;\n    EXCHANGE(A[pivot], A[r - 1]);\n    return partition(A, p, r);\n}\n"
  },
  {
    "path": "other/clrs/09/02/03.markdown",
    "content": "> Write an iterative version of `RANDOMIZED-SELECT`.\n\nWith pleasure.\n"
  },
  {
    "path": "other/clrs/09/02/03.test.c",
    "content": "#include \"03.c\"\n#include \"../../build/ext/test.h\"\n\n#define SIZE 10\n#define SEED 300\n\nvoid generate_array(int *numbers, int size);\n\nTEST(ith_order_statistic) {\n    int numbers[SIZE];\n\n    generate_array(numbers, SIZE);\n    ASSERT_EQUALS(randomized_select(numbers, 0, SIZE, 0), 0);\n\n    generate_array(numbers, SIZE);\n    ASSERT_EQUALS(randomized_select(numbers, 0, SIZE, SIZE / 2), SIZE / 2);\n\n    generate_array(numbers, SIZE);\n    ASSERT_EQUALS(randomized_select(numbers, 0, SIZE, SIZE - 1), SIZE - 1);\n}\n\nvoid generate_array(int *numbers, int size) {\n    srand(SEED);\n    for (int i = 0; i < size; i++) {\n        numbers[i] = i;\n    }\n\n    for (int i = size; i >= 1; i--) {\n        int pos = rand() % i;\n        EXCHANGE(numbers[i - 1], numbers[pos]);\n    }\n}\n"
  },
  {
    "path": "other/clrs/09/02/04.markdown",
    "content": "> Suppose we use `RANDOMIZED-SELECT` to select the minimum element of the\n> array $A = \\langle 3, 2, 9, 0, 7, 5, 4, 8, 6, 1 \\rangle$. Describe a\n> sequence of partitions that results in a worst-case performance of\n> `RANDOMIZED-SELECT`.\n\nThis happens if all the elements get picked up in reverse order ­ that is, the\nfirst pivot chosen is 9, the second is 8, the third is 7 and so on.\n"
  },
  {
    "path": "other/clrs/09/03/01.markdown",
    "content": "> In the algorithm `SELECT`, the input elements are divided into groups of 5.\n> Will the algorithm work in linear time if they are divided into groups of 7?\n> Argue that `SELECT` does not run in linear time if groups of 3 are used.\n\n### Groups of 7\n\nThe algorithm will work if the elements are divided in groups of 7. On each\npartitioning, the minimum number of elements that are less than (or greater\nthan) $x$ will be:\n\n$$ 4 \\bigg(\\bigg\\lceil \\frac{1}{2} \\Big\\lceil \\frac{n}{7} \\Big\\rceil \\bigg\\rceil\n           - 2 \\bigg) \\ge \\frac{2n}{7} - 8 $$\n\nThe partitioning will reduce the subproblem to size at most $5n/7 + 8$. This\nyields the following recurrence:\n\n$$ T(n) = \\begin{cases}\n            \\O(1) & \\text{ if } n < n_0 \\\\\\\\\n            T(\\lceil n/7 \\rceil) + T(5n/7 + 8) + \\O(n) & \\text{ if } n \\ge n_0\n          \\end{cases} $$\n\nWe guess $T(n) \\le cn$ and bound the non-recursive term with $an$:\n\n$$ \\begin{aligned}\n   T(n) & \\le c\\lceil n/7 \\rceil + c(5n/7 + 8) + an \\\\\\\\\n        & \\le cn/7 + c + 5cn/7 + 8c + an \\\\\\\\\n        & = 6cn/7 + 9c + an \\\\\\\\\n        & = cn + (-cn/7 + 9c + an) \\\\\\\\\n        & \\le cn \\\\\\\\\n        & = \\O(n)\n   \\end{aligned} $$\n\nThe last step holds when $(-cn/7 + 9c + an) \\le 0$. That is:\n\n$$ -cn/7 + 9c + an \\le 0 \\\\\\\\\n   \\Downarrow \\\\\\\\\n   c(n/7 - 9) \\ge an \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\frac{c(n - 63)}{7} \\ge an \\\\\\\\\n   \\Downarrow \\\\\\\\\n   c \\ge \\frac{7an}{n - 63}\n$$\n\nBy picking $n_0 = 126$ and $n \\le n_0$, we get that $n/(n - 63) \\le 2$. Then\nwe just need $c \\ge 14a$.\n\n### Groups of 3\n\nThe algorithm will not work for groups of three. The number of elements that\nare less than (or greater than) the median-of-medians is:\n\n$$ 2 \\bigg(\\bigg\\lceil \\frac{1}{2} \\Big\\lceil \\frac{n}{3} \\Big\\rceil \\bigg\\rceil\n           - 2 \\bigg) \\ge \\frac{n}{3} - 4 $$\n\nThe recurrence is thus:\n\n$$ T(n) = T(\\lceil n/3 \\rceil) + T(2n/3 + 4) + \\O(n) $$\n\nWe're going to prove that $T(n) = \\omega(n)$ using the substitution method. We\nguess that $T(n) > cn$ and bound the non-recursive term with $an$.\n\n$$ \\begin{aligned}\n   T(n) & > c\\lceil n/3 \\rceil + c(2n/3 + 2) + an \\\\\\\\\n        & > cn/3 + c + 2cn/3 + 2c + an \\\\\\\\\n        & = cn + 3c + an & (c > 0, a > 0, n > 0)\\\\\\\\\n        & > cn \\\\\\\\\n        & = \\omega(n)\n   \\end{aligned} $$\n\nThe calculation above holds for any $c > 0$.\n"
  },
  {
    "path": "other/clrs/09/03/02.markdown",
    "content": "> Analyze `SELECT` to show that if $n \\ge 140$, then at least $\\lceil n/4\n> \\rceil$ elements are greater than the median-of-medians $x$ and at least\n> $\\lceil n/4 \\rceil$ elements are less than $x$.\n\nThe problem can be reduced to the following inequality:\n\n$$ \\frac{3n}{10} - 6 \\ge \\bigg\\lceil \\frac{n}{4} \\bigg\\rceil \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\frac{3n}{10} - 6 \\ge \\frac{n}{4} + 1 \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\frac{3n}{10} - 7 \\ge \\frac{n}{4} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   12n - 280 \\ge 10n \\\\\\\\\n   \\Downarrow \\\\\\\\\n   2n \\ge 280 \\\\\\\\\n   \\Downarrow \\\\\\\\\n   n \\ge 140 $$\n"
  },
  {
    "path": "other/clrs/09/03/03.markdown",
    "content": "> Show how quicksort can be made to run in $\\O(n\\lg{n})$ time in the worst\n> case, assuming that all elements are distinct.\n\nIf we rewrite `PARTITION` to use the same approach as `SELECT`, it will\nperform in $\\O(n)$ time, but the smallest partition will be at least\none-fourth of the input (for large enough $n$, as illustrated in\nexercise 9.3.2). This will yield a worst-case recurrence of:\n\n$ T(n) = T(n/4) + T(3n/4) + \\O(n) $\n\nAs of exercise 4.4.9, we know that this is $\\Theta(n\\lg{n})$.\n\nAnd that's how we can prevent quicksort from getting quadratic in the worst\ncase, although this approach probably has a constant that is too large for\npractical purposes.\n\nAnother approach would be to find the median in linear time (with `SELECT`)\nand partition around it. That will always give an even split.\n"
  },
  {
    "path": "other/clrs/09/03/04.markdown",
    "content": "> $\\star$ Suppose that an algorithm uses only comparisons to find the $i$th\n> smallest element in a set of $n$ elements. Show that it can also find the\n> $i - 1$ smaller elements and the $n - i$ larger elements without performing\n> any additional comparisons.\n\nA strict proof might require a more advanced proof apparatus than I command\n(like graphs and adversary algorithms, for example?), so I will just sketch it\nbriefly.\n\nIn order to determine the $i$th order statistic, any algorithm needs to\nestablish in some way that there are $i - 1$ elements smaller than the result\nand $n - i$ elements larger than the result. We can visualize the algorithm as\na directed graph, where all the elements are edges. Each comparison introduces\na node from the smaller to the larger element. To produce a result, there must\nbe $i - 1$ elements that (transitively) point to the $i$th order statistic and\n$n - i$ elements that the $i$th order statistic (transitively) points to.\nThere cannot be more (property of the order statistics) and if there are less,\nthen there are elements whose position in regard to the $i$th order statistic\nis undetermined.\n\nIn order to find the result, the algorithm needs to build the knowledge\npresented in such a graph and it can use it to return the sets of smaller and\nlarger elements.\n\nAs an example, both algorithms presented in the chapter leave the array\npartitioned around the $i$th order statistic.\n"
  },
  {
    "path": "other/clrs/09/03/05.markdown",
    "content": "> Suppose that you have a \"black-box\" worst-case linear time median\n> subroutine. Give a simple, linear-time algorithm that solves the selection\n> problem for an arbitrary order statistic.\n\nWe find the median in linear time partition the array around it (again, in\nlinear time). If the median index (always $\\lceil n/2 \\rceil$) equals $n$ we\nreturn the median. Otherwise, we recurse either in the lower or upper part of\nthe array, adjusting $n$ accordingly.\n\nThis yields the following recurrence:\n\n$$ T(n) = T(n/2) + \\O(n) $$\n\nApplying the master method, we get an upper bound of $\\O(n)$.\n"
  },
  {
    "path": "other/clrs/09/03/05.py",
    "content": "def select(items, n):\n    med     = median(items)\n    smaller = [item for item in items if item < med]\n    larger  = [item for item in items if item > med]\n\n    if len(smaller) == n:\n        return med\n    elif len(smaller) > n:\n        return select(smaller, n)\n    else:\n        return select(list(larger), n - len(smaller) - 1)\n\ndef median(items):\n    def median_index(n):\n        if n % 2:\n            return n // 2\n        else:\n            return n // 2 - 1\n\n    def partition(items, element):\n        i = 0\n\n        for j in range(len(items) - 1):\n            if items[j] == element:\n                items[j], items[-1] = items[-1], items[j]\n\n            if items[j] < element:\n                items[i], items[j] = items[j], items[i]\n                i += 1\n\n        items[i], items[-1] = items[-1], items[i]\n\n        return i\n\n    def select(items, n):\n        if len(items) <= 1:\n            return items[0]\n\n        medians = []\n\n        for i in range(0, len(items), 5):\n            group = sorted(items[i:i + 5])\n            items[i:i + 5] = group\n            median = group[median_index(len(group))]\n            medians.append(median)\n\n        pivot = select(medians, median_index(len(medians)))\n        index = partition(items, pivot)\n\n        if n == index:\n            return items[index]\n        elif n < index:\n            return select(items[:index], n)\n        else:\n            return select(items[index + 1:], n - index - 1)\n\n    return select(items[:], median_index(len(items)))\n"
  },
  {
    "path": "other/clrs/09/03/05.test.py",
    "content": "import unittest\nimport os.path as path\n\nfilename = path.join(path.dirname(__file__), '05.py')\nexec(open(filename).read())\n\nimport random\n\nclass SelectionTest(unittest.TestCase):\n    def test_select(self):\n        items = list(range(1, 10000))\n        random.shuffle(items)\n        self.assertEqual(select(items[:], 42), 43)\n        self.assertEqual(select(items[:], 5012), 5013)\n        self.assertEqual(select(items[:], 9998), 9999)\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/09/03/06.markdown",
    "content": "> The $k$th **quantiles** of an $n$-element set are $k - 1$ order statistics\n> that divide the sorted set into $k$ equal-sized sets (to within 1). Give an\n> $\\O(n\\lg{k})$-time algorithm to list the $k$th quantiles of a set.\n\n1. If $k = 1$ we return an empty list.\n2. If $k$ is even, we find the median, partition around it, solve two similar\n   subproblems of size $\\lfloor n / 2 \\rfloor$ and return their solutions plus\n   the median.\n3. If $k$ is odd, we find the $\\lfloor k/2 \\rfloor$ and $\\lceil k/2 \\rceil$\n   boundaries and the we reduce to two subproblems, each with size less than\n   $n/2$.\nThe worst case recurrence is:\n\n$$ T(n, k) = 2T(\\lfloor n/2 \\rfloor, k / 2) + O(n) $$\n\nWhich is the desired bound ­ $\\O(n\\lg{k})$.\n\nThis works easily when the number of elements is $ak + k - 1$ for a positive\ninteger $a$. When they are a different number, some care with rounding needs\nto be taken in order to avoid creating two segments that differ by more than\n1.\n\n"
  },
  {
    "path": "other/clrs/09/03/06.py",
    "content": "import math\n\ndef k_quantiles(items, k):\n    index = median_index(len(items))\n\n    if k == 1:\n        return []\n    elif k % 2:\n        n = len(items)\n        left_index  = math.ceil((k // 2) * (n / k)) - 1\n        right_index = n - left_index - 1\n\n        left  = select(items, left_index)\n        right = select(items, right_index)\n\n        partition(items, left)\n        lower = k_quantiles(items[:left], k // 2)\n        partition(items, right)\n        upper = k_quantiles(items[right + 1:], k // 2)\n\n        return lower + [left, right] + upper\n    else:\n        index = median_index(len(items))\n        median = select(items, index)\n        partition(items, median)\n\n        return k_quantiles(items[:index], k // 2) + \\\n                    [median] + \\\n                    k_quantiles(items[index + 1:], k // 2)\n\ndef median_index(n):\n    if n % 2:\n        return n // 2\n    else:\n        return n // 2 - 1\n\ndef partition(items, element):\n    i = 0\n\n    for j in range(len(items) - 1):\n        if items[j] == element:\n            items[j], items[-1] = items[-1], items[j]\n\n        if items[j] < element:\n            items[i], items[j] = items[j], items[i]\n            i += 1\n\n    items[i], items[-1] = items[-1], items[i]\n\n    return i\n\ndef select(items, n):\n    if len(items) <= 1:\n        return items[0]\n\n    medians = []\n\n    for i in range(0, len(items), 5):\n        group = sorted(items[i:i + 5])\n        items[i:i + 5] = group\n        median = group[median_index(len(group))]\n        medians.append(median)\n\n    pivot = select(medians, median_index(len(medians)))\n    index = partition(items, pivot)\n\n    if n == index:\n        return items[index]\n    elif n < index:\n        return select(items[:index], n)\n    else:\n        return select(items[index + 1:], n - index - 1)\n\n"
  },
  {
    "path": "other/clrs/09/03/06.test.py",
    "content": "import unittest\nimport os.path as path\n\nfilename = path.join(path.dirname(__file__), '06.py')\nexec(open(filename).read())\n\nimport random\n\ndef shuffled(n):\n    items = list(range(n))\n    random.shuffle(items)\n    return items\n\ndef visualize(n, k):\n    items = shuffled(n)\n    quantiles = k_quantiles(items, k)\n    result = '-' * len(items)\n\n    for q in quantiles:\n        result = result[:q] + 'o' + result[q+1:]\n\n    return result\n\nclass QuantilesTest(unittest.TestCase):\n    def test_k_quantiles(self):\n        self.assertEqual(k_quantiles(shuffled(11), 4), [2, 5, 8])\n        self.assertEqual(k_quantiles(shuffled(14), 5), [2, 5, 8, 11])\n        self.assertEqual(k_quantiles(shuffled(17), 6), [2, 5, 8, 11, 14])\n        self.assertEqual(k_quantiles(shuffled(20), 7), [2, 5, 8, 11, 14, 17])\n        self.assertEqual(k_quantiles(shuffled(23), 8), [2, 5, 8, 11, 14, 17, 20])\n\n    def test_visualized_quantiles(self):\n        self.assertEqual(visualize(3, 1),  '---')\n        self.assertEqual(visualize(3, 2),  '-o-')\n        self.assertEqual(visualize(5, 2),  '--o--')\n        self.assertEqual(visualize(2, 3),  'oo')\n        self.assertEqual(visualize(5, 3),  '-o-o-')\n        self.assertEqual(visualize(8, 3),  '--o--o--')\n        self.assertEqual(visualize(11, 3), '---o---o---')\n        self.assertEqual(visualize(11, 4), '--o--o--o--')\n        self.assertEqual(visualize(9, 5),  '-o-o-o-o-')\n        self.assertEqual(visualize(14, 5), '--o--o--o--o--')\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/09/03/07.markdown",
    "content": "> Describe an $\\O(n)$-time algorithm that, given a set $S$ of $n$ distinct\n> numbers and a positive integer $k \\le n$, determines the $k$ numbers in $S$\n> that are closest to the median of $S$.\n\nThis is a fun exercise.\n\n1. We find the median of the array in linear time\n2. We find the distance of each other element to the median in linear time\n3. We find the $k$-th order statistic of the distance, again, in linear time\n4. We select only the elements that have distance lower than or equal to the\n   $k$-th order statistic\n"
  },
  {
    "path": "other/clrs/09/03/08.markdown",
    "content": "> Let $X[1..n]$ and $Y[1..n]$ be two arrays, each containing $n$ numbers\n> already in sorted order. Give an $\\O(\\lg{n})$-time algorithm to find the\n> median of all $2n$ elements in arrays $X$ and $Y$.\n\nThis was fun!\n\n1. If the two arrays are of length $1$, we pick the lower of the two elements\n2. We the two medians of the array\n3. We take the lower part of the array with the greater median and the upper\n   part of the array with the lesser median. If each array has $n$ elements,\n   we take the first/last $\\lfloor n / 2 \\rfloor$ elements\n4. We solve the problem for the new arrays\n\nLet's reason about why this works. Since we have $2n$ elements, we know that\nthe length is an even number and we're looking for a lower median. We need to\nobserve that the median we're looking for is between the medians of the two\narrays. Let's elaborate on that.\n\nLet's assume that the median is at position $k$ in array $A$. This means that\nthere are $k - 1$ elements less than the median in $A$ and $n - k$ elements\ngreater than the median in $B$. If $k < n / 2$ then the median of $A$ will be\ngreater than the final median, but the median of $B$ will be lesser than it.\nIt's the other way around for $k \\ge n / 2$. Thus the median of the two arrays\nis always between the medians of each.\n\nStep 3 removes the same number of elements from each array, half of which are\ngreater than the median and half of which are less than it. This reduces the\nsubproblem to two smaller arrays that are sorted and their elements have the\nsame median.\n"
  },
  {
    "path": "other/clrs/09/03/08.py",
    "content": "def two_array_median(a, b):\n    if len(a) == 1:\n        return min(a[0], b[0])\n\n    m = median_index(len(a))\n    i = m + 1\n    if a[m] < b[m]:\n        return two_array_median(a[-i:], b[:i])\n    else:\n        return two_array_median(a[:i], b[-i:])\n\ndef median_index(n):\n    if n % 2:\n        return n // 2\n    else:\n        return n // 2 - 1\n"
  },
  {
    "path": "other/clrs/09/03/08.test.py",
    "content": "import unittest\nimport os.path as path\n\nfilename = path.join(path.dirname(__file__), '08.py')\nexec(open(filename).read())\n\nimport random\n\ndef shuffled(n):\n    items = list(range(n))\n    random.shuffle(items)\n    return items\n\nclass QuantilesTest(unittest.TestCase):\n    def test_k_quantiles(self):\n        size    = 300\n        median  = median_index(size)\n        numbers = shuffled(size)\n        left, right = sorted(numbers[:size//2]), sorted(numbers[size//2:])\n\n        self.assertEqual(two_array_median(left, right), median)\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/09/03/09.markdown",
    "content": "> Professor Olay is consulting for an oil company, which is planning a large\n> pipeline running east to west through an oil fields of $n$ wells. The\n> company wants to connect a spur pipeline from each well directly to the main\n> pipeline along a shortest route (either north or south), as shown on Figure\n> 9.2. Given the $x$- and $y$- coordinates of the wells, how should the\n> professor pick the optimal location of the main pipeline, which would be the\n> one that minimizes the total length of the spurs? Show how to determine the\n> optimal location in linear time.\n\nWe just find the median of the $y$ coordinates. The $x$ coordinates are\nirrelevant.\n\nLet's assume that $n$ is odd. There are $\\lfloor n / 2 \\rfloor$ south of the\nmedian and the same amount of wells north of the median. Let the pipeline pass\nthrough the median. We shall reason about why this location is optimal.\n\nSuppose we move the pipeline one meter north. This reduces the total pipe\nlength with $\\lfloor n/2 \\rfloor$ meters for the pipes north of the median,\nbut adds another $\\lceil n/2 \\rceil$ for the pipes south of median, including\nthe median itself. The more we move north, the more the total pipe length will\nincrease. The same reasoning holds if we move the main pipeline south.\n\nIf $n$ is even, then any location between the lower and upper median is\noptimal.\n"
  },
  {
    "path": "other/clrs/09/problems/01.markdown",
    "content": "## Largest i numbers in sorted order\n\n> Given a set of $n$ numbers, we wish to find the $i$ largest in sorted order\n> using a comparison based algorithm. Find the algorithm that implements each\n> of the following methods with the best asymptotic worst-case running time,\n> and analyze the running time of the algorithms in terms of $n$ and $i$.\n>\n> <ol type=\"a\">\n>   <li>Sort the numbers, and list the $i$ largest\n>   <li>Build a max-priority queue from the numbers, and call\n>       `EXTRACT-MAX` $i$ times\n>   <li>Use an order-statistic algorithm to find the $i$th largest number,\n>       partition around that number, and sort the $i$ largest numbers.\n> </ol>\n\n### Sorting\n\nWe can sort with any of the $n\\lg{n}$ algorithms, that is, merge sort or heap\nsort and then just take the first $i$ elements linearly.\n\nThis will take $n\\lg{n} + i$ time.\n\n### Max-priority queue\n\nWe can build the heap linearly and then take each of the largest $i$ elements\nin logarithmic time.\n\nThis takes $n + i\\lg{n}$.\n\n### Partition and sort\n\nLet's assume we use the `SELECT` algorithm from the chapter. We can find the\n$i$th order statistic and partition around it in $n$ time and then we need to\ndo a sort in $i\\lg{i}$.\n\nThis takes $n + i\\lg{i}$\n"
  },
  {
    "path": "other/clrs/09/problems/02.markdown",
    "content": "## Weighted median\n\n> For $n$ distinct elements $x_1, x_2, \\ldots, x_n$ with positive weights\n> $w_1, w_2, \\ldots, w_n$ such that $\\sum_{i=1}^n w_i = 1$, the **weighted\n> (lower) median** is the element $x_k$ satisfying\n>\n> $$ \\sum_{x_i < x_k} w_i < \\frac{1}{2} $$\n> and\n> $$ \\sum_{x_i > x_k} w_i \\le \\frac{1}{2} $$\n>\n> For example, if the elments are $0.1, 0.35, 0.05, 0.1, 0.15, 0.05, 0.2$ and\n> each element equals its weight (that is, $w_i = x_i$ for $i = 1, 2, \\ldots,\n> 7$, then the median is $0.1$, but the weighted median is $0.2$.\n>\n> <ol type=\"a\">\n>   <li>Argue that the median of $x_1, x_2, \\ldots, x_n$ is the weighted\n>   median of $x_i$ with weights $w_i = 1/n$ for $i = 1, 2, \\ldots, n$.\n>   <li>Show how to compute the weighted median of $n$ elements in\n>   $\\O(n\\lg{n})$ worst-case time using sorting.\n>   <li>Show how to compute the weighted median in $\\Theta(n)$ worst-case time\n>   using a linear-time median algorithm such as `SELECT` from Section 9.3.\n> </ol>\n>\n> The **post-office location problem** is defined as follows. We are given $n$\n> points $p_1, p_2, \\ldots, p_n$ with associated weights $w_1, w_2, \\ldots,\n> w_n$. We wish to find a point $p$ (not necessarily one of the input points)\n> that minimizes the sum $\\sum_{i=1}^n w_i d(p,p_i)$, where $d(a, b)$ is the\n> distance between the points $a$ and $b$.\n>\n> <ol type=\"a\" start=\"4\">\n>   <li>Argue that the weighted median is a best solution for the\n>   1-dimensional post-office location problem, in which points are simply\n>   real numbers and the distance between points $a$ and $b$ is $d(a,b) = |a -\n>   b|$.\n>   <li>Find the best solution for the 2-dimensional post-office location\n>   problem, in which the points are $(x,y)$ coordinate pairs and the distance\n>   between points $a = (x_1, y_1)$ and $b = (x_2, y_2)$ is the **Manhattan\n>   distance** given by $d(a, b) = |x_1 - x_2| + |y_1 - y_2|$.\n> </ol>\n\n### Median and weighted median\n\nIf the weights all elements are $1/n$, then the sum of the weights of the\nelements, smaller than the median, is $\\lfloor \\frac{n - 1}{2} \\rfloor\n\\frac{1}{n}$ and the sum of the weights of the larger elements is $\\lceil\n\\frac{n - 1}{2} \\rceil \\frac{1}{n}$. This satisfies the condition for weighted\nmedian. Furthermore, choosing a smaller or greater value will not hold in the\ncondition.\n\n### Computing with sorting\n\n1. Sort the array\n2. Start walking the array from left to right, accumulating the weights of the\n   elements encountered\n3. The first element with accumulated weight $w \\ge 1/2$ is the weighted\n   median\n\n### Computing in linear time\n\nIt's a very similar to `SELECT`, but instead of passing $i$, we pass a number\naround which the weights should partition (initially $1/2$). We find a good\npivot in linear time and we partition around it. When we sum the weights in\nthe lower part of the array and the weights in the upper part. If they fulfill\nthe condition, we have our weighted median.\n\n### 1-dimensional post-office location problem\n\nI'll present an informal argument, since it is convincing enough. A more\nformal one can be found in the instructor's manual.\n\nThe situation is similar to exercise 9.3.8. Let's assume that we pick the\nweighted median as the solution and then start moving left or right. As we\nmove away from the weighted median (in any direction), we're moving towards\nelements with combined weight less than $1/2$ and away from elements wight\ncombined weight greater than $1/2$. Every \"step\" we take, we're increasing the\ntotal distance.\n\n### 2-dimensional post-office location problem with Manhattan distance\n\nThe solution is finding $(x_m, y_m)$ where those are the weighted medians of\nthe $x$- and $y$- coordinates.\n\nI'm not even going to start proving this formally, since it requires\nmathematics above my current comfort level. Reasoning informally, by the\ndefinition of Manhattan distance, the $x$ coordinates and the $y$ coordinates\nare independent ­ we can rearrange the $x$ in any way we want, without\naffecting the $y$ coordinate of the solution and vice-versa.\n"
  },
  {
    "path": "other/clrs/09/problems/03.markdown",
    "content": "## Small order statistics\n\n> We showed that the worst-case number $T(n)$ of comparisons used by `SELECT`\n> to select the $i$th order statistic from $n$ numbers satisfies $T(n) =\n> \\Theta(n)$, but the constant hidden by the $\\Theta$-notation is rather\n> large. When $i$ is small relative to $n$, we can implement a different\n> procedure that uses `SELECT` as a subroutine but makes fewer comparisons in\n> the worst case.\n>\n> <ol type=\"a\">\n>   <li>Describe an algorithm that uses $U_i(n)$ comparisons to find the $i$th\n>   smallest of $n$ elements, where\n>   $$ U_i(n) = \\begin{cases}\n>                 T(n) & \\text{if } i \\ge n/2 \\\\\\\\\n>                 \\lfloor n/2 \\rfloor + U_i(\\lceil n/2 \\rceil) + T(2i) & \\text{otherwise}\n>               \\end{cases} $$\n>   (<i>Hint:</i> Begin with $\\lfloor n/2 \\rfloor$ disjoint pairwise\n>   comparisons, and recurse on the set containing the smaller element from\n>   each pair.)\n>   <li>Show that, if $i < n/2$, then $U_i(n) = n + \\O(T(2i)\\lg(n/i))$.\n>   <li>Show that, if $i$ is a constant less than $n/2$, then $U_i(n) = n +\n>   \\O(\\lg{n})$.\n>   <li>Show that, if $i = n/k$ for $k \\ge 2$, then $U_i(n) = n +\n>   \\O(T(2n/k)\\lg{k})$.\n> </ul>\n\n### The algorithm\n\nThis is a modified version of `SELECT`. Not only it finds the $i$th order\nstatistic, but it also partitions the array, thus finding the $i-1$ smaller\nelements.\n\n1. If $i \\ge n/2$, we just use `SELECT`\n2. Otherwise, split the array in pairs and compare each pair.\n3. We take the smaller elements of each pair, but keep track of the other one.\n4. We recursively find the first $i$ elements among the smaller elements\n5. The $i$th order statistic is among the pairs containing the smaller\n   elements we found in the previous step. We call `SELECT` on those $2i$\n   elements. That's the final answer.\n\nJust picking the smaller element of each pair is not enough. For example, if\nwe're looking for the 2nd order statistic and our pairs are `1, 2`, `3, 4`,\n`5, 6`, `7, 8`, `9, 10`, the answer is in the larger part of the first pair.\nThat's why we need to keep track and later perform `SELECT` on $2i$ elements.\n\nSteps 1-4 can be implemented in place by modifying the algorithm to put the\nlarger elements of the pairs on the inactive side of the pivot and modifying\n`PARTITION` to swap the elements on the inactive side every time it swaps\nelements on the active side. More details can be found in the Instructor's\nManual.\n\n### The math\n\nWe can prove (b) by induction. This is the step:\n\n$$ \\begin{aligned}\n   U_i(n) &= \\lfloor n/2 \\rfloor + U_i(\\lceil n/2 \\rceil) + T(2i) \\\\\\\\\n          &= \\lfloor n/2 \\rfloor + \\lceil n/2 \\rceil +\n             \\O(T(2i)\\lg(\\lfloor n/2 \\rfloor / i)) + T(2i) \\\\\\\\\n          &= n + \\O(T(2i)\\lg(n/i)) + T(2i) \\\\\\\\\n          &= n + \\O(T(2i)\\lg(n/i))\n   \\end{aligned} $$\n\nThis is a bit more sloppy that doing it with the substitution method, but that\nfeels like grunt work to me at this point.\n\nThe other two are obvious:\n\n$$ \\begin{aligned}\n   U_i(n) &= n + \\O(T(2i)\\lg(n/i)) \\\\\\\\\n          &= n + \\O(\\O(1)\\lg(n/i)) \\\\\\\\\n          &= n + \\O(\\lg{n} - \\lg{i}) \\\\\\\\\n          &= n + \\O(\\lg{n} - \\O(1)) \\\\\\\\\n          &= n + \\O(\\lg{n})\n   \\end{aligned} $$\n\n$$ \\begin{aligned}\n   U_i(n) &= n + \\O(T(2i)\\lg(n/i)) \\\\\\\\\n          &= n + \\O(T(2n/k)\\lg(n/(n/k))) \\\\\\\\\n          &= n + \\O(T(2n/k)\\lg{k}) \\\\\\\\\n   \\end{aligned} $$\n\nAgain, this reasoning is sloppy, but I don't feel like applying the\nsubstitution method.\n"
  },
  {
    "path": "other/clrs/09/problems/04.markdown",
    "content": "## Alternative analysis of randomized selection\n\n> In this problem, we use indicator random variables to analyze the\n> `RANDOMIZED-SELECT` procedure in a manner akin to our analysis of\n> `RANDOMIZED-QUICKSORT` in section 7.4.2.\n>\n> As in the quicksort analysis, we assume that all the elements are distinct,\n> and we rename the elements of the input array $A$ as $z_1, z_2, \\ldots,\n> z_n$, where $z_i$ is the $i$th smallest element. Thus, the call\n> `RANDOMIZED-SELECT(A,1,n,k)` returns $z_k$.\n>\n> For $i \\le i < j \\le n$, let\n>\n> $$ X_{ijk} = I\\\\{z_i \\text{ is compared with } z_j \\text{ sometime during\n>    the execution of the algorithm to find } z_k \\\\} $$\n>\n> <ol type=\"a\">\n>   <li>Give an exact expression for $\\E[X_{ijk}]$. (<i>Hint:</i> Your\n>   expression may have different values, depending on the values of $i$, $j$,\n>   and $k$.)\n>   <li>Let $X_k$ denote the total number of comparisons between elements of\n>   array $A$ when finding $z_k$. Show that\n>   $$ \\E[X_k] \\le 2 \\bigg(\n>        \\sum_{i=1}^k \\sum_{j=k}^n \\frac{1}{j - i + 1} +\n>        \\sum_{j=k+1}^n \\frac{j - k - 1}{j - k + 1} +\n>        \\sum_{i=1}^{k-2} \\frac{k - i - 1}{k - i + 1}\n>        \\bigg) $$\n>   <li>Show that $\\E[X_k] \\le 4n$.\n>   <li>Conclude that, assuming all elements of array $A$ are distinct,\n>   `RANDOMIZED-SELECT` runs in expected time $\\O(n)$.\n> </ol>\n\n### Expectation of exchanging two elements\n\nThe situation is very similar to the quicksort analysis, although $k$ matters.\n$z_i$ and $z_j$ will be compared if one of them is the first element to get\npicked as a pivot in the smallest interval containing $i$, $j$ and $k$. The\nexact expression depends on the position of $k$ in regards to the other two:\n\n$$ \\E[X_{ijk}] =\n     \\begin{cases}\n       2 / (k - i + 1) & \\text{if } i < j \\le k \\\\\\\\\n       2 / (j - i + 1) & \\text{if } i \\le k \\le j \\\\\\\\\n       2 / (j - k + 1) & \\text{if } k \\le i < j\n     \\end{cases}\n$$\n\n### The expected number of comparisons\n\nIt's a long derivation:\n\n$$ \\begin{aligned}\n   \\E[X_k] &= \\sum_{i=1}^{n-1}   \\sum_{j=i+1}^n \\E[X_{ijk}] \\\\\\\\\n           &= \\sum_{i=1}^k       \\sum_{j=i+1}^n \\E[X_{ijk}]\n            + \\sum_{i=k+1}^{n-1} \\sum_{j=i+1}^n \\E[X_{ijk}] \\\\\\\\\n           &= \\sum_{i=1}^k \\bigg(\\sum_{j=i+1}^{k-1}\\E[X_{ijk}]\n                                 + \\sum_{j=k}^n\\E[X_{ijk}] \\bigg)\n            + \\sum_{i=k+1}^{n-1}\\sum_{j=i+1}^n\\E[X_{ijk}] \\\\\\\\\n           &= \\sum_{i=1}^k       \\sum_{j=i+1}^{k-1} \\E[X_{ijk}]\n            + \\sum_{i=1}^k       \\sum_{j=k}^n       \\E[X_{ijk}]\n            + \\sum_{i=k+1}^{n-1} \\sum_{j=i+1}^n     \\E[X_{ijk}] \\\\\\\\\n           &= \\sum_{i=1}^{k-2}   \\sum_{j=i+1}^{k-1} \\E[X_{ijk}]\n            + \\sum_{i=1}^k       \\sum_{j=k}^n       \\E[X_{ijk}]\n            + \\sum_{i=k+1}^{n-1} \\sum_{j=i+1}^n     \\E[X_{ijk}] \\\\\\\\\n           &= \\sum_{i=1}^{k-2}   \\sum_{j=i+1}^{k-1} \\frac{2}{k - i + 1}\n            + \\sum_{i=1}^k       \\sum_{j=k}^n       \\frac{2}{j - i + 1}\n            + \\sum_{i=k+1}^{n-1} \\sum_{j=i+1}^n     \\frac{2}{j - k + 1} \\\\\\\\\n           &= 2\\bigg(\n                \\sum_{i=1}^k       \\sum_{j=k}^n       \\frac{1}{j - i + 1}\n              + \\sum_{i=k+1}^{n-1} \\sum_{j=i+1}^n     \\frac{1}{j - k + 1}\n              + \\sum_{i=1}^{k-2}   \\sum_{j=i+1}^{k-1} \\frac{1}{k - i + 1}\n              \\bigg) \\\\\\\\\n           &= 2\\bigg(\n                \\sum_{i=1}^k       \\sum_{j=k}^n       \\frac{1}{j - i + 1}\n              + \\sum_{i=k+1}^{n-1} \\sum_{j=i+1}^n     \\frac{1}{j - k + 1}\n              + \\sum_{i=1}^{k-2}   \\frac{k - i - 1}{k - i + 1}\n              \\bigg) \\\\\\\\\n           &= 2\\bigg(\n                \\sum_{i=1}^k       \\sum_{j=k}^n       \\frac{1}{j - i + 1}\n              + \\sum_{j=k+2}^n     \\sum_{i=k+1}^{j-1} \\frac{1}{j - k + 1}\n              + \\sum_{i=1}^{k-2}   \\frac{k - i - 1}{k - i + 1}\n              \\bigg) & \\text{(note below)} \\\\\\\\\n           &= 2\\bigg(\n                \\sum_{i=1}^k       \\sum_{j=k}^n       \\frac{1}{j - i + 1}\n              + \\sum_{j=k+2}^n     \\frac{j - k - 1}{j - k + 1}\n              + \\sum_{i=1}^{k-2}   \\frac{k - i - 1}{k - i + 1}\n              \\bigg) \\\\\\\\\n           &\\le 2\\bigg(\n                \\sum_{i=1}^k       \\sum_{j=k}^n       \\frac{1}{j - i + 1}\n              + \\sum_{j=k+1}^n     \\frac{j - k - 1}{j - k + 1}\n              + \\sum_{i=1}^{k-2}   \\frac{k - i - 1}{k - i + 1}\n              \\bigg) \\\\\\\\\n   \\end{aligned} $$\n\nThe last noted derivation is valid because of the following iversonian\nequation:\n\n$$ [k+1 \\le i \\le n - 1][i+1 \\le j \\le n] =\n   [k+1 \\le i < i + 1 < j \\le n] =\n   [k + 1 < j \\le n][k + 1 \\le i < j]$$\n\nConcrete mathematics helped a lot!\n\n### Bounding to 4n\n\nLet's take the expressions in parts. The last two are straightforward enough:\n\n$$ \\sum_{j=k+1}^n\\frac{j-k-1}{j-k+1} + \\sum_{i=1}^{k-2}\\frac{k-i-1}{k-i+1}\n   \\le \\sum_{j=k+1}^n 1 + \\sum_{i=1}^{k-2} 1\n   = n - k + k - 2\n   \\le n $$\n\nThis one is a bit trickier for me:\n\n$$ \\sum_{i=1}^k \\sum_{j=k}^n \\frac{1}{j - i + 1} $$\n\nIt contains terms of the form $1/m$ where $1 \\le m \\le n$. It contains $1/1$\nat most once, $1/2$ at most twice, $1/3$ at most three times and so on. Thus,\nthe sum of the expressions $1/m$ for each $m$ is at most $1$ and there are $n$\nsuch different expressions, which bounds the whole sum to $n$.\n\nThere should be a way to manipulate the sums to prove that, but I cannot find\nit. In any case, both expressions are at most $2n$, which means that $\\E[X_k]\n\\le 4n$.\n\n### Conclusion\n\nWell, it's rather obvious, isn't it? The number of operations in\n`RANDOMIZED-SELECT` are linear to the number of comparisons, and the expected\nnumber of comparisons are bound by a linear function, which means that the\nexpected running time is linear.\n"
  },
  {
    "path": "other/clrs/10/01/01.markdown",
    "content": "> Using figure 10.1 as a model, illustrate the result of each operation in the\n> sequence `PUSH(S, 4)`, `PUSH(S, 1)`, `PUSH(S, 3)`, `POP(S)`, `PUSH(S, 8)`,\n> and `POP(S)` on an initially empty stack `S` stored in array `S[1..6]`.\n\nWell, ASCII art to the rescue.\n\n      +---+---+---+---+---+---+\n      |   |   |   |   |   |   |\n      +---+---+---+---+---+---+\n    ^\n    S.top = 0\n\n    PUSH(S, 4)\n      +---+---+---+---+---+---+\n      | 4 |   |   |   |   |   |\n      +---+---+---+---+---+---+\n        ^\n        S.top = 1\n\n    PUSH(S, 1)\n      +---+---+---+---+---+---+\n      | 4 | 1 |   |   |   |   |\n      +---+---+---+---+---+---+\n            ^\n            S.top = 2\n\n    PUSH(S, 3)\n      +---+---+---+---+---+---+\n      | 4 | 1 | 3 |   |   |   |\n      +---+---+---+---+---+---+\n                ^\n                S.top = 3\n\n    POP(S)\n      +---+---+---+---+---+---+\n      | 4 | 1 | 3 |   |   |   |\n      +---+---+---+---+---+---+\n            ^\n            S.top = 2\n\n    PUSH(S, 8)\n      +---+---+---+---+---+---+\n      | 4 | 1 | 8 |   |   |   |\n      +---+---+---+---+---+---+\n                ^\n                S.top = 3\n\n    POP(S)\n      +---+---+---+---+---+---+\n      | 4 | 1 | 8 |   |   |   |\n      +---+---+---+---+---+---+\n            ^\n            S.top = 2\n"
  },
  {
    "path": "other/clrs/10/01/02.markdown",
    "content": "> Explain how to implement two stacks in one array $A[1..n]$ in such a way\n> that neither stack overflows unless the total number of elements in both\n> stacks together is $n$. The `PUSH` and `POP` operations should run in\n> $\\O(1)$ time.\n\nThe first stack starts at $1$ and grows up towards $n$, while the second\nstarts form $n$ and grows down towards $1$. Stack overflow happens when an\nelement is pushed when the two stack pointers are adjacent.\n"
  },
  {
    "path": "other/clrs/10/01/03.markdown",
    "content": "> Using figure 10.2 as a model, illustrate the result of each operation in the\n> sequence `ENQUEUE(Q, 4)`, `ENQUEUE(Q, 1)`, `ENQUEUE(Q, 3)`, `DEQUEUE(Q)`,\n> `ENQUEUE(Q, 8)`, and `DEQUEUE(Q)` on an initially empty queue `Q` stored in\n> array `Q[1..6]`.\n\nAgain, ASCII art to the rescue:\n\n      +---+---+---+---+---+---+\n      |   |   |   |   |   |   |\n      +---+---+---+---+---+---+\n        ^\n        Q.head = Q.tail = 1\n\n    ENQUEUE(Q, 4)\n      +---+---+---+---+---+---+\n      | 4 |   |   |   |   |   |\n      +---+---+---+---+---+---+\n        ^   ^\n        Q.head = 1\n        Q.tail = 2\n\n    ENQUEUE(Q, 1)\n      +---+---+---+---+---+---+\n      | 4 | 1 |   |   |   |   |\n      +---+---+---+---+---+---+\n        ^       ^\n        Q.head = 1\n        Q.tail = 3\n\n    ENQUEUE(Q, 3)\n      +---+---+---+---+---+---+\n      | 4 | 1 | 3 |   |   |   |\n      +---+---+---+---+---+---+\n        ^           ^\n        Q.head = 1\n        Q.tail = 4\n\n    DEQUEUE(Q)\n      +---+---+---+---+---+---+\n      | 4 | 1 | 3 |   |   |   |\n      +---+---+---+---+---+---+\n            ^       ^\n            Q.head = 2\n            Q.tail = 4\n\n    ENQUEUE(Q, 8)\n      +---+---+---+---+---+---+\n      | 4 | 1 | 3 | 8 |   |   |\n      +---+---+---+---+---+---+\n            ^           ^\n            Q.head = 2\n            Q.tail = 5\n\n    DEQUEUE(Q)\n      +---+---+---+---+---+---+\n      | 4 | 1 | 3 | 8 |   |   |\n      +---+---+---+---+---+---+\n                ^       ^\n                Q.head = 3\n                Q.tail = 5\n"
  },
  {
    "path": "other/clrs/10/01/04.markdown",
    "content": "> Rewrite `ENQUEUE` and `DEQUEUE` to detect underflow and overflow of a queue.\n\nI shall go with the pseudo-code version, since I'm too lazy to bother figuring\nout how to test it in C.\n\nWe need to do a slight modification, since the current version provides no way\nto tell whether a queue is empty or full. We should have `Q.head == NIL` when\nthe queue is empty and `Q.head == Q.tail` when the queue is full. An empty\nqueue is initializes with `NIL` in its head and `Q.tail = `. We need to update\n`Q.head` when a `DEQUEUE` operation causes the queue to become empty.\n\n    ENQUEUE(Q, x)\n      if Q.head == Q.tail\n          error \"Queue overflow\"\n\n      Q[Q.tail] = x\n\n      if Q.head == NIL\n          Q.head = Q.tail\n\n      if Q.tail == Q.length\n          Q.tail = 1\n      else\n          Q.tail = Q.tail + 1\n\n    DEQUEUE(Q)\n      if Q.head == NIL\n          error \"Queue underflow\"\n\n      x = Q[Q.head]\n\n      if Q.head == Q.length\n          Q.head = 1\n      else\n          Q.head = Q.head + 1\n\n      if Q.head == Q.tail\n          Q.head = NIL\n      return x\n"
  },
  {
    "path": "other/clrs/10/01/05.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n\n#define MAX_SIZE 10\n\ntypedef struct {\n    int items[MAX_SIZE];\n    int head;\n    int tail;\n} deque_t;\n\nvoid init_deque(deque_t *deque) {\n    deque->head = -1;\n    deque->tail = 0;\n}\n\nint is_empty(deque_t *deque) {\n    return (deque->head == -1);\n}\n\nvoid push(deque_t *deque, int n) {\n    if (deque->head == deque->tail) {\n        fprintf(stderr, \"Deque overflow\\n\");\n        exit(1);\n    }\n\n    deque->items[deque->tail] = n;\n\n    if (deque->head == -1) {\n        deque->head = deque->tail;\n    }\n\n    deque->tail = (deque->tail + 1) % MAX_SIZE;\n}\n\nvoid unshift(deque_t *deque, int n) {\n    if (deque->head == deque->tail) {\n        fprintf(stderr, \"Deque overflow\\n\");\n        exit(1);\n    }\n\n    if (deque->head == -1) {\n        deque->head = deque->tail;\n    }\n\n    deque->head = (deque->head - 1 + MAX_SIZE) % MAX_SIZE;\n    deque->items[deque->head] = n;\n}\n\nint pop(deque_t *deque) {\n    if (deque->head == -1) {\n        fprintf(stderr, \"Deque underflow\\n\");\n        exit(1);\n    }\n\n    deque->tail = (deque->tail + MAX_SIZE - 1) % MAX_SIZE;\n\n    if (deque->tail == deque->head) {\n        deque->head = -1;\n    }\n\n    return deque->items[deque->tail];\n}\n\nint shift(deque_t *deque) {\n    if (deque->head == -1) {\n        fprintf(stderr, \"Deque underflow\\n\");\n        exit(1);\n    }\n\n    int result = deque->items[deque->head];\n\n    deque->head = (deque->head + 1) % MAX_SIZE;\n\n    if (deque->head == deque->tail) {\n        deque->head = -1;\n    }\n\n    return result;\n}\n\n"
  },
  {
    "path": "other/clrs/10/01/05.markdown",
    "content": "> Whereas a stack allows insertion and deletion of elements at only one end,\n> and a queue allows insertion at one end and deletion at the other end, a\n> **deque** (double-ended queue) allows insertion and deletion at both ends.\n> Write four $\\O(1)$-time procedures to insert elements into and delete\n> elements from both ends of a deque implemented by an array.\n"
  },
  {
    "path": "other/clrs/10/01/05.test.c",
    "content": "#include \"05.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(using_as_a_stack) {\n    deque_t deque;\n\n    init_deque(&deque);\n    push(&deque, 1);\n    push(&deque, 2);\n    push(&deque, 3);\n\n    ASSERT_FALSE(is_empty(&deque));\n    ASSERT_EQUALS(pop(&deque), 3);\n    ASSERT_EQUALS(pop(&deque), 2);\n    ASSERT_EQUALS(pop(&deque), 1);\n    ASSERT_TRUE(is_empty(&deque));\n\n    push(&deque, 4);\n    ASSERT_FALSE(is_empty(&deque));\n    ASSERT_EQUALS(pop(&deque), 4);\n    ASSERT_TRUE(is_empty(&deque));\n}\n\nTEST(using_as_queue) {\n    deque_t deque;\n\n    init_deque(&deque);\n    push(&deque, 1);\n    push(&deque, 2);\n    push(&deque, 3);\n\n    ASSERT_FALSE(is_empty(&deque));\n    ASSERT_EQUALS(shift(&deque), 1);\n    ASSERT_EQUALS(shift(&deque), 2);\n    ASSERT_EQUALS(shift(&deque), 3);\n    ASSERT_TRUE(is_empty(&deque));\n}\n\nTEST(unshifting) {\n    deque_t deque;\n\n    init_deque(&deque);\n    unshift(&deque, 1);\n    unshift(&deque, 2);\n    unshift(&deque, 3);\n\n    ASSERT_FALSE(is_empty(&deque));\n    ASSERT_EQUALS(pop(&deque), 1);\n    ASSERT_EQUALS(pop(&deque), 2);\n    ASSERT_EQUALS(pop(&deque), 3);\n    ASSERT_TRUE(is_empty(&deque));\n}\n\nTEST(wrapping_around_on_push) {\n    deque_t deque;\n    int i;\n\n    init_deque(&deque);\n\n    for (i = 0; i < MAX_SIZE; i++) {\n        push(&deque, i);\n    }\n\n    shift(&deque);\n    push(&deque, i);\n\n    ASSERT_EQUALS(deque.items[0], i);\n}\n\nTEST(wrapping_around_on_shift) {\n    deque_t deque;\n    int i;\n\n    init_deque(&deque);\n\n    for (i = 0; i < MAX_SIZE - 1; i++) {\n        unshift(&deque, i);\n    }\n\n    unshift(&deque, i);\n\n    ASSERT_EQUALS(deque.items[0], i);\n}\n"
  },
  {
    "path": "other/clrs/10/01/06.markdown",
    "content": "> Show how to implement a queue using two stacks. Analyze the running time of\n> the queue operations.\n\nLet the two stacks be `A` and `B`.\n\n`ENQUEUE` pushes elements on `B`. `DEQUEUE` pops elements from `A`. If `A` is\nempty, the contents of `B` are transfered to `A` by popping them out of `B`\nand pushing them to `A`. That way they appear in reverse order and are popped\nin the original.\n\nA `DEQUEUE` operation can perform in $\\Theta(n)$ time, but that will happen\nonly when `A` is empty. If many `ENQUEUE`s and `DEQUEUE`s are performed, the\ntotal time will be linear to the number of elements, not to the largest length\nof the queue.\n"
  },
  {
    "path": "other/clrs/10/01/07.markdown",
    "content": "> Show how to implement a stack using two queues. Analyze the running time of\n> the stack operations.\n\nWe have two queues and mark one of them as active. `PUSH` queues an element on\nthe active queue. `POP` should dequeue all but one element of the active queue\nand queue them on the inactive. The roles of the queues are then reversed, and\nthe final element left in the (now) inactive queue is returned.\n\nThe `PUSH` operation is $\\Theta(1)$, but the `POP` operation is $\\Theta(n)$\nwhere $n$ is the number of elements in the stack.\n"
  },
  {
    "path": "other/clrs/10/02/01.markdown",
    "content": "> Can you implement the dynamic-set operation `INSERT` on a singly linked list\n> in $\\O(1)$ time? How about `DELETE`?\n\nYou can implement `INSERT` in constant time by prepending it to the list.\n\nYou cannot implement `DELETE` in constant time, unless you pass to it as an\nargument the predecessor of the element you are deleting.\n"
  },
  {
    "path": "other/clrs/10/02/02.markdown",
    "content": "> Implement a stack using a singly linked list `L`. The operations `PUSH` and\n> `POP` should still take $\\O(1)$ time.\n\nThis is too simple to be worth implementing.\n\nThe `PUSH` operation adds an element in the beginning of the list and the\n`POP` operation removes the first element from the list.\n"
  },
  {
    "path": "other/clrs/10/02/03.markdown",
    "content": "> Implement a queue by using a singly linked list `L`. The operations\n> `ENQUEUE` and `DEQUEUE` should still take $\\O(1)$ time.\n\nThis is a bit trickier than the previous one, but still simple.\n\n* We need to keep track of the last element of the list.\n* Whenever we `ENQUEUE`, we should be inserting the element after it and\n  marking the new last element of the list.\n* Whenever we `DEQUEUE`, we should pop the first element of the list.\n"
  },
  {
    "path": "other/clrs/10/02/04.markdown",
    "content": "> As written, each loop iteration in the `LIST-SEARCH'` procedure requires two\n> tests: one for `x ≠ L.nil` and one for `x.key ≠ k`. Show how to eliminate\n> the test for `x ≠ L.nil` in each iteration.\n\nWe can set the key of the sentinel and then return the sentinel itself. It's\nsomehow weird, but it can work in some contexts:\n\n    LIST-SEARCH'(L, k):\n      x = L.nil.next\n      L.nil.key = k\n      while x.key ≠ k\n          x = x.net\n      return x\n\nI have implemented this in exercise 10.2.5.\n"
  },
  {
    "path": "other/clrs/10/02/05.c",
    "content": "#include <stdlib.h>\n\ntypedef struct node_t {\n    int key;\n    struct node_t *next;\n} node_t;\n\ntypedef struct {\n    struct node_t nil;\n} list_t;\n\nvoid init_list(list_t *list) {\n    list->nil.key = 0;\n    list->nil.next = &(list->nil);\n}\n\nvoid destroy_list(list_t *list) {\n    node_t *node = list->nil.next;\n    node_t *next;\n\n    while (node != &(list->nil)) {\n        next = node->next;\n        free(node);\n        node = next;\n    }\n}\n\nvoid insert(list_t *list, int key) {\n    node_t *new = (node_t *) malloc(sizeof(node_t));\n    new->key = key;\n    new->next = list->nil.next;\n    list->nil.next = new;\n}\n\nnode_t *search(list_t *list, int key) {\n    node_t *node = list->nil.next;\n\n    // The trick from exercise 10.2.4\n    list->nil.key = key;\n    while (node->key != key) {\n        node = node->next;\n    }\n\n    if (node == &(list->nil)) {\n        return NULL;\n    } else {\n        return node;\n    }\n}\n\nvoid delete(list_t *list, int key) {\n    node_t *node = &(list->nil);\n\n    while (node->next != &(list->nil)) {\n        if (node->next->key == key) {\n            node_t *to_be_deleted = node->next;\n            node->next = node->next->next;\n            free(to_be_deleted);\n        } else {\n            node = node->next;\n        }\n    }\n}\n"
  },
  {
    "path": "other/clrs/10/02/05.markdown",
    "content": "> Implement the dictionary operations `INSERT`, `DELETE`, and `SEARCH` using\n> singly linked, circular lists. What are the running times of your\n> procedures?\n\nI assume this should use a sentinel. Otherwise, there is no good way to\nterminate the search. We can track a pointer and abort when we reach it again,\nbut not all languages allow us to compare pointers that way.\n\nThe C implementation uses the trick from exercise 10.2.4.\n"
  },
  {
    "path": "other/clrs/10/02/05.test.c",
    "content": "#include \"05.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(inserting_and_searching) {\n    list_t list;\n    init_list(&list);\n\n    insert(&list, 1);\n    insert(&list, 2);\n    insert(&list, 3);\n\n    ASSERT_TRUE(search(&list, 1) != NULL);\n    ASSERT_TRUE(search(&list, 2) != NULL);\n    ASSERT_TRUE(search(&list, 3) != NULL);\n    ASSERT_TRUE(search(&list, 4) == NULL);\n\n    destroy_list(&list);\n}\n\nTEST(deleting) {\n    list_t list;\n    init_list(&list);\n\n    insert(&list, 1);\n    insert(&list, 2);\n    insert(&list, 3);\n\n    ASSERT_TRUE(search(&list, 1) != NULL);\n\n    delete(&list, 2);\n\n    ASSERT_TRUE(search(&list, 2) == NULL);\n\n    delete(&list, 3);\n\n    ASSERT_TRUE(search(&list, 3) == NULL);\n    ASSERT_TRUE(search(&list, 1) != NULL);\n\n    destroy_list(&list);\n}\n\nTEST(deleting_an_element_inserted_multiple_times) {\n    list_t list;\n    init_list(&list);\n\n    insert(&list, 1);\n    insert(&list, 2);\n    insert(&list, 2);\n    insert(&list, 3);\n    insert(&list, 2);\n\n    ASSERT_TRUE(search(&list, 2) != NULL);\n\n    delete(&list, 2);\n\n    ASSERT_TRUE(search(&list, 2) == NULL);\n\n    destroy_list(&list);\n}\n"
  },
  {
    "path": "other/clrs/10/02/06.markdown",
    "content": "> The dynamic-set operation `UNION` takes two disjoint sets $S_1$ and $S_2$ as\n> input, and it returns a set $S = S_1 \\cup S_2$ consisting of all the\n> elements $S_1$ and $S_2$. The sets $S_1$ and $S_2$ are usually destroyed by\n> the operation. Show how to support `UNION` in $\\O(1)$ time using a suitable\n> list data structure.\n\nIf both sets are a doubly linked lists, we just point link the last element of\nthe first list to the first element in the second. If the implementation uses\nsentinels, we need to destroy one of them.\n"
  },
  {
    "path": "other/clrs/10/02/07.c",
    "content": "#include <stdlib.h>\n\ntypedef struct node_t {\n    int key;\n    struct node_t *next;\n} node_t;\n\ntypedef struct {\n    struct node_t nil;\n} list_t;\n\nvoid init_list(list_t *list) {\n    list->nil.key = 0;\n    list->nil.next = &(list->nil);\n}\n\nvoid destroy_list(list_t *list) {\n    node_t *node = list->nil.next;\n    node_t *next;\n\n    while (node != &(list->nil)) {\n        next = node->next;\n        free(node);\n        node = next;\n    }\n}\n\nvoid insert(list_t *list, int key) {\n    node_t *new = (node_t *) malloc(sizeof(node_t));\n    new->key = key;\n    new->next = list->nil.next;\n    list->nil.next = new;\n}\n\nvoid reverse(list_t *list) {\n    node_t *prev = &(list->nil);\n    node_t *node = list->nil.next;\n    node_t *next;\n\n    while (node != &(list->nil)) {\n        next = node->next;\n        node->next = prev;\n        prev = node;\n        node = next;\n    }\n\n    list->nil.next = prev;\n}\n"
  },
  {
    "path": "other/clrs/10/02/07.markdown",
    "content": "> Give a $\\Theta(n)$-time nonrecursive procedure that reverses a singly linked\n> list of $n$ elements. The procedure should use no more than a constant\n> storage beyond that needed for the list itself.\n"
  },
  {
    "path": "other/clrs/10/02/07.test.c",
    "content": "#include \"07.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(inserting_and_searching) {\n    list_t list;\n    init_list(&list);\n\n    insert(&list, 1);\n    insert(&list, 2);\n    insert(&list, 3);\n\n    reverse(&list);\n\n    ASSERT_EQUALS(list.nil.next->key,             1);\n    ASSERT_EQUALS(list.nil.next->next->key,       2);\n    ASSERT_EQUALS(list.nil.next->next->next->key, 3);\n\n    destroy_list(&list);\n}\n\n"
  },
  {
    "path": "other/clrs/10/02/08.c",
    "content": "#include <stdlib.h>\n#include <stdio.h>\n\ntypedef struct node_t {\n    int key;\n    struct node_t *np;\n} node_t;\n\ntypedef struct {\n    struct node_t *head;\n    struct node_t *tail;\n} list_t;\n\nnode_t *xor(node_t *left, node_t *right) {\n    return (node_t *) (((unsigned long) left) ^ ((unsigned long) right));\n}\n\nvoid init_list(list_t *list) {\n    list->head = NULL;\n    list->tail = NULL;\n}\n\nvoid destroy_list(list_t *list) {\n    node_t *prev = NULL;\n    node_t *node = list->head;\n    node_t *next;\n\n    while (node) {\n        next = xor(node->np, prev);\n        free(node);\n        prev = node;\n        node = next;\n    }\n}\n\nvoid insert(list_t *list, int key) {\n    node_t *new = (node_t *) malloc(sizeof(node_t));\n    new->key = key;\n    new->np = xor(NULL, list->tail);\n\n    if (list->tail) {\n        list->tail->np = xor(new, xor(NULL, list->tail->np));\n    }\n\n    if (!list->head) {\n        list->head = new;\n    }\n\n    list->tail = new;\n}\n\nint get(list_t *list, int index) {\n    node_t *node = list->head;\n    node_t *prev = NULL;\n    node_t *next;\n\n    while (index--) {\n        if (!node) {\n            fprintf(stderr, \"Index out of bounds\\n\");\n            exit(1);\n        }\n        next = xor(node->np, prev);\n        prev = node;\n        node = next;\n    }\n\n    return node->key;\n}\n\nnode_t *search(list_t *list, int key) {\n    node_t *node = list->head;\n    node_t *prev = NULL;\n    node_t *next;\n\n    while (node) {\n        if (node->key == key) {\n            return node;\n        }\n\n        next = xor(node->np, prev);\n        prev = node;\n        node = next;\n    }\n\n    return NULL;\n}\n\nvoid delete(list_t *list, int key) {\n    node_t *node = list->head;\n    node_t *prev = NULL;\n    node_t *next;\n\n    while (node) {\n        if (node->key == key) {\n            next = xor(node->np, prev);\n\n            if (prev) {\n                prev->np = xor(xor(prev->np, node), next);\n            } else {\n                list->head = next;\n            }\n\n            if (next) {\n                next->np = xor(xor(next->np, node), prev);\n            } else {\n                list->tail = prev;\n            }\n\n            node = next;\n        } else {\n            next = xor(node->np, prev);\n            prev = node;\n            node = next;\n        }\n    }\n}\n\nvoid reverse(list_t *list) {\n    node_t *tmp;\n    tmp = list->head;\n    list->head = list->tail;\n    list->tail = tmp;\n}\n"
  },
  {
    "path": "other/clrs/10/02/08.markdown",
    "content": "> $\\star$ Explain how to implement doubly linked lists using only one pointer\n> value `x.np` per item instead of the usual two (`next` and `prev`). Assume\n> that all pointer values can be interpreted as $k$-bit integers, and define\n> `x.np = x.next XOR x.prev`, the $k$-bit \"exclusive-or\" of `x.next` and\n> `x.prev`. (The value `NIL` is represented by 0). Be sure to describe what\n> information you need to access the head of the list. Show how to implement\n> the `SEARCH`, `INSERT` and `DELETE` operations on such a list. Also show how\n> to reverse such a list in $\\O(1)$ time.\n\nWe can find the pointer to the next item by XOR-ing `np` with the pointer to\nthe previous item and vice-versa. If the previous pointer of the head of the\nlist is to NIL and the next pointer of the tail is to NIL, then we only need a\npointer to either end of the list to access it. Reversing the list is just\nswapping the head and the tail.\n"
  },
  {
    "path": "other/clrs/10/02/08.test.c",
    "content": "#include \"08.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(inserting_and_searching) {\n    list_t list;\n    init_list(&list);\n\n    insert(&list, 1);\n    insert(&list, 2);\n    insert(&list, 3);\n\n    ASSERT_TRUE(search(&list, 0) == NULL);\n    ASSERT_TRUE(search(&list, 1) != NULL);\n    ASSERT_TRUE(search(&list, 2) != NULL);\n    ASSERT_TRUE(search(&list, 3) != NULL);\n    ASSERT_TRUE(search(&list, 4) == NULL);\n\n    destroy_list(&list);\n}\n\nTEST(deleting) {\n    list_t list;\n    init_list(&list);\n\n    insert(&list, 2);\n    insert(&list, 1);\n    insert(&list, 2);\n    insert(&list, 3);\n    insert(&list, 2);\n    insert(&list, 2);\n\n    delete(&list, 2);\n\n    ASSERT_TRUE(search(&list, 2) == NULL);\n\n    destroy_list(&list);\n}\n\nTEST(reversing) {\n    list_t list;\n    init_list(&list);\n\n    insert(&list, 1);\n    insert(&list, 2);\n    insert(&list, 3);\n\n    reverse(&list);\n\n    ASSERT_EQUALS(get(&list, 0), 3);\n    ASSERT_EQUALS(get(&list, 1), 2);\n    ASSERT_EQUALS(get(&list, 2), 1);\n\n    destroy_list(&list);\n}\n"
  },
  {
    "path": "other/clrs/10/03/01.markdown",
    "content": "> Draw a picture of the sequence $\\langle 13, 4, 8, 19, 5, 11 \\rangle$ stored\n> as a doubly linked list using the multiple-array representation. Do the same\n> for the single-array representation.\n\nLet the indexes start from 1. To make things interesting, let's write the\nelements in increasing order:\n\n    +---+\n    | L |--------------------------------------+\n    +---+                                      V\n            1    2    3    4    5    6    7    8    9   10   11   12\n         +----+----+----+----+----+----+----+----+----+----+----+----+\n    next |    |  5 |    |  7 | 10 |    |  / |  2 |    |  4 |    |    |\n         +----+----+----+----+----+----+----+----+----+----+----+----+\n     key |    |  4 |    |  5 |  8 |    | 11 | 13 |    | 19 |    |    |\n         +----+----+----+----+----+----+----+----+----+----+----+----+\n    prev |    |  8 |    | 10 |  2 |    |  4 |  / |    |  5 |    |    |\n         +----+----+----+----+----+----+----+----+----+----+----+----+\n\nI'll do the next one in a slightly more compact fashion:\n\n       1    2    3     4    5    6     7    8    9    10   11   12\n    +----+----+----++----+----+----++----+----+----++----+----+----++--\n    |  4 |  7 | 13 ||  5 | 10 | 16 ||  8 | 16 |  1 || 11 |  / |  4 ||\n    +----+----+----++----+----+----++----+----+----++----+----+----++--\n\n            13   14   15    16   17   18\n       --++----+----+----++----+----+----+\n         || 13 |  1 |  / || 19 |  4 |  7 |\n       --++----+----+----++----+----+----+\n"
  },
  {
    "path": "other/clrs/10/03/02.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n\n#define MAX_SIZE 3\n\ntypedef int list_t;\ntypedef int obj_t;\n\nint empty_list = -1;\nint cells[MAX_SIZE * 3];\nint free_list;\n\n#define NEXT(i) cells[(i) + 1]\n#define PREV(i) cells[(i) + 2]\n#define KEY(i)  cells[i]\n\nvoid init_storage() {\n    int i;\n    for (i = 0; i < (MAX_SIZE - 1) * 3; i += 3)\n        NEXT(i) = i + 3;\n\n    NEXT(i) = -1;\n    free_list = 0;\n}\n\nlist_t allocate_object() {\n    if (free_list == -1) {\n        fprintf(stderr, \"Storage depleted\\n\");\n        exit(1);\n    }\n\n    list_t new = free_list;\n    free_list = NEXT(free_list);\n    return new;\n}\n\nvoid free_object(list_t list) {\n    NEXT(list) = free_list;\n    free_list = list;\n}\n\nlist_t cons(obj_t key, list_t list) {\n    list_t new = allocate_object();\n\n    NEXT(new) = list;\n    PREV(new) = empty_list;\n    KEY(new) = key;\n\n    if (list != empty_list) {\n        PREV(list) = new;\n    }\n\n    return new;\n}\n\nvoid delete(list_t list) {\n    if (PREV(list) != empty_list) {\n        NEXT(PREV(list)) = NEXT(list);\n    }\n\n    if (NEXT(list) != empty_list) {\n        PREV(NEXT(list)) = PREV(list);\n    }\n\n    free_object(list);\n}\n\nobj_t get(list) {\n    if (list == empty_list) return -1;\n    return KEY(list);\n}\n\nlist_t next(list) {\n    if (list == empty_list) return -1;\n    return NEXT(list);\n}\n"
  },
  {
    "path": "other/clrs/10/03/02.markdown",
    "content": "> Write the procedures `ALLOCATE-OBJECT` and `FREE-OBJECT` for a homogeneous\n> collection of objects implemented by the single-array representation.\n"
  },
  {
    "path": "other/clrs/10/03/02.test.c",
    "content": "#include \"02.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(adding_elements) {\n    list_t list;\n\n    init_storage();\n\n    list = cons(1, empty_list);\n    list = cons(2, list);\n    list = cons(3, list);\n\n    ASSERT_EQUALS(get(list), 3);\n    ASSERT_EQUALS(get(next(list)), 2);\n    ASSERT_EQUALS(get(next(next(list))), 1);\n    ASSERT_EQUALS(get(next(next(next(list)))), empty_list);\n}\n\nTEST(removing_elements) {\n    list_t list, freed;\n\n    init_storage();\n\n    list = cons(1, empty_list);\n    list = freed = cons(2, list);\n    list = cons(3, list);\n\n    delete(freed);\n\n    ASSERT_EQUALS(get(list), 3);\n    ASSERT_EQUALS(get(next(list)), 1);\n    ASSERT_EQUALS(get(next(next(list))), empty_list);\n    ASSERT_EQUALS(free_list, freed);\n}\n\nTEST(removing_and_adding) {\n    list_t list, freed;\n\n    init_storage();\n\n    list = cons(1, empty_list);\n    list = freed = cons(2, list);\n    list = cons(3, list);\n\n    delete(freed);\n\n    list = cons(4, list);\n\n    ASSERT_EQUALS(get(list), 4);\n    ASSERT_EQUALS(get(next(list)), 3);\n    ASSERT_EQUALS(get(next(next(list))), 1);\n    ASSERT_EQUALS(get(next(next(next(list)))), empty_list);\n    ASSERT_EQUALS(free_list, -1);\n}\n"
  },
  {
    "path": "other/clrs/10/03/03.markdown",
    "content": "> Why don't we need to set or reset the `prev` attributes of objects in the\n> implementation of the `ALLOCATE-OBJECT` and `FREE-OBJECT` procedures?\n\nBecause we're not using them. Having a singly linked free list is sufficient.\nWe don't need the `prev` attribute and we don't even need the `key` attribute.\nWhenever we allocate and free objects, we're setting those fields anyway, so\nit does not matter that we don't reset them.\n"
  },
  {
    "path": "other/clrs/10/03/04.markdown",
    "content": "> It is often desirable to keep all elements of a doubly linked list compact\n> in storage, using, for example, the first $m$ index locations in the\n> multiple-array representation. (This is the case in a paged, virtual-memory\n> computing environment.) Explain how to implement the procedures\n> `ALLOCATE-OBJECT` and `FREE-OBJECT` so that the representation is compact.\n> Assume that there are no pointers to elements of the linked list outside the\n> list itself. (<i>Hint:</i> Use the array implementation of a stack.)\n\nWe can allocate elements in the beginning of the array. Whenever we\ndeallocate an element, other than the last (in the stack), we need to shift\nall elements after it left and then update all the indices that point beyond\nthe deleted element (by decrementing them). This will take linear time. As an\noptimization, whenever we deallocate the last element in the array, we don't\nneed to scan the array and update pointers.\n"
  },
  {
    "path": "other/clrs/10/03/05.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n\n#define MAX_SIZE 100\n\ntypedef int list_t;\ntypedef int obj_t;\n\nint empty_list = -1;\n\nint   prev[MAX_SIZE];\nint   next[MAX_SIZE];\nobj_t keys[MAX_SIZE];\n\nint free_list;\n\nvoid init_storage() {\n    int i;\n    for (i = 0; i < MAX_SIZE - 1; i++)\n        next[i] = i + 1;\n\n    next[i] = -1;\n    free_list = 0;\n}\n\nlist_t allocate_object() {\n    if (free_list == -1) {\n        fprintf(stderr, \"Storage depleted\\n\");\n        exit(1);\n    }\n\n    list_t new = free_list;\n    free_list = next[free_list];\n    return new;\n}\n\nvoid free_object(list_t list) {\n    next[list] = free_list;\n    free_list = list;\n}\n\nlist_t cons(obj_t key, list_t list) {\n    list_t new = allocate_object();\n\n    next[new] = list;\n    prev[new] = empty_list;\n    keys[new] = key;\n\n    if (list != empty_list) {\n        prev[list] = new;\n    }\n\n    return new;\n}\n\nvoid delete(list_t list) {\n    if (prev[list] != empty_list) {\n        next[prev[list]] = next[list];\n    }\n\n    if (next[list] != empty_list) {\n        prev[next[list]] = prev[list];\n    }\n\n    free_object(list);\n}\n\nobj_t get(list) {\n    if (list == empty_list) return -1;\n    return keys[list];\n}\n\nlist_t next_obj(list) {\n    if (list == empty_list) return -1;\n    return next[list];\n}\n\nlist_t compatify_list(list_t list) {\n    list_t left, right, i;\n\n    if (free_list == empty_list) {\n        return list;\n    }\n\n    i = free_list;\n    while (i != empty_list) {\n        prev[i] = -2;\n        i = next[i];\n    }\n\n    left  = 0;\n    right = MAX_SIZE - 1;\n    while (1) {\n        while (prev[left] != -2)\n            left++;\n\n        while (prev[right] == -2)\n            right--;\n\n        if (left >= right) break;\n\n        prev[left] = prev[right];\n        next[left] = next[right];\n        keys[left] = keys[right];\n\n        next[right] = left;\n\n        right--;\n        left++;\n    }\n\n    right++;\n\n    for (int i = 0; i < right; i++) {\n        if (prev[i] >= right) {\n            prev[i] = next[prev[i]];\n        }\n\n        if (next[i] >= right) {\n            next[i] = next[next[i]];\n        }\n    }\n\n    if (list >= right) {\n        list = next[list];\n    }\n\n    for (i = right; i < MAX_SIZE - 1; i++) {\n        next[i] = i+1;\n    }\n    next[i] = -1;\n\n    free_list = right;\n\n    return list;\n}\n"
  },
  {
    "path": "other/clrs/10/03/05.markdown",
    "content": "> Let $L$ be a doubly linked list of length $n$ stored in arrays `key`,\n> `prev`, and `next` of length $m$. Suppose that these arrays are managed by\n> `ALLOCATE-OBJECT` and `FREE-OBJECT` procedures that keep a doubly linked\n> free list $L$. Suppose further that of the $m$ items, exactly $n$ are on the\n> list $L$ and $m - n$ are on the free list. Write a procedure\n> `COMPACTIFY-LIST(L, F)` that, given the list $L$ and the free list $F$,\n> moves the items in $L$ so that they occupy array positions $1, 2, \\ldots, n$\n> and adjust the free list $F$ so that it remains correct, occupying array\n> positions $n + 1, n + 2, \\ldots, m$. The running time of your procedure\n> should be $\\Theta(n)$, and it should use only a constant amount of extra\n> space. Argue that your procedure is correct.\n\nI'll use this approach:\n\n1. We traverse the free list and mark each element by putting a special value\n   in its `prev` pointer (it is not used by the free list)\n2. We start two pointers, one from the beginning of the memory and one from\n   the end. We increment the left pointer until it reaches an empty cell and\n   decrement the right until it reaches a non-empty cell. We move the right\n   cell to the left position and leave a forwarding address in the `next`\n   field. This terminates when the two pointers catch up. At this point the\n   \"active\" memory is in the beginning of the array and the free - in the end.\n   We take note of the threshold.\n3. We linearly scan the first part of the array and update all the pointers\n   that point beyond the threshold, by using the forwarding address in `next`.\n4. Finally, we organize the memory beyond the threshold in a free list.\n"
  },
  {
    "path": "other/clrs/10/03/05.test.c",
    "content": "#include \"05.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(compactify) {\n    list_t list;\n\n    init_storage();\n\n    list = cons(0, empty_list);\n    list = cons(1, list);\n    list = cons(2, list);\n    list = cons(3, list);\n    list = cons(4, list);\n    list = cons(5, list);\n    list = cons(6, list);\n    list = cons(7, list);\n    list = cons(8, list);\n\n    delete(2);\n    delete(3);\n    delete(5);\n    delete(6);\n\n    list = compatify_list(list);\n\n    ASSERT_EQUALS(get(list), 8);\n    ASSERT_EQUALS(get(next_obj(list)), 7);\n    ASSERT_EQUALS(get(next_obj(next_obj(list))), 4);\n    ASSERT_EQUALS(get(next_obj(next_obj(next_obj(list)))), 1);\n    ASSERT_EQUALS(get(next_obj(next_obj(next_obj(next_obj(list))))), 0);\n    ASSERT_EQUALS(get(next_obj(next_obj(next_obj(next_obj(next_obj(list)))))), -1);\n    ASSERT_EQUALS(free_list, 5);\n}\n"
  },
  {
    "path": "other/clrs/10/04/01.dot",
    "content": "graph {\n  node[shape=\"circle\"];\n  n1[label=\"12\"];\n  n2[label=\"15\"];\n  n3[label=\"4\"];\n  n4[label=\"10\"];\n  n5[label=\"2\"];\n  n6[label=\"18\"];\n  n7[label=\"7\"];\n  n8[label=\"14\"];\n  n9[label=\"21\"];\n  n10[label=\"5\"];\n\n  n6 -- n1; n6 -- n4;\n\n  n1 -- n7; n1 -- n3;\n  n4 -- n5; n4 -- n9;\n\n  n3 -- n10;\n}\n"
  },
  {
    "path": "other/clrs/10/04/01.markdown",
    "content": "> Draw the binary tree rooted at index 6 that is represented by the following\n> attributes:\n>\n> | index |  key |  left | right |\n> |:-----:|:----:|:-----:|:-----:|\n> |    1  |  12  |   7   |   3   |\n> |    2  |  15  |   8   |  NIL  |\n> |    3  |   4  |  10   |  NIL  |\n> |    4  |  10  |   5   |   9   |\n> |    5  |   2  |  NIL  |  NIL  |\n> |    6  |  18  |   1   |   4   |\n> |    7  |   7  |  NIL  |  NIL  |\n> |    8  |  14  |   6   |   2   |\n> |    9  |  21  |  NIL  |  NIL  |\n> |   10  |   5  |  NIL  |  NIL  |\n\nThis is a subtree, that does not contain two of the elements.\n"
  },
  {
    "path": "other/clrs/10/04/02.c",
    "content": "struct tree_t {\n    struct tree_t *left;\n    struct tree_t *right;\n    struct tree_t *parent;\n    int key;\n};\ntypedef struct tree_t tree_t;\nvoid store(int);\n\nvoid print_tree(tree_t *tree) {\n    store(tree->key);\n\n    if (tree->left)\n        print_tree(tree->left);\n\n    if (tree->right)\n        print_tree(tree->right);\n}\n\n#define MAX_SIZE 10\nint keys[MAX_SIZE];\nint count = 0;\n\nvoid reset_storage() {\n    count = 0;\n}\n\nvoid store(int key) {\n    keys[count++] = key;\n}\n"
  },
  {
    "path": "other/clrs/10/04/02.markdown",
    "content": "> Write an $\\O(n)$-time recursive procedure that, given an $n$-node binary\n> tree, prints out the key of each node in the tree.\n"
  },
  {
    "path": "other/clrs/10/04/02.test.c",
    "content": "#include \"02.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n\ntree_t* make_tree(int key) {\n    tree_t *new = malloc(sizeof(tree_t));\n    new->key    = key;\n    new->left   = NULL;\n    new->right  = NULL;\n    new->parent = NULL;\n    return new;\n}\n\ntree_t* make_left(tree_t *parent, int key) {\n    tree_t *new = make_tree(key);\n    new->parent = parent;\n    parent->left = new;\n    return new;\n}\n\ntree_t* make_right(tree_t *parent, int key) {\n    tree_t *new = make_tree(key);\n    new->parent = parent;\n    parent->right = new;\n    return new;\n}\n\nTEST(quote_printing_unquote) {\n    tree_t *t1 = make_tree(1);\n    tree_t *t2 = make_left(t1, 2);\n    tree_t *t3 = make_right(t1, 3);\n    tree_t *t4 = make_left(t2, 4);\n    tree_t *t5 = make_left(t3, 5);\n    tree_t *t6 = make_right(t3, 6);\n    int expected[] = {1, 2, 4, 3, 5, 6};\n\n    print_tree(t1);\n\n    ASSERT_SAME_ARRAYS_S(keys, expected, count);\n}\n"
  },
  {
    "path": "other/clrs/10/04/03.c",
    "content": "#define MAX_SIZE 10\n\nstruct tree_t {\n    struct tree_t *left;\n    struct tree_t *right;\n    struct tree_t *parent;\n    int key;\n};\ntypedef struct tree_t tree_t;\nvoid store(int);\n\nvoid print_tree(tree_t *tree) {\n    tree_t *stack[MAX_SIZE];\n    int count = 0;\n\n    stack[count++] = tree;\n\n    while (count) {\n        tree = stack[--count];\n\n        store(tree->key);\n\n        if (tree->right)\n            stack[count++] = tree->right;\n\n        if (tree->left)\n            stack[count++] = tree->left;\n    }\n}\n\nint keys[MAX_SIZE];\nint count = 0;\n\nvoid reset_storage() {\n    count = 0;\n}\n\nvoid store(int key) {\n    keys[count++] = key;\n}\n"
  },
  {
    "path": "other/clrs/10/04/03.markdown",
    "content": "> Write an $\\O(n)$-time nonrecursive procedure that, given an $n$-node binary\n> tree, prints out the key of each node in the tree. Use a stack as an\n> auxiliary data structure.\n"
  },
  {
    "path": "other/clrs/10/04/03.test.c",
    "content": "#include \"03.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n\ntree_t* make_tree(int key) {\n    tree_t *new = malloc(sizeof(tree_t));\n    new->key    = key;\n    new->left   = NULL;\n    new->right  = NULL;\n    new->parent = NULL;\n    return new;\n}\n\ntree_t* make_left(tree_t *parent, int key) {\n    tree_t *new = make_tree(key);\n    new->parent = parent;\n    parent->left = new;\n    return new;\n}\n\ntree_t* make_right(tree_t *parent, int key) {\n    tree_t *new = make_tree(key);\n    new->parent = parent;\n    parent->right = new;\n    return new;\n}\n\nTEST(quote_printing_unquote) {\n    tree_t *t1 = make_tree(1);\n    tree_t *t2 = make_left(t1, 2);\n    tree_t *t3 = make_right(t1, 3);\n    tree_t *t4 = make_left(t2, 4);\n    tree_t *t5 = make_left(t3, 5);\n    tree_t *t6 = make_right(t3, 6);\n    int expected[] = {1, 2, 4, 3, 5, 6};\n\n    print_tree(t1);\n\n    ASSERT_SAME_ARRAYS_S(keys, expected, 6);\n}\n"
  },
  {
    "path": "other/clrs/10/04/04.c",
    "content": "#define MAX_SIZE 10\n\nstruct tree_t {\n    struct tree_t *child;\n    struct tree_t *sibling;\n    struct tree_t *parent;\n    int key;\n};\ntypedef struct tree_t tree_t;\nvoid store(int);\n\nvoid print_tree(tree_t *tree) {\n    store(tree->key);\n\n    if (tree->child)\n        print_tree(tree->child);\n\n    if (tree->sibling)\n        print_tree(tree->sibling);\n}\n\nint keys[MAX_SIZE];\nint count = 0;\n\nvoid reset_storage() {\n    count = 0;\n}\n\nvoid store(int key) {\n    keys[count++] = key;\n}\n"
  },
  {
    "path": "other/clrs/10/04/04.markdown",
    "content": "> Write an $\\O(n)$-time procedure that prints all the keys of an arbitrary\n> rooted tree with $n$ nodes, where the tree is stored using the left-child,\n> right-sibling representation.\n"
  },
  {
    "path": "other/clrs/10/04/04.test.c",
    "content": "#include \"04.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n\ntree_t *make_tree(int key) {\n    tree_t *new = malloc(sizeof(tree_t));\n    new->key = key;\n    new->parent  = NULL;\n    new->child   = NULL;\n    new->sibling = NULL;\n    return new;\n}\n\ntree_t *make_child(tree_t *parent, int key) {\n    tree_t *new = make_tree(key);\n    new->parent = parent;\n    parent->child = new;\n    return new;\n}\n\ntree_t *make_sibling(tree_t *left, int key) {\n    tree_t *new = make_tree(key);\n    new->parent = left->parent;\n    left->sibling = new;\n    return new;\n}\n\nTEST(quote_printing_unquote) {\n    tree_t *t1  = make_tree(1);\n    tree_t *t2  = make_child(t1, 2);\n    tree_t *t3  = make_sibling(t2, 3);\n    tree_t *t4  = make_child(t3, 4);\n    tree_t *t5  = make_sibling(t4, 5);\n    tree_t *t6  = make_sibling(t5, 6);\n    tree_t *t7  = make_child(t2, 7);\n    tree_t *t8  = make_sibling(t7, 8);\n    tree_t *t9  = make_child(t8, 9);\n    tree_t *t10 = make_sibling(t9, 10);\n    tree_t *t11 = make_sibling(t8, 11);\n\n    int expected[] = {1, 2, 7, 8, 9, 10, 11, 3, 4, 5, 6};\n\n    print_tree(t1);\n\n    ASSERT_SAME_ARRAYS_S(expected, keys, 11);\n}\n"
  },
  {
    "path": "other/clrs/10/04/05.c",
    "content": "struct tree_t {\n    struct tree_t *left;\n    struct tree_t *right;\n    struct tree_t *parent;\n    int key;\n};\ntypedef struct tree_t tree_t;\nvoid store(int);\n\nvoid print_tree(tree_t *tree) {\n    tree_t *prev;\n    prev = 0;\n\n    while (tree) {\n        if (prev == tree->parent) {\n            store(tree->key);\n            prev = tree;\n            tree = tree->left  ? tree->left :\n                   tree->right ? tree->right :\n                                 tree->parent;\n        } else if (prev == tree->left && tree->right) {\n            prev = tree;\n            tree = tree->right;\n        } else {\n            prev = tree;\n            tree = tree->parent;\n        }\n    }\n}\n\n#define MAX_SIZE 10\nint keys[MAX_SIZE];\nint count = 0;\n\nvoid reset_storage() {\n    count = 0;\n}\n\nvoid store(int key) {\n    keys[count++] = key;\n}\n"
  },
  {
    "path": "other/clrs/10/04/05.markdown",
    "content": "> $\\star$ Write an $\\O(n)$-time nonrecursive procedure that, given an $n$-node\n> binary tree prints out the key of each node. Use no more than constant extra\n> space outside the tree itself and do not modify the tree, even temporarily,\n> during the procedure.\n\nThis is tricky. We need a pointer to the parent. We keep track of the previous\npointer (starting with NIL) and do the following.\n\n1. If we're coming from the parent, move to the left child\n2. If we're coming from the left child, move to the right child\n3. If we're coming from the right child, move to the parent\n\nTo handle cases of less than two children, we skip to the next step if the\nconditions allow for it. That is:\n\n* If there is only a right child, and we're coming form the parent, we move to\n  the right child\n* If we come from the left child, but there is no right child, we move to the\n  parent.\n* If we there are no children, we move to the parent.\n"
  },
  {
    "path": "other/clrs/10/04/05.test.c",
    "content": "#include \"05.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n\ntree_t* make_tree(int key) {\n    tree_t *new = malloc(sizeof(tree_t));\n    new->key    = key;\n    new->left   = NULL;\n    new->right  = NULL;\n    new->parent = NULL;\n    return new;\n}\n\ntree_t* make_left(tree_t *parent, int key) {\n    tree_t *new = make_tree(key);\n    new->parent = parent;\n    parent->left = new;\n    return new;\n}\n\ntree_t* make_right(tree_t *parent, int key) {\n    tree_t *new = make_tree(key);\n    new->parent = parent;\n    parent->right = new;\n    return new;\n}\n\nTEST(quote_printing_unquote) {\n    tree_t *t1 = make_tree(1);\n    tree_t *t2 = make_left(t1, 2);\n    tree_t *t3 = make_right(t1, 3);\n    tree_t *t4 = make_left(t2, 4);\n    tree_t *t5 = make_left(t3, 5);\n    tree_t *t6 = make_right(t3, 6);\n    int expected[] = {1, 2, 4, 3, 5, 6};\n\n    print_tree(t1);\n\n    ASSERT_SAME_ARRAYS_S(keys, expected, 6);\n}\n"
  },
  {
    "path": "other/clrs/10/04/06.markdown",
    "content": "> $\\star$ The left-child, right-sibling representation of an arbitrary rooted\n> tree uses three pointers in each node: _left-child_, _right-sibling_, and\n> _parent_. From any node, its parent can be reached and identified in\n> constant time and all its children can be reached and identified in time\n> linear in the number of children. Show how to use only two pointers and one\n> boolean value in each node so that the parent of a node or all of its\n> children can be reached and identified in time linear in the number of\n> children.\n\nThe two pointers will be _left-child_ and _next_. The boolean should be called\n_last-sibling_. Identifying the children is by starting with _left-child_ and\nmoving through _next_ until the last sibling is reached. Identifying the\nparent is moving through _next_ until the last sibling is reached and then\nmoving through it once again.\n"
  },
  {
    "path": "other/clrs/10/problems/01.markdown",
    "content": "## Comparisons among lists\n\n> For each of the four types of lists in the following table, what is\n> the asymptotic worst-case running time fore each dynamic-set\n> operation listed?\n\n|                     | unsorted, singly linked | sorted, singly linked | unsorted, doubly linked | sorted, doubly linked |\n|:--------------------|:-----------------------:|:---------------------:|:-----------------------:|:---------------------:|\n| `SEARCH(L, k)`      | linear                  | linear                | linear                  | linear                |\n| `INSERT(L, x)`      | constant                | linear                | constant                | linear                |\n| `DELETE(L, x)`      | linear                  | linear                | constant                | constant              |\n| `SUCCESSOR(L, x)`   | linear                  | constant              | linear                  | constant              |\n| `PREDECESSOR(L, x)` | linear                  | linear                | linear                  | constant              |\n| `MINIMUM(L, k)`     | linear                  | constant              | linear                  | constant              |\n| `MAXIMUM(L, k)`     | linear                  | linear                | linear                  | linear                |\n\n* `MAXIMUM` assumes that we don't keep track of the tail of the list. If it\n  does, we can make the algorithms constant when the list is sorted\n"
  },
  {
    "path": "other/clrs/10/problems/02.c",
    "content": "#include <stdlib.h>\n#include <stdarg.h>\n\n/////////////////////////////////////////////////////////////////////////////\n// List operations\n/////////////////////////////////////////////////////////////////////////////\n\nstruct list_t {\n    int key;\n    struct list_t *next;\n};\n\ntypedef struct list_t list_t;\n\nlist_t *insert_sorted(list_t *list, int key) {\n    list_t *new = malloc(sizeof(list_t));\n    new->key = key;\n\n    if (!list || key < list->key) {\n        new->next = list;\n        return new;\n    }\n\n    list_t *l = list;\n    while (l->next && l->next->key < key) {\n        l = l->next;\n    }\n\n    new->next = l->next;\n    l->next = new;\n\n    return list;\n}\n\nlist_t *delete_key(list_t *list, int key) {\n    list_t *match;\n    while (list && list->key == key) {\n        match = list;\n        list = list->next;\n        free(match);\n    }\n\n    if (!list) {\n        return NULL;\n    }\n\n    list_t *node = list;\n    while (node->next) {\n        if (node->next->key == key) {\n            match = node->next;\n            node->next = match->next;\n            free(match);\n        } else {\n            node = node->next;\n        }\n    }\n\n    return list;\n}\n\nlist_t *prepend(list_t *list, int key) {\n    list_t *new = malloc(sizeof(list_t));\n\n    new->key = key;\n    new->next = list;\n\n    return new;\n}\n\nint find_min(list_t *list) {\n    int min = list->key;\n    list = list->next;\n\n    while (list) {\n        if (list->key < min) {\n            min = list->key;\n        }\n        list = list->next;\n    }\n\n    return min;\n}\n\nlist_t *link_together(list_t *a, list_t *b) {\n    list_t *result;\n\n    if (!a) {\n        result = b;\n    } else {\n        result = a;\n        while (a->next) {\n            a = a->next;\n        }\n        a->next = b;\n    }\n\n    return result;\n}\n\nlist_t *merge_sorted(list_t *a, list_t *b) {\n    list_t dummy;\n    list_t *new = &dummy;\n\n    while (a && b) {\n        if (a->key < b->key) {\n            new->next = a;\n            a = a->next;\n            new = new->next;\n        } else {\n            new->next = b;\n            b = b->next;\n            new = new->next;\n        }\n    }\n\n    if (a) {\n        new->next = a;\n    } else {\n        new->next = b;\n    }\n\n    return dummy.next;\n}\n\n/////////////////////////////////////////////////////////////////////////////\n// 1. Mergreable heaps with sorted list\n/////////////////////////////////////////////////////////////////////////////\n\ntypedef struct {\n    list_t *head;\n} heap1;\n\nheap1 *make_heap1() {\n    heap1 *result = malloc(sizeof(heap1));\n    result->head = NULL;\n    return result;\n}\n\nvoid insert1(heap1 *heap, int key) {\n    heap->head = insert_sorted(heap->head, key);\n}\n\nint minimum1(heap1 *heap) {\n    return heap->head->key;\n}\n\nint extract_min1(heap1 *heap) {\n    list_t *head = heap->head;\n    int result = head->key;\n    heap->head = head->next;\n    free(head);\n    return result;\n}\n\nheap1 *union1(heap1 *ha, heap1 *hb) {\n    heap1 *result = malloc(sizeof(heap1));\n    result->head = merge_sorted(ha->head, hb->head);\n\n    free(ha);\n    free(hb);\n\n    return result;\n}\n\n/////////////////////////////////////////////////////////////////////////////\n// 2. Mergreable heaps with unsorted lists\n/////////////////////////////////////////////////////////////////////////////\n\ntypedef struct {\n    list_t *head;\n} heap2;\n\nheap2 *make_heap2() {\n    heap2 *result = malloc(sizeof(heap2));\n    result->head = NULL;\n    return result;\n}\n\nvoid insert2(heap2 *heap, int key) {\n    heap->head = prepend(heap->head, key);\n}\n\nint minimum2(heap2 *heap) {\n    return find_min(heap->head);\n}\n\nint extract_min2(heap2 *heap) {\n    int min = minimum2(heap);\n    heap->head = delete_key(heap->head, min);\n    return min;\n}\n\nheap2 *union2(heap2 *ha, heap2 *hb) {\n    heap2 *result = make_heap2();\n    result->head = link_together(ha->head, hb->head);\n\n    free(ha);\n    free(hb);\n\n    return result;\n}\n"
  },
  {
    "path": "other/clrs/10/problems/02.markdown",
    "content": "## Mergeable heaps using linked lists\n\n> A **mergeable heap** supports the following operations: `MAKE-HEAP` (which\n> creates an empty mergeable heap), `INSERT`, `MINIMUM`, `EXTRACT-MIN`, and\n> `UNION`. Show how to implement mergeable heaps using linked lists in each of\n> the following cases. Try to make each operation as efficient as possible.\n> Analyze the running time of each operation in terms of the size of the\n> dynamic set(s) being operated on.\n>\n> <ol type=\"a\">\n>   <li>Lists are sorted.\n>   <li>Lists are unsorted.\n>   <li>Lists are unsorted, and dynamic sets to be merged are disjoint.\n> </ol>\n\nThere isn't a difference in my implementation between the sorted and unsorted\nlists. There will be a difference between (a) and (b) if we don't allow\nrepetitions in the lists, but since this will make insertion linear, I find it\nbetter to let insert create duplicates and them remove them on `EXTRACT-MIN`.\nThat way the latter is linear (even if with a larger constant),  but `UNION`\ncan be implemented constantly with doubly-linked lists.\n\nI've chosen singly-linked lists for no good reason. Mostly because I did not\nrealize `UNION` is going to take linear time with such an implementation (in\norder to find the last element of the first list). If we switch to\ndoubly-linked, we can make it constant easily.\n\nI find this problem too simple to bother further.\n\nOtherwise, the running times are as follows\n\n|               | sorted   | unsorted |\n|:--------------|:--------:|:--------:|\n| `MAKE-HEAP`   | constant | constant |\n| `INSERT`      |  linear  | constant |\n| `MINIMUM`     | constant |  linear  |\n| `EXTRACT-MIN` | constant |  linear  |\n| `UNION`       |  linear  |  linear* |\n\nAs I noted, `UNION` can be made constant if we keep track of the last element\nof the list.\n"
  },
  {
    "path": "other/clrs/10/problems/02.test.c",
    "content": "#include \"02.c\"\n#include \"../../build/ext/test.h\"\n\nheap1 *build1(int first, ...) {\n    heap1 *result = make_heap1();\n    va_list marker;\n    int i = first;\n\n    va_start(marker, first);\n    while (i != -1) {\n        insert1(result, i);\n        i = va_arg(marker, int);\n    }\n    va_end(marker);\n\n    return result;\n}\n\nheap2 *build2(int first, ...) {\n    heap2 *result = make_heap2();\n    va_list marker;\n    int i = first;\n\n    va_start(marker, first);\n    while (i != -1) {\n        insert2(result, i);\n        i = va_arg(marker, int);\n    }\n    va_end(marker);\n\n    return result;\n}\n\nTEST(heap1) {\n    heap1 *h1 = build1(4, 6, 1, -1);\n    heap1 *h2 = build1(2, 5, 3, -1);\n\n    ASSERT_EQUALS(minimum1(h1), 1);\n    ASSERT_EQUALS(minimum1(h2), 2);\n\n    heap1 *h3 = union1(h2, h1);\n    ASSERT_EQUALS(extract_min1(h3), 1);\n    ASSERT_EQUALS(extract_min1(h3), 2);\n    ASSERT_EQUALS(extract_min1(h3), 3);\n}\n\nTEST(heap2) {\n    heap2 *h1 = build2(4, 2, 6, 1, -1);\n    heap2 *h2 = build2(2, 5, 3, 3, -1);\n\n    ASSERT_EQUALS(minimum2(h2), 2);\n    ASSERT_EQUALS(minimum2(h1), 1);\n\n    heap2 *h3 = union2(h2, h1);\n    ASSERT_EQUALS(extract_min2(h3), 1);\n    ASSERT_EQUALS(extract_min2(h3), 2);\n    ASSERT_EQUALS(extract_min2(h3), 3);\n    ASSERT_EQUALS(extract_min2(h3), 4);\n}\n"
  },
  {
    "path": "other/clrs/10/problems/03.markdown",
    "content": "## Searching a sorted compact list\n\n> Exercise 10.3-4 asked how we might maintain an $n$-element list compactly in\n> the first $n$ positions of an array. We shall assume that the keys are\n> distinct and that the compact list is also sorted, that is, `key[i] <\n> key[next[i]]` for all $i = 1, 2, \\ldots, n$ such that `next[i] ≠ NIL`. We\n> will also assume that we have a variable $L$ that contains the index of the\n> first element on the list. Under these assumptions, you will show that we\n> can use the following randomized algorithm to search the list in\n> $\\O(\\sqrt{n})$ expected time.\n>\n>     COMPACT-LIST-SEARCH(L, n, k)\n>       i = L\n>       while i ≠ ␀ and key[i] < k\n>           j = RANDOM(1, n)\n>           if key[i] < key[j] and key[j] ≤ k\n>               i = j\n>               if key[i] == k\n>                   return i\n>           i = next[i]\n>       if i == ␀ or key[i] > k\n>           return ␀\n>\n> If we ignore lines 3-7 of the procedure, we have an ordinary algorithm for\n> searching a sorted linked list, in which index $i$ points to each position\n> of the list in turn. The search terminates once the index $i$ \"falls off\"\n> the end of the list or once `key[i] ≥ k`. In the latter case, if `key[i] =\n> k`, clearly we have found a key with value $k$. If, however, `key[i] > k`,\n> then we will never find a key with the value $k$, and so terminating the\n> search was the right thing to do.\n>\n> Lines 3-7 attempt to skip ahead to a randomly chosen position $j$. Such a\n> skip benefits us if `key[j]` is larger than `key[i]` and no larger than $k$;\n> in such a case, $j$ marks a position in the list that $i$ would have to\n> reach during an ordinary list search. Because the list is compact, we know\n> that in any choice of $j$ between $1$ and $n$ indexes some object in the\n> list rather than a slot on the free list.\n>\n> Instead of analyzing the performance of `COMPACT-LIST-SEARCH` directly, we\n> shall analyze a related algorithm, `COMPACT-LIST-SEARCH'`, which executes\n> two separate loops. This algorithm takes an additional parameter $t$ which\n> determines an upper bound on the number of iterations of the first loop.\n>\n>     COMPACT-LIST-SEARCH(L, n, k)\n>       i = L\n>       for q = 1 to t\n>           j = RANDOM(1, n)\n>           if key[i] < key[j] and key[j] ≤ k\n>               i = j\n>               if key[i] == k\n>                   return i\n>       while i ≠ ␀ and key[i] < k\n>           i = next[i]\n>       if i == ␀ or key[i] > k\n>           return ␀\n>       else\n>           return i\n>\n> To compare the execution of the algorithms `COMPACT-LIST-SEARCH(L, n, k)`\n> and `COMPACT-LIST-SEARCH(L, n, k, t)`, assume that the sequence of integers\n> returned by the calls of `RANDOM(1, n)` is the same for both algorithms.\n>\n> <ol type=\"a\">\n>   <li>Suppose that <code>COMPACT-LIST-SEARCH(L, n, k)</code> takes $t$\n>   iterations of the <strong>while</strong> loop of lines 2-8. Argue that\n>   <code>COMPACT-LIST-SEARCH'(L, n, k, t)</code> returns the same answer and\n>   that total number of iterations of both the <strong>for</strong> and\n>   <strong>while</strong> loops within <code>COMPACT-LIST-SEARCH'</code> is\n>   at least $t$.\n> </ol>\n>\n> In the call `COMPACT-LIST-SEARCH'(L, n, k, t)`, let $X_t$ be the random\n> variable that describes the distance in the linked list (that is, through\n> the chain of _next_ pointers) from position $i$ in the desired key $k$ after\n> $t$ iterations of the **for** loop of lines 2-7 have occurred.\n>\n> <ol type=\"a\" start=\"2\">\n>   <li>Argue that the expected running time of <code>COMPACT-LIST-SEARCH'(L,\n>   n, k, t)</code> is $\\O(t + \\E[X_t])$.\n>   <li>Show that $\\E[X_t] \\le \\sum_{r=1}^n(1 - r/n)^t$. (<i>Hint:</i> Use\n>   equation (C.25).)\n>   <li>Show that $\\sum_{r=0}^{n-1} r^t \\le n^{t+1}/(t + 1)$.\n>   <li>Prove that $\\E[X_t] \\le n/(t+1)$.\n>   <li>Show that <code>COMPACT-LIST-SEARCH'(L, n, k, t)</code> runs in $\\O(t\n>   + n/t)$ expected time.\n>   <li>Conclude that <code>COMPACT-LIST-SEARCH</code> runs in $\\O(\\sqrt{n})$\n>   expected time.\n>   <li>Why do we assume that all keys are distinct in\n>   <code>COMPACT-LIST-SEARCH</code>? Argue that random skips do not\n>   necessarily help asymptotically when the list contains repeated key\n>   values.\n> </ol>\n\nThis is a very interesting problem.\n\nFirst, let's note that `COMPACT-LIST-SEARCH` a number of iterations, less or\nequal to those of `COMPACT-LIST-SEARCH'`. If the first version found the\nelement on a random skip-ahead in $t$ iterations, so will the second version.\nIf not, the last $k$ iterations only advanced the pointer until the result was\nfound. Furthermore, none of the last $t - k$ iterations made a skip-ahead (by\nthe definition of $k$. Since the second version does not advance inbetween\nskip-aheads, it has to perform $k$ additional iterations of its **while** loop\nuntil the result is found.\n\nNote also, that the first version minimizes the number of iterations. That is,\n$t$ is picked in an optimal way.\n\nLet's move on to the math. The expected running time of `COMPACT-LIST-SEARCH'`\nis indeed $\\O(t + \\E[X_t])$, since it either finds the element in $t$\nskip-aheads, or it has to move forward a number of times, equal to the\ndistance to $X_t$. Note that if the key is not present, this distance will\neither be the successor of that key or the last element of the array, so the\nanalysis still holds.\n\nLet's find the value of the expectation. The probability of having a distance\nat least $r$ is the probability less than $r$. The probability of having\ndistance less than $k$ when $t = 1$ is $(n-r)/n$, thus:\n\n$$ \\Pr\\\\{X_t \\ge r\\\\} = \\bigg(\\frac{n - r}{n}\\bigg)^t\n                      = \\bigg(1 - \\frac{r}{n}\\bigg)^t$$\n\nThat is, one of the `RANDOM` calls should advance to the desired distance,\nwhile the rest should advance to elements before it.\n\nUsing the (C.25), we get:\n\n$$ \\E[X_t] = \\sum_{r=1}^{\\infty} \\Pr\\\\{X_t \\ge r\\\\}\n           = \\sum_{r=1}^n \\Pr\\\\{X_t \\ge r\\\\}\n           = \\sum_{r=1}^n \\bigg(1 - \\frac{r}{n}\\bigg)^t $$\n\nThe probability of getting distance, larger than $n$ is 0, so that's why we\ncan bound the sum index to $n$.\n\nWe can show (d) by approximating the sum with an integral with (A.11):\n\n$$ \\sum_{r=0}^{n-1} r^t \\le \\int_0^n x^t dx = \\frac{n^{t+1}}{t+1} $$\n\nThis lets us give an upper bound on the expectation:\n\n$$ \\begin{aligned}\n   \\E[X_t] &= \\sum_{r=1}^n \\bigg(1 - \\frac{r}{n}\\bigg)^t \\\\\\\\\n           &= \\sum_{r=0}^{n-1} \\bigg(\\frac{r}{n}\\bigg)^t \\\\\\\\\n           &= \\frac{1}{n^t} \\sum_{r=0}^{n-1} r^t \\\\\\\\\n           &\\le \\frac{1}{n^t} \\cdot \\frac{n^{t+1}}{t + 1} \\\\\\\\\n           &= \\frac{n}{t+1}\n   \\end{aligned} $$\n\nThe expected running time of `COMPACT-LIST-SEARCH'(L, n, k, t)` is thus:\n\n$$ \\O(t + \\E[X_t]) = \\O(t + n/(t+1)) = \\O(t + n/t) $$\n\nSince `COMPACT-LIST-SEARCH` minimizes this running time, we need to find the\nminimum of $t + n/t$. The first derivative is $1 - n/t^2$ which is zero at\n$\\sqrt{n}$ and this is a local minimum. It's also the minimum in the interval\n$[1,n]$.\n\nThis makes the expected running time of the first version of the algorithm\n$\\O(\\sqrt{n})$.\n\nAs for duplicates, we won't be able to conclude (c) if there are duplicates.\nThe algorithm is able to skip ahead only if the value found by `RANDOM` is\ngreater than the current. For example, if we have a list of `0`s and we're\nlooking for a `1`, the algorithm will still need to iterate to the end of the\nlist, since it will not skip-ahead at all.\n"
  },
  {
    "path": "other/clrs/11/01/01.markdown",
    "content": "> Suppose that a dynamic set $S$ is represented by a direct-address table $T$\n> of length $m$. Describe a procedure that finds a maximum element of $S$.\n> What is the worst-case performance of your procedure?\n\nWe start with the bottom of the table (the largest element) and scan the table\nbackwards until we find a slot that contains an element. The worst case\nperformance is $\\Theta(m)$, if the maximum element is in the first position of\nthe table (or the dynamic set is empty).\n"
  },
  {
    "path": "other/clrs/11/01/02.markdown",
    "content": "> A **bit vector** is simply an array of bits (0s and 1s). A bit vector of\n> length $m$ takes much less space than an array of $m$ pointers. Describe how\n> to use a bit vector to represent a dynamic set of distinct elements with no\n> satellite data. Dictionary operations should run in $\\O(1)$ time.\n\nThe elements have to be numbers.\n\nEach bit in the bit vector represents whether an element is present (1) or not\npresent (0) in the dynamic set. This is sufficient when we're not storing\nsatellite data. We need to use some binary operations (`&`, `|`) in order to\nmodify the bit vector or query it.\n\nThe operations are pretty straightforward. The only tricky part is the bit\nvector size. If a dynamic set is to store the element `1000`, then the vector\nneeds to be at least `1000` bits.\n"
  },
  {
    "path": "other/clrs/11/01/03.markdown",
    "content": "> Suggest how to implement a direct-address table in which the keys of stored\n> elements do not need to be distinct and the elements can have satellite\n> data. All three dictionary operations (`INSERT`, `DELETE`, and `SEARCH`)\n> should run in $\\O(1)$ time. (Don't forget that `DELETE` takes as an argument\n> a pointer to an object to be deleted, not a key).\n\nAssuming that fetching an element should return the satellite data of all the\nstored elements, we can have each key map to a doubly linked list.\n\n* `INSERT` appends the element to the list in constant time\n* `DELETE` removes the element from the linked list in constant time (the\n  element contains pointers to the previous and next element)\n* `SEARCH` returns the first element, which is a node in a linked list, in\n  constant time\n"
  },
  {
    "path": "other/clrs/11/01/04.markdown",
    "content": "> $\\star$ We wish to implement a dictionary by using direct addressing on a\n> _huge_ array. At the start, the array entries may contain garbage, and\n> initializing the entire array is impractical because of its size. Describe a\n> scheme for implementing a direct-address dictionary on a huge array. Each\n> stored object should use $\\O(1)$ space; the operations `SEARCH`, `INSERT`,\n> and `DELETE` should take $\\O(1)$ time. (<i>Hint:</i> Use an additional\n> array, treated somewhat like a stack whose size is the number of keys\n> actually stored in the dictionary, to help determine whether a given entry\n> in the huge array is valid or not.)\n\nI don't really understand why this is an exercise - it's far to tricky for the\ncommon good. Anyhow.\n\nAs the hint suggests, we use an addition stack. Each stack item will contain a\npointer in the huge array. Each cell in the huge array will contain the index\nof the stack item.\n\nWhen we `INSERT` a new item, we push the pointer address in the huge array on\nthe stack and set the value of that cell to the stack index.\n\nWhen we `SEARCH`, we get the value in the array. If it is a valid stack index\n(that is, if the value is $n$, the stack has at most $n$ items) and the value\nat that position of the stack is the original pointer, then we have a match.\nOtherwise, we don't.\n\nWhen we `DELETE` there would be a hole in the stack. We can fix it by moving\nthe top item to the hole and updating the value in the huge array.\n\nIf we need satellite data, we can keep it in a parallel stack that we also\nmodify on those operations.\n\nThere is an elaboration on this algorithm in the Instructor's Manual.\n"
  },
  {
    "path": "other/clrs/11/02/01.markdown",
    "content": "> Suppose we use a hash function $h$ to hash $n$ distinct keys into an array $T$\n> of length $m$. Assuming simple uniform hashing, what is the expected number of\n> collisions? More precisely, what is the expected cardinality of $ \\\\{ \\\\{ k, l\n> \\\\} : k \\neq l \\text{ and } h(k) = h(l) \\\\} $?\n\nLet's use an indicator random variable $I_{kl} = 1$ when there is a collision of\nkeys $k$ and $l$. We know that\n\n$$ \\Pr \\\\{ I_{kl} = 1 \\\\} = \\frac{1}{m} = \\E[I_{kl}] $$\n\nSo the expectation of the total number of collisions is:\n\n$$\n    \\E \\Big[ \\sum_{ k \\neq l } { I_{kl} } \\Big]\n        = \\sum_{ k \\neq l }{ \\E[I_{kl}] }\n        = \\sum_{ k \\neq l }{ I_{kl} }\n        = \\sum_{ k \\neq l }{ \\frac{1}{m} }\n        = \\binom{n}{2} \\frac{1}{m}\n        = \\frac{ n (n - 1) }{ 2m }\n$$\n"
  },
  {
    "path": "other/clrs/11/02/02.markdown",
    "content": "> Demonstrate what happens when we insert the keys 5, 28, 19, 15, 20, 33, 12,\n> 17, 10 into a hash table with collisions resolved by chaining. Let the table\n> have 9 slots, and let the hash function be $h(k) = k \\bmod 9$.\n\nFirst, let's calculate the hashes:\n\n    h(5)  = 5\n    h(28) = 1\n    h(19) = 1\n    h(15) = 6\n    h(20) = 2\n    h(33) = 6\n    h(12) = 3\n    h(17) = 8\n    h(10) = 1\n\nNext, let's ASCII-ART this bad boy:\n\n      +-----+\n    0 |     |\n      +-----+\n    1 |  o--|---> [ 10 ] ---> [ 19 ] ---> [ 28 ]\n      +-----+\n    2 |  o--|---> [ 20 ]\n      +-----+\n    3 |  o--|---> [ 12 ]\n      +-----+\n    4 |     |\n      +-----+\n    5 |  o--|---> [  5 ]\n      +-----+\n    6 |  o--|---> [ 33 ] ---> [ 15 ]\n      +-----+\n    7 |     |\n      +-----+\n    8 |  o--|---> [ 17 ]\n      +-----+\n\nWhere each cell of the array is a null pointer (empty bucket) or the pointer to\na head of a linked list.\n"
  },
  {
    "path": "other/clrs/11/02/03.markdown",
    "content": "> Professor Marley hypothesizes that he can obtain substantial performance gains\n> by modifying the chaining scheme to keep each list in sorted order. How does\n> the professor's modification affect the running time for successful searches,\n> unsuccessful searches, insertions, and deletions?\n\nI'm not sure the professor is right.\n\nIf we assume with delete with a key (instead of a pointer to an element), we\nhave the following times (with regards to the number of collisions) without\nsorting:\n\n| operation | complexity     |\n|-----------|----------------|\n| `SEARCH`  | linear (both)  |\n| `INSERT`  | constant       |\n| `DELETE`  | linear         |\n\nThe only thing that changes when we sort the list, is that instead of prepending\nthe item to the list, we have to find its right place, making `INSERT` linear:\n\n| operation | complexity     |\n|-----------|----------------|\n| `SEARCH`  | linear (both)  |\n| `INSERT`  | **linear**     |\n| `DELETE`  | linear         |\n\nI'm not sure what the professor had in mind, but I believe he was mistaken.\n"
  },
  {
    "path": "other/clrs/11/02/04.c",
    "content": "#include <stdlib.h>\n#include <stdio.h>\n#include <assert.h>\n\n#define SIZE 10\n#define HASH(v) (v % 10)\n\n// --- Types and internals --------------------------------------------------\n\ntypedef int value_t;\n\nstruct element_t;\n\ntypedef struct element_t {\n    char free;\n    union {\n        struct {\n            struct element_t *prev;\n            struct element_t *next;\n        } empty;\n\n        struct {\n            value_t value;\n            struct element_t *next;\n        } used;\n    };\n} element_t;\n\ntypedef struct {\n    element_t buckets[SIZE];\n    element_t free_list;\n} hash_t;\n\n// --- Helpers --------------------------------------------------------------\n\nint hash_value(value_t value) {\n    return HASH(value);\n}\n\nvoid remove_from_free_list(hash_t *hash, element_t *element) {\n    element->empty.prev->empty.next = element->empty.next;\n    element->empty.next->empty.prev = element->empty.prev;\n    element->free = 0;\n}\n\nvoid return_to_free_list(hash_t *hash, element_t *element) {\n    element_t *sentinel = &(hash->free_list);\n\n    element->free = 1;\n    element->empty.next = sentinel->empty.next;\n    element->empty.prev = sentinel;\n\n    sentinel->empty.next = element;\n}\n\nelement_t *allocate(hash_t *hash) {\n    element_t *element = hash->free_list.used.next;\n\n    assert(element != &(hash->free_list));\n\n    remove_from_free_list(hash, element);\n\n    return element;\n}\n\nvoid reallocate(hash_t *hash, element_t *element) {\n    int index = hash_value(element->used.value);\n\n    element_t *location = &(hash->buckets[index]);\n\n    assert(!location->free);\n\n    element_t *new = allocate(hash);\n    new->used.value = element->used.value;\n    new->used.next = element->used.next;\n\n    while (location->used.next != element) {\n        location = location->used.next;\n\n        assert(location);\n        assert(!location->free);\n    }\n\n    location->used.next = new;\n}\n\n// --- Public interface -----------------------------------------------------\n\nhash_t *make_hash() {\n    hash_t *hash = malloc(sizeof(hash_t));\n\n    hash->free_list.empty.next = hash->buckets;\n    hash->free_list.empty.prev = hash->buckets + SIZE;\n\n    element_t *current = &(hash->free_list);\n    current->free = 1;\n\n    for (int i = 0; i < SIZE; i++) {\n        element_t *next = &(hash->buckets[i]);\n\n        next->free = 1;\n        next->empty.prev = current;\n\n        current->empty.next = next;\n\n        current = next;\n    }\n\n    current->empty.next = &(hash->free_list);\n    hash->free_list.empty.prev = current;\n\n    return hash;\n}\n\nelement_t *search(hash_t *hash, value_t value) {\n    int index = hash_value(value);\n\n    element_t *element = &(hash->buckets[index]);\n\n    while (element && !element->free) {\n        if (element->used.value == value) {\n            return element;\n        }\n\n        element = element->used.next;\n    }\n\n    return NULL;\n}\n\nvoid insert(hash_t *hash, value_t value) {\n    int index = hash_value(value);\n\n    element_t *element = &(hash->buckets[index]);\n\n    if (element->free) {\n        remove_from_free_list(hash, element);\n\n        element->used.value = value;\n        element->used.next = NULL;\n    } else if (hash_value(element->used.value) == index) {\n        element_t *new = allocate(hash);\n\n        new->used.value = value;\n        new->used.next = element->used.next;\n        element->used.next = new;\n    } else {\n        reallocate(hash, element);\n\n        element->used.value = value;\n        element->used.next = NULL;\n    }\n}\n\nvoid delete(hash_t *hash, value_t value) {\n    int index = hash_value(value);\n\n    element_t *head = &(hash->buckets[index]);\n\n    if (head->free || hash_value(head->used.value) != index) {\n        return;\n    }\n\n    while (head->used.value == value) {\n        element_t *next = head->used.next;\n\n        if (next) {\n            assert(!next->free);\n            assert(hash_value(next->used.value) == index);\n\n            head->used.value = next->used.value;\n            head->used.next = next->used.next;\n            return_to_free_list(hash, next);\n        } else {\n            return_to_free_list(hash, head);\n            return;\n        }\n    }\n\n    element_t *element = head;\n\n    while (element->used.next) {\n        element_t *next = element->used.next;\n\n        assert(!next->free);\n        assert(hash_value(next->used.value) == index);\n\n        if (next->used.value == value) {\n            element->used.next = next->used.next;\n            return_to_free_list(hash, next);\n        } else {\n            element = next;\n        }\n    }\n}\n\n// --- Debug ----------------------------------------------------------------\n\nvoid print_hash(hash_t *hash) {\n    int free_slots = 0;\n    element_t *item = hash->free_list.empty.next;\n\n    while (item != &(hash->free_list)) {\n        item = item->empty.next;\n        free_slots++;\n    }\n\n    printf(\"\\nfree slots in linked list: %d\\n\", free_slots);\n\n    free_slots = 0;\n\n    for (int i = 0; i < SIZE; i++) {\n        if (hash->buckets[i].free) free_slots++;\n    }\n\n    printf(\"free slots in hash array:  %d\\n\\n\", free_slots);\n\n    for (int i = 0; i < SIZE; i++) {\n        element_t *element = &(hash->buckets[i]);\n\n        printf(\"    +------+\\n\");\n        printf(\" %-2d | \", i);\n\n        if (element->free) {\n            printf(\"     |\");\n        } else {\n            int foreign = hash_value(element->used.value) != i;\n            printf(\"%1s %2d |\", (foreign ? \"/\" : \" \"), element->used.value);\n\n            if (!foreign) {\n                while (element->used.next) {\n                    printf(\" -> \");\n                    element = element->used.next;\n\n                    if (element->free) {\n                        printf(\"!!FREE\\n\");\n                        break;\n                    }\n\n                    printf(\"%2d\", element->used.value);\n                }\n            }\n        }\n        printf(\"\\n\");\n    }\n\n    printf(\"    +------+\\n\");\n    printf(\"\\n\\n\");\n}\n"
  },
  {
    "path": "other/clrs/11/02/04.markdown",
    "content": "> Suggest how to allocate and deallocate storage for elements within the hash\n> table itself by linking all unused slots into a free list. Assume that one\n> slot can store a flag and either one element plus a pointer or two pointers.\n> All dictionary and free-list operations should run in $\\O(1)$ expected time.\n> Does the free list need to be doubly linked or does a singly linked free list\n> suffice?\n\nOh, wow. That was a doozy.\n\nFirst of all, in my 15+ years of professional programming and 20+ years of just\ncoding, this is absolutely the first time I implement a hash table. Can you\nbelieve it? It's worth a celebration.\n\nSecond, this is a bit exotic. It involves a few things:\n\n* Doubly linked lists with sentinels\n* Maintaining a free list\n* Hash tables\n\n## Explanation\n\nThe key phrase in the problem definition is \"expected time\". There's no way to\nsolve this in constant time if every key hashes to the same bucket.\n\n### How?\n\nWell, each element of the table is either:\n\n* `{free : boolean = false, value : element, next : pointer}`, when the slot is\n  taken. `element` holds the value of the stored item, and `next` points to the\n  next node in the chain.\n* `{free : boolean = true, prev : pointer, next : pointer}`, when the slot is\n  empty. `prev` and `next` form a doubly linked list with a sentinel stored in\n  the hash table.\n\nWhen we initialize the hash table, we need to iterate it and make sure that each\nslot is linked together in a free list.\n\nTo allocate a slot, we remove it from the free list by modifying `prev` and\n`next` to point to each other, and setting `free` to false.\n\nTo return a slot to the free list, we set `free` to true and insert it in the\nbeginning.\n\n### Searching\n\nNothing really changes, apart from a small optimization - if the head of a chain\nin a bucket hashes to a value, different than the bucket index, we can treat\nthis slot as empty (it's hosting an element for another chain). We don't need to\nwalk it.\n\n### Inserting\n\nThere are three possibilities:\n\n1. The bucket slot is empty. We allocate the slot (setting `free = true` and\n   removing it from the free list), and put the element in there with an empty\n   `next`.\n\n2. The bucket slot contains an element with the same hash value. We allocate a\n   new slot, and insert it after the head of the chain (avoids moving items).\n\n3. The bucket slot contains an element with a different hash value. This means\n   the slot is hosting an element from another chain. We need to relocate it to\n   another empty slot and update the chain by starting from the head (which we\n   can find with the hash value) and finding the pointer we need to update. Once\n   the element has been reallocated, we can insert like in step 2.\n\n### Deleting\n\nWe hash the value to `h` and lookup the `h`-th slot.\n\nWhile the slot's value matches the value we need to delete, we copy the next\nelement in the chain over, and free its slot. We repeat that until the chain is\nempty, or until it starts with an element with the same hash, but different\nvalue.\n\nWe proceed with the rest of the chain to remove the other elements that match\nthe value, returning slots to the free list.\n\n### Does the free list need to be doubly linked?\n\nYes.\n\nOtherwise, reserving a free slot will be linear to the size of the free list\n(e.g. the size of the hash), because we're not interested in _any_ free slot,\nbut rather _a specific_ free slot.\n\n## Code\n\nIf the above didn't make sense, hopefully the code below might:\n"
  },
  {
    "path": "other/clrs/11/02/04.test.c",
    "content": "#include \"04.c\"\n#include \"../../build/ext/test.h\"\n\nTEST(insertion) {\n    hash_t *hash = make_hash();\n\n    insert(hash, 1);\n    ASSERT_NOT_NULL(search(hash, 1));\n    ASSERT_NULL(search(hash, 2));\n}\n\nTEST(deletion) {\n    hash_t *hash = make_hash();\n\n    insert(hash, 1);\n    delete(hash, 1);\n\n    ASSERT_NULL(search(hash, 1));\n}\n\nTEST(deleting_second_in_chain) {\n    hash_t *hash = make_hash();\n\n    insert(hash, 1);\n    insert(hash, 11);\n\n    delete(hash, 11);\n\n    ASSERT_NULL(search(hash, 11));\n    ASSERT_NOT_NULL(search(hash, 1));\n}\n\nTEST(deleting_first_in_chain) {\n    hash_t *hash = make_hash();\n\n    insert(hash, 1);\n    insert(hash, 11);\n\n    delete(hash, 1);\n\n    ASSERT_NULL(search(hash, 1));\n    ASSERT_NOT_NULL(search(hash, 11));\n}\n\nTEST(deleting_duplicates) {\n}\n\nTEST(inserting_duplicates) {\n    hash_t *hash = make_hash();\n\n    insert(hash, 1);\n    insert(hash, 1);\n\n    ASSERT_NOT_NULL(search(hash, 1));\n\n    delete(hash, 1);\n    ASSERT_NULL(search(hash, 1));\n}\n\nTEST(inserting_colisions) {\n    hash_t *hash = make_hash();\n\n    insert(hash, 1);\n    insert(hash, 11);\n\n    ASSERT_NOT_NULL(search(hash, 1));\n    ASSERT_NOT_NULL(search(hash, 11));\n}\n\nTEST(inserting_in_foreign_slots) {\n    hash_t *hash = make_hash();\n\n    insert(hash, 1);\n    insert(hash, 11);\n    insert(hash, 10);\n\n    ASSERT_NOT_NULL(search(hash, 1));\n    ASSERT_NOT_NULL(search(hash, 11));\n    ASSERT_NOT_NULL(search(hash, 10));\n}\n\nTEST(complicated_example) {\n    hash_t *hash;\n    hash = make_hash();\n\n    insert(hash, 1);\n    insert(hash, 11);\n    insert(hash, 21);\n    insert(hash, 31);\n\n    insert(hash, 3);\n    insert(hash, 13);\n    insert(hash, 23);\n\n    insert(hash, 5);\n    insert(hash, 15);\n\n    ASSERT_NOT_NULL(search(hash, 1));\n    ASSERT_NOT_NULL(search(hash, 11));\n    ASSERT_NOT_NULL(search(hash, 21));\n    ASSERT_NOT_NULL(search(hash, 31));\n\n    ASSERT_NOT_NULL(search(hash, 3));\n    ASSERT_NOT_NULL(search(hash, 13));\n    ASSERT_NOT_NULL(search(hash, 23));\n\n    ASSERT_NOT_NULL(search(hash, 5));\n    ASSERT_NOT_NULL(search(hash, 15));\n}\n"
  },
  {
    "path": "other/clrs/11/02/05.markdown",
    "content": "> Suppose that we are storing a set of $n$ keys into a hash table of size $m$.\n> Show that if the keys are drawn from a universe $U$ with $\\| U \\| > nm$ then\n> $U$ has a subset of size $n$ consisting of keys that all hash to the same\n> slot, so that the worst-case searching time for hashing with chaining is\n> $\\Theta(n)$.\n\nObvious statement is obvious. Oh well.\n\nWe are hashing elements into $m$ distinct buckets. Let $h$ be the hash function,\nthat is for $u \\in U$ we have $0 \\le h(u) < m$.\n\nFurthermore, let $C(k)$ be the number of elements in $U$ that hash to $k$.\n\nWe need to demonstrate that there is some $j: 0 \\le j < m$ for which there are are at\nleast $n$ elements $x_i \\in U$ (where for $i \\in \\\\{1, 2, \\dots, n\\\\} )$ such\nthat $h(x_i) = j$, that is, there exists a $k$ such that $C(k) \\ge n$.\n\nLet's assume this is incorrect, that is, every $j$ has at most $n - 1$ elements\nhashing into it, or in other words $C(x) \\le n - 1$ for every $x$. We know that\nevery element of $U$ needs to hash to one of $m$ values, that is:\n\n$$\n    \\sum_{i = 0}^{i<m}{ C(i) } = \\| U \\| \\gt nm \\\\\\\\\n    \\Downarrow \\\\\\\\\n    C(0) + \\sum_{i = 1}^{i<m}{ C(i) } \\gt nm \\\\\\\\\n    \\Downarrow \\\\\\\\\n    C(0) \\gt nm - \\sum_{i = 1}^{i<m}{ C(i) } \\ge nm - \\sum_{i=1}^{i<m}{(n - 1)} = nm - (m - 1)(n - 1)\\\\\\\\\n$$\n\n\n"
  },
  {
    "path": "other/clrs/11/02/06.markdown",
    "content": "> Suppose we have stored $n$ keys in a hash table of size $m$, with collisions\n> resolved by chaining, and that we know the length of each chain, including the\n> length $L$ of the longest chain. Describe a procedure that selects a key\n> uniformly at random from among the keys in the hash table and returns it in\n> expected time $\\O(L \\cdot (1 + 1 / \\alpha))$.\n\nThink about the hash table as a matrix with $m$ rows and $L$ columns. The first\nelement of chain with hash $k$ is put in the first column of the $k$-th row, the\nsecond is put in the second column of the $k$-th row and so on. Essentially,\neach row contains a chain followed by some empty elements.\n\nThe procedure is:\n\n1. Keep picking a random cell in that table (that is, pick a number\n   `s = rand(m * L)`, row `s / L` and column `s % L`) until we get a non-empty\n   one.\n2. Walk the linked list for the chosen row until we get to the chosen column.\n\nNote that when step 1 picks a non-empty element, it does so uniformly. That is,\neach element has equal chance of getting picked.\n\nWe need to calculate the time for the first step (say $A$) and add it to the\ntime of the second step (say $B$).\n\nThe probability to pick an element in step 1 is:\n\n$$ \\Pr \\\\{ \\text{not empty} \\\\} = \\frac{n}{mL} = \\frac{\\alpha}{L} $$\n\nThe expected number of trials to pick a non-empty element is modelled by the\ngeometric distribution (Bernoulli trials, (C.32)), and has $\\E[X] = 1 / p$. That\nis, on average we expect the following number of trials:\n\n$$ A = \\frac{L}{\\alpha} = \\O( L / \\alpha ) $$\n\nOnce we have picked up the `i`th row and the `j`th column, we need to walk the\nlinked list on row `i` and advance `j` elements. Worst case, that takes $L$\nsteps, because the longest chain has that many elements. That is:\n\n$$ B = \\O(L) $$\n\nAnd thence, the expected time is:\n\n$$ A + B = \\O(L / \\alpha) + \\O(L) = \\O( L \\cdot ( 1 + 1 / \\alpha ) ) $$\n"
  },
  {
    "path": "other/clrs/11/03/01.markdown",
    "content": "> Suppose we wish to search a linked list of length $n$, where each element\n> contains a key $k$ along with a hash value $h(k)$. Each key is a long\n> character string. How might we take advantage of the hash values when\n> searching the list for an element with a given key?\n\nWe can compute the hash of the key we search for, and then compare with a string\nin the list only if the hash value matches. We know that the same key hashes to\nthe same hash value, so if the hash values are different, we can infer the\nstrings are different.\n\nIt will have an effect when the strings in the list have particularly bad\ncomparison performance against the string we search for. For example, the\ncomparison algorithm checks the first characters, and if they differ, the second\ncharacters, etc, and the strings have a very long common prefix.\n"
  },
  {
    "path": "other/clrs/11/03/02.markdown",
    "content": "> Suppose that we hash a string of $r$ characters into $m$ slots by treating it\n> as a radix-128 number and then using the division method. We can easily\n> represent the number $m$ as a 32-bit computer word, but the string of $r$\n> characters, treated as a radix-128 number, takes many words. How can we apply\n> the division method to compute the hash value of the string without using more\n> than a constant number of words of storage outside the string itself?\n\nYes, this follows pretty easily from the laws of modulo arithmetic. We need to\nobserve that if the string is $s = \\langle a_n, \\ldots, a\\_1, a\\_0 \\rangle$,\nthen its hash $h(s)$ is going to be:\n\n$$\n    \\begin{aligned}\n      h(s) &= \\left( \\sum_{i=0}^{n}{a_i \\cdot {128}^{i}} \\right) \\bmod m \\\\\\\\\n           &= \\sum_{i=0}^{n}{ \\Big( \\left( a_i \\cdot {128}^{i} \\right) \\bmod m \\Big) } \\\\\\\\\n           &= \\sum_{i=0}^{n}{ \\Big( ( a_i \\bmod m ) ( {128}^{i} \\bmod m ) \\Big) } \\\\\\\\\n    \\end{aligned}\n$$\n\nWe can easily compute $a_i \\bmod m$ without extra memory. To compute ${128}^{i}\n\\bmod m$ without extra memory, we just need to observe that $k^i \\bmod m =\nk(k^{i-1} \\bmod m) \\bmod m$, that is, we can compute the module for each power\nincrementally, without ever needing unbound memory.\n"
  },
  {
    "path": "other/clrs/11/03/02.py",
    "content": "K = 128\n\n\ndef consthash(digits, m):\n    result = 0\n    power = 1\n\n    for d in reversed(digits):\n        result += ((d % m) * power) % m\n        result %= m\n        power = (power * K) % m\n\n    return result\n"
  },
  {
    "path": "other/clrs/11/03/02.test.py",
    "content": "import unittest\nimport os.path as path\n\nfrom functools import reduce\n\nfilename = path.join(path.dirname(__file__), '02.py')\nexec(open(filename).read())\n\n\ndef digits_to_number(digits):\n    return reduce(lambda a, b: a + b,\n                  (d * (K ** i) for (i, d) in enumerate(reversed(digits))))\n\n\n\nclass HashingTest(unittest.TestCase):\n    def test_select(self):\n        m = 25\n        instances = [\n            [127],\n            [123, 42],\n            [1, 1],\n            [12, 31, 85, 12]\n        ]\n        for instance in instances:\n            self.assertEqual(consthash(instance, m),\n                             digits_to_number(instance) % m)\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/11/03/03.markdown",
    "content": "> Consider a version of the division method in which $h(k) = k \\bmod m$, where\n> $m = 2^p - 1$ and $k$ is a character string interpreted in radix $2^p$. Show\n> that if we can derive string $x$ from string $y$ by permuting its characters,\n> then $x$ and $y$ hash to the same value. Give an example of an application in\n> which this property would be undesirable in a hash function.\n\nWe need to observe that the hash of the string is the sum of the hashes of each\ncharacter, and it does not depend on the order they are in. If $x = \\langle x_n,\n\\ldots, x_1, x_0 \\rangle$.\n\n$$\n    \\begin{aligned}\n      h(x) &= \\left( \\sum_{i=0}^{n}{x_i}{2^{ip}} \\right) \\bmod m \\\\\\\\\n           &= \\sum_{i=0}^{n}{ (x_i \\bmod m) \\left( 2^{ip} \\bmod {(2^p - 1)} \\right) } \\\\\\\\\n           &= \\sum_{i=0}^{n}{ (x_i \\bmod m) \\left( \\prod_{1}^{i}{\\left( 2^p \\bmod {(2^p - 1)} \\right)} \\right) } \\\\\\\\\n           &= \\sum_{i=0}^{n}{ (x_i \\bmod m) \\left( \\prod_{1}^{i}{1} \\right) } \\\\\\\\\n           &= \\sum_{i=0}^{n}{ (x_i \\bmod m) }\n    \\end{aligned}\n$$\n\nWe can put the elements of $x$ in any other order, and the result will still be\nthe same.\n"
  },
  {
    "path": "other/clrs/11/03/04.markdown",
    "content": "> Consider a hash table of size $m = 1000$ and a corresponding hash function\n> $h(k) = \\lfloor m (kA \\bmod 1) \\rfloor$ for $A = (\\sqrt{5} - 1)/2$. Compute\n> the locations to which the keys 61, 62, 63, 64, and 65 are mapped.\n\nIt would have been nice if we could $m$ was a power of 2, in which case we could\nhave bit-shifted.\n\nOtherwise, he's the answer, along with some Python code to generate it\n"
  },
  {
    "path": "other/clrs/11/03/04.py",
    "content": "from math import floor\n\nm = 1000\ns = 2654435769\nA = s / (2 ** 32)\n\n\ndef h(k):\n    ka = k * A\n    frac = ka - floor(ka)\n\n    return int(m * frac)\n"
  },
  {
    "path": "other/clrs/11/03/04.run.py",
    "content": "import os.path as path\n\nfilename = path.join(path.dirname(__file__), '04.py')\nexec(open(filename).read())\n\nkeys = [61, 62, 63, 64, 65]\n\n\nfor key in keys:\n    print(\"h({}) = {}\".format(key, h(key)))\n"
  },
  {
    "path": "other/clrs/11/03/05.markdown",
    "content": "> $\\star$ Define a family $\\mathscr{H}$ of hash functions from a finite set $U$\n> to a finite set $B$ to be **$\\epsilon$-universal** if for all pairs of\n> distinct elements $k$ and $l$ in $U$,\n>\n> $$ \\Pr\\\\{ h(k) = h(l) \\\\} \\le \\epsilon $$\n>\n> where the probability is over the choice of the hash function $h$ drawn at\n> random from the family $\\mathscr{H}$. Show that an $\\epsilon$-universal family\n> of hash functions must have\n>\n> $$ \\epsilon \\ge \\frac{1}{|B|} - \\frac{1}{|U|} $$\n\nI've found this a bit tricky, especially with (1) trying to wrap my brain around\nthe notation, and (2) sticking to the formalism. Let's try to build some\nintuition here, and then use it to fill potential holes in a more formal proof.\n\nTo save some typing, let $b = |B|$ and $u = |U|$.\n\nThe assertion tells use that $Pr \\\\{ h(k) = h(l) \\\\} \\ge \\frac{1}{b} -\n\\frac{1}{u} = (u - b) / bu$. If $b \\ge u$, this means that we can design the\nfunction so that there are no collisions. If $b$ is lower, there are bound to be\nsome collisions, however. For example, if $b = 5$ and $u = 8$, at most 4\nelements can be stored without any collisions. The other 4 will collide to the\nsame hash value. Alternatively, 6 elements can be mapped into three pairwise\ncollisions, and the other two can be without any collisions.\n\nLet's sketch both, assuming without any loss of generality, that $B = \\\\{1, 2, 3,\n4, 5\\\\}$ and $U = \\\\{ 1, 2, \\ldots, 8 \\\\} $. $h_1$ will spread the collisions\nevenly, where $h_2$ will put them in a single bucket.\n\n| $v \\in U$  | $h_1(v)$ | $h_2(v)$|\n|------------|----------|---------|\n| 1          | **1**    | 1       |\n| 2          | **1**    | 2       |\n| 3          | **2**    | 3       |\n| 4          | **2**    | 4       |\n| 5          | **3**    | **5**   |\n| 6          | **3**    | **5**   |\n| 7          | 4        | **5**   |\n| 8          | 5        | **5**   |\n\nColliding elements are in **bold**.\n\nWhich one is better? Note that it depends on whether we're talking about\nnon-colliding elements, or no-colliding pairs. $h_2$ has fewer colliding\nelements (4), but more colliding pairs ($\\\\{5, 6\\\\}, \\\\{5, 7\\\\}, \\\\{5, 8\\\\},\n\\\\{6, 7\\\\}, \\\\{6, 8\\\\}, \\\\{7, 8\\\\}$). On the other hand, $h_1$ has 6 colliding\nelements, but only 4 colliding pairs. Note that if $k$ elements are mapped to\nthe same value in $B$, there are $\\binom{k}{2}$ pairs that collide.\n\nLet's consider how to minimize the number of colliding pairs.\n\nAgain, let's assume that $U = \\\\{1, 2, \\ldots, |U| \\\\}$ and $B = \\\\{1, 2,\n\\ldots, |B| \\\\}$. This is OK, because however we pick the original $U$ and $B$,\nthere is a trivial bijection to the first few natural numbers.\n\nLet $c_i$ be the number of pairs for elements that map to $i \\in B$. The total\nnumber of collisions, $C$, is then:\n\n$$ C = \\sum_{i=1}^{b}{\\binom{c_i}{2}} = \\frac{1}{2} \\sum_{i=1}^{k}{c_i (c_i - 1)} $$\n\nLet's do a bit of hand-waving. What's better in order to minimize $C$ - (1) to\ndistribute the collisions evenly across the buckets, or (2) to let $b - 1$\nelements be without collisions, and put the remaining $u - b + 1$ elements go in\nthe same bucket? In the first approach ($C_1$), each bucket would have at most\n$\\binom{\\lceil u/b \\rceil}{2}$ pairs that collide. In the other approach, we\nwould have $C_2 = \\binom{u - b + 1}{2}$ total collisions for a single bucket.\n\nFor $h_1(x)$, we have:\n\n$$\n    C_1 = \\sum_{i=1}^{b} \\binom{\\lceil u/b \\rceil}{2}\n        = b \\frac{ \\lceil u/b \\rceil ( \\lceil u/b - 1 \\rceil ) } { 2 }\n        \\le b \\frac{ (u/b) (u/b - 1) } { 2 }\n        = \\frac { u (u - b) } { 2b }\n$$\n\nFor $h_2(x)$ we have:\n\n$$\n    C_2 = \\binom{u - b + 1}{2} = \\frac{ (u - b + 1)(u - b) }{2}\n        = \\frac{u^2 + u + b^2 - 2bu - b }{2}\n$$\n\nIt appears that $C_1$ is smaller and always minimizes the number of collisions.\nPlug in some concrete values to convince yourself (e.g. with $u = 1000$ and $b =\n970$, $C_1$ is $15$, but $C_2$ is $456$; with a bigger in $u$ and $b$, we get a\nmuch bigger difference between the number of collisions).\n\nLet's try this another way – lower bound for number of colliding pairs:\n\n$$\n    C = \\sum_{i=1}^{b}{c_i (c_i - 1) }\n      = \\sum_{i=1}^{b}{c_i^2} - \\sum_{i=1}^{b}{c_i}\n      = \\sum_{i=1}^{b}{c_i^2} - |U| $$\n\nThe final bit, $|U| = \\sum{c_i}$, is because each element from $U$ maps to a\nparticular bucket $i$ and is counted once and only once.\n\nWe also notice that (sort of):\n\n$$ c_i \\ge \\frac{u}{b} $$\n\nAnd:\n\n$$ \\sum_{i=1}^{b}{c_i} \\ge \\sum_{i=1}^{b}{\\frac{u^2}{b^2}} = \\frac{u^2}{b} $$\n\nThus, finally:\n\n$$\n    \\epsilon \\ge \\Pr\\\\{h(k) = h(l)\\\\}\n      = \\frac{ \\sum_{i=1}^{b}{ c_i (c_i - 1) } } { u(u - 1) }\n      \\ge \\frac { \\sum_{i=1}^{b}{c_i^2} - \\sum_{i=1}^{b}{c_i} } {u^2}\n      \\ge \\frac { \\frac{u^2}{b} - u } {u^2}\n      = \\frac {u^2 - ub }{u^2b}\n      = \\frac{u - b}{ub}\n      = \\frac{1}{b} - \\frac{1}{u}\n$$\n"
  },
  {
    "path": "other/clrs/11/03/06.markdown",
    "content": "> $\\star$ Let $U$ be the set of $n$-tuples of values drawn from $\\mathbb{Z}\\_p$,\n> and let $B = \\mathbb{Z}\\_p$, where $p$ is prime. Define the hash function $h_b\n> : U \\rightarrow B$ for $b \\in \\mathbb{Z}_p$ on an input $n$-tuple $ \\langle\n> a\\_0, a\\_1, \\ldots , a\\_{n-1} \\rangle $ from $U$ as\n>\n> $$\n>     h_b( \\langle a_0, a_1, \\ldots, a_{n-1} \\rangle ) =\n>     \\left( \\sum_{j=0}^{n-1}{a_j b^j} \\right) \\bmod p\n> $$\n>\n> and let $\\mathscr{H} = \\left\\\\{ h\\_b : b \\in \\mathbb{Z}\\_p \\right\\\\}$. Argue\n> that $\\mathscr{H}$ is $((n - 1)/p)$-universal according to the definition of\n> $\\epsilon$-universal in Exercise 11.3-5. (_Hint:_ See Exercise 31.4-4).\n\nLet's figure out when when we have a colliding pair. We need to have:\n\n$$ h_b(k) = h_b(l) $$\n\nWhich is better written as:\n\n$$ h_b(k) - h_b(l) = 0 \\mod p $$\n\nWell, if we calculate the difference:\n\n$$\n    h_b(k) - h_b(l) = \\sum_{j=0}^{n-1}{k_j b^j} - \\sum_{j=0}^{n-1}{l_j b^j}\n                    = \\sum_{j=0}^{n-1}{(k_j - l_j) b^j}\n$$\n\nWhich is a polynomial of the $(n-1)$-th degree. The referred exercise is a\ntheorem, that tells us this polynomial would have a most $n-1$ zeroes modulo\n$p$.\n\nThere are $p$ possible functions, at most $n-1$ of which will cause any pair to\nhave a collision, therefore:\n\n$$ \\Pr\\\\{ h(k) = h(l) \\\\} \\le \\frac{n-1}{p} $$\n"
  },
  {
    "path": "other/clrs/11/04/01.markdown",
    "content": "> Consider inserting the keys 10, 22, 31, 4, 15, 28, 17, 88, 59 into a hash\n> table of length $m = 11$ using open addressing with the auxiliary hash\n> function $h'(k) = k$. Illustrate the result of inserting these keys using\n> linear probing, using quadratic probing with $c_1 = 1$ and $c_2 = 3$ and using\n> double hashing with $h_1(k) = k$ and $h_2(k) = 1 + (k \\bmod (m-1))$.\n\nHere's a hand-rolled table:\n\n       linear      quadratic   double\n       +------+    +------+    +------+\n     0 |  22  |    |  22  |    |  22  |\n       +------+    +------+    +------+\n     1 |  88  |    |      |    |      |\n       +------+    +------+    +------+\n     2 |      |    |  88  |    |  59  |\n       +------+    +------+    +------+\n     3 |      |    |  17  |    |  17  |\n       +------+    +------+    +------+\n     4 |   4  |    |   4  |    |   4  |\n       +------+    +------+    +------+\n     5 |  15  |    |      |    |  15  |\n       +------+    +------+    +------+\n     6 |  28  |    |  28  |    |  28  |\n       +------+    +------+    +------+\n     7 |  17  |    |  59  |    |  88  |\n       +------+    +------+    +------+\n     8 |  59  |    |  15  |    |      |\n       +------+    +------+    +------+\n     9 |  31  |    |  31  |    |  31  |\n       +------+    +------+    +------+\n    10 |  10  |    |  10  |    |  10  |\n       +------+    +------+    +------+\n\nHere's some python code as well:\n"
  },
  {
    "path": "other/clrs/11/04/01.py",
    "content": "def populate(m, keys, probe):\n    table = [None] * m\n\n    for key in keys:\n        i = 0\n        for _ in range(m):\n            pos = probe(key, i)\n            i += 1\n\n            if table[pos] is None:\n                table[pos] = key\n                break\n        else:\n            raise RuntimeError(f\"Could not put element {key} in {table!r}\")\n\n    return table\n\n\ndef linear(m):\n    return lambda key, i: (key + i) % m\n\n\ndef quadratic(m, c1, c2):\n    return lambda key, i: (key + i * c1 + i * c2 * c2) % m\n\n\ndef double(m):\n    return lambda key, i: (key + i * (1 + key % (m - 1))) % m\n"
  },
  {
    "path": "other/clrs/11/04/01.run.py",
    "content": "import os.path as path\n\nfilename = path.join(path.dirname(__file__), '01.py')\nexec(open(filename).read())\n\n\nkeys = [10, 22, 31, 4, 15, 28, 17, 88, 59]\nm = 11\nprobes = [\n    ('linear', linear(m)),\n    ('quadratic', quadratic(m, 1, 3)),\n    ('double', double(m)),\n]\n\nfor (name, probe) in probes:\n    table = \" | \".join((\"{:>2}\".format(n) if n else \"  \" for n in populate(m, keys, probe)))\n    print(\"{:<10}:  {}\".format(name, table))\n"
  },
  {
    "path": "other/clrs/11/04/02.markdown",
    "content": "> Write pseudocode for `HASH-DELETE` as outlined in the text and modify\n> `HASH-INSERT` to handle the special value `DELETED`.\n\nDeleting an element:\n\n    HASH-DELETE(T, k)\n      i = 0\n      repeat\n          j = h(k, i)\n          if T[j] == k\n              T[j] == DELETED\n          i = i + 1\n      until T[j] == NIL or i == m\n\n\nAs for searching, interestingly enough we don't need to modify it, as long as\n`k` is never `DELETED` and `DELETED != NIL`.\n\n    HASH-SEARCH(T, k)\n      i = 0\n      repeat\n          j = h(k, i)\n          if T[j] == k\n              return j\n          i = i + 1\n          until T[j] == NIL or i == m\n      return NIL\n\n\n"
  },
  {
    "path": "other/clrs/11/04/03.markdown",
    "content": "> Consider an open-address hash table with uniform hashing. Give upper bounds on\n> the expected number of probes in an unsuccessful search and on the expected\n> number of problems in a successful search when the load factor is $3/4$ and\n> when it is $7/8$.\n\nThose come directly from our formulas:\n\n| $\\alpha$ | Unsuccessful | Successful |\n|----------|--------------|------------|\n| $3/4$    | $4$          | $1.84839$  |\n| $7/8$    | $8$          | $2.37650$  |\n\nWhat I find interesting, is that successful searches are dramatically less\nprobes than unsuccessful searches. This implies that with uniform hashing the\nload factor can be pretty high if we're using the hash looking things up as\nopposed to checking if an element exists.\n"
  },
  {
    "path": "other/clrs/11/04/04.markdown",
    "content": "> $\\star$ Suppose that we use double hashing to resolve collisions – that is, we\n> use the hash function $h(k, i) = (h_1(k) + i h_2(k)) \\bmod m$. Show that if\n> $m$ and $h_2(k)$ greatest common divisor $d \\ge 1$ for some key $k$, then an\n> unsuccessful search for key $k$ examines $(1/d)$th of the hash table before\n> returning to slot $h_1(k)$. Thus, when $d = 1$, so that $m$ and $h_2(k)$ are\n> relatively prime, the search may examine the entire hash table (_Hint:_ See\n> Chapter 31).\n\nThis is a bit obvious.\n\nAs the book made the argument either, the probe starts with $h_1(k)$ and then\nsteps $h_2(k)$ places to check the next until it wraps around. If $\\gcd(h_2(k),\nm) = d$, then probing would loop through $m/d$ elements before returning to\nstarting position.\n\nFor example, if $h_1(k) = 3$, $h_2(k) = 2$ and $m = 10$, we'll probe the\nfollowing sequence: $3, 5, 7, 9, 1, 3, \\ldots$, that is, we're looking only at\nthe odd numbers.\n\nBut, eh, let's try to make a formal argument.\n\nIf $\\gcd(h_2(k), m) = d$, let's define $s = m/d$ and $c = h_2(k)/d$, both of\nwhich are integers. The probe sequence $f_k(i)$ is defined to be:\n\n$$ f_k(i) = \\left( h_1(k) + i h_2(k) \\right) \\mod m $$\n\nLet's unpack the right part:\n\n$$\n    \\begin{aligned}\n      f_k(i) &= \\left( h_1(k) + i h_2(k) \\right) \\bmod m \\\\\\\\\n             &= \\big( h_1(k) \\bmod m \\big) + \\big( icd \\bmod m \\big) \\\\\\\\\n             &= C + \\big( icd \\bmod m \\big)\n    \\end{aligned}\n$$\n\n...where $=$ implies \"modulo m\". $C$ is constant in regards to $i$ and the only\nvariable is $icd$. Note that function is $s$-periodic modulo $m$, because we\nhave:\n\n$$ f_k(i + s) = C + (i + s)cd = C + icd + scd = C + icd = f_k(i) $$\n\nBecause $scd = mc = 0$ (modulo m). This means it can take $s$ distinct values,\nwhich means the probe sequence examines $s/m$th of the table before returning to\nthe initial slot. $s/m = s/(sd) = 1/d$, which is what the exercise asks us to\nprove.\n"
  },
  {
    "path": "other/clrs/11/04/05.markdown",
    "content": "> Consider an open-address hash table with a load factor $\\alpha$. Find the\n> nonzero value $\\alpha$ for which the expected number of probes in an\n> unsuccessful search equals twice the expected number of problems in a\n> successful search. Use the upper bounds given by Theorems 11.6 and 11.8 for\n> these expected number of probes.\n\nUsing the theorems, we get the following equation:\n\n$$ \\frac{1}{1 - \\alpha} = 2 \\frac{1}{\\alpha} \\ln{\\left(\\frac{1}{1 - \\alpha}\\right)} $$\n\nWe can try to simplify it, but we get to a $x = 2 \\ln x - 1$, or something\nsimilar, which I don't know how to solve in closed form.\n\nLuckily, that's why SciPY exists.\n"
  },
  {
    "path": "other/clrs/11/04/05.py",
    "content": "import numpy as np\nfrom scipy.optimize import root\n\n\ndef fn(a):\n    one = np.array([1.0])\n    two = np.array([2.0])\n    return (two / a) * np.log(one / (one - a)) - one/(one - a)\n\n\nprint(\"alpha =\", root(fn, 0.6).x[0])\n"
  },
  {
    "path": "other/clrs/11/04/05.run.py",
    "content": "import os.path as path\nfilename = path.join(path.dirname(__file__), '05.py')\nexec(open(filename).read())\n"
  },
  {
    "path": "other/clrs/11/05/01.markdown",
    "content": "> $\\star$ Suppose that we insert $n$ keys into a hash table of size $m$ using\n> open addressing and uniform hashing. Let $p(n,m)$ be the probability that no\n> collisions occur. Show that $p(n, m) \\le e^{-n(n-1)/2m}$. (_Hint:_ see\n> equation (3.12).) Argue that when $n$ exceeds $\\sqrt{m}$, the probability of\n> avoiding collisions goes rapidly to zero.\n\nEquation (3.12) states that:\n\n$$ e^x \\ge 1 + x $$\n\nLet's observe that:\n\n$$ p(n, m) = \\frac{m}{m} \\cdot \\frac{m-1}{m} \\cdots \\frac{m-n+1}{m} = \\frac{m!}{n!m^n} $$\n\nAnd that\n\n$$ p(k + 1, m) = p(k, m) \\cdot \\frac{m - k}{m} = p(k, m) \\cdot \\left(1 - \\frac{k}{m} \\right) $$\n\nLet's prove $p(n, m) \\le e^{-n(n-1)/2m}$ by induction, fixing $m$ and treating\n$k = n$ as a variable.\n\nFor $n = 1$:\n\n$$ p(1, m) = 1 \\le e^{0} = 1 $$\n\nIf we assume the inequality holds for $k$, then for $k - 1$ we have:\n\n$$\n    \\begin{aligned}\n      p(k + 1, m) &= p(k, m) \\cdot \\left( 1 - \\frac{k}{m} \\right) \\\\\\\\\n                   &\\le e^{-k(k-1)/2m} \\cdot \\left( 1 - \\frac{k}{m} \\right) \\\\\\\\\n                   &\\le e^{-k(k-1)/2m} \\cdot e^{-k/m} \\\\\\\\\n                   &= e^{-k(k-1)/2m - k/m} \\\\\\\\\n                   &= e^{-k(k-1)/2m - 2k/2m} \\\\\\\\\n                   &= e^{-(k(k-1) + 2k)/2m} \\\\\\\\\n                   &= e^{-k(k+1)/2m} \\\\\\\\\n    \\end{aligned}\n$$\n\nAs for the \"rapidly goes to zero\" part, observe that if we rewrite the equation\na bit, we get:\n\n$$ pr(n, m) = \\frac{1}{e^{n(n-1)/2m}} $$\n\nAnd that if $n \\ge \\sqrt{m}$ the power in the denominator becomes greater than\n1, at which point it starts rapidly (exponentially) growing, and the fraction\nstarts rapidly (exponentially) approaching zero.\n"
  },
  {
    "path": "other/clrs/11/problems/01.markdown",
    "content": "## Longest-probe bound for hashing\n\n> Suppose that we use an open-addressed hash table of size $m$ to store $n \\le\n> m/2$ items.\n>\n> a. Assuming uniform hashing, show that for $i = 1, 2, \\ldots, n$, the\n>    probability is at most $2^{-k}$ that the $i$th insertion requires strictly\n>    more than $k$ probes.\n>\n> b. Show that for $i = 1, 2, \\ldots, n$, the probability is $\\O(1/n^2)$ that\n>    the $i$th insertion requires more than $2\\lg{n}$ probes.\n>\n> Let the random variable $X_i$ denote the number of probes required by the\n> $i$th insertion. You have shown in part (b) that $\\Pr\\\\{X_i > 2\\lg{n}\\\\} =\n> \\O(1/n^2)$. Let the random variable $X = \\max_{1 \\le i \\le n} X_i$ denote the\n> maximum number of probes required by any of the $n$ insertions.\n>\n> c. Show that $\\Pr\\\\{X > 2 \\lg{n}\\\\} = \\O(1/n)$\n>\n> d. Show that the expected length $\\E[X]$ of the longest probe sequence is\n> $\\O(\\lg{n})$.\n\nAlright.\n\n### a. Number of probes\n\nFrom the text we know that:\n\n$$\n    \\Pr\\\\{ X \\ge i \\\\} = \\Pr\\\\{ X > i - 1 \\\\} = \\frac{n}{m} \\cdot \\frac{n-1}{m-1}\n       \\cdots \\frac{n-i+2}{m-i+2} \\le \\left( \\frac{n}{m} \\right)^{i-1} =\n       \\alpha^{i-1}\n$$\n\nSince we know that $n \\le m/2$, we know that:\n\n$$\n    \\Pr\\\\{X > k\\\\} = \\Pr\\\\{X \\ge k+1 \\\\}\n                  \\le \\left( \\frac{n}{m} \\right)^k\n                  \\le \\left( \\frac{m}{2m} \\right)^k\n                  = \\left( \\frac{1}{2} \\right)^k\n                  = 2^{-k}\n$$\n\n### b. Insertion requiring more than $2\\lg{n}$ probes\n\nWell, just substitute in the previous with $k = 2\\lg{n} = \\lg{n^2}$:\n\n$$ \\Pr\\\\{X > \\lg{n^2}\\\\} \\le 2^{-\\lg{n^2}} = \\frac{1}{n^2} = \\O(1/n^2) $$\n\n### c. Probability for longest probe\n\n$$\n    \\begin{aligned}\n      \\Pr\\\\{X > 2\\lg{n}\\\\} &= \\Pr\\\\{\\bigcup_{i=1}^n \\left( X_i > 2\\lg{n} \\right) \\\\} && \\\\\\\\\n                           &\\le \\sum_{i=1}^{n} \\Pr\\\\{X_i > 2\\lg{n} \\\\} &&\n                                \\text{since } \\Pr\\\\{A \\cup B\\\\} \\le \\Pr\\\\{A\\\\} + \\Pr\\\\{B\\\\} \\\\\\\\\n                           &\\le \\sum_{i=1}^{n} \\frac{1}{n^2} &&\n                                \\text{because of (b)} \\\\\\\\\n                           &= \\frac{n}{n^2} \\\\\\\\\n                           &= \\O(1/n)\n    \\end{aligned}\n$$\n\n### d. Expectation of the longest probe sequence\n\nHere's a weird way to do it that I lifted from the Instructor's Manual after I\ngave up. The point is to split the expectation into two parts:\n\n$$\n    \\begin{aligned}\n      \\E[X] &= \\sum_{k=1}^{n} k \\Pr \\\\{ X = k \\\\} \\\\\\\\\n            &= \\sum_{k=1}^{\\lceil 2\\lg{n} \\rceil} k \\Pr\\\\{X = k\\\\} + \\sum_{\\lceil 2\\lg{n} \\rceil + 1}^n k \\Pr\\\\{X = k\\\\} \\\\\\\\\n            &\\le \\sum_{k=1}^{\\lceil 2\\lg{n} \\rceil} \\lceil 2\\lg{n} \\rceil \\cdot \\Pr\\\\{X = k\\\\} + \\sum_{\\lceil 2\\lg{n} \\rceil + 1}^n n \\cdot \\Pr\\\\{X = k\\\\} \\\\\\\\\n            &= \\lceil 2\\lg{n} \\rceil \\sum_{k=1}^{\\lceil 2\\lg{n} \\rceil} \\Pr\\\\{X = k\\\\} + n \\sum_{\\lceil 2\\lg{n} \\rceil + 1}^n \\Pr\\\\{X = k\\\\} \\\\\\\\\n    \\end{aligned}\n$$\n\nWe can then simplify the two parts of the sum.\n\nWe know that $X$ takes only one value, so the sum of probabilities in the left\npart is at most $1$.\n\nWe know from (c) that the sum in the right part is $\\O(n)$.\n\nThus:\n\n$$\n    \\begin{aligned}\n      \\E[X] &\\le \\lceil 2 \\lg{n} \\rceil \\cdot 1 + n \\cdot \\O(1/n) \\\\\\\\\n            &= \\lceil 2 \\lg{n} \\rceil + \\O(1) \\\\\\\\\n            &= \\O(\\lg{n})\n    \\end{aligned}\n$$\n\n### Take-away\n\nThis is basically saying that as long we keep half of the hash table empty, we\ncan expect the longest probe to be no more than $\\lg{n}$.\n"
  },
  {
    "path": "other/clrs/11/problems/02.markdown",
    "content": "## Slot-size bound for chaining\n\n> Suppose that we have a hash table with $n$ slots with collisions resolved by\n> chaining, and suppose that $n$ keys are inserted into the table. Each key is\n> equally likely to be hashed in each slot. Let $M$ be the maximum number of\n> keys in any slot after all the keys have been inserted. Your mission is to\n> prove an $\\O(\\lg{n}/\\lg\\lg{n})$ upper bound on $\\E[M]$, the expected value of\n> $M$.\n>\n> a. Argue that the probability $\\mathcal{Q}\\_k$ that exactly $k$ keys hash to a\n>    particular slot is given by:\n>    $$ \\mathcal{Q}\\_k = \\left( \\frac{1}{n} \\right)^k \\left( 1 - \\frac{1}{n} \\right)^{n-k} \\binom{n}{k} $$\n>\n> b. Let $P_k$ be the probability that $M = k$, that is, the probability that\n>    the slot containing the most keys contains $k$ keys. Show that $P_k \\le\n>    n\\mathcal{Q}_k$.\n>\n> c. Use Stirling's approximation, equation (3.18), to show that $\\mathcal{Q}_k\n>    < e^k / k^k$.\n>\n> d. Show that there exists a constant $c > 1$ such that $\\mathcal{Q}_{k_0} < 1\n>    / n^3$ for $k_0 = c \\lg{n} / \\lg\\lg{n}$. Conclude that $P_k < 1/n^2$ for $k\n>    \\ge k_0 = c \\lg{n} / \\lg\\lg{n}$.\n>\n> e. Argue that\n>\n> $$\n>      \\E[M] \\le \\Pr \\left\\\\{ M > \\frac{c\\lg{n}}{\\lg\\lg{n}} \\right\\\\} \\cdot n +\n>                \\Pr \\left\\\\{ M \\le \\frac{c\\lg{n}}{\\lg\\lg{n}} \\right\\\\} \\cdot\n>                \\frac{c \\lg{n}}{\\lg\\lg{n}}\n> $$\n>\n> Conclude that $\\E[M] = \\O(\\lg{n} / \\lg\\lg{n})$.\n\n### a. Probability of exactly $k$ keys in a slot\n\nThat's kinda obvious by the definition. $k$ keys need to be in that slot, each\nhaving probability $1/n$, $n-k$ keys need to be in a different slot with\n$(n-1)/n = 1 - 1/n$ probability, and there are $\\binom{n}{k}$ ways to pick the\n$k$ keys out that collide out of the $n$ keys in total.\n\n### b. Probability that the longest slot is $k$\n\nWe're looking for an upper bound on the probability that the longest chain is\nexactly $k$, that is $M = k$. This is less than the probability of $M \\ge k$,\nwhich in turn is the probability that any of the chains has length $k$, which in\nturn is $\\mathcal{Q}_k$.\n\nIf $M_i$ is the number of keys contained in the $i$th element of the table, we\nhave:\n\n$$\n  \\Pr\\\\{M = k\\\\} \\le \\Pr\\\\{\\bigcup_{i=1}^n \\left( M_i = k \\right)\\\\} \\le\n  \\sum_{i=1}^n \\Pr\\\\{M = k\\\\} = n \\mathcal{Q}_k\n$$\n\n### c. Bounding $\\mathcal{Q}_k$\n\nFrom Stirling's approximation:\n\n$$ n! = \\sqrt{2 \\pi n} \\left( \\frac{n}{e} \\right)^n \\left( 1 + \\Theta \\left(\n\\frac{1}{n} \\right) \\right) $$\n\nWe can get:\n\n$$\n    n! = \\sqrt{2 \\pi n} \\left( \\frac{n}{e} \\right)^n \\left( 1 + \\Theta \\left( \\frac{1}{n} \\right) \\right)\n       \\ge \\sqrt{2 \\pi n} \\left( \\frac{n}{e} \\right)^n\n       > \\frac{n^n}{e^n}\n$$\n\nOr simply: $k! > k^k / e^k$.\n\n$$\n    \\begin{aligned}\n      \\mathcal{Q}_k &= \\left( \\frac{1}{n} \\right)^k \\left( 1 - \\frac{1}{n} \\right)^{n-k} \\binom{n}{k} \\\\\\\\\n                    &= \\frac{1}{n^k} \\cdot \\frac{(n-1)^{n-k}}{n^{n-k}} \\frac{n!}{k!(n-k)!} \\\\\\\\\n                    &= \\left( 1 - \\frac{1}{n} \\right)^{n-k} \\cdot \\frac{n \\cdot (n-1) \\cdots (n-k+1)}{n^k} \\cdot \\frac{1}{k!} \\\\\\\\\n                    &\\le \\frac{ \\overbrace{n \\cdot (n-1) \\cdots (n-k+1) }^\\text{k times}}{ n^k } \\cdot \\frac{1}{k!} && \\text{(product of probability)} \\\\\\\\\n                    &\\le \\frac{ \\overbrace{n \\cdot n \\cdots n}^\\text{k times} }{n^k} \\cdot \\frac{1}{k!} \\\\\\\\\n                    &= \\frac{n^k}{n^k} \\cdot \\frac{1}{k!} \\\\\\\\\n                    &= \\frac{1}{k!} \\\\\\\\\n                    &< \\frac{e^k}{k^k}\n    \\end{aligned}\n$$\n\n### d. More bounds\n\nI got stuck here, consulted the Instructor Manual, and discovered it also did a\nbunch of hand-waving. Go and consult it if you want, I'll try to summarize how I\nunderstood the approach here.\n\nWe're looking for $\\frac{e^{k_0}}{k^{k_0}} < \\frac{1}{n^3}$, also known as $n^3\n< \\frac{k^{k_0}}{e^{k_0}}$. Taking $\\lg$ of each side we get:\n\n$$\n  3\\lg{n} < k_0(\\lg k_0 - \\lg e) \\\\\\\\\n  \\Updownarrow \\\\\\\\\n  3 < \\frac{ k_0(\\lg k_0 - \\lg e) }{ \\lg n }\n$$\n\nWe now plug $k_0$ in to get Lovecraftian:\n\n$$\n  \\begin{aligned}\n    3 &< \\frac{ c \\lg n }{ \\lg n \\lg \\lg n } \\left( \\lg \\frac{ c \\lg n }{ \\lg \\lg n } - \\lg e \\right) \\\\\\\\\n      &= \\frac{ c }{ \\lg \\lg n } \\left( \\lg c + \\lg \\lg n - \\lg \\lg \\lg n - \\lg e \\right) \\\\\\\\\n      &= c \\left( \\frac{\\lg c}{\\lg \\lg n} + \\frac{\\lg \\lg n}{\\lg \\lg n} - \\frac{\\lg \\lg \\lg n}{\\lg \\lg n} - \\frac{\\lg e}{\\lg \\lg n} \\right) \\\\\\\\\n      &= c \\left(1 + \\frac{ \\lg c - \\lg e }{ \\lg \\lg n } - \\frac{ \\lg \\lg n }{ \\lg \\lg \\lg n } \\right)\n  \\end{aligned}\n$$\n\nNow for the hand-waving. First, we notice that picking the necessary $c$ depends\non the value of $n$. Next, let's call the expression in parentheses $A$ and\nnotice that:\n\n$$\n  \\lim_{n \\to \\infty} A = 1\n$$\n\nHence, there is a $n_0$ for which if $n \\ge n_0$ we have that $A \\ge 1/2$ and\ntherefore if we pick $c > 6$ we have $3 < cA$ when $n$ is larger than $n_0$.\nNext we need to figure it out for $n < n_0$. We notice that $n \\ge 3$, because\n$\\lg \\lg 2 = \\lg 1 = 0$ and that won't work, because we'll be dividing by $0$ in\n$c$.\n\nSo for $3 \\le n < n_0$ we choose $\\max_{3 \\le n < n_{0}}\\\\{ c : 3 < cx \\\\}$,\nthat is, any $c$ that is large enough to satisfy all of the cases. We then pick\n$c$ to be the larger of that and $6$ and we're done. We're convinced a number\nlike that exists, although we haven't spelled it out.\n\nNow we know that $\\mathcal{Q}_k < 1 / n^3$. We can easily conclude, then, than:\n\n$$ P_k \\le n \\mathcal{Q}_k < n \\frac{1}{n^3} = 1/n^2 $$\n\n### e. Expectation\n\nThis is simpler:\n\n$$\n  \\begin{aligned}\n    \\E[M] &= \\sum_{k=0}^{n} k \\cdot \\Pr \\\\{ M = k \\\\} \\\\\\\\\n          &= \\sum_{k=0}^{k_0} k \\cdot \\Pr \\\\{ M = k \\\\} + \\sum_{k=k_0 + 1}^{n} k \\cdot \\Pr \\\\{ M = k \\\\} \\\\\\\\\n          &\\le \\sum_{k=0}^{k_0} k_0 \\cdot \\Pr \\\\{ M = k \\\\} + \\sum_{k=k_0 + 1}^{n} n \\cdot \\Pr \\\\{ M = k \\\\} \\\\\\\\\n          &= k_0 \\cdot \\sum_{k=0}^{k_0} \\Pr \\\\{ M = k \\\\} + n \\cdot \\sum_{k=k_0 + 1}^{n} \\Pr \\\\{ M = k \\\\} \\\\\\\\\n          &= k_0 \\cdot \\Pr\\\\{ M \\le k_0 \\\\} + n \\cdot \\Pr \\\\{ M > k_0 \\\\}\n  \\end{aligned}\n$$\n\nWhich is the long expression we needed to prove.\n\nTaking the last piece, we have:\n\n$$\n    \\Pr \\\\{ M > k_0 \\\\} = \\sum_{k=k_0+1}^{n} \\Pr\\\\{ M = k \\\\}\n      \\le \\sum_{k=k_0+1}^{n} \\frac{1}{n^2}\n      \\le n \\frac{1}{n^2}\n      = \\frac{1}{n}\n$$\n\nWe know that $\\Pr\\\\{M \\le k_0\\\\} \\le 1$ (probability axiom), so:\n\n$$\n  \\begin{aligned}\n    \\E[M] &= k_0 \\cdot \\Pr\\\\{ M \\le k_0 \\\\} + n \\cdot \\Pr \\\\{ M > k_0 \\\\} \\\\\\\\\n          &\\le k_0 + n \\cdot \\frac{1}{n} \\\\\\\\\n          &= \\frac{c \\lg n}{\\lg \\lg n} + 1 \\\\\\\\\n          &= \\O(\\lg n / \\lg \\lg n)\n  \\end{aligned}\n$$\n\nHow is one supposed to figure this out, I have no idea. Maybe by reading Knuth.\n"
  },
  {
    "path": "other/clrs/11/problems/03.markdown",
    "content": "## Quadratic probing\n\n> Suppose that we are given a key $k$ to search for in a hash table with\n> positions $0, 1, \\ldots, m - 1$, and suppose that we have a hash function $h$\n> mapping the key space into the set $\\\\{0, 1, \\ldots, m - 1\\\\}$. The search\n> scheme is as follows:\n>\n> 1. Compute the value of $j = h(k)$, and set $i = 0$.\n> 2. Probe in position $j$ for the desired key $k$. If you find it, or if this\n>    position is empty, terminate the search.\n> 3. Set $i = i + 1$. If $i$ now equals $m$, the table is full, so terminate the\n>    search. Otherwise, set $j = (i + j) \\bmod m$, and return to step 2.\n>\n> Assume that $m$ is a power of $2$.\n>\n> a. Show that this scheme is an instance of the general \"quadratic probing\"\n> scheme by exhibiting the appropriate constants $c_1$ and $c_2$ for equation\n> (11.5).\n>\n> b. Prove that this algorithm examines every table position in the worst case.\n\n\n### a. Is it quadratic?\n\nObserving what this process yields, and let's calculate a few values for $f(k,\ni)$ produced by this method.\n\n$$\n    \\begin{aligned}\n    & f(k, 0) = h(k) + 0 & = C + 0 \\\\\\\\\n    & f(k, 1) = f(0) + 1 = h(k) + 1 &= C + 1 \\\\\\\\\n    & f(k, 2) = f(1) + 2 = f(0) + 1 + 2 = h(k) + 3 &= C + 3 \\\\\\\\\n    & f(k, 3) = f(2) + 3 = f(1) + 2 + 3 = f(0) + 1 + 2 + 3 = h(k) + 6 &= C + 6 \\\\\\\\\n    \\end{aligned}\n$$\n\nOr generally:\n\n$$ f(k, i) = f(k, i - 1) + i $$\n\nWhich is a recurring relation that we can use induction to prove that\n\n$$ f(k, i) = h(k) + \\sum_{j=0}^{j} j = h(k) + \\frac{n(n+1)}{2} $$\n\n(because the sum is just an arithmetic progression)\n\nThis fits equation (11.5) with $c_1 = c_2 = 1/2$, because:\n\n$$ f(k, i) = h(k) + \\frac{1}{2}i + \\frac{1}{2}i^2 $$\n\n### b. Does it examine every position?\n\nHad to consult the Instructor Manual yet again.\n\nLet's assume it doesn't. This means that there are two separate values $a$ and\n$b$ such that $0 \\le a < b < m$ for which $f(k, a) = f(k, b)$ modulo $m$, that\nis:\n\n$$\n    h(k) + \\frac{a(a + 1)}{2} = h(k) \\frac{b(b + 1)}{2} \\mod m \\\\\\\\\n    \\Downarrow \\\\\\\\\n    \\frac{a(a + 1)}{2} = \\frac{b(b + 1)}{2} \\mod m \\\\\\\\\n    \\Downarrow \\\\\\\\\n    \\frac{a(a + 1)}{2} - \\frac{b(b + 1)}{2} = 0 \\mod m \\\\\\\\\n    \\Downarrow \\\\\\\\\n    \\frac{a^2 + a - b^2 - b}{2} = 0 \\mod m \\\\\\\\\n    \\Downarrow \\\\\\\\\n    \\frac{a^2 + a + ab - b^2 - b -ab}{2} = 0 \\mod m \\\\\\\\\n    \\Downarrow \\\\\\\\\n    \\frac{(a - b)(a + b + 1)}{2} = 0 \\mod m\n$$\n\nThe final part means that there is an integer $r$ so that:\n\n$$\n    \\frac{(a - b)(a + b + 1)}{2} = rm \\\\\\\\\n    \\Downarrow \\\\\\\\\n    (a - b)(a + b + 1) = 2rm \\\\\\\\\n    \\Downarrow \\\\\\\\\n    (a - b)(a + b + 1) = r \\cdot 2^{p+1}\n$$\n\nThe last step is because we know that $m$ is a power of $2$, that is there is an\ninteger $p$ such that $m = 2^p$.\n\nNow, since $a$ and $b$ are both integers, this means that $a - b$ and $a + b +\n1$ are integers as well, and more importantly, one of them is even, and another\none is odd. That is, at least one of them is not dividable by $2$. This means\nthe other is dividable by $2^{p+1}$. But it can't be $(a - b)$ because $a - b <\nm < 2^{p+1}$. It can't be $(a + b + 1)$, because $a + b + 1 \\le (m - 1) + (m -\n2) + 1 = 2m - 2 < 2^{p+1}$. We've reacted a contradiction, which means that\n$f(k, a) \\ne f(k, b)$, for $0 \\le a < b < m$, which means that the algorithm\nwill exhaust all slots before it reaches $m$.\n"
  },
  {
    "path": "other/clrs/11/problems/04.markdown",
    "content": "## Hashing and authentication\n\n> Let $\\mathscr{H}$ be a class of hash functions in which each hash function $h\n> \\in \\mathscr{H}$ maps the universe $U$ of keys to $\\\\{0, 1, \\ldots, m - 1\\\\}$.\n> We say that $\\mathscr{H}$ is **k-universal** if, for every fixed sequence of\n> $k$ distinct keys $\\langle x^{(1)}, x^{(2)}, \\ldots, x^{(k)} \\rangle$ and for\n> any $h$ chosen at random from $\\mathscr{H}$, the sequence $\\langle h(x^{(1)}),\n> h(x^{(2)}), \\ldots, h(x^{(k)}) \\rangle$ is equally likely to be any of the\n> $m^k$ sequences of length $k$ with elements drawn from $\\\\{0, 1, \\ldots, m -\n> 1\\\\}$.\n>\n> **a.** Show that if the family $\\mathscr{H}$ of hash functions is 2-universal,\n> then it is universal.\n>\n> **b.** Suppose that the universe $U$ is the set of $n$-tuples of values drawn\n> from $\\mathbb{Z}\\_p = \\\\{0, 1, \\ldots, p - 1\\\\}$, where $p$ is prime. Consider\n> an example $x = \\langle x\\_0, x\\_1, \\ldots, x_{n-1} \\rangle \\in U$. For\n> any $n$-tuple $a = \\langle a_0, a_1, \\ldots, a_{n-1} \\rangle \\in U$, define\n> the hash function $h_a$ by\n>\n> $$ h_a(x) = \\left( \\sum_{j=0}^{n-1} a_j x_j \\right) \\bmod p $$\n>\n> Let $\\mathscr{H} = \\\\{h_a\\\\}$. Show that $\\mathscr{H}$ is universal, but not\n> 2-universal. (_Hint:_ Find a key for which all hash functions in $\\mathscr{H}$\n> produce the same value.)\n>\n> **c.** Suppose that we modify $\\mathscr{H}$ slightly from part (b): for any $a\n> \\in U$ and for any $b \\in \\mathbb{Z}_p$, define\n>\n> $$ h_{ab}'(x) = \\left( \\sum_{j=0}^{n-1} a_j x_j + b \\right) \\bmod p $$\n>\n> and $\\mathscr{H}' = \\\\{h_{ab}'\\\\}$. Argue that $\\mathscr{H}'$ is 2-universal.\n> (_Hint:_ Consider fixed $n$-tuples $x \\in U$ and $y \\in U$, with $x_i \\ne y_i$\n> for some $i$. What happens to $h_{ab}'(x)$ and $h_{ab}'(y)$ and $a_i$ and $b$\n> over range $\\mathbb{Z}_p$?)\n>\n> **d.** Suppose that Alice and Bob secretly agree on a hash function $h$ from a\n> 2-universal family $\\mathscr{H}$ of hash functions. Each $h \\in \\mathscr{H}$\n> maps from a universe of keys $U$ to $\\mathbb{Z}_p$, where $p$ is prime. Later,\n> Alice sends a message $m$ to BoB over the Internet, where $m \\in U$. She\n> authenticates this message to Bob by also sending an authentication tag $t =\n> h(m)$, and Bob checks that the pair $(m, t)$ he receives indeed satisfies $t =\n> h(m)$. Suppose that an adversary intercepts $(m, t)$ en route and tries to\n> fool Bob by replacing the pair $(m, t)$ with a different pair $(m', t')$.\n> Argue that the probability that the adversary succeeds in fooling Bob into\n> accepting $(m', t')$ is at most $1/p$, no matter how much computing power the\n> adversary has, and even if the adversary knows the family $\\mathscr{H}$ of\n> hash functions used.\n\n### a. 2-universal implies universal\n\nThis is pretty much by the definition. 2-universal means that the tuple/pair\n$\\langle a, b \\rangle$ is equally likely to be any of the $m^2$ possible pairs,\n$m$ of which contain the same element repeating, placing the chance of collision\nat $1/m$, which is the requirement for \"universal\".\n\n### b. One possible family of hash functions\n\nIn order to convince ourselves that it's universal, we need to establish an\nupper bound on the probability of $h_a(x) = h_a(y)$ when $x \\ne y$. This holds\nwhen:\n\n$$ \\sum_{j=0}^{n-1} (x_k - y_k)a_j = 0 \\mod p $$\n\n...or fully we're looking for:\n\n$$ \\Pr\\\\{ \\sum_{j=0}^{n-1} (x_k - y_k)a_j \\bmod p = 0 \\\\} \\le \\frac{1}{p} $$\n\nLet's acknowledge that $(x_k - y_k)$ is fixed, and the only thing we're\nconsidering is the possible values for $a\\_j$. Furthermore, let's also note that\n$a_j < p$.\n\nNow let's establish for which tuples the above condition holds. If we fix the\nfirst $n - 1$ elements of the tuple, we're left with a choice of the last one.\nSince $a_{n-1} < p$, there is only one possible value for the last element that\nwill be produce a sum equal to 0 modulo $p$. All other will be $\\ne p$. That is,\n$1$ in every $p$ functions will produce a collision, and the overall probability\nis $1/p$, which is the requirement for universality.\n\nIt's not 2-universal, however, because all functions of the family produce\n$h_a(x) = 0$ when $x = \\langle 0, 0, \\ldots, 0 \\rangle$.\n\n### c. A better family of functions\n\nAt this point it gets pretty intuitive that this is 2-universal, because it\neliminates the problem with the zeroes. Following the hint, if we have two\ntuples that differ only for some it, that is $x_i \\ne y_i$, we'll have\n$h_{ab}'(x) = h_{ab}'(y)$ only when:\n\n$$ a_i x_i + b = a_i y_i + b \\mod p $$\n\nOr rather:\n\n$$ a_i (x_i - y_i) + b = 0 \\mod p $$\n\nSince $x_i - y_i$ is fixed, and both $a_i < p$ and $b < p$, there is only one\nvalue of $b$ that satisfies the equation for a given value of $a_i$. That is,\nthere are $p/p^2 = 1/p$ pairs which collide.\n\nThis argument can be formalized, but honestly, it's not worth it.\n\n### d. Hash fingerprints, but with more words\n\nWell, there if the adversary has $(m, t)$ and they would like to craft $m'$,\nthey need to calculate $t'$ correctly. They can limit the family of functions in\n$\\mathscr{H}$ to only those that produce $h(m) = t$. But even then, 2-universal\nimplies that for $\\langle m, m' \\rangle$, any of the possible $\\langle t, t'\n\\rangle$ are equality likely (probability $1/p^2$), which in turn means that for\nany fixed $t$, any of the $p$ possible values of $t'$ is equally likely as well.\n\nWith no additional information, the only thing our adversary can do is pick any\nof the subset they identified, and they have only $1/p$ chance to get it right\n_for the next message_.\n\n---\n\nIt's worth noting two things:\n\n1. If the adversary had multiple pairs of $(m_i, t_i)$, they can narrow it down\n   further, assuming they can compute the subset of the family $\\mathscr{H}$.\n   Now, if the family is $(i+1)$-universal, they are back to looking at $1/p$\n   probability after the $i$th message.\n\n2. The functions in the family can be [picked in a way][one-way-fn], where the\n   adversary cannot easily identify the ones for which $h(m) = t$ given $m$ and\n   $t$, given that $P \\ne NP$.\n\n[one-way-fn]: https://en.wikipedia.org/wiki/One-way_function\n"
  },
  {
    "path": "other/clrs/12/01/01.dot",
    "content": "graph {\n  node[shape=\"circle\"];\n\n  a1[label=\"1\"];\n  a4[label=\"4\"];\n  a5[label=\"5\"];\n  a10[label=\"10\"];\n  a16[label=\"16\"];\n  a17[label=\"17\"];\n  a21[label=\"21\"];\n\n  a10 -- a4; a10 -- a17;\n  a4 -- a1; a4 -- a5; a17 -- a16; a17 -- a21;\n\n  b1[label=\"1\"];\n  b4[label=\"4\"];\n  b5[label=\"5\"];\n  b10[label=\"10\"];\n  b16[label=\"16\"];\n  b16l[shape=point];\n  b17[label=\"17\"];\n  b17l[shape=point];\n  b21[label=\"21\"];\n  b5r[shape=point];\n  b4r[shape=point];\n\n  b10 -- b5; b10 -- b16;\n  b5 -- b4; b5 -- b5r; b16 -- b16l; b16 -- b17;\n  b4 -- b1; b4 -- b4r; b17 -- b17l; b17 -- b21;\n\n  c1[label=\"1\"];\n  c4[label=\"4\"];\n  c5[label=\"5\"];\n  c10[label=\"10\"];\n  c10r[shape=point];\n  c16[label=\"16\"];\n  c17[label=\"17\"];\n  c17l[shape=point];\n  c21[label=\"21\"];\n  c5r[shape=point];\n  c4r[shape=point];\n\n  c16 -- c10;\n  c10 -- c5; c10 -- c10r; c16 -- c17;\n  c5 -- c4; c5 -- c5r;\n  c4 -- c1; c4 -- c4r; c17 -- c17l; c17 -- c21;\n\n  d1[label=\"1\"];\n  d4[label=\"4\"];\n  d5[label=\"5\"];\n  d10[label=\"10\"];\n  d10r[shape=point];\n  d16[label=\"16\"];\n  d16r[shape=point];\n  d17[label=\"17\"];\n  d21[label=\"21\"];\n  d5r[shape=point];\n  d4r[shape=point];\n\n  d17 -- d16; d17 -- d21;\n  d16 -- d10; d16 -- d16r;\n  d10 -- d5; d10 -- d10r;\n  d5 -- d4; d5 -- d5r;\n  d4 -- d1; d4 -- d4r;\n\n  e1[label=\"1\"];\n  e4[label=\"4\"];\n  e5[label=\"5\"];\n  e10[label=\"10\"];\n  e10r[shape=point];\n  e16[label=\"16\"];\n  e16r[shape=point];\n  e17[label=\"17\"];\n  e21[label=\"21\"];\n  e5r[shape=point];\n  e4r[shape=point];\n  e21r[shape=point];\n  e17r[shape=point];\n\n  e21 -- e17; e21 -- e21r;\n  e17 -- e16; e17 -- e17r;\n  e16 -- e10; e16 -- e16r;\n  e10 -- e5; e10 -- e10r;\n  e5 -- e4; e5 -- e5r;\n  e4 -- e1; e4 -- e4r;\n}\n"
  },
  {
    "path": "other/clrs/12/01/01.markdown",
    "content": "> For the set of $\\\\{1, 4, 5, 10, 16, 17, 21\\\\}$ of keys, draw binary search\n> trees of heights 2, 3, 4, 5 and 6.\n\nGraphviz is, again, unideal to visualize this, but let's try\n\nWorth noting that heigh is defined so the heigh of a leaf is 0.\n"
  },
  {
    "path": "other/clrs/12/01/02.markdown",
    "content": "> What is the difference between the binary-search-tree property and the\n> min-heap property (see page 153)? Can the min-heap property be used to print\n> out the keys of an $n$-node tree in sorted order in $\\O(n)$ time? Show how, or\n> explain why not.\n\nThe min-heap property established that each node in the tree is smaller than its\nchildren, without distinguishing between them. The binary-search tree property\nis somehow similar, but defines a strict relation between the node and its two\nchildren.\n\nThe min-help can indeed be used to print out the keys, but not in linear time,\nfor two reasons.\n\nFirst, and generally, Theorem 8.1 proves the well-established fact that sorting\nwith comparison has a lower bound of $\\Omega(n \\lg n)$, and sorting in $\\O(n)$\nwill be a contradiction.\n\nSecond, and more specifically, the algorithm would require removing the minimal\nelement from the heap on each print. Finding the element is $\\O(1)$, but\nremoving it and while maintaining the min-heap property is an $\\O(\\lg n)$\noperation, which will in turn make it a $\\O(n \\lg n)$ algorithm.\n\nAnd basically, this is just the description of heap sort.\n"
  },
  {
    "path": "other/clrs/12/01/03.markdown",
    "content": "> Give a nonrecursive algorithm that performs an inorder tree walk. (_Hint:_ An\n> easy solution uses a stack as an auxiliary data structure. A more complicated,\n> but elegant, solution uses no stack but assumes that we can test two points of\n> equality.)\n\nWe already implemented that in Exercise 10.4.5.\n\nThe summarize:\n\n1. We need the node to have a pointer to the parent.\n2. We keep track of a current node (starting at root) and a previous node\n   (starting at nil)\n3. At each step, we use the previous node to determine which is the last element\n   element we visited. If it's the parent, we proceed to the left child. If it's\n   the left child, we print/mark the element and continue to the right child. If\n   it's the right child, we move up.\n"
  },
  {
    "path": "other/clrs/12/01/04.c",
    "content": "struct tree_t {\n    struct tree_t *left;\n    struct tree_t *right;\n    int key;\n};\ntypedef struct tree_t tree_t;\n\ntypedef void callback_t(tree_t *node);\n\nvoid preorder(tree_t *tree, callback_t *callback) {\n    if (!tree) return;\n\n    callback(tree);\n    preorder(tree->left, callback);\n    preorder(tree->right, callback);\n}\n\nvoid postorder(tree_t *tree, callback_t *callback) {\n    if (!tree) return;\n\n    postorder(tree->left, callback);\n    postorder(tree->right, callback);\n    callback(tree);\n}\n"
  },
  {
    "path": "other/clrs/12/01/04.markdown",
    "content": "> Give recursive algorithms that perform preorder and postorder tree walks in\n> $\\Theta(n)$ time on a tree of $n$ nodes.\n"
  },
  {
    "path": "other/clrs/12/01/04.test.c",
    "content": "#include \"04.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n\n#define MAX_SIZE 10\nint keys[MAX_SIZE];\nint count = 0;\n\nvoid reset_storage() {\n    count = 0;\n}\n\nvoid store(tree_t *tree) {\n    keys[count++] = tree->key;\n}\n\ntree_t *s(int key, tree_t *left, tree_t *right) {\n    tree_t *new = malloc(sizeof(tree_t));\n    new->key = key;\n    new->left = left;\n    new->right = right;\n    return new;\n}\n\nTEST(preorder_walk) {\n    tree_t *tree =\n        s(10, s(6, s(4, s(1, NULL, NULL),\n                        s(5, NULL, NULL)),\n                    NULL),\n              s(16, s(15, NULL, NULL),\n                    s(20, s(19, NULL, NULL),\n                          NULL)));\n\n    reset_storage();\n\n    preorder(tree, store);\n\n    int expected[] = {10, 6, 4, 1, 5, 16, 15, 20, 19};\n\n    ASSERT_SAME_ARRAYS_S(keys, expected, 9);\n}\n\nTEST(postorder_walk) {\n    tree_t *tree =\n        s(10, s(6, s(4, s(1, NULL, NULL),\n                        s(5, NULL, NULL)),\n                    NULL),\n              s(16, s(15, NULL, NULL),\n                    s(20, s(19, NULL, NULL),\n                          NULL)));\n\n    reset_storage();\n\n    postorder(tree, store);\n\n    int expected[] = {1, 5, 4, 6, 15, 19, 20, 16, 10};\n\n    ASSERT_SAME_ARRAYS_S(keys, expected, 9);\n}\n\n"
  },
  {
    "path": "other/clrs/12/01/05.markdown",
    "content": "> Argue that since sorting $n$ elements takes $\\Omega(n \\lg n)$ time in the\n> worst case in the comparison model, any comparison-based algorithm for\n> constructing a binary search tree from an arbitrary list of $n$ elements takes\n> $\\Omega(n \\lg n)$ time in the worst case.\n\nLet's make a reductio ad absurdum argument.\n\nLet's assume that there exists $\\o(n \\lg n)$ algorithm for constructing a binary\nsearch tree of $n$ elements. We can then use it to create a tree of $n$ elements\nand then use an inorder walk to gather the elements in an array in $\\Omega(n)$ time.\nThis way we will produce an sorted array in $\\o(n \\lg n)$ worst-case time, which\ncontradicts with the lower bound on comparison sort.\n"
  },
  {
    "path": "other/clrs/12/02/01.markdown",
    "content": "> Suppose that we have numbers between 1 and 1000 in a binary search tree, and\n> we want to search for the number 363. Which of the following sequences could\n> _not_ be the sequence of nodes examined?\n>\n> 1. 2, 252, 401, 398, 330, 344, 397, 363.\n> 2. 924, 220, 911, 244, 898, 258, 362, 363.\n> 3. 925, 202, 911, 240, 912, 245, 363.\n> 4. 2, 399, 387, 219, 266, 382, 381, 278, 363.\n> 5. 935, 278, 347, 621, 299, 392, 358, 363.\n\nEach element of the sequence asserts something for the following elements,\nnamely, that they are greater than it if it's smaller than the searched one, or\nsmaller than it, if it is greater. E.g. in the first sequence, the first\nelement asserts that the following are > 2, the second that it's following are >\n252, the third that they are < 401 and so on. Thus:\n\n* 3 is invalid because 912 > 911\n* 5 is invalid because 229 < 347\n\nThe rest are valid.\n"
  },
  {
    "path": "other/clrs/12/02/02.c",
    "content": "struct tree_t {\n    struct tree_t *left;\n    struct tree_t *right;\n    struct tree_t *parent;\n    int key;\n};\ntypedef struct tree_t tree_t;\n\ntree_t *minimum(tree_t *tree) {\n    return tree->left ? minimum(tree->left) : tree;\n}\n\ntree_t *maximum(tree_t *tree) {\n    return tree->right ? maximum(tree->right) : tree;\n}\n\n"
  },
  {
    "path": "other/clrs/12/02/02.markdown",
    "content": "> Write recursive versions of `TREE-MINIMUM` and `TREE-MAXIMUM`\n"
  },
  {
    "path": "other/clrs/12/02/02.test.c",
    "content": "#include \"02.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n\ntree_t *s(int key, tree_t *left, tree_t *right) {\n    tree_t *new = malloc(sizeof(tree_t));\n    new->parent = NULL;\n\n    new->key = key;\n    new->left = left;\n    new->right = right;\n\n    if (left) left->parent = new;\n    if (right) right->parent = new;\n\n    return new;\n}\n\nTEST(minumum) {\n    tree_t *tree =\n        s(15, s(6, s(3, s(2, NULL, NULL),\n                        s(4, NULL, NULL)),\n                    s(7, NULL,\n                         s(13, s(9, NULL, NULL),\n                               NULL))),\n              s(18, s(17, NULL, NULL),\n                    s(20, NULL, NULL)));\n\n    ASSERT_EQUALS(minimum(tree)->key, 2);\n}\n\n\nTEST(maximum) {\n    tree_t *tree =\n        s(15, s(6, s(3, s(2, NULL, NULL),\n                        s(4, NULL, NULL)),\n                    s(7, NULL,\n                         s(13, s(9, NULL, NULL),\n                               NULL))),\n              s(18, s(17, NULL, NULL),\n                    s(20, NULL, NULL)));\n\n    ASSERT_EQUALS(maximum(tree)->key, 20);\n}\n"
  },
  {
    "path": "other/clrs/12/02/03.c",
    "content": "struct tree_t {\n    struct tree_t *left;\n    struct tree_t *right;\n    struct tree_t *parent;\n    int key;\n};\ntypedef struct tree_t tree_t;\n\ntree_t *maximum(tree_t *tree) {\n    while (tree->right) tree = tree->right;\n    return tree;\n}\n\ntree_t *predecessor(tree_t *tree) {\n    if (tree->left) {\n        return maximum(tree->left);\n    }\n\n    tree_t *parent = tree->parent;\n\n    while (parent && parent->left == tree) {\n        tree = tree->parent;\n        parent = tree->parent;\n    }\n\n    return parent;\n}\n"
  },
  {
    "path": "other/clrs/12/02/03.markdown",
    "content": "> Write the `TREE-PREDECESSOR` procedure\n"
  },
  {
    "path": "other/clrs/12/02/03.test.c",
    "content": "#include \"03.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n\ntree_t *s(int key, tree_t *left, tree_t *right) {\n    tree_t *new = malloc(sizeof(tree_t));\n    new->parent = NULL;\n\n    new->key = key;\n    new->left = left;\n    new->right = right;\n\n    if (left) left->parent = new;\n    if (right) right->parent = new;\n\n    return new;\n}\n\nTEST(predecessor) {\n    tree_t *t13;\n    tree_t *t17;\n    tree_t *t9;\n    tree_t *t6;\n\n    // Based on figure 12.2\n    tree_t *tree =\n        s(15, t6 = s(6, s(3, s(2, NULL, NULL),\n                             s(4, NULL, NULL)),\n                        s(7, NULL,\n                             t13 = s(13, t9 = s(9, NULL, NULL),\n                                         NULL))),\n              s(18, t17 = s(17, NULL, NULL),\n                    s(20, NULL, NULL)));\n\n    ASSERT_EQUALS(predecessor(t13)->key, 9);\n    ASSERT_EQUALS(predecessor(t17)->key, 15);\n    ASSERT_EQUALS(predecessor(t9)->key, 7);\n    ASSERT_EQUALS(predecessor(t6)->key, 4);\n    ASSERT_EQUALS(predecessor(tree)->key, 13);\n}\n\n"
  },
  {
    "path": "other/clrs/12/02/04.dot",
    "content": "graph {\n  node[shape=circle];\n  4; 2; 1 3;\n  null[shape=point];\n\n  4 -- 2; 4 -- null;\n  2 -- 1; 2 --3;\n}\n"
  },
  {
    "path": "other/clrs/12/02/04.markdown",
    "content": "> Professor Bunyan thinks he has discovered a remarkable property of binary\n> search trees. Suppose that the search for key $k$ in a binary search tree ends\n> up in a leaf. Consider three sets: $A$, the keys to the left of the search\n> path; $B$, the keys on the search path; and $C$, the keys to the right of the\n> search path. Professor Bunyan claims that any three keys $a \\in A$, $b \\in B$,\n> and $c \\in C$ must satisfy $a \\le b \\le c$. Give a smallest possible\n> counterexample to the professor's claim.\n\nIn the tree below, $B = \\\\{4, 2, 1\\\\}$ and $C = \\\\{3\\\\}$, but for $b = 4$ and $c\n= 3$ we don't have $b \\le c$.\n"
  },
  {
    "path": "other/clrs/12/02/05.markdown",
    "content": "> Show that if a node in a binary search tree has two children, then its\n> successor has no left child and its predecessor has no right child.\n\nLet's say we have a tree $T$ with left subtree $L$ and right subtree $R$ and\nparent $P$. Let's also assume distinct keys.\n\nHaving two children implies that both the successor and the predecessor is going\nto be among them. To illustrate this, let's consider the successor. It can't be\nto the right of an ancestor $A$, because this makes $T$ on the left of $A$,\ntherefore making $A$ a better candidate as $T < A$. It can't be that ancestor\neither, because $T < R$ and $R < A$, making $R$ a better candidate than $A$.\nFurthermore, if $R$ exists, it's going to contain the (it can't be in $L$, as\nthose elements are smaller).\n\nFurthermore, if the successor (somewhere in $R$) had a left child, that would be\na better candidate for a successor, since it's smaller than $R$ but still bigger\nthan $T$.\n\nSame logic applies for the predecessor.\n"
  },
  {
    "path": "other/clrs/12/02/06.markdown",
    "content": "> Consider a binary search tree $T$ whose keys are distinct. Show that if the\n> right subtree of a node $x$ in $T$ is empty and $x$ has a successor $y$, then\n> $y$ is the lowest ancestor of $x$ whose left child is also an ancestor of $x$.\n> (Recall that every node is its own ancestor)\n\nThe successor is clearly not in the left child, as those elements are smaller.\nWe can then start examining the parents. If $x$ is on the right child of the\nparent, $x$ is going to be maxim element in the parent. We can continue\nconsidering parents, this way, until we reach one, $K$, that has the current\ntree on the left. We know that $x < K.key$. We also know that $K.right$ will\ncontain bigger elements. So far $K.key$ is the smaller element we've\nencountered, bigger than $x$.\n\nIf we keep going up the tree, we will either find ourselves on the left site of\nthe parent $P$, which means $K.key < P.key$ or the right side, in which case we\nknow that $P.key < x$.\n"
  },
  {
    "path": "other/clrs/12/02/07.markdown",
    "content": "> An alternative method of performing inorder tree walk of an $n$-node binary\n> search tree finds the minimum element in the tree by calling `TREE-MINIMUM`\n> and then making $n-1$ calls to `TREE-SUCCESSOR`. Prove that this algorithm\n> runs in $\\Theta(n)$ time.\n\nIt's a bit obvious, and it's not worth (read I'm too lazy) to create a formal\nargument. We simply need to observe that we visit each node twice – once on the\nway down (through `TREE-MINIMUM`) and once on the way up in the `while` loop of\n`TREE-SUCCESSOR` – and we don't do extra steps inbetween.\n"
  },
  {
    "path": "other/clrs/12/02/08.markdown",
    "content": "> Prove that no matter what node we start at in a heigh-$h$ binary search tree,\n> $k$ successive calls to `TREE-SUCCESSOR` take $\\O(k + h)$ time.\n\nThis algorithm will walk a number of full subtrees, plus at most two partial\npaths to the common ancestor of the first and last node. The subtrees will be\n$\\O(k)$ (since we visit each edge twice) and the partial paths will be $\\O(h)$\nsince we may need to skip until we find a parent on the way up and then skip\nuntil we find a minimum on the way down.\n\nYeah, informal, I know.\n"
  },
  {
    "path": "other/clrs/12/02/09.markdown",
    "content": "> Let $T$ be a binary search tree whose keys are distinct, let $x$ be a leaf\n> node, and let $y$ be its parent. Show that $y.key$ is either the smallest key\n> in $T$ larger than $x.key$ or the largest key in $T$ smaller than $x.key$.\n\nWe explored this already in the previous few exercises.\n\nLet's consider $y.left = x$. $y.right$ will not contain elements larger than\n$x.key$ but smaller than $y.key$ (binary search tree property). $y$'s parents\nwill be either left of it (which means their key is smaller than $x.key$, as are\nthose of their left subtree) or right of it (in which case their key would be\nbigger than $y.key$.\n\nIf $y.right = x$ similar logic applies.\n"
  },
  {
    "path": "other/clrs/12/03/01.c",
    "content": "#include <stdlib.h>\n\nstruct node_t {\n    struct node_t *parent;\n    struct node_t *left;\n    struct node_t *right;\n    int key;\n};\ntypedef struct node_t node_t;\n\ntypedef struct {\n    node_t *root;\n} tree_t;\n\ntree_t *make_tree() {\n    tree_t *tree = malloc(sizeof(tree_t));\n    tree->root = NULL;\n    return tree;\n}\n\nnode_t *make_node(int key) {\n    node_t *node = malloc(sizeof(node_t));\n\n    node->parent = NULL;\n    node->left = NULL;\n    node->right = NULL;\n    node->key = key;\n\n    return node;\n}\n\nnode_t *insert_node(node_t *node, int key) {\n    if (node->key < key) {\n        if (node->right) {\n            return insert_node(node->right, key);\n        } else {\n            node_t *new = make_node(key);\n            new->parent = node;\n            node->right = new;\n            return new;\n        }\n    } else {\n        if (node->left) {\n            return insert_node(node->left, key);\n        } else {\n            node_t *new = make_node(key);\n            new->parent = node;\n            node->left = new;\n            return new;\n        }\n    }\n}\n\nnode_t *insert(tree_t *tree, int key) {\n    if (tree->root) {\n        return insert_node(tree->root, key);\n    } else {\n        node_t *node = make_node(key);\n        tree->root = node;\n        return node;\n    }\n}\n\nnode_t *search(tree_t *tree, int key) {\n    node_t *node = tree->root;\n\n    while (node) {\n        if (node->key == key) {\n            return node;\n        } else if (node->key < key) {\n            node = node->right;\n        } else {\n            node = node->left;\n        }\n    }\n\n    return NULL;\n}\n"
  },
  {
    "path": "other/clrs/12/03/01.markdown",
    "content": "> Give a recursive version of the `TREE-INSERT` procedure.\n"
  },
  {
    "path": "other/clrs/12/03/01.test.c",
    "content": "#include \"01.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n\nTEST(insert) {\n    tree_t *tree = make_tree();\n    insert(tree, 7);\n    insert(tree, 3);\n    insert(tree, 5);\n    insert(tree, 1);\n    insert(tree, 9);\n    insert(tree, 11);\n\n    ASSERT_NOT_NULL(search(tree, 3));\n    ASSERT_NOT_NULL(search(tree, 5));\n    ASSERT_NOT_NULL(search(tree, 7));\n    ASSERT_NOT_NULL(search(tree, 9));\n    ASSERT_NOT_NULL(search(tree, 11));\n\n    ASSERT_NULL(search(tree, 2));\n    ASSERT_NULL(search(tree, 4));\n    ASSERT_NULL(search(tree, 6));\n}\n"
  },
  {
    "path": "other/clrs/12/03/02.markdown",
    "content": "> Suppose that we construct a binary search tree by repeatedly inserting\n> distinct values into the tree. Argue that the number of nodes examined in\n> searching for a value in the tree is one plus the number of nodes examined\n> when the value was first inserted into the tree.\n\nWith the current implementation of `TREE-INSERT` (one that does not\nself-balance), we are looking for a path from to root to the parent of the node\nwe are about to insert. Let's assume that that number is $n$. When we\nsubsequently search, we are going to walk exactly the same path (there is no\nother option, really) until we reach the same parent. Then we will examine one\nmore node, which is the node we inserted previously, that is $n+1$ in total.\n\nThis argument holds, since we're always inserting distinct values, and there is\nonly one possible path to resulting to the value we're searching for.\n"
  },
  {
    "path": "other/clrs/12/03/03.markdown",
    "content": "> We can sort a given set of $n$ numbers by first building a binary search tree\n> containing these numbers (using `TREE-INSERT` repeatedly to insert the numbers\n> one by one) and then printing the numbers by an inorder tree walk. What are\n> the worst-case and best-case running times for this sorting algorithm?\n\nThe worst case is going to be $\\Theta(n^2)$, which will be achieved if we insert\nelements in decreasing or increasing order. On each step we will need to walk\nwhat is essentially a linked list and append at it's end. That will perform\n$\\sum_{i=1}^{n} i = n(n + 1)/2 = \\Theta(n^2)$ operations.\n\nIn the best case we will insert each node at the highest level that has at least\nempty position. We can then insert 1 element with 1 operation, 2 elements with 2\noperations, 4 elements with 3 operations, 8 elements with 4 operations and so\non. This is the well-known $\\Theta(n \\lg n)$.\n\nIf we slightly modify our algorithm to be able to insert directly at the root,\nwe can achieve this in linear time, but only if we are already inserting the\nelements in sorted order.\n"
  },
  {
    "path": "other/clrs/12/03/04.markdown",
    "content": "> Is the operation of deletion \"commutative\" in the sense that deleting $x$ and\n> then $y$ from a binary search tree leaves the same tree as deleting $y$ and\n> then $x$? Argue why it is or give a counter example.\n\nIt's not commutative. Let's explore the following tree:\n\n         2\n       /   \\\n     1       4\n            /\n           3\n\nIf we first delete 1, and then 2 we get:\n\n         2              4\n           \\          /\n             4      3\n            /\n           3\n\nIf we do it the other way around, deleting 2 first, we replace it with its\nsuccessor (3) and then when we delete 1, we get:\n\n         3          3\n       /   \\          \\\n     1       4          4\n"
  },
  {
    "path": "other/clrs/12/03/05.c",
    "content": "#include <stdlib.h>\n\nstruct node_t {\n    struct node_t *left;\n    struct node_t *right;\n    struct node_t *succ;\n    int key;\n};\ntypedef struct node_t node_t;\n\ntypedef struct {\n    node_t *root;\n} tree_t;\n\ntree_t *make_tree() {\n    tree_t *tree = malloc(sizeof(tree_t));\n    tree->root = NULL;\n    return tree;\n}\n\nnode_t *make_node(int key) {\n    node_t *node = malloc(sizeof(node_t));\n\n    node->succ = NULL;\n    node->left = NULL;\n    node->right = NULL;\n    node->key = key;\n\n    return node;\n}\n\nnode_t *insert(tree_t *tree, int key) {\n    node_t *parent = NULL;\n    node_t *current = tree->root;\n    node_t *new = make_node(key);\n    node_t *pred = NULL;\n\n    while (current) {\n        parent = current;\n        if (new->key < current->key) {\n            new->succ = current;\n            current = current->left;\n        } else {\n            pred = current;\n            current = current->right;\n        }\n    }\n\n    if (!parent) {\n        tree->root = new;\n    } else if (new->key < parent->key) {\n        parent->left = new;\n    } else {\n        parent->right = new;\n        pred = parent;\n    }\n\n    if (pred) pred->succ = new;\n\n    return new;\n}\n\nnode_t *find_parent(tree_t *tree, node_t *node) {\n    node_t *previous = NULL;\n    node_t *current = tree->root;\n\n    while (current && current->key != node->key) {\n        if (current->key < node->key) {\n            previous = current;\n            current = current->right;\n        } else {\n            previous = current;\n            current = current->left;\n        }\n    }\n\n    return previous;\n}\n\nvoid find_parent_and_predecessor(tree_t *tree, node_t *node, node_t **parent, node_t **predecessor) {\n    *parent = NULL;\n    *predecessor = NULL;\n    node_t *current = tree->root;\n\n    while (current && current->key != node->key) {\n        if (current->key < node->key) {\n            *parent = current;\n            *predecessor = current;\n            current = current->right;\n        } else {\n            *parent = current;\n            current = current->left;\n        }\n    }\n\n    if (!current) return;\n\n    current = current->left;\n\n    while (current) {\n        *predecessor = current;\n        current = current->right;\n    }\n}\n\nvoid transplant(tree_t *tree, node_t *parent, node_t *target, node_t *source) {\n    if (!parent) {\n        tree->root = source;\n    } else if (target == parent->left) {\n        parent->left = source;\n    } else {\n        parent->right = source;\n    }\n}\n\nvoid delete_tree(tree_t *tree, node_t *node) {\n    node_t *parent;\n    node_t *predecessor;\n\n    find_parent_and_predecessor(tree, node, &parent, &predecessor);\n\n    if (!node->left) {\n        transplant(tree, parent, node, node->right);\n    } else if (!node->right) {\n        transplant(tree, parent, node, node->left);\n    } else {\n        node_t *successor = node->succ;\n\n        if (node->right != successor) {\n            node_t *sparent = find_parent(tree, successor);\n            transplant(tree, sparent, successor, successor->right);\n            successor->right = node->right;\n        }\n\n        transplant(tree, parent, node, successor);\n        successor->left = node->left;\n    }\n\n    if (predecessor) predecessor->succ = node->succ;\n}\n\nnode_t *search(tree_t *tree, int key) {\n    node_t *node = tree->root;\n\n    while (node) {\n        if (node->key == key) {\n            return node;\n        } else if (node->key < key) {\n            node = node->right;\n        } else {\n            node = node->left;\n        }\n    }\n\n    return NULL;\n}\n\ntypedef void (*callback_t)(node_t *);\n\nvoid inorder_walk(node_t *node, callback_t callback) {\n    if (!node) return;\n    inorder_walk(node->left, callback);\n    callback(node);\n    inorder_walk(node->right, callback);\n}\n\nvoid successor_walk(node_t *node, callback_t callback) {\n    while (node->left) node = node->left;\n\n    while (node) {\n        callback(node);\n        node = node->succ;\n    }\n}\n"
  },
  {
    "path": "other/clrs/12/03/05.debug.c",
    "content": "#include \"05.c\"\n#include <stdio.h>\n\n#define W 6\n#define P 2\n#define MAX(a,b) (((a)>(b))?(a):(b))\n\nint height(node_t *tree) {\n    if (!tree) return 0;\n\n    return MAX(height(tree->left), height(tree->right)) + 1;\n}\n\nnode_t **make_array(int size) {\n    return calloc(sizeof(node_t *), size);\n}\n\nint size(node_t *node) {\n    if (!node) return 0;\n    return size(node->left) + size(node->right) + 1;\n}\n\nvoid space(int i) {\n    while(i-- > 0) putchar(' ');\n}\n\nint level_pad(int h) {\n    int n = 1 << (h - 1);\n    return (n - 1) * (W + P) / 2;\n}\n\nvoid print_node(node_t *tree) {\n    if (!tree) printf(\"      \");\n    else if (tree->succ) printf(\"%2d(%2d)\", tree->key, tree->succ->key);\n    else printf(\"%2d(--)\", tree->key);\n}\n\nvoid print_tree(tree_t *tree) {\n    int h = height(tree->root);\n\n    int width = 1;\n    node_t **row = make_array(width);\n    row[0] = tree->root;\n\n    for (int level = 0; level < h; level++) {\n        int padding = level_pad(h - level);\n        for (int i = 0; i < width; i++) {\n            space(padding);\n            print_node(row[i]);\n            space(padding);\n            space(P);\n        }\n        puts(\"\");\n        puts(\"\");\n\n        node_t **next = make_array(width * 2);\n\n        for (int c = 0, t = 0; c < width; c++) {\n            next[t++] = row[c] ? row[c]->left : NULL;\n            next[t++] = row[c] ? row[c]->right : NULL;\n        }\n\n        free(row);\n        width *= 2;\n        row = next;\n    }\n\n    free(row);\n}\n"
  },
  {
    "path": "other/clrs/12/03/05.markdown",
    "content": "> Suppose that instead of each node $x$ keeping the attribute $x.p$ pointing to\n> $x$'s parent, it keeps $x.succ$, pointing to $x$'s successor. Give pseudocode\n> for `SEARCH`, `INSERT`, and `DELETE` on a binary search tree $T$ using this\n> representation. These procedures should operate in time $\\O(h)$, where $h$ is\n> the height of the tree $T$. (_Hint:_ You may wish to implement a subroutine\n> that returns the parent of a node.)\n\nI've got to admit, I was skeptical about this one. It was quite a good exercise,\nhowever, as it forces you to internalize a lot about binary search trees and\ntheir predecessor/successor invariants.\n\nThe pseudocode and the C code differ a bit, as the C code is a bit more\ncomplicated to avoid a few extra steps. It even can be optimized a bit further,\nbut it's not worth the complexity. The asymptotic bounds are going to be the\nsame as the pseudocode\n\n### Some thoughts\n\nI pondered a bit about why it would be useful to keep track of the successor\ninstead of the parent. I may be missing something, but I can find a single\nadvantage – the tree can be walked inorder without extra space and a bit more\noptimally. Another benefit is that it simplifies finding the successor of the\ndeleted node in `DELETE`. Apart from that, not keeping track of the parent\nintroduces some overhead, especially when deleting.\n\n### Notable differences\n\nThe pseudocode needs two change in two significant ways:\n\n* As the parent is no longer findable through a pointer, we need to walk the\n  three from the root and find it. On the flip side, we don't need to update\n  parent pointers.\n\n* Whenever we remove a node, we need to preserve the invariant of the successor\n  field. This means that we need to find the predecessor of the node we are\n  deleting, and have it successor point to the deleted node's successor.\n\n### Pseudocode\n\n`SEARCH` remains unchanged:\n\n    TREE-SEARCH(x, k)\n        if x = NIL or k == x.key\n            return x\n        if k < x.key\n            return TREE-SEARCH(x.left, k)\n        else\n            return TREE-SEARCH(x.right, k)\n\n`INSERT` needs to allocate the correct successor of the newly inserted node and\nupdate it's predecessor. Since we're only inserting leaf nodes, both predecessor\nand successor are findable through their invariants:\n\n* The predecessor is going to be the last parent at which we branched right. It\n  might be the parent of the inserted node, if we put it at the left position.\n\n* The successor is going to be the last parent at which at branched left.\n\n* Notably, we don't need to explore the new node's children, as they don't exist\n  because it's a leaf node.\n\n    TREE-INSERT(T, z)\n        y = NIL\n        x = T.root\n        pred = NIL\n\n        while x != NIL\n            y = x\n            if z.key < x.key\n                z.succ = x\n                x = x.left\n            else\n                pred = x\n                x = x.right\n\n        if y == NIL\n            T.root = z\n        else if z.key < y.key\n            y.left = z\n        else\n            y.right = z\n            pred = y\n\n        if pred != NIL\n            pred.succ = z\n\nThe final one, `DELETE` is a bit more complicated. It needs `TREE-PARENT`, that\nfinds the parent of a node, starting from the root, and `TREE-PREDECESSOR` that\nfinds finds the predecessor of a node, starting from the root. It also needs\na modified version of `TRANSPLANT`. Since those are pretty self-explanatory,\nlet's start with `DELETE` and explore them afterwards.\n\nIt's worth noting that we don't need to call `TREE-MINIMUM` on `z.right` in the\ntwo-children case, as we already know its successor.\n\n    TREE-DELETE(T, z)\n        pred = TREE-PREDECESSOR(z)\n\n        if z.left == NIL\n            TRANSPLANT(T, z, z.right)\n        else if z.right == NIL\n            TRANSPLANT(T, z, z.left)\n        else\n            y = z.succ\n\n            if (z.right != y)\n                TRANSPLANT(T, y, y.right)\n                y.right = z.right\n\n            TRANSPLANT(T, z, y)\n            y.left = z.left\n\n        if pred != NIL\n            pred.succ = z.succ\n\nNode that `y.p != z` needs to be changed to `z.right != y`, which means the same\nthing.\n\n`TRANSPLANT` now needs to explicitly find the parent:\n\n    TRANSPLANT(T, u, v)\n        p = TREE-PARENT(T, u)\n\n        if p == NIL\n            T.root = v\n        else if u == p.left\n            p.left = v\n        else\n            p.right = v\n\nThe notable change here is that we don't need to update the `v`'s parent, as we\ndon't keep track of it.\n\nFinally, `TREE-PREDECESSOR` is fairly needs to start from the root, instead of\nthe node:\n\n    TREE-PREDECESSOR(T, x)\n        y = NIL\n        z = T.root\n\n        while z != x\n            if z.key < x.key\n                y = z\n                z = z.right\n            else\n                z = z.left\n\n        z = z.left\n\n        while z != NIL\n            y = z\n            z = z.right\n\n        return y\n\nThe first loop traverses the tree from the root to `x`, keeping track of the\nlast right branch to mark it as a potential predecessor. When it finishes, `z`\nequals `x`. If there is no left child, we're done, and the ancestor is the\npredecessor. If there is a left child, we follow it and keep going left, until\nthere are no no mode left children to follow. The last is essentially what\n`TREE-MINIMUM` does. We could change the order of the loops (find the minimum of\nthe left child and go through the root only if it doesn't exist). While it will\nimprove the constant, it's asymptotically the same.\n\nThe C code merges `TREE-PREDECESSOR` and `TREE-PARENT` into one.\n\nIt's pretty easy to illustrate that the result is $\\O(h)$, so I won't bother.\n"
  },
  {
    "path": "other/clrs/12/03/05.test.c",
    "content": "#include \"05.debug.c\"\n#include \"../../build/ext/test.h\"\n\n#include <stdlib.h>\n#include <stdbool.h>\n#include <string.h>\n\nvoid randomized_numbers(int seed, int max, int target[], int count) {\n    bool used[max];\n\n    for (int i = 0; i < max; i++) used[i] = false;\n\n    srand(seed);\n\n    for (int i = 0; i < count; i++) {\n        while (true) {\n            int number = rand() % (max - 1);\n\n            if (!used[number]) {\n                used[number] = true;\n                target[i] = number + 1;\n                break;\n            }\n        }\n    }\n}\n\nint cmp(const void *pa, const void *pb) {\n    int *a = (int *) pa;\n    int *b = (int *) pb;\n    return *a - *b;\n}\n\n#define M 30\n#define L 100\n\nint buffer[M];\nint count;\n\nvoid reset_buffer() {\n    memset(buffer, 0, sizeof(int) * M);\n    count = 0;\n}\n\nvoid append_to_buffer(node_t *node) {\n    buffer[count++] = node->key;\n}\n\nvoid check_successor_invariant(tree_t *tree) {\n    reset_buffer();\n    int n = size(tree->root);\n    successor_walk(tree->root, append_to_buffer);\n    ASSERT_EQUALS(n, count);\n\n    for (int i = 1; i < n; i++) {\n        ASSERT_TRUE(buffer[i - 1] < buffer[i]);\n    }\n}\n\nTEST(inserting) {\n    int numbers[M];\n    randomized_numbers(0, 100, numbers, M);\n\n    tree_t *tree = make_tree();\n\n    for (int i = 0; i < M; i++) {\n        insert(tree, numbers[i]);\n    }\n\n    for (int i = 0; i < M; i++) {\n        ASSERT_NOT_NULL(search(tree, numbers[i]));\n    }\n\n    check_successor_invariant(tree);\n}\n\nTEST(inorder_walk) {\n    int numbers[M];\n    randomized_numbers(0, 100, numbers, M);\n\n    int sorted[M];\n    memcpy(sorted, numbers, M * sizeof(int));\n    qsort(sorted, M, sizeof(int), cmp);\n\n    tree_t *tree = make_tree();\n\n    for (int i = 0; i < M; i++) {\n        insert(tree, numbers[i]);\n    }\n\n    reset_buffer();\n    inorder_walk(tree->root, append_to_buffer);\n\n    ASSERT_SAME_ARRAYS_S(buffer, sorted, M);\n}\n\nTEST(randomized_successor_walk) {\n    int numbers[M];\n    int sorted[M];\n\n    for (int s = 0; s < 100; s++) {\n        randomized_numbers(s, 100, numbers, M);\n\n        memcpy(sorted, numbers, M * sizeof(int));\n        qsort(sorted, M, sizeof(int), cmp);\n\n        tree_t *tree = make_tree();\n\n        for (int i = 0; i < M; i++) {\n            insert(tree, numbers[i]);\n        }\n\n        reset_buffer();\n        successor_walk(tree->root, append_to_buffer);\n\n        ASSERT_SAME_ARRAYS_S(buffer, sorted, M);\n    }\n}\n\nTEST(deleting_case_a) {\n    tree_t *tree = make_tree();\n\n    insert(tree, 5);\n    insert(tree, 10);\n    insert(tree, 13);\n    insert(tree, 14);\n    insert(tree, 12);\n\n    delete_tree(tree, search(tree, 10));\n\n    ASSERT_NULL(search(tree, 10));\n    ASSERT_NOT_NULL(search(tree, 5));\n    ASSERT_NOT_NULL(search(tree, 12));\n    ASSERT_NOT_NULL(search(tree, 13));\n    ASSERT_NOT_NULL(search(tree, 14));\n\n    check_successor_invariant(tree);\n}\n\nTEST(deleting_case_a_2) {\n    tree_t *tree = make_tree();\n\n    insert(tree, 5);\n    insert(tree, 10);\n\n    delete_tree(tree, search(tree, 10));\n\n    ASSERT_NULL(search(tree, 10));\n    ASSERT_NOT_NULL(search(tree, 5));\n\n    check_successor_invariant(tree);\n}\n\nTEST(deleting_case_b) {\n    tree_t *tree = make_tree();\n\n    insert(tree, 15);\n    insert(tree, 10);\n    insert(tree, 7);\n    insert(tree, 8);\n    insert(tree, 6);\n\n    delete_tree(tree, search(tree, 10));\n\n    ASSERT_NULL(search(tree, 10));\n    ASSERT_NOT_NULL(search(tree, 15));\n    ASSERT_NOT_NULL(search(tree, 7));\n    ASSERT_NOT_NULL(search(tree, 6));\n    ASSERT_NOT_NULL(search(tree, 8));\n\n    check_successor_invariant(tree);\n}\n\n\nTEST(deleting_case_c) {\n    tree_t *tree = make_tree();\n\n    insert(tree, 5);\n    insert(tree, 10);\n    insert(tree, 7);\n    insert(tree, 13);\n\n    delete_tree(tree, search(tree, 10));\n\n    ASSERT_NOT_NULL(search(tree, 5));\n    ASSERT_NOT_NULL(search(tree, 7));\n    ASSERT_NOT_NULL(search(tree, 13));\n\n    check_successor_invariant(tree);\n}\n\nTEST(deleting_case_d) {\n    tree_t *tree = make_tree();\n\n    insert(tree, 7);\n    insert(tree, 5);\n    insert(tree, 3);\n    insert(tree, 10);\n    insert(tree, 8);\n    insert(tree, 15);\n    insert(tree, 19);\n    insert(tree, 11);\n    insert(tree, 12);\n\n    delete_tree(tree, search(tree, 10));\n\n    ASSERT_NULL(search(tree, 10));\n    ASSERT_NOT_NULL(search(tree, 7));\n    ASSERT_NOT_NULL(search(tree, 5));\n    ASSERT_NOT_NULL(search(tree, 3));\n    ASSERT_NOT_NULL(search(tree, 8));\n    ASSERT_NOT_NULL(search(tree, 15));\n    ASSERT_NOT_NULL(search(tree, 19));\n    ASSERT_NOT_NULL(search(tree, 11));\n    ASSERT_NOT_NULL(search(tree, 12));\n\n    check_successor_invariant(tree);\n}\n\nTEST(deleting_in_random_trees) {\n    int numbers[M];\n    int to_delete = 12;\n\n    for (int s = 0; s < 100; s++) {\n        bool removed[L];\n\n        randomized_numbers(s, L, numbers, M);\n\n        tree_t *tree = make_tree();\n\n        for (int i = 0; i < L; i++) removed[i] = false;\n        for (int i = 0; i < M; i++) insert(tree, numbers[i]);\n\n        for (int i = 0; i < to_delete; i++) {\n            int index = rand() % M;\n            int value = numbers[index];\n\n            if (!removed[value]) {\n                removed[value] = true;\n                ASSERT_NOT_NULL(search(tree, value));\n                delete_tree(tree, search(tree, value));\n            }\n        }\n\n        check_successor_invariant(tree);\n\n        for (int i = 0; i < M; i++) {\n            if (removed[numbers[i]]) {\n                ASSERT_NULL(search(tree, numbers[i]));\n            } else {\n                ASSERT_NOT_NULL(search(tree, numbers[i]));\n            }\n        }\n\n    }\n}\n"
  },
  {
    "path": "other/clrs/12/03/06.markdown",
    "content": "> When node $z$ in `TREE-DELETE` has two children, we could choose node $y$ as\n> its predecessor rather than its successor. What other changes to `TREE-DELETE`\n> would be necessary if we did so? Some have argued that a fair strategy, giving\n> equal priority to predecessor and successor, yields better empirical\n> performance. How might `TREE-DELETE` be changed to implement such a fair\n> strategy?\n\nWe need to write a symmetrical function:\n\n    TREE-DELETE(T, z)\n        if z.left = NIL\n            TRANSPLANT(T, z, z.right)\n        else if z.right == NIL\n            TRANSPLANT(T, z, z.left)\n        else\n            y = TREE-MAXIMUM(z.left)\n\n            if y.p != z\n                TRANSPLANT(T, y, y.left)\n                y.left = z.left\n                y.left.p = y\n\n            TRANSPLANT(T, z, y)\n            y.right = z.right\n            y.right.p = y\n\nBasically, call `TREE-MAXIMUM` and swap `left` and `right`.\n\nBeware of the code above; I've not even proven it correct, let alone tested it.\n\nAs for implementing a fair strategy – we can have both versions of the function\nand then randomly decide which node to choose.\n"
  },
  {
    "path": "other/clrs/12/04/01.markdown",
    "content": "> Prove equation (12.3).\n>\n> $$ \\sum_{i=0}^{n-1} \\binom{i+3}{3} = \\binom{n+3}{4} $$\n\nLet's use induction here.\n\nWe'll start with $n=2$ in the base, as it will illustrate the step more clearly:\n\n$$\n    \\sum_{i=0}^{1} \\binom{i+3}{3}\n      = \\binom{3}{3} + \\binom{4!}{3!}\n      = \\frac{3!}{3!} + \\binom{4!}{3!}\n      = \\frac{3 \\cdot 2 \\cdot 1}{3!} + \\frac{4 \\cdot 3 \\cdot 2}{3!}\n      = \\frac{(4 + 1) \\cdot 3 \\cdot 2 \\cdot 1}{3!}\n      = \\frac{4 \\cdot 5 \\cdot 3 \\cdot 2}{4 \\cdot 3!}\n      = \\frac{5!}{4! \\cdot 1!}\n      = \\binom{5}{4}\n      = \\binom{2 + 3}{4}\n$$\n\nFor the step, we do this:\n\n$$\n    \\begin{aligned}\n      \\sum_{i=0}^{n} \\binom{i+3}{3} &= \\sum_{i=0}^{n} \\binom{i+3}{3} \\\\\\\\\n        &= \\sum_{i=0}^{n-1} \\binom{i+3}{3} + \\binom{n+3}{3} \\\\\\\\\n        &= \\binom{n+2}{4} + \\binom{n+3}{3} \\\\\\\\\n        &= \\frac{(n+3)(n+2)(n+1)n}{4!} + \\frac{(n+3)(n+2)(n+1)}{3!} \\cdot \\frac{4}{4} \\\\\\\\\n        &= \\frac{(n+3)(n+2)(n+1)(n + 4)}{4!} \\\\\\\\\n        &= \\binom{n+4}{4}\n    \\end{aligned}\n$$\n"
  },
  {
    "path": "other/clrs/12/04/02.markdown",
    "content": "> Describe a binary search tree on $n$ nodes such that the average depth of a\n> node in the tree $\\Theta(\\lg n)$ but the height of the tree is $\\omega(\\lg\n> n)$. Give an asymptotic upper bound on the height of an $n$-node binary search\n> tree in which the average depth of a node is $\\Theta(\\lg n)$.\n\nThis is a bit weird. Let's consider how to maximize the height of the tree while\nminimizing the average depth. One approach would be having a long\nright-child-only chain of $f(n)$ nodes and a perfect binary tree with the ontop\nwith the remaining $n - f(n)$ nodes.\n\nThe answer, for the upper bound, after some desperate attempts and even more\ndesperate googling, is $O(\\sqrt{n \\lg n})$. Let's prove it.\n\nLet's take the average depth $D$. Let $d_i$ be the depth of the $i$-th node, and\nlet's split the nodes into two sets - $P$ and $Q$, where $P$ are the nodes from\nthe root to a specific node at maximal height, and $Q$ are the rest. That is,\n$P$ is the set of node that form a longest path in the tree.\n\nWe have:\n\n$$\n    D = \\frac{1}{n} \\left( \\sum_{i \\in P} d_i + \\sum_{i \\in Q} d_i \\right)\n      \\ge \\frac{1}{n} \\sum_{i \\in P} d_i\n      = \\frac{1}{n} \\sum_{i = 0}^h i\n      = \\Theta(h^2)\n$$\n\nNow let's assume that $\\O(\\sqrt{n \\lg n})$ is not an upper bound, that is, $h =\n\\omega(\\sqrt{n \\lg n})$.\n\nWe then have:\n\n$$ D = \\frac{1}{n} \\Theta(h^2) = \\frac{1}{n} \\omega(n \\lg n) = \\omega(\\lg n) $$\n\nThis, however, is a contradiction, as we know the average depth is\n$\\Omega(\\lg{n})$, so we can infer that $\\O(\\sqrt{n \\lg n})$ is an upper bound.\n\n"
  },
  {
    "path": "other/clrs/12/04/03.markdown",
    "content": "> Show that the notion of a randomly chosen binary search tree on $n$ keys,\n> where each binary search tree of $n$ keys is equally likely to be chosen, is\n> different from the notion of a randomly built binary search tree given in this\n> section. (_Hint:_ List the possibilities when $n = 3$.)\n\nWith the elements 1, 2 and 3, there are only $5$ possible binary search trees:\n\n    1             1            2           3           3\n      \\             \\        /  \\        /           /\n        2             3     1    3      1          2\n          \\         /                    \\       /\n            3     2                       2     1\n\nThere are, however $3! = 6$ by the definition of the chapter.\n"
  },
  {
    "path": "other/clrs/12/04/04.markdown",
    "content": "> Show that the function $f(x) = 2^x$ is convex.\n\nLike $f'(x) = 2^x \\ln{2}$ and $f''(x) = 2^x \\ln^2 2$ which is positive for all\nreal numbers, thus the function is convex.\n\nThe again, the Instructor Manual solves this without calculus. Key point: learn\ncalculus.\n"
  },
  {
    "path": "other/clrs/12/04/05.markdown",
    "content": "> $\\star$ Consider `RANDOMIZED-QUICKSORT` operating on a sequence of $n$\n> distinct input numbers. Prove that for any constant $k > 0$, all but\n> $\\O(1/n^k)$ of the $n!$ input permutations yield an $\\O(n \\lg n)$ running\n> time.\n\n**UNSOLVED**. Yeah, this formulation is very confusing and I don't get it.\n\nLet's move on.\n"
  },
  {
    "path": "other/clrs/12/problems/01.markdown",
    "content": "## Binary search trees with equal keys\n\n> Equal keys pose a problem for the implementation of binary search trees.\n>\n> <ol type=\"a\">\n>  <li>\n>   What is the asymptotic performance of <code>TREE-INSERT</code> when used\n>   to insert $n$ items with identical keys into an initially empty binary\n>   search tree?\n>  </li>\n> </ol>\n>\n> We propose to improve `TREE-INSERT` by testing before line 5 to determine\n> whether $z.key = x.key$ and by testing before line 11 to determine whether\n> $z.key = x.key$. If equality holds, we implement one of the following\n> strategies. For each strategy, find the asymptotic performance of inserting\n> $n$ items with identical keys into an initially empty binary search tree. (The\n> strategies are described for line 5, in which we compare the keys of $z$ and\n> $x$. Substitute $y$ for $x$ to arrive at the strategies for line 11.)\n>\n> <ol type=\"a\" start=\"2\">\n>  <li>\n>   Keep a boolean flag $x.b$ at node $x$, and set $x$ to either $x.left$ or\n>   $x.right$ based on the value of $x.b$, which alternates between\n>   <code>FALSE</code> and <code>TRUE</code> each time we visit $x$ while\n>   inserting a node with the same key as $x$.\n>  </li>\n>  <li>\n>   Keep a list of nodes with equal keys at $x$, and insert $z$ into the list\n>  </li>\n>  <li>\n>   Randomly set $x$ to either $x.left$ or $x.right$. (Give the worst case\n>   performance and informally derive the expected running time.\n>  </li>\n> </ol>\n\nTo begin with (a), the implementation in the book always insert to the right of\na leaf node, which means it needs to iterate over the existing node, which means\neach subsequent insert will perform an additional operation, yielding\n$\\Theta(n^2)$.\n\n### First strategy\n\nThis is interesting. If you work it out through inserting, you'll notice that it\nfills each level before advancing to the next one, building a perfect binary\ntree. The time is therefore going to be $\\Theta(n \\lg n)$.\n\n### Second strategy\n\nAssuming a doubly-linked list or inserting in the beginning of the list, this\nwill result in $\\Theta(n)$ time, as each insert is going to be $\\O(1)$ (constant\ntime to find the root, and constant time to insert in the list).\n\n### Third strategy\n\nThe worst case performance is clearly $\\Theta(n^2)$.\n\nReasoning informally, we'll pick the left and right subtree roughly the same\namount of time, which means the elements will roughly be equal in the two main\nbranches. Applying this logic recursively, we end up with a roughly balanced\ntree, which means $\\Theta(n \\lg n)$ expected time.\n"
  },
  {
    "path": "other/clrs/12/problems/02.c",
    "content": "#include <stdlib.h>\n#include <stdio.h>\n\nstruct node_t {\n    struct node_t *zero;\n    struct node_t *one;\n    const char *str;\n};\n\ntypedef struct node_t node_t;\n\ntypedef struct {\n    node_t *root;\n} radix_tree_t;\n\ntypedef void (*callback_t)(const char *);\n\nnode_t *make_node() {\n    node_t *new = malloc(sizeof(node_t));\n    new->zero = NULL;\n    new->one = NULL;\n    new->str = NULL;\n    return new;\n}\n\nradix_tree_t *make_radix_tree() {\n    radix_tree_t *new = malloc(sizeof(radix_tree_t));\n    new->root = make_node();\n    return new;\n}\n\nvoid insert(radix_tree_t *tree, const char *string) {\n    const char *s = string;\n    node_t *current = tree->root;\n\n    while (*s != '\\0') {\n        if (*s == '0') {\n            if (!current->zero) current->zero = make_node();\n            current = current->zero;\n        } else if (*s == '1') {\n            if (!current->one) current->one = make_node();\n            current = current->one;\n        } else {\n            fprintf(stderr, \"Invalid string: %s\", s);\n            exit(1);\n        }\n        s++;\n    }\n\n    current->str = string;\n}\n\nvoid walk(node_t *node, callback_t callback) {\n    if (node->str) callback(node->str);\n    if (node->zero) walk(node->zero, callback);\n    if (node->one) walk(node->one, callback);\n}\n\nvoid walk_sorted(radix_tree_t *tree, callback_t callback) {\n    walk(tree->root, callback);\n}\n"
  },
  {
    "path": "other/clrs/12/problems/02.markdown",
    "content": "## Radix trees\n\n> Given two strings $a = a_0 a_1 \\ldots a_p$ and $b = b_0 b_1 \\ldots b_p$, where\n> each $a_i$ and each $b_j$ is in some ordered set of characters, we say that\n> string $a$ is **lexicographically less than** string $b$ if either:\n>\n> 1. there exists an integer $j$, where $0 \\le j \\le \\min(p, q)$, such that $a_i\n>    = b_i$ for all $i = 0, 1, \\ldots, j - 1$ and $a_j < $b_j$, or\n> 2. $p < q$ and $a_i = b_i$ for all $i = 0, 1, \\ldots p$.\n>\n> For example, if $a$ and $b$ are bit strings, then $10100 < 10110$ by rule 1\n> (letting $j = 3$) and $10100 < 101000$ by rule 2. This ordering is similar to\n> that used in English-language dictionaries.\n>\n> The **radix tree** data structure shown in Figure 12.5 stores the bit strings\n> $1011$, $10$, $011$, $100$, and $0$. When searching for a key $a = a_0 a_1\n> \\ldots a_p$, we go left at node of depth $i$ if $a_i = 0$ and right if $a_i =\n> 1$. Let $S$ be a set of distinct bit strings whose lengths sum to $n$. Show\n> how to use a radix tree to sort $S$ lexicographically in $\\Theta(n)$ time. For\n> example, in Figure 12.5, the output of the sort should be the sequence $0,\n> 011, 10, 100, 1011$.\n\nThis is as simple as building the tree and then doing a preorder walk. Each\ninsertion will take $m$ steps, where $m$ is the length of the string being\ninserted. Given that upper nodes sort lexicographically before lower nodes, and\nzeroes sort before ones, we need to report the parent before the children, and\nthe left subtree before the right.\n"
  },
  {
    "path": "other/clrs/12/problems/02.test.c",
    "content": "#include \"02.c\"\n#include \"../../build/ext/test.h\"\n\n#include <string.h>\n#include <stdlib.h>\n\n#define N 10\nconst char *actual[N];\nint count = 0;\n\nvoid append(const char *s) {\n    actual[count++] = s;\n}\n\nTEST(sort) {\n    char *s1011 = \"1011\";\n    char *s10 = \"10\";\n    char *s011 = \"011\";\n    char *s100 = \"100\";\n    char *s0 = \"0\";\n\n    radix_tree_t *tree = make_radix_tree();\n\n    insert(tree, s1011);\n    insert(tree, s10);\n    insert(tree, s011);\n    insert(tree, s100);\n    insert(tree, s0);\n\n    walk_sorted(tree, append);\n\n    ASSERT_TRUE(strcmp(s0, actual[0]) == 0);\n    ASSERT_TRUE(strcmp(s011, actual[1]) == 0);\n    ASSERT_TRUE(strcmp(s10, actual[2]) == 0);\n    ASSERT_TRUE(strcmp(s100, actual[3]) == 0);\n    ASSERT_TRUE(strcmp(s1011, actual[4]) == 0);\n}\n"
  },
  {
    "path": "other/clrs/12/problems/03.markdown",
    "content": "## Average node depth in a randomly built binary search tree\n\n> In this problem, we prove that the average depth of a node in a randomly built\n> binary search tree with $n$ nodes is $\\O(\\lg n)$. Although this result is\n> weaker than that of Theorem 12.4, the technique we shall use reveals a\n> surprising similarity between the building of a binary search tree and the\n> execution of `RANDOMIZED-QUICKSORT` from Section 7.3.\n>\n> We define the **total path length** $P(T)$ of a binary search tree as the sum,\n> over all nodes $x$ in $T$, of the depth of node $x$, which we denote by $d(x,\n> T)$.\n>\n> <ol type=\"a\">\n>  <li>\n>   Argue that the average depth of a node in $T$ is\n>   $$ \\frac{1}{n}\\sum_{x \\in T}^{n-1} d(x, T) = \\frac{1}{n} P(T) $$\n>  </li>\n> </ol>\n>\n> Thus, we wish to show that the expected value of $P(T)$ is $O(n \\lg n)$.\n> <ol type=\"a\" start=\"2\">\n>  <li>\n>   Let $T_L$ and $T_R$ denote the left and right subtrees of tree $T$,\n>   respectively. Argue that if $T$ has $n$ nodes, then\n>\n>   $$ P(T) = P(T_L) + P(T_R) + n - 1 $$\n>  </li>\n>  <li>\n>   Let $P(n)$ denote the average total path length of a randomly built binary\n>   search tree with $n$ nodes. Show that:\n>\n>   $$ P(n) = \\frac{1}{n} \\sum_{i=0}^{n-1}(P(i) + P(n-i-1) + n - 1) $$\n>  </li>\n>  <li>\n>   Show how to rewrite $P(n)$ as\n>   $$ P(n) = \\frac{2}{n} \\sum_{k=1}^{n-1} P(k) + \\Theta(n) $$\n>  </li>\n>  <li>\n>   Recalling the alternative analysis of the randomized version of quicksort\n>   given in Problem 7.3, conclude that $P(n) = \\O(n \\lg n)$.\n>  </li>\n> </ol>\n>\n> At each recursive invocation of quicksort, we choose a random pivot element to\n> partition the set of elements being sorted. Each node of a binary search tree\n> partitions the set of elements that fall into the subtree rooted at that node.\n>\n> <ol type=\"a\" start=\"6\">\n>  <li>\n>   Describe an implementation of quicksort in which the comparisons to sort a\n>   set of elements are exactly the same as the comparisons to insert the\n>   elements into a binary search tree. (The order in which comparisons are made\n>   may differ, but the same comparisons must occur.)\n>  </li>\n> </ol>\n\n### Average depth of the node\n\nThis is literally by definition.\n\n### Total path length expressed through subtrees\n\nLet's say that $T_L$ contains $l$ nodes. If we add a new node above $T_L$ as a\nnew root of the tree, each of the $l$ nodes will get one extra edge connecting\nit to the root. A similar argument can be made for $T_R$ with $r$ nodes. Thus,\nwhen we take two trees, $T_L$ and $T_R$ and make them the left and right\nsubtrees of a new tree, we add $l + r$ to the total path length of both trees,\nas each node now has an extra edge to the root. Observe that if the new tree has\n$n$ elements, then $n - 1 = l + r$. Hence we have that:\n\n$$ P(T) = P(T_L) + P(T_R) + n - 1 $$\n\n### Average total path length of randomly built tree\n\nWhen we're building the tree randomly, each element of $\\\\{1, 2, \\ldots, n\\\\}$\nis equally likely to be the root. This follows pretty straightforwardly from the\nlast two parts.\n\n\n### Rewritten expression\n\nWe need to observe that each $P(i)$ appears twice because of the sum. That is:\n\n$$\n    \\begin{aligned}\n    P(n) &= \\frac{1}{n} \\sum_{i=0}^{n-1}(P(i) + P(n-i-1) + n - 1) \\\\\\\\\n         &= \\frac{1}{n} \\sum_{i=0}^{n-1}(P(i) + P(n-i-1)) + \\frac{1}{n} \\sum_{i=0}^{n-1}(n - 1) \\\\\\\\\n         &= \\frac{1}{n} \\Big( P(0) + P(n - 1) + P(1) + P(n - 2) + \\ldots + P(n - 2) + P(1) + P(n - 1) + P(0) \\Big) + \\Theta(n) \\\\\\\\\n         &= \\frac{2}{n} \\sum_{k=0}^{n-1} P(k) \\\\\\\\\n         &= \\frac{2}{n} \\sum_{k=1}^{n-1} P(k) \\\\\\\\\n    \\end{aligned}\n$$\n\nThe last step holds because $P(0) = 0$.\n\n### Upper bound\n\nProblem 7.3 established that:\n\n$$ \\sum_{k=2}^{n-1}k\\lg{k} \\le \\frac{1}{2}n^2\\lg{n} - \\frac{1}{8}n^2 $$\n\nKeeping that in mind, let's use the substitution method to establish an upper\nbound on $P(n)$. Let's assume $O(n\\lg{n})$ and plug in $an\\lg{n} + b$.\n\n$$\n    \\begin{aligned}\n      P(n) &= \\frac{2}{n} \\sum_{k=1}^{n-1}P(k) + \\Theta(n) \\\\\\\\\n           &= \\frac{2}{n} \\sum_{k=2}^{n-1}P(k) + \\Theta(n) && \\text{(because }P(1) = 0 \\text{)} \\\\\\\\\n           &\\le \\frac{2}{n} \\sum_{k=2}^{n-1}(ak\\lg{k} + b) + \\Theta(n) \\\\\\\\\n           &= \\frac{2a}{n} \\sum_{k=2}^{n-1}(k\\lg{k}) + \\frac{2b}{n}(n - 1) + \\Theta(n) \\\\\\\\\n           &\\le \\frac{2a}{n} \\sum_{k=2}^{n-1}(k\\lg{k}) + 2b + \\Theta(n) \\\\\\\\\n           &\\le \\frac{2a}{n} \\left( \\frac{1}{2} n^2 \\lg{n} - \\frac{1}{8} n^2 \\right) + 2b + \\Theta(n) \\\\\\\\\n           &= an \\lg{n} - \\frac{4}{a} n + 2b + \\Theta(n) \\\\\\\\\n           &= an \\lg{n} + b + \\left(\\Theta(n) + b - \\frac{4}{a}n\\right) \\\\\\\\\n           &\\le an \\lg{n} + b\n    \\end{aligned}\n$$\n\nIf we choose a large enough $a$ so $\\frac{a}{4}n \\ge \\Theta(n) + b$. Chapter 4\nadvises against asymptotic notation when using the substitution method, but I\nlike to live dangerously.\n\n### Describe an implementation of quicksort(?)\n\nIn quicksort, once a pivot is chosen, every element is compared against it.\nSimilarly, once the root is chosen, every other element is compared against it.\nApplying this thinking recursively, we end up at the same number of comparisons.\n"
  },
  {
    "path": "other/clrs/12/problems/04.markdown",
    "content": "## Number of different binary trees\n\n> Let $b_n$ denote the number of different binary trees with $n$ nodes. In this\n> problem you will find a formula for $b_n$, as well as an asymptotic estimate.\n>\n> <ol type=\"a\">\n>   <li><p>Show that $b = 1$ and that, for $n \\ge 1$,\n>   $$ b_n = \\sum_{k=0}^{n-1} b_k b_{n-1-k} $$\n>   <li><p>Referring to <a href=\"/04/problems/04.html\">Problem 4-4</a> for the\n>   definition of a generating function, let $B(x)$ be the generating function\n>   $$ B(x) = \\sum_{n=0}^{\\infty} b_n x^n $$\n>   Show that $B(x) = xB(x)^2 + 1$, and hence one way to express $B(x)$ in\n>   closed form is\n>   $$ B(x) = \\frac{1}{2x}(1 - \\sqrt{1 - 4x}) $$\n> </ol>\n>\n> The **Taylor expansion** of $f(x)$ around the point $x = a$ is given by\n>\n> $$ f(x) = \\sum_{k=0}^{\\infty} \\frac{f^{(k)}(a)}{k!}(x - a)^k $$\n>\n> where $f^{(k)}(x)$ is the $k$th derivative of $f$ evaluated at $x$.\n>\n> <ol type=\"a\" start=\"3\">\n>   <li><p>Show that\n>   $$ b_n = \\frac{1}{n + 1} \\binom{2n}{n} $$\n>   (the $n$th <b>Catalan number</b>) by using the Taylor expansion of $\\sqrt{1 -\n>   4x}$ around $x = 0$. (If you wish, instead of using the Taylor expansion,\n>   you may use the generalization of the binomial expansion (C.4) to\n>   nonintegral exponents $n$, where for any real number $n$ and for any integer\n>   $k$, we interpret $\\binom{n}{k}$ to be $n(n-1)\\ldots(n-k+1)/k!$ if $k \\ge\n>   0$, and 0 otherwise).\n>   <li><p>Show that\n>   $$ b_n = \\frac{4^n}{\\sqrt{\\pi} n^{3/2}} (1 + O(1/n)) $$\n> </ol>\n\n### a. Calculating $b_0$ and $b_n$\n\nThere is exactly one tree with 0 nodes (the empty tree), therefore $b_0 = 1$.\n\nWhen we construct a tree with $n$ nodes, we have $n$ choices for the root, and\nthe remaining $n - 1$ nodes will be either in the left subtree or the right\nsubtree. This is exactly the given formula:\n\n$$ b_n = \\sum_{k=0}^{n-1} b_k b_{n-1-k} $$\n\nWhere $k$ is the number of elements that are smaller than the chosen root and $n\n- 1 - k$ is the number of elements larger than the chosen root.\n\n### b. Generating function\n\nThis is trippy.\n\n$$\n    \\begin{aligned}\n    xB(x) + 1 &= 1 + x \\Big( b_0 x^0 + b_1 x^1 + b_2 x^2 + \\ldots \\Big)^2 \\\\\\\\\n              &= 1 + x \\Big( b_0^2 + x^0 + (b_0 b_1 + b_1 b_0) x^1 + (b_0 b_2 + b_1 b_1 + b_2 b_0) x^2 + \\ldots \\Big) \\\\\\\\\n              &= 1 + x \\Big( \\sum_{k=0}^{0} b_k b_{0-k} x^0 + \\sum_{k=0}^{1} b_k b_{1-k} x^1 + \\sum_{k=0}^{2} b_k b_{2-k} x^2 + \\ldots \\Big) \\\\\\\\\n              &= 1 + x \\Big( \\sum_{j=0}^{\\infty} \\sum_{k=0}^{j} b_k b_{j-k} x^j \\Big) \\\\\\\\\n              &= 1 + x \\Big( \\sum_{j=0}^{\\infty} \\sum_{k=0}^{j+1-1} b_k b_{j+1-1-k} x^j \\Big) \\\\\\\\\n              &= 1 + \\sum_{j=0}^{\\infty} \\sum_{k=0}^{j+1-1} b_k b_{j+1-1-k} x^{j+1} \\\\\\\\\n              &= 1 + \\sum_{j=0}^{\\infty} b_{j+1} x^{j+1} && \\big( \\text{because of (a)} \\big)\\\\\\\\\n              &= 1 + \\sum_{k=1}^{\\infty} b_{k} x^{k} && \\big( \\text{substituting } k = j + 1 \\big)\\\\\\\\\n              &= b_0 x^0 + \\sum_{k=1}^{\\infty} b_{k} x^{k} \\\\\\\\\n              &= \\sum_{k=0}^{\\infty} b_{k} x^{k} \\\\\\\\\n              &= B(x)\n    \\end{aligned}\n$$\n\nThen, to verify the possible solution, we just substitute:\n\n$$\n    \\begin{aligned}\n    xB(x)^2 + 1 &= x \\Big( \\frac{1}{2x}(1 - \\sqrt{1 - 4x}) \\Big)^2 + 1 \\\\\\\\\n                &= \\frac{1}{4x}(1 - 2 \\sqrt{1 - 4x} + 1 - 4x) + 1 \\\\\\\\\n                &= \\frac{1}{4x}(2 - 2 \\sqrt{1 - 4x}) - \\frac{4x}{4x} + 1 \\\\\\\\\n                &= \\frac{1}{2x}(1 - \\sqrt{1 - 4x}) \\\\\\\\\n                &= B(x)\n    \\end{aligned}\n$$\n\n### c. Taylor series expansion\n\nUgh!\n\nAlright, let's calculate some derivatives for $f(x) = \\sqrt{1 - 4x} = (1 -\n4x)^{1/2}$.\n\n$$\n    \\begin{aligned}\n    f^{(1)}(x) &= \\Big[ (1 - 4x)^{1/2} \\Big]' = \\frac{1}{2} (1 - 4x)^{-1/2} (1 - 4x)' = -2 (1 - 4x)^{-1/2} = \\frac{-2}{(1 - 4x)^{1/2}} \\\\\\\\\n    f^{(2)}(x) &= \\Big[ -2 (1 - 4x)^{-1/2} \\Big]' = (- \\frac{1}{2})(-2)(1 - 4x)^{-3/2}(1 - 4x)' = -4(1 - 4x)^{-3/2} = \\frac{-3}{(1 - 4x)^{3/2}} \\\\\\\\\n    f^{(3)}(x) &= \\Big[ -4 (1 - 4x)^{-3/2} \\Big]' = \\frac{3 \\cdot 4}{2}(1 - 4x)^{-5/2}(1 - 4x)' = -24(1 - 4x)^{-5/2} = \\frac{-24}{(1 - 4x)^{5/2}} \\\\\\\\\n    f^{(4)}(x) &= \\Big[ -24 (1 - 4x)^{-5/2} \\Big]' = \\frac{24 \\cdot 5}{2}(1 - 4x)^{-7/2}(1 - 4x)' = -240(1 - 4x)^{-7/2} = \\frac{-240}{(1 - 4x)^{7/2}} \\\\\\\\\n    f^{(5)}(x) &= \\Big[ -24 (1 - 4x)^{-7/2} \\Big]' = \\frac{240 \\cdot 7}{2}(1 - 4x)^{-9/2}(1 - 4x)' = -3360(1 - 4x)^{-9/2} = \\frac{-3360}{(1 - 4x)^{9/2}} \\\\\\\\\n    \\end{aligned}\n$$\n\nLet's observe that for $x = 0$ the denominator is going to be $1$, so we're\ninterested only in the numerator. Let's also notice that the numerator $n_k$ for\nthe $k$-th derivative is:\n\n$$ n_k = - 2^k \\prod_{i=0}^{k-2} (2k + 1) = - 2^k \\frac{(2(k - 1))!}{2^{k-1}(k-1)!} = - \\frac{2(2(k - 1))!}{(k-1)!} $$\n\nThus, the Taylor expansion is:\n\n$$ f(x) = \\sum_{k=0}^{\\infty} - \\frac{n_k}{k!}x^k = \\sum_{k=0}^{\\infty} - \\frac{2(2(k-1))!}{k!(k-1)!}x^k$$\n\nOr\n\n$$ f(x) = 1 - 2x - 2x^2 - 4x^3 - 10x^4 - 28x^5 - \\ldots $$\n\nSubstituting that into $B(x)$, we get:\n\n$$\n    \\begin{aligned}\n    B(x) &= \\frac{1}{2x}(1 - f(x)) \\\\\\\\\n         &= \\frac{1}{2x} (1 - 1 + 2x + 2x^2 + 4x^3 + 10x^4 + 28x^5 + \\ldots) \\\\\\\\\n         &= 1 + x + 2x^2 + 5x^3 + 14x^4 + \\ldots \\\\\\\\\n         &= \\sum_{k=0}^{\\infty} \\frac{(2k)!}{(k + 1)!k!} x^k \\\\\\\\\n         &= \\sum_{k=0}^{\\infty} \\frac{1}{k+1} \\frac{(2k)!}{k!k!} x^k \\\\\\\\\n         &= \\sum_{k=0}^{\\infty} \\frac{1}{k+1} \\binom{2k}{k} x^k\n    \\end{aligned}\n$$\n\nWhich illustrates that:\n\n$$ b_k = \\frac{1}{n+1} \\binom{2k}{k} $$\n\n### d. Upper bound\n\nWe use Stirling's approximation,\n\n$$ n! = \\sqrt{2 \\pi n}\\Big(\\frac{n}{e}\\Big)^n \\Bigg(1 + \\Theta \\Big( \\frac{1}{n} \\Big) \\Bigg) = \\sqrt{2 \\pi n} n^n e^{-n} (1 + \\Theta(1/n)) $$\n\nand go on to produce some very ugly math:\n\n$$\n    \\begin{aligned}\n    b_n &= \\frac{1}{n+1}\\frac{(2n)!}{n!n!} \\\\\\\\\n        &= \\frac{1}{n+1}\\frac{ \\sqrt{4 \\pi n}(2n)^{2n} e^{-2n} (1 + \\Theta(1/n)) }{2 \\pi n n^{2n} e^{-2n} (1 + \\Theta(1/n)) } \\\\\\\\\n        &= \\frac{1}{n+1}\\frac{ \\sqrt{4 \\pi n} 4^{n} n^{2n} (1 + \\Theta(1/n)) }{2 \\pi n n^{2n} (1 + \\Theta(1/n)) } \\\\\\\\\n        &= \\frac{1}{n+1}\\frac{ 2 \\sqrt{\\pi n} 4^{n}  (1 + \\Theta(1/n)) }{2 \\pi n (1 + \\Theta(1/n)) } \\\\\\\\\n        &= \\frac{1}{n+1}\\frac{ 4^{n} (1 + \\Theta(1/n)) }{\\sqrt{\\pi n} (1 + \\Theta(1/n)) } \\\\\\\\\n        &= \\frac{ 4^n }{\\sqrt{\\pi} n^{3/2} } (1 + \\Theta(1/n))\n    \\end{aligned}\n$$\n"
  },
  {
    "path": "other/clrs/13/01/01.draw.py",
    "content": "import drawing\n\nB = drawing.RedBlackTrees.Black\nR = drawing.RedBlackTrees.Red\n\ntree01 = B(8,\n            R(4,\n                B(2, R(1), R(3)),\n                B(6, R(5), R(7))),\n            R(12,\n                B(10, R(9), R(11)),\n                B(14, R(13), R(15)))).dot()\n\ntree02 = B(8,\n            B(4,\n                R(2, B(1), B(3)),\n                R(6, B(5), B(7))),\n            B(12,\n                R(10, B(9), B(11)),\n                R(14, B(13), B(15)))).dot()\n\n\ntree03 = B(8,\n            B(4,\n                B(2, B(1), B(3)),\n                B(6, B(5), B(7))),\n            B(12,\n                B(10, B(9), B(11)),\n                B(14, B(13), B(15)))).dot()\n\ndrawings = [\n    {'name': 'Black-height 2', 'dot': tree01, 'display': False},\n    {'name': 'Black-height 3', 'dot': tree02, 'display': False},\n    {'name': 'Black-height 4', 'dot': tree03, 'display': False},\n]\n\ndrawing.process(drawings)\n"
  },
  {
    "path": "other/clrs/13/01/01.markdown",
    "content": "> In the style of Figure 13.1(a), draw the complete binary search tree of height\n> 3 on the keys ${1, 2, \\ldots, 15}$. Add the $\\mathrm{NIL}$ leaves and color\n> the nodes in three different ways such that the black-heights of the resulting\n> red-black trees are 2, 3 and 4.\n\nHere's a tree with black-height $2$.\n\n![](13/01/01.drawing.01.svg)\n\nThis is the most \"balanced\" tree possible.\n\nProperty 4 is the most limiting one – red nodes need to have black children.\nThere's nothing preventing a black node to have black children. Thus, one way to\nreach black-height $3$ is:\n\n![](13/01/01.drawing.02.svg)\n\nFinally, to get black-height of $4$, all the nodes need to be black:\n\n![](13/01/01.drawing.03.svg)\n"
  },
  {
    "path": "other/clrs/13/01/02.draw.py",
    "content": "import drawing\n\nB = drawing.RedBlackTrees.Black\nR = drawing.RedBlackTrees.Red\nG = drawing.RedBlackTrees.Gray\n\ntree = B(\n    26,\n    R(17,\n        B(14,\n            R(10,\n                B(7, R(3)),\n                B(12)),\n            B(16, R(15))),\n        B(21,\n            B(19, None, R(20)),\n            B(23))),\n    B(41,\n        R(30,\n            B(28),\n            B(38,\n                R(35, None, G(36)),\n                R(39))),\n        B(47)))\n\ndrawings = [\n    {'name': 'Figure 13.1', 'dot': tree.dot(), 'display': False},\n]\n\ndrawing.process(drawings)\n"
  },
  {
    "path": "other/clrs/13/01/02.markdown",
    "content": "> Draw the red-black tree that results after `TREE-INSERT` is called on the tree\n> in Figure 13.1 with key $36$. If the inserted node is colored red, is the\n> resulting tree a red-black tree? What if it is colored black?\n\nThe new element is going to be the gray one:\n\n![](13/01/02.drawing.01.svg)\n\nIf we color it red, it will violate property 4, that is, red nodes need to have\nblack children. In this case, it's parent, 35 is red, so it must be black.\n\nIf we color it black, it will violate property 5. The path to the descendants of\n36 from the root will have 4 black nodes, but the one to the descendants of 39\nwill have 3.\n\nThat is, `TREE-INSERT` does not produce a valid red-black tree in this case,\nregardless of how we color the node.\n"
  },
  {
    "path": "other/clrs/13/01/03.markdown",
    "content": "> Let us define a **relaxed red-black tree** as a binary search tree that\n> satisfies red-black properties 1, 3, 4, and 5. In other words, the root may be\n> either red or black. Consider a relaxed red-black tree $T$ whose root is red.\n> If we color the root of $T$ black but make no other changes to $T$, is the\n> resulting tree a red-black tree?\n\nYes. Checking the properties:\n\n1. **Every node is either red or black**. Holds.\n2. **The root is black.** Holds after coloring.\n3. **Every leaf ($\\mathrm{NIL}$) is black.** Holds, since the leaves were black\n   in the relaxed tree.\n4. **If a node is red, then both its children are black**. Holds. The only\n   potential candidate to break the property is the root, which is now black,\n   and has no parents.\n5. **For each node, all simple paths from the node to descendant leaves contain\n   the same number of black nodes**. Continues to hold, as the all paths from\n   the root get a potential extra black node and the rest remain unchanged.\n"
  },
  {
    "path": "other/clrs/13/01/04.draw.py",
    "content": "import drawing\n\nB = drawing.RedBlackTrees.Black\nR = drawing.RedBlackTrees.Red\n\ntree = B(4,\n        R(2, B(1), B(3)),\n        R(6, B(5), B(7)))\n\ndrawings = [\n    {'name': 'Max degree', 'dot': tree.dot(nils=False), 'display': False},\n]\n\ndrawing.process(drawings)\n"
  },
  {
    "path": "other/clrs/13/01/04.markdown",
    "content": "> Suppose that we \"absorb\" every red node in a red-black tree into its black\n> parent, so that the children of the red node become children of the black\n> parent. (Ignore what happens to the keys.) What are the possible degrees a of\n> black node after all its red children are absorbed? What can you say about the\n> depths of the leaves of the resulting tree?\n\nTwo things are clear from the properties:\n\n1. Red nodes have black children.\n2. Red nodes have black parents.\n\nBoth follow from property 4, which implies that a red node cannot be a parent of\nanother red node. Alternatively put, each path to a leaf may go through\nsubsequent black nodes, but no two red nodes in a row.\n\nThis means that the most complicated subtree is going to look like this:\n\n![](13/01/04.drawing.01.svg)\n\nIf we \"absorb\" the red nodes, node 4 will end up having four children (1, 3, 5,\n7), that is, a degree of $4$ and no more.\n\nThe depth of the resulting leaves can at most halve. That is, if a leaf had\ndepth $n$, it's new depth is going to be at least $\\lceil n / 2 \\rceil$.\n"
  },
  {
    "path": "other/clrs/13/01/05.markdown",
    "content": "> Show that the longest simple path from a node $x$ in a red-black tree to a\n> descendent leaf has length at most twice that of the shortest simple path from\n> node $x$ to a descendant leaf.\n\nBoth the shortest path $s$ and the longest path $l$ will have the same number of\nblack nodes, as per property 5. Because of property 4, each red node must have a\nblack parent and black children. This means that the number of red nodes must be\nless than or equal to the number of black nodes in any path in a valid red-black\ntree.\n\nThe biggest difference then, can be obtained if $s$ contains only black nodes\nand $l$ contains the same number of black nodes with the maximum possible red\nnodes added to it, which is $2s$.\n"
  },
  {
    "path": "other/clrs/13/01/06.markdown",
    "content": "> What is the largest possible number of internal nodes in a red-black tree with\n> black height $k$? What is the smallest possible number.\n\nAs discussed in the previous two exercises, there can be no more red nodes than\nblack nodes.\n\nThe smallest possible number will be obtained if all the nodes are black, that\nis $2^k - 1$.\n\nThe largest possible number will be obtained if we have a layer of red nodes,\nfollowed by a layer of black nodes, producing a tree of height $2k$, and $2^{2k}\n- 1$ nodes.\n"
  },
  {
    "path": "other/clrs/13/01/07.draw.py",
    "content": "import drawing\n\nB = drawing.RedBlackTrees.Black\nR = drawing.RedBlackTrees.Red\n\ntree = B(8,\n        R(4,\n            B(2, R(1), R(3)),\n            B(6, R(5), R(7))),\n        R(12,\n            B(10, R(9), R(11)),\n            B(14, R(13), R(15))))\n\ndrawings = [\n    {'name': 'Biggest ratio', 'dot': tree.dot(nils=False), 'display': False},\n]\n\ndrawing.process(drawings)\n"
  },
  {
    "path": "other/clrs/13/01/07.markdown",
    "content": "> Describe a red-black tree on $n$ keys that realizes the largest possible ratio\n> of red internal nodes to black internal nodes. What is this ratio? What tree\n> has the smallest possible ratio, and what is the ratio?\n\nThe math can get quite complicated if $n$ is not one less than a power of $2$.\nReasoning informally:\n\nThe smallest possible ratio is obtained by black-only nodes and is going to be\n$0$.\n\nThe largest possible ratio is obtained by each black node having two red\nchildren, and is going to be $2$. Here's an illustration:\n\n![](13/01/07.drawing.01.svg)\n\nThere are 5 black internal nodes and 10 red internal nodes, making a ratio of\n$2$.\n"
  },
  {
    "path": "other/clrs/13/02/01.markdown",
    "content": "> Write the pseudocode for `RIGHT-ROTATE`.\n\nI'm pretty sure I'll end up implementing rotations in C in the later exercises,\nso I'm gonna wing it with the pseudocode here:\n\n    RIGHT-ROTATE(T, y)\n        x = y.left\n        y.left = x.right\n        if x.right != T.nil\n            x.right.p = y\n        x.p = y.p\n\n        if y.p == T.nil\n            T.root = x\n        elseif y == y.p.left\n            y.p.left = x\n        else\n            y.p.right = x\n        x.right = y\n        y.p = x\n\nI've chosen to name the variable `y` to match the figure in the text.\n"
  },
  {
    "path": "other/clrs/13/02/02.markdown",
    "content": "> Argue that in every $n$-node binary search tree, there are exactly $n-1$\n> possible rotations.\n\nThere is a very simple argument to illustrate this.\n\nEach rotation is possible along an internal edge from a child to a parent. In a\ntree of $n$ nodes, there are at exactly $n - 1$ internal edges (each node has a\nparent, apart from the root). Thus, there are only $n - 1$ possible rotations.\n"
  },
  {
    "path": "other/clrs/13/02/03.markdown",
    "content": "> Let $a$, $b$, and $c$ be arbitrary nodes in subtrees $\\alpha$, $\\beta$ and\n> $\\gamma$, respectively, in the left tree of Figure 13.2. How do the depths of\n> $a$, $b$, and $c$ change when a left rotation is performed on node $x$ in the\n> figure?\n\n* $b$ retains its depth.\n* $a$'s depth is increased by one.\n* $c$'s depth is decreased by one.\n"
  },
  {
    "path": "other/clrs/13/02/04.markdown",
    "content": "> Show that any arbitrary $n$-node binary search tree can be transformed into\n> any other arbitrary $n$-node binary search tree using $\\O(n)$ rotations.\n> (_Hint_: First show that at most $n-1$ right rotations suffice to transform\n> the tree into a right-going chain.)\n\nAn informal argument:\n\nLet's that the right-going chain of nodes in the tree, that is, nodes that can\nbe reached by following only right-going edges. This right-going chain either\ncontains the whole tree, or there are some nodes that are left children of the\nchain. If we perform a right rotation on such a child and its parent in the\nchain, the length of the chain increases by one and the number of nodes not in\nthe chain gets reduced by one. We can keep iterating, until the tree is a\nright-going chain. There would be at most $n - 1$ nodes, so we can perform this\nin $\\O(n)$ rotations.\n\nIt should be noted that this operation is reversible. That is, we can apply the\nsymmetric left rotation in reverse order to obtain the original tree from the\nresulting right-going chain. Since there is only one possible right-going chain\n(sorting the elements in increasing order), we can transform any tree to another\nby first transforming it to a right-going chain, and then applying the reverse\ntransformation that the target tree will need to become a right-going chain.\n"
  },
  {
    "path": "other/clrs/13/02/05.markdown",
    "content": "> $\\star$ We say that a binary search tree $T_1$ can be **right-converted** to a\n> binary search tree $T_2$ if it is possible to obtain $T_2$ from $T_1$ via a\n> series of calls to `RIGHT-ROTATE`. Give an example of two trees $T_1$ and\n> $T_2$ such that $T_1$ cannot be right-converted to $T_2$. Then, show that if a\n> tree $T_1$ can be right-converted to $T_2$, it can be right-converted using\n> $\\O(n^2)$ calls to `RIGHT-ROTATE`.\n\nHere are two trees, the second of which can't be produced by right-rotating the\nright:\n\n       1             2\n         \\         /\n           2     1\n\nWe need a left rotation here.\n\nMore specifically, right rotations can only decrease the value of the root, but\nnot increase it.\n\nNow, reasoning very informally, and making some unverified assumptions, we can\nconvert $T_1$ to $T_2$ by first doing $\\O(n)$ right rotations to get the roots\nto match, and then performing right rotations on the two sub-trees recursively\nto position their roots. An upper bound of this approach (assuming it works)\nwill be $\\O(n^2)$.\n"
  },
  {
    "path": "other/clrs/13/03/01.markdown",
    "content": "> In line 16 of `RB-INSERT`, we set the color of the newly inserted node $z$ to\n> red. Observe that if we had chosen to set $z$'s color to black, then property\n> 4 of a red-black tree would not be violated. Why didn't we choose to set $z$'s\n> color to black?\n\nIf we color it black, we will violate property 5, namely that all paths have the\nsame number of black nodes. This would be a harder invariant to reintroduce.\n"
  },
  {
    "path": "other/clrs/13/03/02.draw.py",
    "content": "import os.path as path\nimport drawing\n\nexec(open(path.join(path.dirname(__file__), '02.py')).read())\n\nB = drawing.RedBlackTrees.Black\nR = drawing.RedBlackTrees.Red\n\n\ndef dot(tree):\n    def convert(node, nil):\n        if node is nil:\n            return None\n\n        cons = R if node.color == Color.RED else B\n        left = convert(node.left, nil)\n        right = convert(node.right, nil)\n\n        return cons(node.key, left, right)\n\n    return convert(tree.root, tree.nil).dot()\n\ntree = Tree()\ndrawings = []\n\nfor n in [41, 38, 31, 12, 19, 8]:\n    tree.insert(n)\n    drawings.append({'name': f'After inserting {n}', 'dot': dot(tree), 'display': True})\n\ndrawing.process(drawings)\n"
  },
  {
    "path": "other/clrs/13/03/02.markdown",
    "content": "> Show the red-black trees that result after successfully inserting the keys\n> $41, 38, 31, 12, 19, 8$ into an initially empty red-black tree.\n\nThis was a curious exercise. It was worth doing this on a piece of paper and\nthen writing the code to verify that it works.\n"
  },
  {
    "path": "other/clrs/13/03/02.py",
    "content": "from enum import Enum\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nclass Node:\n    def __init__(self, color, key, parent, left, right):\n        self.color = color\n        self.key = key\n        self.parent = parent\n        self.left = left\n        self.right = right\n\n\nclass Tree:\n    def __init__(self):\n        self.nil = Node(Color.BLACK, None, None, None, None)\n        self.nil.parent = self.nil\n        self.nil.left = self.nil\n        self.nil.right = self.nil\n\n        self.root = self.nil\n\n    def insert(self, key):\n        z = Node(Color.RED, key, None, None, None)\n        y = self.nil\n        x = self.root\n        while x is not self.nil:\n            y = x\n            if z.key < x.key:\n                x = x.left\n            else:\n                x = x.right\n\n        z.parent = y\n\n        if y is self.nil:\n            self.root = z\n        elif z.key < y.key:\n            y.left = z\n        else:\n            y.right = z\n\n        z.left = self.nil\n        z.right = self.nil\n        z.color = Color.RED\n\n        self.fixup(z)\n\n    def fixup(self, z):\n        while z.parent.color == Color.RED:\n            if z.parent is z.parent.parent.left:\n                y = z.parent.parent.right\n                if y.color == Color.RED:\n                    z.parent.color = Color.BLACK\n                    y.color = Color.BLACK\n                    z.parent.parent.color = Color.RED\n                    z = z.parent.parent\n                else:\n                    if z is z.parent.right:\n                        z = z.parent\n                        self.left_rotate(z)\n                    z.parent.color = Color.BLACK\n                    z.parent.parent.color = Color.RED\n                    self.right_rotate(z.parent.parent)\n            else:\n                y = z.parent.parent.left\n                if y.color == Color.RED:\n                    z.parent.color = Color.BLACK\n                    y.color = Color.BLACK\n                    z.parent.parent.color = Color.RED\n                    z = z.parent.parent\n                else:\n                    if z is z.parent.left:\n                        z = z.parent\n                        self.right_rotate(z)\n                    z.parent.color = Color.BLACK\n                    z.parent.parent.color = Color.RED\n                    self.left_rotate(z.parent.parent)\n        self.root.color = Color.BLACK\n\n    def left_rotate(self, x):\n        y = x.right\n        x.right = y.left\n\n        if y.left is not self.nil:\n            y.left.parent = x\n\n        y.parent = x.parent\n\n        if x.parent is self.nil:\n            self.root = y\n        elif x is x.parent.left:\n            x.parent.left = y\n        else:\n            x.parent.right = y\n\n        y.left = x\n        x.parent = y\n\n    def right_rotate(self, y):\n        x = y.left\n        y.left = x.right\n\n        if x.right is not self.nil:\n            x.right.parent = y\n\n        x.parent = y.parent\n\n        if y.parent is self.nil:\n            self.root = x\n        elif y is y.parent.left:\n            y.parent.left = x\n        else:\n            y.parent.right = x\n\n        x.right = y\n        y.parent = x\n"
  },
  {
    "path": "other/clrs/13/03/03.markdown",
    "content": "> Suppose that the black-height of each of the subtrees $\\alpha$, $\\beta$,\n> $\\gamma$, $\\delta$, $\\epsilon$ in Figures 13.5 and 13.6 is $k$. Label each\n> node in each figure with its black-height to verify that the indicated\n> transformation preserves property 5.\n\nThis is kinda obvious. You can see that regardless of the transformation, there\nis always only one black parent above the subtree in the figure.\n"
  },
  {
    "path": "other/clrs/13/03/04.markdown",
    "content": "> Professor Teach is concerned that `RB-INSERT-FIXTUP` might set $T.nil.color$\n> to `RED`, in which case the test in line 1 would not cause the loop to\n> terminate when $z$ is the root. Show that the professor's concern is unfounded\n> by arguing that `RB-INSERT-FIXUP` never sets $T.nil.color$ to `RED`.\n\nThe professor worries too much.\n\nWe only set the color to red of $z.p.p$ and the text goes at great lengths to\nestablish that it always exists (because $z.p$ is `RED`, which means it can't be\nthe root, which means $z.p.p$ is not `NIL`).\n"
  },
  {
    "path": "other/clrs/13/03/05.markdown",
    "content": "> Consider a red-black tree formed by inserting $n$ nodes with `RB-INSERT`.\n> Argue that if $n > 1$, the tree has at least one red node.\n\nThe way `RB-INSERT` is defined, it always introduces a new node colored red. The\nonly time it changes it's color to black is if it is the root, that is, if it's\na tree with 1 node. After we have a black root, each insert will color the newly\nintroduced element red and keep it red, regardless of how it rearranges the rest\nof the tree.\n"
  },
  {
    "path": "other/clrs/13/03/06.markdown",
    "content": "> Suggest how to implement `RB-INSERT` efficiently if the representation for\n> red-black trees include no storage for parent pointers.\n\nWe can do it by allocating extra $\\O(\\lg n)$ memory.\n\nWhen inserting, we're descending the tree to the position we want to insert in.\nIf we keep track of the stack of parents we visit (there $\\O(\\lg n)$ are of\nthem), we can then calculate $z.p$ and $z.p.p$ using that stack. We will need to\npass the relevant parent to `LEFT-ROTATE` and `RIGHT-ROTATE` as well.\n\nProblem 13.1 actually implements this.\n"
  },
  {
    "path": "other/clrs/13/04/01.markdown",
    "content": "> Argue that after executing `RB-DELETE-FIXUP`, the root of the tree must be\n> black.\n\nFirst, let's observe that all the cases in `RB-DELETE-FIXUP` retains the color\nof the root of the subtree. If the deleted node is not the root or an immediate\ndescendent of the root, the root's color will remain the same, regardless of\nrotations.\n\nThe only case that's not obvious is when the deleted node is the root and it has\na single child. In this case, `RB-DELETE-FIXUP` will immediately color it red,\nand the property will be preserved.\n"
  },
  {
    "path": "other/clrs/13/04/02.markdown",
    "content": "> Argue that if in `RB-DELETE-FIXUP` both $x$ and $x.p$ are red, then property 4\n> is restored by the call to `RB-DELETE-FIXUP(T, x)`\n\nSimilar to the previous exercise, just observe that `RB-DELETE-FIXUP(T, x)` will\nimmediately color x black if it was red. Thus, if both $x$ and $x.p$ are red,\n$x$ will become black and the property will be retained (as $x.p$ is red and\nit's other child was unchanged, it's bound to be black).\n"
  },
  {
    "path": "other/clrs/13/04/03.draw.py",
    "content": "import os.path as path\nimport drawing\n\nexec(open(path.join(path.dirname(__file__), '03.py')).read())\n\nB = drawing.RedBlackTrees.Black\nR = drawing.RedBlackTrees.Red\n\n\ndef dot(tree):\n    def convert(node, nil):\n        if node is nil:\n            return None\n\n        cons = R if node.color == Color.RED else B\n        left = convert(node.left, nil)\n        right = convert(node.right, nil)\n\n        return cons(node.key, left, right)\n\n    return convert(tree.root, tree.nil).dot()\n\n\ntree = Tree()\ndrawings = []\n\nfor n in [41, 38, 31, 12, 19, 8]:\n    tree.insert(n)\n\nfor n in [8, 12, 19, 31, 38]:\n    tree.delete(n)\n    drawings.append({'name': f'After deleting {n}', 'dot': dot(tree), 'display': True})\n\ndrawing.process(drawings)\n"
  },
  {
    "path": "other/clrs/13/04/03.markdown",
    "content": "> In Exercise 13.3-2, you found the red-black tree that results from\n> successively inserting the keys $41, 38, 31, 12, 19, 8$ into an initially\n> empty tree. Now show the red-black trees that result from the successive\n> deletion of the keys in the order $8, 12, 19, 31, 38, 41$.\n\nI did this on paper, but in order to be certain of the results, it's worth\nimplementing deletion and seeing whether they match when I came up with. Let's\nsee.\n"
  },
  {
    "path": "other/clrs/13/04/03.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nclass Node:\n    def __init__(self, color, key, parent, left, right):\n        self.color = color\n        self.key = key\n        self.parent = parent\n        self.left = left\n        self.right = right\n\n    def sexp(self, nil):\n        if self is nil:\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.key}, {self.left.sexp(nil)}, {self.right.sexp(nil)})\"\n\n    def black_height(self, nil):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n\nclass Tree:\n    def __init__(self):\n        self.nil = Node(Color.BLACK, None, None, None, None)\n        self.nil.parent = self.nil\n        self.nil.left = self.nil\n        self.nil.right = self.nil\n\n        self.root = self.nil\n\n    def __str__(self):\n        return self.root.sexp(self.nil)\n\n    def search(self, key):\n        node = self.root\n\n        while node is not self.nil:\n            if node.key == key:\n                return node\n            elif key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def nodes(self):\n        items = deque()\n\n        if self.root is not self.nil:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left is not self.nil:\n                items.append(node.left)\n\n            if node.right is not self.nil:\n                items.append(node.right)\n\n    def insert(self, key):\n        z = Node(Color.RED, key, None, None, None)\n        y = self.nil\n        x = self.root\n        while x is not self.nil:\n            y = x\n            if z.key < x.key:\n                x = x.left\n            else:\n                x = x.right\n\n        z.parent = y\n\n        if y is self.nil:\n            self.root = z\n        elif z.key < y.key:\n            y.left = z\n        else:\n            y.right = z\n\n        z.left = self.nil\n        z.right = self.nil\n        z.color = Color.RED\n\n        self.insert_fixup(z)\n\n    def insert_fixup(self, z):\n        while z.parent.color == Color.RED:\n            if z.parent is z.parent.parent.left:\n                y = z.parent.parent.right\n                if y.color == Color.RED:\n                    z.parent.color = Color.BLACK\n                    y.color = Color.BLACK\n                    z.parent.parent.color = Color.RED\n                    z = z.parent.parent\n                else:\n                    if z is z.parent.right:\n                        z = z.parent\n                        self.left_rotate(z)\n                    z.parent.color = Color.BLACK\n                    z.parent.parent.color = Color.RED\n                    self.right_rotate(z.parent.parent)\n            else:\n                y = z.parent.parent.left\n                if y.color == Color.RED:\n                    z.parent.color = Color.BLACK\n                    y.color = Color.BLACK\n                    z.parent.parent.color = Color.RED\n                    z = z.parent.parent\n                else:\n                    if z is z.parent.left:\n                        z = z.parent\n                        self.right_rotate(z)\n                    z.parent.color = Color.BLACK\n                    z.parent.parent.color = Color.RED\n                    self.left_rotate(z.parent.parent)\n        self.root.color = Color.BLACK\n\n    def delete(self, z):\n        z = self.search(z)\n        y = z\n        y_original_color = y.color\n        if z.left is self.nil:\n            x = z.right\n            self.transplant(z, z.right)\n        elif z.right is self.nil:\n            x = z.left\n            self.transplant(z, z.left)\n        else:\n            y = self.minimum(z.right)\n            y_original_color = y.color\n            x = y.right\n            if y.parent is z:\n                x.parent = y\n            else:\n                self.transplant(y, y.right)\n                y.right = z.right\n                y.right.parent = y\n            self.transplant(z, y)\n            y.left = z.left\n            y.left.parent = y\n            y.color = z.color\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(x)\n\n    def delete_fixup(self, x):\n        while x is not self.root and x.color == Color.BLACK:\n            if x is x.parent.left:\n                w = x.parent.right\n\n                if w.color == Color.RED:\n                    w.color = Color.BLACK\n                    x.parent.color = Color.RED\n                    self.left_rotate(x.parent)\n                    w = x.parent.right\n\n                if w.left.color == Color.BLACK and w.right.color == Color.BLACK:\n                    w.color = Color.RED\n                    x = x.parent\n                else:\n                    if w.right.color == Color.BLACK:\n                        w.left.color = Color.BLACK\n                        w.color = Color.RED\n                        self.right_rotate(w)\n                        w = x.parent.right\n\n                    w.color = x.parent.color\n                    x.parent.color = Color.BLACK\n                    w.right.color = Color.BLACK\n                    self.left_rotate(w.parent)\n                    x = self.root\n            else:\n                w = x.parent.left\n\n                if w.color == Color.RED:\n                    w.color = Color.BLACK\n                    x.parent.color = Color.RED\n                    self.right_rotate(x.parent)\n                    w = x.parent.left\n\n                if w.left.color == Color.BLACK and w.right.color == Color.BLACK:\n                    w.color = Color.RED\n                    x = x.parent\n                else:\n                    if w.left.color == Color.BLACK:\n                        w.left.color = Color.BLACK\n                        w.color = Color.RED\n                        self.left_rotate(w)\n                        w = x.parent.left\n\n                    w.color = x.parent.color\n                    x.parent.color = Color.BLACK\n                    w.left.color = Color.BLACK\n                    self.right_rotate(w.parent)\n                    x = self.root\n\n        x.color = Color.BLACK\n\n    def minimum(self, node):\n        while node.left is not self.nil:\n            node = node.left\n\n        return node\n\n    def transplant(self, u, v):\n        if u.parent is self.nil:\n            self.root = v\n        elif u is u.parent.left:\n            u.parent.left = v\n        else:\n            u.parent.right = v\n        v.parent = u.parent\n\n    def left_rotate(self, x):\n        y = x.right\n        x.right = y.left\n\n        if y.left is not self.nil:\n            y.left.parent = x\n\n        y.parent = x.parent\n\n        if x.parent is self.nil:\n            self.root = y\n        elif x is x.parent.left:\n            x.parent.left = y\n        else:\n            x.parent.right = y\n\n        y.left = x\n        x.parent = y\n\n    def right_rotate(self, y):\n        x = y.left\n        y.left = x.right\n\n        if x.right is not self.nil:\n            x.right.parent = y\n\n        x.parent = y.parent\n\n        if y.parent is self.nil:\n            self.root = x\n        elif y is y.parent.left:\n            y.parent.left = x\n        else:\n            y.parent.right = x\n\n        x.right = y\n        y.parent = x\n"
  },
  {
    "path": "other/clrs/13/04/03.test.py",
    "content": "import unittest\nimport os.path as path\nimport random\n\nfilename = path.join(path.dirname(__file__), '03.py')\nexec(open(filename).read())\n\n\nclass RedBlackTest(unittest.TestCase):\n    def generate(self, m, n):\n        numbers = list(range(m))\n        random.shuffle(numbers)\n        return numbers[0:n]\n\n    def assertContains(self, tree, numbers):\n        for n in numbers:\n            self.assertIsNotNone(tree.search(n), f\"should contain {n}\")\n            self.assertEqual(tree.search(n).key, n)\n\n    def assertProperties(self, tree):\n        heights = set()\n        for n in tree.nodes():\n            if n.left is tree.nil or n.right is tree.nil:\n                heights.add(n.black_height(tree.nil))\n\n            if n.color == Color.RED:\n                self.assertEqual(n.left.color, Color.BLACK)\n                self.assertEqual(n.right.color, Color.BLACK)\n\n        self.assertEqual(len(heights), 1)\n        self.assertEqual(tree.root.color, Color.BLACK)\n        self.assertEqual(tree.nil.color, Color.BLACK)\n\n    def test_insertions(self):\n        numbers = self.generate(300, 100)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertContains(tree, numbers)\n\n    def test_properties(self):\n        numbers = self.generate(300, 100)\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertProperties(tree)\n\n    def test_deletion(self):\n        numbers = self.generate(1000, 500)\n        removed = numbers[:]\n        random.shuffle(removed)\n        removed = removed[0:250]\n        remaining = list(set(numbers) - set(removed))\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in removed:\n            tree.delete(n)\n\n        self.assertContains(tree, remaining)\n\n        for n in removed:\n            self.assertIsNone(tree.search(n))\n\n        self.assertProperties(tree)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/13/04/04.markdown",
    "content": "> In which lines of the code for `RB-DELETE-FIXUP` might we examine or modify\n> the sentinel $T.nil$?\n\n$x$ can initially be the sentinel, and all the checks and modifications against\nit (lines 2, 3, 6, 7, 8, 11, 16, 17, 18, 20) examine the sentinel. It happens to\nhave the right pointers, because `RB-DELETE` has set them up before calling\n`RB-DELETE-FIXUP`.\n"
  },
  {
    "path": "other/clrs/13/04/05.markdown",
    "content": "> In each of the cases of Figure 13.7, give the count of black nodes from the\n> root of the subtree shown to each of the subtrees $\\alpha, \\beta, \\ldots,\n> \\zeta$, and verify that each count remains the same after the transformation.\n> When a node has $color$ attribute $c$ or $c'$, use the notation\n> $\\text{count}(c)$ or $\\text{count}(c')$ symbolically in your count.\n\nAah, nice. An attempt to shoehorn more math.\n\nLet's denote $A = 1$, $B = 1$ and so on, and count it when the note is black.\nAlso, if a node has \"extra black\", let's denote that as $x$. Finally, let's say\nthat the count is $2+$ if there are two certain blacks and some optional ones,\nexpressed through $\\text{count}$. Thus:\n\n## Case 1\n\n$$\n    \\begin{aligned}\n    \\alpha   : && A + B + x &= 3 && \\Rightarrow & A + D + x &= 3 \\\\\\\\\n    \\beta    : && A + B + x &= 3 && \\Rightarrow & A + D + x &= 3 \\\\\\\\\n    \\gamma   : && C + B     &= 2 && \\Rightarrow & C + D     &= 2 \\\\\\\\\n    \\delta   : && C + B     &= 2 && \\Rightarrow & C + D     &= 2 \\\\\\\\\n    \\epsilon : && E + B     &= 2 && \\Rightarrow & E + D     &= 2 \\\\\\\\\n    \\zeta    : && E + B     &= 2 && \\Rightarrow & E + D     &= 2 \\\\\\\\\n    \\end{aligned}\n$$\n\n## Case 2\n\n$$\n    \\begin{aligned}\n    \\alpha   : && A + \\text{count}(c) + x &= 2+ && \\Rightarrow & A + \\text{count}(c) + x &= 2+ \\\\\\\\\n    \\beta    : && A + \\text{count}(c) + x &= 2+ && \\Rightarrow & A + \\text{count}(c) + x &= 2+ \\\\\\\\\n    \\gamma   : && C + D + \\text{count}(c) &= 2+ && \\Rightarrow & C + \\text{count}(c) + x &= 2+ \\\\\\\\\n    \\delta   : && C + D + \\text{count}(c) &= 2+ && \\Rightarrow & C + \\text{count}(c) + x &= 2+ \\\\\\\\\n    \\epsilon : && E + D + \\text{count}(c) &= 2+ && \\Rightarrow & E + \\text{count}(c) + x &= 2+ \\\\\\\\\n    \\zeta    : && E + D + \\text{count}(c) &= 2+ && \\Rightarrow & E + \\text{count}(c) + x &= 2+ \\\\\\\\\n    \\end{aligned}\n$$\n\n## Case 3\n\n$$\n    \\begin{aligned}\n    \\alpha   : && A + \\text{count}(c) + x &= 2+ && \\Rightarrow & A + \\text{count}(c) + x &= 2+ \\\\\\\\\n    \\beta    : && A + \\text{count}(c) + x &= 2+ && \\Rightarrow & A + \\text{count}(c) + x &= 2+ \\\\\\\\\n    \\gamma   : && D + \\text{count}(c)     &= 1+ && \\Rightarrow & C + \\text{count}(c)     &= 1+ \\\\\\\\\n    \\delta   : && D + \\text{count}(c)     &= 1+ && \\Rightarrow & C + \\text{count}(c)     &= 1+ \\\\\\\\\n    \\epsilon : && E + D + \\text{count}(c) &= 2+ && \\Rightarrow & E + C + \\text{count}(c) &= 2+ \\\\\\\\\n    \\zeta    : && E + D + \\text{count}(c) &= 2+ && \\Rightarrow & E + C + \\text{count}(c) &= 2+ \\\\\\\\\n    \\end{aligned}\n$$\n\n## Case 4\n\n$$\n    \\begin{aligned}\n    \\alpha   : && A + x + \\text{count}(c)                &= 2+  && \\Rightarrow & A + B + \\text{count}(c)                &= 2+ \\\\\\\\\n    \\beta    : && A + x + \\text{count}(c)                &= 2+  && \\Rightarrow & A + B + \\text{count}(c)                &= 2+ \\\\\\\\\n    \\gamma   : && \\text{count}(c') + D + \\text{count}(c) &= 1++ && \\Rightarrow & \\text{count}(c') + B + \\text{count}(c) &= 1++ \\\\\\\\\n    \\delta   : && \\text{count}(c') + D + \\text{count}(c) &= 1++ && \\Rightarrow & \\text{count}(c') + B + \\text{count}(c) &= 1++ \\\\\\\\\n    \\epsilon : && D + \\text{count}(c)                    &= 1+  && \\Rightarrow & E + \\text{count}(c)                    &= 1+ \\\\\\\\\n    \\zeta    : && D + \\text{count}(c)                    &= 1+  && \\Rightarrow & E + \\text{count}(c)                    &= 1+ \\\\\\\\\n    \\end{aligned}\n$$\n"
  },
  {
    "path": "other/clrs/13/04/06.markdown",
    "content": "> Professors Skelton and Baron are concerned that at the start of case 1 of\n> `RB-DELETE-FIXUP`, the node $x.p$ might not be black. If the professors are\n> correct, then lines 5–6 are wrong. Show that $x.p$ must be black at the start\n> of case 1, so that the professors have nothing to worry about.\n\nAt the start of case 1 we check that $w$, the other child of $x.p$ is red. If it\nis, it means that $x.p$ has to be black (if it was red, it would have a red\nchild, which violates property 4).\n"
  },
  {
    "path": "other/clrs/13/04/07.draw.py",
    "content": "import os.path as path\nimport drawing\n\nexec(open(path.join(path.dirname(__file__), '03.py')).read())\n\nB = drawing.RedBlackTrees.Black\nR = drawing.RedBlackTrees.Red\n\n\ndef dot(tree):\n    def convert(node, nil):\n        if node is nil:\n            return None\n\n        cons = R if node.color == Color.RED else B\n        left = convert(node.left, nil)\n        right = convert(node.right, nil)\n\n        return cons(node.key, left, right)\n\n    return convert(tree.root, tree.nil).dot()\n\n\ntree = Tree()\ndrawings = []\ntree.insert(5)\ntree.insert(4)\ntree.insert(6)\n\ndrawings.append({'name': f'Before insert', 'dot': dot(tree), 'display': True})\n\ntree.insert(3)\n\ndrawings.append({'name': f'After insert', 'dot': dot(tree), 'display': True})\n\ntree.delete(3)\n\ndrawings.append({'name': f'After delete', 'dot': dot(tree), 'display': True})\n\ndrawing.process(drawings)\n"
  },
  {
    "path": "other/clrs/13/04/07.markdown",
    "content": "> Suppose that a node $x$ is inserted into a red-black tree with `RB-INSERT` and\n> then is immediately deleted with `RB-DELETE`. Is the resulting red-black tree\n> the same as the initial red-black tree? Justify your answer.\n\nIt's not, necessarily.\n\nInformally, (1) there is more than one way to color the same tree and (2)\nnothing in the functions strives to accomplish a canonical coloring. In fact,\nall the functions try to do as little work as possible.\n\nHere's a counter-example:\n"
  },
  {
    "path": "other/clrs/13/misc/red_black_tree.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nNIL_KEY = object()\n\n\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\n\nclass Node:\n    def __init__(self, color, key, parent, left, right, tree):\n        self.color = color\n        self.key = key\n        self.parent = parent\n        self.left = left\n        self.right = right\n        self.tree = tree\n\n    def sexp(self):\n        if self.isNil():\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.key}, {self.left}, {self.right})\"\n\n    __str__ = sexp\n\n    def black_height(self):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def isNil(self):\n        return self.key is NIL_KEY\n\n    def isNotNil(self):\n        return not self.isNil()\n\n    def __bool__(self):\n        return self.isNotNil()\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    __getitem__ = child\n    __setitem__ = set_child\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def rotate(self, direction):\n        child = self.other(direction)\n        self[other(direction)] = child[direction]\n\n        if child[direction]:\n            child[direction].parent = self\n\n        child.parent = self.parent\n\n        if not self.parent:\n            self.tree.root = child\n        elif self is self.parent[direction]:\n            self.parent[direction] = child\n        else:\n            self.parent[other(direction)] = child\n\n        child[direction] = self\n        self.parent = child\n\n    def left_rotate(self):\n        self.rotate('left')\n\n    def right_rotate(self):\n        self.rotate('right')\n\n    def transplant(self, other):\n        if not self.parent:\n            self.tree.root = other\n        elif self is self.parent.left:\n            self.parent.left = other\n        else:\n            self.parent.right = other\n        other.parent = self.parent\n\n    def set(self, parent=None, left=None, right=None, color=None):\n        if color:\n            self.color = color\n        if left is not None:\n            self.left = left\n        if right is not None:\n            self.right = right\n        if parent is not None:\n            self.parent = parent\n\n    def minimum(self):\n        node = self\n\n        while node.left:\n            node = node.left\n\n        return node\n\n\nnil = Node(Color.BLACK, NIL_KEY, None, None, None, None)\nnil.parent = nil\nnil.left = nil\nnil.right = nil\n\n\nclass Tree:\n    def __init__(self):\n        self.root = nil\n\n    def __str__(self):\n        return self.root.sexp()\n\n    def search(self, key):\n        node = self.root\n\n        while node:\n            if node.key == key:\n                return node\n            elif key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def insert(self, key):\n        new = Node(Color.RED, key, None, None, None, self)\n        parent = nil\n        node = self.root\n        while node:\n            parent = node\n            if new.key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        new.parent = parent\n\n        if not parent:\n            self.root = new\n        elif new.key < parent.key:\n            parent.left = new\n        else:\n            parent.right = new\n\n        new.set(left=nil, right=nil, color=Color.RED)\n\n        self.insert_fixup(new)\n\n    def insert_fixup(self, node):\n        while node.parent.isRed():\n            if node.parent is node.parent.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            if direction == 'left' or direction == 'right':\n                uncle = node.parent.parent[other(direction)]\n                if uncle.isRed():\n                    node.parent.color = Color.BLACK\n                    uncle.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node = node.parent.parent\n                else:\n                    if node is node.parent[other(direction)]:\n                        node = node.parent\n                        node.rotate(direction)\n                    node.parent.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node.parent.parent.rotate(other(direction))\n\n        self.root.color = Color.BLACK\n\n    def delete(self, key):\n        deleted = self.search(key)\n        y = deleted\n        y_original_color = y.color\n\n        if not deleted.left:\n            extra_black = deleted.right\n            deleted.transplant(deleted.right)\n        elif not deleted.right:\n            extra_black = deleted.left\n            deleted.transplant(deleted.left)\n        else:\n            y = deleted.right.minimum()\n            y_original_color = y.color\n            extra_black = y.right\n\n            if y.parent is deleted:\n                extra_black.parent = y\n            else:\n                y.transplant(y.right)\n                y.right = deleted.right\n                y.right.parent = y\n\n            deleted.transplant(y)\n            y.left = deleted.left\n            y.left.parent = y\n            y.color = deleted.color\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(extra_black)\n\n    def delete_fixup(self, node):\n        while node is not self.root and node.isBlack():\n            if node is node.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            sibling = node.parent[other(direction)]\n\n            if sibling.isRed():\n                sibling.color = Color.BLACK\n                node.parent.color = Color.RED\n                node.parent.rotate(direction)\n                sibling = node.parent[other(direction)]\n\n            if sibling.left.isBlack() and sibling.right.isBlack():\n                sibling.color = Color.RED\n                node = node.parent\n            else:\n                if sibling[other(direction)].isBlack():\n                    sibling[direction].color = Color.BLACK\n                    sibling.color = Color.RED\n                    sibling.rotate(other(direction))\n                    sibling = node.parent[other(direction)]\n\n                sibling.color = node.parent.color\n                node.parent.color = Color.BLACK\n                sibling[other(direction)].color = Color.BLACK\n                sibling.parent.rotate(direction)\n                node = self.root\n\n        node.color = Color.BLACK\n"
  },
  {
    "path": "other/clrs/13/misc/red_black_tree_test.py",
    "content": "import unittest\nfrom red_black_tree import Tree, Color\nimport random\n\n\nclass RedBlackTest(unittest.TestCase):\n    def generate(self, m, n):\n        numbers = list(range(m))\n        random.shuffle(numbers)\n        return numbers[0:n]\n\n    def assertContains(self, tree, numbers):\n        for n in numbers:\n            self.assertIsNotNone(tree.search(n), f\"should contain {n}\")\n            self.assertEqual(tree.search(n).key, n)\n\n    def assertProperties(self, tree):\n        heights = set()\n        for n in tree.nodes():\n            if not n.left or not n.right:\n                heights.add(n.black_height())\n\n            if n.color == Color.RED:\n                self.assertEqual(n.left.color, Color.BLACK)\n                self.assertEqual(n.right.color, Color.BLACK)\n\n        self.assertEqual(len(heights), 1)\n        self.assertEqual(tree.root.color, Color.BLACK)\n\n    def test_insertions(self):\n        numbers = self.generate(300, 100)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertContains(tree, numbers)\n\n    def test_properties(self):\n        numbers = self.generate(300, 100)\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertProperties(tree)\n\n    def test_deletion(self):\n        numbers = self.generate(1000, 500)\n        removed = numbers[:]\n        random.shuffle(removed)\n        removed = removed[0:250]\n        remaining = list(set(numbers) - set(removed))\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in removed:\n            tree.delete(n)\n\n        self.assertContains(tree, remaining)\n\n        for n in removed:\n            self.assertIsNone(tree.search(n))\n\n        self.assertProperties(tree)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/13/problems/01.markdown",
    "content": "## Persistent dynamic sets\n\n> During the course of an algorithm, we sometimes find that we need to maintain\n> past versions of a dynamic set as it is updated. We call such a set\n> **persistent**. One way to implement a persistent set is to copy the entire\n> set whenever it is modified, but this approach can slow down a program and\n> also consume much space. Sometimes, we can do much better.\n>\n> Consider a persistent set $S$ with the operations `INSERT`, `DELETE`, and\n> `SEARCH` which we implement using binary search trees as shown in Figure\n> 13.8(a). We maintain a separate root for every version of the set. In order to\n> insert the key 5 into the set, we create a new node with key 5. This node\n> becomes the left child of a new node with key 7, since we cannot modify the\n> existing node with key 7. Similarly, the new node with key 7 becomes the left\n> child of a new node with key 8 whose right child is the existing node with key\n> 10. The new node with key 8 become, in turn, the right child of a new root\n> $r'$ with key 4 whose left child is the existing node with key 3. We thus copy\n> only part of the tree and share some of the nodes with the original tree, as\n> shown in Figure 13.8(b).\n>\n> Assume that each tree node has the attributes $key$, $left$, and $right$ but\n> no parent (See also Exercise 13.3-6).\n>\n> <ol type=\"a\">\n>   <li>For a general persistent binary search tree, identify the nodes that we\n>   need to change to insert a key $k$ or delete a node $y$.\n>   <li>Write a procedure <code>PERSISTENT-TREE-INSERT</code> that, given a\n>   persistent tree $T$ and a key $k$ to insert, return a new persistent tree\n>   $T'$ that is the result of inserting $k$ into $T$.\n>   <li>If the height of the persistent binary search tree $T$ is $h$, what are\n>   the time and space requirements of your implementation of\n>   <code>PERSISTENT-TREE-INSERT</code>? (The space requirement is proportional\n>   to the number of new nodes allocated.)\n>   <li>Suppose that we had included the parent attribute in each node. In this\n>   case, <code>PERSISTENT-TREE-INSERT</code> would need to perform additional\n>   copying. Prove that <code>PERSISTENT-TREE-INSERT</code> would then require\n>   $\\Omega(n)$ time and space, where $n$ is the number of nodes in the tree.\n>   <li>Show how to use red-black trees to guarantee that the worst-case running\n>   time and space are $\\O(\\lg n)$ per insertion and deletion.\n> </ol>\n\n### What needs to change\n\nVery simply, every time we need to change a node, we have to make a copy of the\nnode an all its ancestors.\n\n### Including a parent attribute\n\nIf we included a parent attribute, every time we make a copy of the parent, we\nwould have to copy both of it's children, because the children need to refer to\nthe new parent. This essentially means that the whole tree will need to be\ncopied. By not keeping track of the parent, we can reuse the unchanged child.\n\n### Complexity\n\nThe complexity of insertion and deletion is $\\O(\\lg n)$, since We only modify\nnodes from the inserted/deleted position to the root, plus a constant number of\nother nodes.\n\n### Implementation\n\nThe exercise just for `PERSISTENT-TREE-INSERT`, but I decided to go for the full\nthing, and implement a persistent red-black tree. It was a horrible ordeal that\nwas pretty hard to debug and get right. I shudder to imagine the agony if I\nattempted to do it in C, instead of Python.\n\nAnyway, here are some notes.\n\nFirst, both `RB-INSERT-FIXUP` and `RB-DELETE-FIXUP` repeat a lot of code in the\ntwo branches, with \"left\" and \"right\" reversed. This is too much work, so I will\ngeneralized the operations a bit so they can work with a `direction` (that can\nbe either `left` or `right`) and flip that direction when necessary.\n\nSince we no longer keep track of parents, we need to calculate the ancestor\nchain when we get to a node, so we can later make copies. A few functions have\nbeen modified to keep track of the chain.\n\nMaintaining a sentinel becomes tricky as well, so the sentinel is removed and\nreplaced with `None`, along with all the necessary checks.\n"
  },
  {
    "path": "other/clrs/13/problems/01.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nUNCHANGED = object()\n\n\n# In order to avoid duplicating symmetric code based on whether a child is left\n# or right, we can work with directions instead. In order to be able to, we need\n# to be able to flip a direction as well.\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\n\ndef isBlackOrNil(node):\n    return not node or node.isBlack()\n\n\nclass Node:\n    def __init__(self, color, key, left=None, right=None):\n        self.color = color\n        self.key = key\n        self.left = left\n        self.right = right\n\n    def __str__(self):\n        return str(self.key)\n\n    __repr__ = __str__\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def child_direction(self, child):\n        assert(child is not None)\n\n        if self.left is child:\n            return 'left'\n        elif self.right is child:\n            return 'right'\n        else:\n            assert(False)\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    def with_replaced_child(self, replacement, child):\n        assert(child is not None)\n\n        if self.left is child:\n            return self.copy(left=replacement)\n        elif self.right is child:\n            return self.copy(right=replacement)\n        else:\n            assert(False)\n\n    def replace_child(self, replacement, child):\n        assert(child is not None)\n\n        if self.left is child:\n            self.left = replacement\n            return replacement\n        elif self.right is child:\n            self.right = replacement\n            return replacement\n        else:\n            assert(False)\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def sexp(self):\n        def sexp(node):\n            if node:\n                return node.sexp()\n            else:\n                return '_'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.key}, {sexp(self.left)}, {sexp(self.right)})\"\n\n    def copy(self, key=UNCHANGED, color=UNCHANGED, left=UNCHANGED, right=UNCHANGED):\n        new = Node(self.color, self.key, self.left, self.right)\n\n        if key is not UNCHANGED:\n            new.key = key\n        if color is not UNCHANGED:\n            new.color = color\n        if left is not UNCHANGED:\n            new.left = left\n        if right is not UNCHANGED:\n            new.right = right\n\n        return new\n\n    def left_rotate(self):\n        y = self.right\n        return y.copy(left=self.copy(right=y.left))\n\n    def right_rotate(self):\n        x = self.left\n        return x.copy(right=self.copy(left=x.right))\n\n    def rotate(self, direction):\n        if direction == 'left':\n            return self.left_rotate()\n        elif direction == 'right':\n            return self.right_rotate()\n        else:\n            assert(False)\n\n    # Returns the minimal node and the chain of ancestors that was traversed in\n    # order to find it\n    def minimum_with_ancestors(self):\n        node = self\n        ancestors = []\n\n        while node.left:\n            ancestors.append(node)\n            node = node.left\n\n        return (node, ancestors)\n\n\n# Replaces a node at the bottom of an ancestor chains, and creates a new version\n# of the chain where each parent is copied and updated to point to a newly\n# created child.\n#\n# The final parent in `ancestors` should have `replaced` as a child. It creates\n# a copy of the parent, replacing the child with `inserted` and then proceeds up\n# the chain, updating every ancestor.\n#\n# At the end, it returns a new ancestor chain, where each node is a copy of the\n# original, with an updated child.\ndef update_ancestor_chain(inserted, replaced, ancestors):\n    ancestors = ancestors[:]\n    result = [inserted]\n\n    while ancestors:\n        ancestor = ancestors.pop()\n        inserted = ancestor.with_replaced_child(inserted, replaced)\n        result.append(inserted)\n        replaced = ancestor\n\n    result.reverse()\n\n    return result\n\n\nclass Tree:\n    def __init__(self, root=None):\n        self.root = root\n\n    def __str__(self):\n        if self.root:\n            return self.root.sexp()\n        else:\n            return \"NIL\"\n\n    __repr__ = __str__\n\n    def search(self, key):\n        node = self.root\n\n        while node:\n            if node.key == key:\n                return node\n            elif key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def black_heights(self):\n        if not self.root:\n            return {0}\n\n        heights = set()\n        left = deque()\n\n        if self.root:\n            left.append((self.root, 0))\n\n        while left:\n            (node, height) = left.popleft()\n            if node.isBlack():\n                height += 1\n\n            if node.left:\n                left.append((node.left, height))\n            else:\n                heights.add(height + 1)\n\n            if node.right:\n                left.append((node.right, height))\n            else:\n                heights.add(height + 1)\n\n        return heights\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def insert(self, key):\n        new = Node(Color.RED, key)\n        parent = None\n        current = self.root\n        ancestors = []\n\n        while current:\n            parent = current\n            ancestors.append(parent)\n\n            if new.key < current.key:\n                current = current.left\n            else:\n                current = current.right\n\n        if ancestors:\n            ancestors.pop()\n\n        if not parent:\n            return Tree(root=new.copy(color=Color.BLACK))\n        elif new.key < parent.key:\n            ancestors = update_ancestor_chain(parent.copy(left=new), parent, ancestors)\n        else:\n            ancestors = update_ancestor_chain(parent.copy(right=new), parent, ancestors)\n\n        root = self.insert_fixup(new, ancestors)\n\n        return Tree(root=root)\n\n    def insert_fixup(self, current, ancestors):\n        root = ancestors[0]\n\n        while ancestors and ancestors[-1].isRed():\n            parent = ancestors[-1]\n            direction = ancestors[-2].child_direction(parent)\n            grandfather = ancestors[-2]\n            uncle = grandfather.other(direction)\n\n            if uncle and uncle.isRed():\n                parent.color = Color.BLACK\n                grandfather.color = Color.RED\n                grandfather.set_child(other(direction), uncle.copy(color=Color.BLACK))\n\n                current = grandfather\n                ancestors.pop()\n                ancestors.pop()\n            else:\n                if current is parent.other(direction):\n                    parent = parent.rotate(direction)\n                    grandfather.set_child(direction, parent)\n                    ancestors[-1] = parent\n                    current = parent.child(direction)\n\n                parent.color = Color.BLACK\n                grandfather.color = Color.RED\n                grandgrandfather = ancestors[-3] if len(ancestors) >= 3 else None\n                parent = grandfather.rotate(other(direction))\n\n                if not grandgrandfather:\n                    root = parent\n                else:\n                    grandgrandfather.replace_child(parent, grandfather)\n\n                break\n\n        root.color = Color.BLACK\n\n        return root\n\n    def search_with_ancestors(self, key):\n        node = self.root\n        ancestors = []\n\n        while node:\n            if key == node.key:\n                return (node, ancestors)\n            elif key < node.key:\n                ancestors.append(node)\n                node = node.left\n            else:\n                ancestors.append(node)\n                node = node.right\n\n        return (None, None)\n\n    def delete(self, key):\n        deleted, ancestors = self.search_with_ancestors(key)\n        original_color = deleted.color\n\n        if not deleted.left and not deleted.right:\n            ancestors = update_ancestor_chain(None, deleted, ancestors)\n        elif not deleted.left:\n            ancestors = update_ancestor_chain(deleted.right.copy(), deleted, ancestors)\n        elif not deleted.right:\n            ancestors = update_ancestor_chain(deleted.left.copy(), deleted, ancestors)\n        else:\n            moved, moved_ancestors = deleted.right.minimum_with_ancestors()\n\n            original_color = moved.color\n            extra_black = moved.right.copy() if moved.right else None\n            span = []\n\n            if moved_ancestors:\n                span = update_ancestor_chain(extra_black, moved, moved_ancestors)\n                moved = moved.copy(right=span[0])\n                span.pop()\n\n            elif moved.right:\n                moved = moved.copy(right=extra_black)\n\n            ancestors = update_ancestor_chain(\n                    moved.copy(left=deleted.left, color=deleted.color),\n                    deleted,\n                    ancestors\n                )\n\n            ancestors += span\n            ancestors.append(extra_black)\n\n        root = ancestors[0]\n\n        if original_color == Color.BLACK:\n            root = self.delete_fixup(ancestors)\n\n        return Tree(root=root)\n\n    def delete_fixup(self, ancestors):\n        ancestors = ancestors[:]\n        node = ancestors.pop()\n\n        def replace_top(new_top):\n            old_top = ancestors.pop()\n            if ancestors:\n                ancestors[-1].replace_child(new_top, old_top)\n\n            ancestors.append(new_top)\n\n        while ancestors and isBlackOrNil(node):\n            if node:\n                direction = ancestors[-1].child_direction(node)\n            elif ancestors[-1].left:\n                direction = 'right'\n            else:\n                direction = 'left'\n\n            sibling = ancestors[-1].other(direction)\n\n            if sibling and sibling.isRed():\n                new_top = ancestors[-1].rotate(direction)\n                new_top.color = Color.BLACK\n                new_top.child(direction).color = Color.RED\n\n                replace_top(new_top)\n                ancestors.append(new_top.child(direction))\n                node = new_top.child(direction).child(direction)\n                sibling = new_top.child(direction).other(direction)\n\n            if isBlackOrNil(sibling.left) and isBlackOrNil(sibling.right):\n                ancestors[-1].replace_child(sibling.copy(color=Color.RED), sibling)\n                node = ancestors.pop()\n            else:\n                if isBlackOrNil(sibling.other(direction)):\n                    new_sibling = sibling.rotate(other(direction))\n                    new_sibling.color = Color.BLACK\n                    new_sibling.other(direction).color = Color.RED\n\n                    ancestors[-1].replace_child(new_sibling, sibling)\n                    sibling = new_sibling\n\n                new_top = ancestors[-1].rotate(direction)\n                new_top.color = ancestors[-1].color\n                new_top.child(direction).color = Color.BLACK\n                new_top.replace_child(new_top.other(direction).copy(color=Color.BLACK), new_top.other(direction))\n                node = None\n                replace_top(new_top)\n                break\n\n        if node:\n            node.color = Color.BLACK\n\n        return ancestors[0] if ancestors else node\n"
  },
  {
    "path": "other/clrs/13/problems/01.test.py",
    "content": "import unittest\nimport os.path as path\nimport random\n\nfilename = path.join(path.dirname(__file__), '01.py')\nexec(open(filename).read())\n\n\ndef Red(key, left=None, right=None):\n    return Node(key=key, left=left, right=right, color=Color.RED)\n\n\ndef Black(key, left=None, right=None):\n    return Node(key=key, left=left, right=right, color=Color.BLACK)\n\n\nclass RedBlackTest(unittest.TestCase):\n    def generate(self, m, n):\n        numbers = list(range(m))\n        random.shuffle(numbers)\n        return numbers[0:n]\n\n    def assertContains(self, tree, numbers):\n        for n in numbers:\n            self.assertIsNotNone(tree.search(n), f\"should contain {n}\")\n            self.assertEqual(tree.search(n).key, n)\n\n    def assertDoesNotContain(self, tree, numbers):\n        for n in numbers:\n            self.assertIsNone(tree.search(n), f\"should not contain {n}\")\n\n    def assertInAndOut(self, tree, included, excluded):\n        self.assertContains(tree, included)\n        self.assertDoesNotContain(tree, excluded)\n\n    def assertProperties(self, tree):\n        heights = set()\n        for n in tree.nodes():\n            if n.isRed():\n                if n.left:\n                    self.assertEqual(n.left.color, Color.BLACK)\n                if n.right:\n                    self.assertEqual(n.right.color, Color.BLACK)\n\n        self.assertEqual(len(tree.black_heights()), 1)\n\n        if tree.root:\n            self.assertEqual(tree.root.color, Color.BLACK)\n\n    def test_simple_insertion(self):\n        tree = Tree()\n\n        tree = tree.insert(4)\n        tree = tree.insert(3)\n        tree = tree.insert(5)\n\n        modified = tree.insert(1)\n\n        self.assertIsNotNone(modified.search(1))\n        self.assertIsNotNone(modified.search(4))\n        self.assertIsNotNone(modified.search(3))\n        self.assertIsNotNone(modified.search(5))\n\n        self.assertIsNone(tree.search(1))\n        self.assertIsNotNone(tree.search(4))\n        self.assertIsNotNone(tree.search(3))\n        self.assertIsNotNone(tree.search(5))\n\n    def test_exercise_insertion_properties(self):\n        tree = Tree()\n\n        tree = tree.insert(41)\n        tree = tree.insert(38)\n        tree = tree.insert(31)\n        tree = tree.insert(12)\n        tree = tree.insert(19)\n        tree = tree.insert(8)\n\n        self.assertProperties(tree)\n\n    def test_insertions(self):\n        numbers = self.generate(300, 100)\n        sequences = []\n        missing = []\n        trees = []\n        sofar = []\n\n        tree = Tree()\n\n        for n in numbers:\n            sofar.append(n)\n            sequences.append(sofar[:])\n            missing.append(list(set(numbers) - set(sofar)))\n            tree = tree.insert(n)\n            trees.append(tree)\n\n        for (tree, included, excluded) in zip(trees, sequences, missing):\n            self.assertContains(tree, included)\n            self.assertDoesNotContain(tree, excluded)\n            self.assertProperties(tree)\n\n        nodes = []\n        for tree in trees:\n            nodes += tree.nodes()\n\n        self.assertTrue(len(set(nodes)) < len(nodes))\n\n    def test_delete_empty(self):\n        tree = Tree()\n        tree = tree.insert(1)\n        tree = tree.delete(1)\n\n    def test_exercise_deletion_properties(self):\n        tree = Tree()\n\n        tree = tree.insert(41)\n        tree = tree.insert(38)\n        tree = tree.insert(31)\n        tree = tree.insert(12)\n        tree = tree.insert(19)\n        tree = tree.insert(8)\n\n        first  = tree.delete(8)\n        second = first.delete(12)\n        third  = second.delete(19)\n        fourth = third.delete(31)\n        fifth  = fourth.delete(38)\n\n        self.assertInAndOut(first,  [12, 19, 31, 38, 41], [8])\n        self.assertInAndOut(second, [19, 31, 38, 41], [8, 12])\n        self.assertInAndOut(third,  [31, 38, 41], [8, 12, 19])\n        self.assertInAndOut(fourth, [38, 41], [8, 12, 19, 31])\n        self.assertInAndOut(fifth,  [41], [8, 12, 19, 31, 38])\n\n    def test_delete_fixup_case_1(self):\n        subtree = Red(\"B\",\n                left=Black(\"A\"),\n                right=Red(\"D\",\n                    left=Black(\"C\"),\n                    right=Black(\"E\")))\n        tree = Tree(root=subtree)\n        top = tree.delete_fixup([tree.root, tree.root.left])\n\n        self.assertEqual(top.key, \"D\")\n        self.assertEqual(top.left.key, \"B\")\n        self.assertEqual(top.left.left.key, \"A\")\n        self.assertEqual(top.left.right.key, \"C\")\n        self.assertEqual(top.right.key, \"E\")\n\n    def test_delete_fixup_case_2(self):\n        subtree = Red(\"B\",\n                left=Black(\"A\"),\n                right=Black(\"D\",\n                    left=Black(\"C\"),\n                    right=Black(\"E\")))\n        tree = Tree(root=subtree)\n        top = tree.delete_fixup([tree.root, tree.root.left])\n\n        self.assertEqual(top.key, \"B\")\n        self.assertEqual(top.left.key, \"A\")\n        self.assertEqual(top.right.key, \"D\")\n        self.assertEqual(top.right.left.key, \"C\")\n        self.assertEqual(top.right.right.key, \"E\")\n\n    def test_delete_fixup_case_3(self):\n        subtree = Red(\"B\",\n                left=Black(\"A\"),\n                right=Black(\"D\",\n                    left=Red(\"C\"),\n                    right=Black(\"E\")))\n        tree = Tree(root=subtree)\n\n        top = tree.delete_fixup([tree.root, tree.root.left])\n        self.assertEqual(top.key, \"C\")\n        self.assertEqual(top.left.key, \"B\")\n        self.assertEqual(top.left.left.key, \"A\")\n        self.assertEqual(top.right.key, \"D\")\n        self.assertEqual(top.right.right.key, \"E\")\n\n\n    def test_delete_fixup_case_4(self):\n        subtree = Red(\"B\",\n                left=Black(\"A\"),\n                right=Black(\"D\",\n                    left=Red(\"C\"),\n                    right=Red(\"E\")))\n        tree = Tree(root=subtree)\n\n        new_root = tree.delete_fixup([tree.root, tree.root.left])\n\n        top = new_root\n        self.assertEqual(top.key, \"D\")\n        self.assertEqual(top.color, Color.RED)\n        self.assertEqual(top.left.key, \"B\")\n        self.assertEqual(top.left.color, Color.BLACK)\n        self.assertEqual(top.left.left.key, \"A\")\n        self.assertEqual(top.left.left.color, Color.BLACK)\n        self.assertEqual(top.left.right.key, \"C\")\n        self.assertEqual(top.left.right.color, Color.RED)\n        self.assertEqual(top.right.key, \"E\")\n        self.assertEqual(top.right.color, Color.BLACK)\n\n    def test_deletion(self):\n        numbers = self.generate(300, 100)\n        removed = numbers[:]\n\n        tree = Tree()\n        for n in numbers:\n            tree = tree.insert(n)\n\n        trees = []\n        ins = []\n        outs = []\n        k = 100\n\n        random.shuffle(numbers)\n        removed = []\n\n        for _ in range(k):\n            n = numbers.pop()\n            removed.append(n)\n            tree = tree.delete(n)\n            self.assertProperties(tree)\n            ins.append(numbers[:])\n            outs.append(removed[:])\n            trees.append(tree)\n\n        for (tree, included, excluded) in zip(trees, ins, outs):\n            self.assertInAndOut(tree, included, excluded)\n            self.assertProperties(tree)\n\n        nodes = []\n        for tree in trees:\n            nodes += tree.nodes()\n\n        self.assertTrue(len(set(nodes)) < len(nodes))\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/13/problems/02.markdown",
    "content": "## Join operation on red-black trees\n\n> The **join** operation takes two dynamic sets $S_1$ and $S_2$ and an element\n> $x$ such that any $x_1 \\in S_1$ and $x_2 \\in S_2$, we have $x_1.key \\le x.key\n> \\le x_2.key$. It returns a set $S = S_1 \\cup \\\\{x\\\\} \\cup S_2$. In this\n> problem, we investigate how to implement the join operation on red-black\n> trees.\n>\n> <ol type=\"a\">\n>   <li>Given a red-black tree $T$, let us store its black-height as the new\n>   attribute $T.bh$. Argue that <code>RB-INSERT</code> and\n>   <code>RB-DELETE</code> can maintain the $bh$ attribute without requiring\n>   extra storage in the nodes of the tree and without increasing the asymptotic\n>   running times. Show that while descending through $T$, we can determine the\n>   black-heigh of each node we visit in $\\O(1)$ time per node visited.\n> </ol>\n>\n> We wish to implement the operation $\\text{RB-JOIN}(T_1, x, T_2)$, which\n> destroys $T_1$ and $T_2$ and returns a red-black tree $T = T_1 \\cup \\\\{x\\\\}\n> \\cup T_2$. Let $n$ be the total number of nodes in $T_1$ and $T_2$.\n>\n> <ol type=\"a\" start=\"2\">\n>   <li>Assume that $T_1.bh \\ge T_2.bh$. Describe an $\\O(\\lg n)$-time algorithm\n>   that finds a black node $y$ in $T_1$ with the largest key from among those\n>   nodes whose black height is $T_2.bh$.\n>   <li>Let $T_y$ be the subtree rooted at $y$. Describe how $T_y \\cup \\\\{x\\\\}\n>   T_2$ can replace $T_y$ in $\\O(1)$ time without destroying the binary search\n>   tree property.\n>   <li>What color should we make $x$ so that red-black properties 1, 3, and 5\n>   are maintained? Describe how to enforce properties 2 and 4 in $\\O(\\lg n)$\n>   time.\n>   <li>Argue that no generality is lost by making the assumption in part (b).\n>   Describe the symmetric situation that arises when $T_1.bh \\le T_2.bh$.\n>   <li>Argue that the running time of <code>RB-JOIN</code> is $\\O(\\lg n)$.\n> </ol>\n\n### a. Maintaining black height in constant time\n\nTechnically speaking, whenever we perform the fixup operations, we can keep\ntrack of the colors we change in the path we've modified, and rely on that to\nknow whether we have to increment or decrement the black height.\n\nBut it seems to me, that there is a simpler heuristic, that I'm going to just\nguess here, without proving. Specifically, whenever the black height changes, it\nis somehow reflected in the second and third layer of the tree.\n\nWhen inserting, the way the black height increases is by coloring the root red\n(while preserving the properties with `RB-INSERT-FIXUP`) and then finally\ncoloring it black. This is the only operation that increases the black height by\none.\n\nSimilarly, when deleting, the extra-black pointer eventually finds itself to the\nroot, and that's how the black heigh gets decreased.\n\nI may be missing some cases here, but fundamentally - both left and right\nsubtrees of the root need to lose or gain a unit of black height in order for\nthe tree to do so as well, hence we can figure it out by observing what happens\naround the root.\n\n### b. Finding a black node with the largest key with a specific black-height\n\nQuite simply, we start from the root and go right, setting $c = T.bh$. Every\ntime we go through a black node, we decrement $c$ until we reach the $T_2.bh$.\nOnce we do, we have the node in question.\n\n### c. Replacing $T_y$\n\nQuite simply, we replace the node with $x$, and we put $T_y$ as its left child,\nand $T_2$ as it's right child. The binary search tree invariant is preserved, as\nwe have that $x.key$ is smaller than the keys in $T_2$ and larger than the ones\nin $T_1$.\n\n### d. What color should we make $x$?\n\nWe should make it red. This preserves properties 1, 3 and 5.\n\nTwo problems can occur now. Either it's the new root, and it's red, in which\ncase we can color it black and be done with it, or it can have a red parent\n(its left child is black, because we found a black node for $T_y$ and its right\nchild is also black, because it's $T_2$, and the root of $T_2$ is black).\n\nWe then simply need to call `RB-INSERT-FIXUP` to fix the two subsequent red\nnodes.\n\n### e. Generality\n\nPretty trivially, if $T_2$ has the greater black height, we need to find the\nnode with the smallest key of a given black height, replace it with $x$ and put\n$T_1$ as it's left child. The approach is symmetrical.\n\n### f. Running time\n\nThe operation does the following:\n\n1. Descends one of the trees to find $T_y$, and does so in $\\O(\\lg n)$ time.\n2. Replaces it with $x$ and transplants $T_y$ and $T_2$ under it, in $\\O(1)$\n   time.\n3. Runs `RB-INSERT-FIXUP`, which takes $\\O(\\lg n)$ time.\n\nWe get $\\O(\\lg n) + \\O(1) + \\O(\\lg n) = \\O(\\lg n)$.\n"
  },
  {
    "path": "other/clrs/13/problems/03.markdown",
    "content": "## AVL Trees\n\n> An **AVL tree** is a binary search tree that is **heigh balanced**: for each\n> node $x$, the heights of the left and right subtrees of $x$ differ by at most\n> 1. To implement an AVL tree, we maintain an extra attribute in each node:\n> $x.h$ is the height of node $x$. As for any other binary search tree $T$, we\n> assume that $T.root$ points to the root node.\n>\n> <ol type=\"a\">\n>   <li>Prove that an AVL tree with $n$ nodes has height $\\O(\\lg n)$.\n>   (<i>Hint:</i> Prove that an AVL tree of height $h$ has at least $F_h$ nodes,\n>   where $F_h$ is the $h$th Fibonacci number.)\n>   <li>To insert into an AVL tree, we first place a node into the appropriate\n>   place in binary search tree order. Afterward, the tree might no longer be\n>   height balanced. Specifically, the heights of the left and right children of\n>   some node might differ by 2. Describe a procedure <code>BALANCE(x)</code>,\n>   which takes a subtree rooted at $x$ whose left and right children are height\n>   balanced and have height that differ by at most 2, i.e. $|x.right.h -\n>   x.left.h| \\le 2$, and alters the subtree rooted at $x$ to be height\n>   balanced. (<i>Hint:</i> Use rotations).\n>  <li>Using part (b), describe a recursive procedure <code>AVL-INSERT(x,\n>  z)</code> that takes a node $x$ within an AVL tree and a newly created node\n>  $z$ (whose key has already been filled in), and adds $z$ to the subtree\n>  rooted at $x$, maintaining the property that $x$ is the root of an AVL tree.\n>  As in <code>TREE-INSERT</code> from Section 12.3, assume that $z.key$ has\n>  already been filled in and that $z.left = \\mathrm{NIL}$ and $z.right =\n>  \\mathrm{NIL}$; also assume that $z.h = 0$. Thus, to insert the node $z$ into\n>  the AVL tree $T$, we call <code>AVL-INSERT(T.root, z)</code>.\n>  <li>Show that <code>AVL-INSERT</code>, run on an $n$-node AVL tree, takes\n>  $\\O(\\lg n)$ time and performs $\\O(1)$ rotations.\n> </ol>\n\n### a. number of nodes and height\n\nLet $N_h$ be a lower bound of the number of nodes in an AVL tree with height\n$h$.\n\nWhen $h = 1$, we have that $N_1 = 1$ (there is a single root node in the tree).\nLet's also have $N_0 = 0$.\n\nLet's look at $N_h$ more generally. We know two facts:\n\n* The taller subtree will have height $h - 1$ (otherwise we're not calculating\n  heights correctly).\n* The other subtree will have height at least $h - 2$ (otherwise the AVL\n  invariant will be broken).\n\nThis yields the following recurrence:\n\n$$ N_h \\ge N_{h-1} + N_{h-2} $$\n\nThis is the well-known Fibonnaci sequence. This means, that if a tree has height\n$h$, then it will have at least $F_h$ nodes.\n\nNow let's use this fact to establish a bound on a tree with $n$ nodes. Let's\nfind an $i$ such that $F_i \\le n < F_{i+1}$. We know the height of the tree must\nbe less than $i + 1$, otherwise the tree would have at least $F_{i+1} > n$\nnodes. Since $F_i = \\Theta(\\phi^i)$, we have:\n\n$$ n = \\Theta(\\phi^h) $$\n\nAnd taking the logarithm of both sides (and skipping some formal rigour):\n\n$$ h = \\Theta(\\lg n) $$\n\n### b. balance procedure\n\nRefer to the Python code below for some details. Here's a high-level summary.\n\nThere are four different cases in which we need to perform rotations when the\ntree is not balanced:\n\n    (A)   3      (B)   3     (C)  1        (D)  1\n        /            /              \\             \\\n      2            1                  2             3\n     /              \\                  \\           /\n    1                2                  3         2\n\nThe later two are symmetrical to the former two. In both cases, the bottom node\nis the inserted one, and the top node is the one with the inbalance (height = 2\nin one subtree, and height = 0 in the other). We need to perform one or two\nrotations in order to get a balanced tree.\n\n* **(A)** Performing a right rotation on the root is enough to balance the tree\n* **(B)** We need to perform a left-right rotation, that is, we need to rotate\n  the middle node left, which reduced the tree to the one in (A), and then\n  perform a left rotation\n* **(C)** Symmetrically, we just perform a right left rotation\n* **(D)** In a similar fashion, we perform a right-left rotation\n\nNote that once we make the rotation, the height of the taller subtree gets\nreduced by one, and the height of the shorter gets increased by one. This leaves\nthe root of the subtree with an unchanged height. Since the root's height\nremains unchanged, the rest of the tree won't need any additional rotations.\n\n### c. the `AVL-INSERT` procedure\n\nWe insert a node in the standard way, and then we traverse the ancestors,\nupdating the heights, until we find a imbalance. Then we perform one or two\nrebalancing rotations, and the tree is once again balanced.\n\nRefer to the Python code for more detail.\n\n### d. Running time\n\nInsertion needs to\n\n* descend through the tree, to find where to insert the node, in $\\O(\\lg n)$ time;\n* go back the ancestors, and update the heights, in $\\O(\\lg n)$ time;\n* perform a one or two balancing rotations if it encounters an imbalance, in\n  $\\O(1) time\n"
  },
  {
    "path": "other/clrs/13/problems/03.py",
    "content": "from collections import deque\n\n\nclass Node:\n    def __init__(self, key, height=-1, left=None, right=None):\n        self.key = key\n        self.height = height\n        self.left = left\n        self.right = right\n\n    def __str__(self):\n        def dump(node):\n            if not node:\n                return \"NIL\"\n            else:\n                return f\"/{node.height}/({node.key}, {dump(node.left)}, {dump(node.right)})\"\n\n        return dump(self)\n\n    def left_rotate(self):\n        child = self.right\n        assert(child)\n        self.right = child.left\n        child.left = self\n\n        self.height = 1 + max(height(self.left), height(self.right))\n        child.height = 1 + max(height(child.left), height(child.right))\n\n        return child\n\n    def right_rotate(self):\n        child = self.left\n        assert(child)\n        self.left = child.right\n        child.right = self\n\n        self.height = 1 + max(height(self.left), height(self.right))\n        child.height = 1 + max(height(child.left), height(child.right))\n\n        return child\n\n    __repr__ = __str__\n\n\ndef height(node):\n    return node.height if node else 0\n\n\nclass AVL:\n    def __init__(self):\n        self.root = None\n\n    def __str__(self):\n        if not self.root:\n            return \"NIL\"\n        else:\n            return str(self.root)\n\n    __repr__ = __str__\n\n    def nodes(self):\n        if not self.root:\n            return\n\n        remaining = deque()\n        remaining.append(self.root)\n\n        while remaining:\n            node = remaining.popleft()\n            if node.left:\n                remaining.append(node.left)\n            if node.right:\n                remaining.append(node.right)\n            yield node\n\n    def insert(self, key):\n        def insert_node(subtree, node):\n            if not subtree:\n                return node\n            elif node.key < subtree.key:\n                subtree.left = insert_node(subtree.left, node)\n            else:\n                subtree.right = insert_node(subtree.right, node)\n\n            subtree.height = 1 + max(height(subtree.left), height(subtree.right))\n\n            balance = height(subtree.left) - height(subtree.right)\n\n            if balance < -1:\n                if key < subtree.right.key:\n                    subtree.right = subtree.right.right_rotate()\n                return subtree.left_rotate()\n            elif balance > 1:\n                if key > subtree.left.key:\n                    subtree.left = subtree.left.left_rotate()\n                return subtree.right_rotate()\n            else:\n                return subtree\n\n        new = Node(key, height=1)\n        self.root = insert_node(self.root, new)\n\n    def search(self, key):\n        node = self.root\n\n        while node:\n            if node.key == key:\n                return node\n            elif key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n"
  },
  {
    "path": "other/clrs/13/problems/03.test.py",
    "content": "import unittest\nimport os.path as path\nimport random\n\nfilename = path.join(path.dirname(__file__), '03.py')\nexec(open(filename).read())\n\n\nclass AVLTreeTest(unittest.TestCase):\n    def assertBinarySearchTreeProperties(self, tree):\n        for node in tree.nodes():\n            if node.left:\n                self.assertTrue(node.left.key < node.key)\n            if node.right:\n                self.assertTrue(node.right.key > node.key)\n\n    def assertAVLProperties(self, tree):\n        def calculated_height(node):\n            return node.calculated_height if node else 0\n\n        def height(node):\n            return node.height if node else 0\n\n        def calculate_height(node):\n            if node.left:\n                calculate_height(node.left)\n            if node.right:\n                calculate_height(node.right)\n\n            node.calculated_height = 1 + max(calculated_height(node.left), calculated_height(node.right))\n\n        calculate_height(tree.root)\n\n        for node in tree.nodes():\n            self.assertEqual(node.height, node.calculated_height)\n            self.assertTrue(abs(height(node.left) - height(node.right)) <= 1)\n\n    def testInsertionWithLeftRotation(self):\n        tree = AVL()\n        tree.insert(1)\n        tree.insert(2)\n        tree.insert(3)\n\n        self.assertEqual(tree.root.height, 2)\n        self.assertEqual(tree.root.key, 2)\n        self.assertAVLProperties(tree)\n\n    def testInsertionWithLeftRightRotation(self):\n        tree = AVL()\n        tree.insert(1)\n        tree.insert(3)\n        tree.insert(2)\n\n        self.assertEqual(tree.root.height, 2)\n        self.assertEqual(tree.root.key, 2)\n        self.assertAVLProperties(tree)\n\n    def testInsertionWithRightRotation(self):\n        tree = AVL()\n        tree.insert(3)\n        tree.insert(2)\n        tree.insert(1)\n\n        self.assertEqual(tree.root.height, 2)\n        self.assertEqual(tree.root.key, 2)\n        self.assertAVLProperties(tree)\n\n    def testInsertionWithRightLeftRotation(self):\n        tree = AVL()\n        tree.insert(3)\n        tree.insert(1)\n        tree.insert(2)\n\n        self.assertEqual(tree.root.height, 2)\n        self.assertEqual(tree.root.key, 2)\n        self.assertAVLProperties(tree)\n\n    def testInsertion(self):\n        tree = AVL()\n        tree.insert(1)\n        tree.insert(3)\n        tree.insert(5)\n        tree.insert(7)\n        tree.insert(6)\n        tree.insert(4)\n        tree.insert(2)\n        tree.insert(8)\n        tree.insert(9)\n\n        for i in range(1, 10):\n            self.assertIsNotNone(tree.search(i))\n\n        self.assertIsNone(tree.search(0))\n        self.assertBinarySearchTreeProperties(tree)\n        self.assertAVLProperties(tree)\n\n    def testRandomInsertion(self):\n        numbers = list(range(0, 500))\n        random.shuffle(numbers)\n        numbers = numbers[:250]\n\n        tree = AVL()\n        for i in numbers:\n            tree.insert(i)\n\n        for i in numbers:\n            self.assertIsNotNone(tree.search(i))\n\n        self.assertBinarySearchTreeProperties(tree)\n        self.assertAVLProperties(tree)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/13/problems/04.markdown",
    "content": "## Treaps\n\n> If we insert a set of $n$ items into a binary search tree, the resulting tree\n> may be horribly unbalanced, leading to long search times. As we saw in Section\n> 12.4, however, randomly built binary search trees tend to be balanced.\n> Therefore, one strategy that, on average, builds a balanced tree for a fixed\n> set of items would be to randomly permute the items and then insert them in\n> that order into the tree.\n>\n> What if we do not have all the items at once? If we receive the items one at a\n> time, can we still randomly build a binary search tree out of them?\n>\n> We will examine a data structure that answers this question in the\n> affirmative. A **treap** is a binary search tree with a modified way of\n> ordering the nodes. Figure 13.9 shows an example. As usual, each node $x$ in\n> the tree has a key value $x.key$. In addition, we assign $x.priority$, which\n> is a random number chosen independently for each node. The nodes of the treap\n> are ordered so that the keys obey the binary-search-tree property and the\n> priorities obey the min-heap property:\n>\n> * If $v$ is a left child of $u$, then $v.key < u.key$.\n> * If $v$ is a right child of $u$, then $v.key > u.key$.\n> * If $v$ is a child of $u$, then $v.priority > u.priority$.\n>\n> (This combination of properties is why the tree is called a \"treap\": it has\n> features of both a binary search tree and a heap.)\n>\n> It helps to think of treaps in the following way. Suppose that we insert nodes\n> $x_1, x_2, \\ldots, x_n$, with associated keys, into a treap. Then the\n> resulting treap is the tree that would have been formed if the nodes had been\n> inserted into a normal binary search tree in the order given by their\n> (randomly chosen) priorities, i.e., $x_i.priority < x_j.priority$ means that\n> we had inserted $x_i$ before $x_j$.\n>\n> <ol type=\"a\">\n>   <li>Show that given a set of nodes $x_1, x_2, \\ldots, x_n$, with associated\n>   keys and priorities, all distinct, the treap associated with these nodes is\n>   unique.\n>   <li>Show that the expected height of a treap is $\\Theta(\\lg n)$, and hence\n>   the expected time to search for a value in the treap is $\\Theta(\\lg n)$.\n> </ol>\n>\n> Let use see how to insert a new node into an existing treap. The first thing\n> we do is assign the new node a random priority. Then we call the insertion\n> algorithm, which we call `TREAP-INSERT`, whose operation is illustrated in\n> Figure 13.10.\n>\n> <ol type=\"a\" start=\"3\">\n>   <li>Explain how <code>TREAP-INSERT</code> works. Explan the idea in English\n>   and give pseudocode. (<i>Hint:</i> Execute the usual binary-search-tree\n>   insertion procedure and them perform rotations to restore the min-heap order\n>   property.)\n>   <li>Show that the expected running time of <code>TREAP-INSERT</code> is\n>   $\\Theta(\\lg n)$.\n> </ol>\n>\n> `TREAP-INSERT` performs a search and then a sequence of rotations. Although\n> these two operations have the same expected running time, they have different\n> costs in practice. A search reads information from the treap without modifying\n> it. In contrast, a rotation changes parent and child pointers within the\n> treap. On most computers, read operations are much faster than write\n> operations. Thus we would like `TREAP-INSERT` to perform few rotations. We\n> will show that the expected number of rotations performed is bounded by a\n> constant.\n>\n> In order to do so, we will need some definitions, which Figure 13.11 depicts.\n> The **left spine** of a binary search tree $T$ is the simple path from the\n> root to the node with the smallest key. In other words, the left spine is the\n> simple path from the root that consists of only left edges. Symmetrically, the\n> **right spine** of $T$ is the simple path from the root consisting of only\n> right edges. The **length** of a spine is the number of nodes it contains.\n>\n> <ol type=\"a\" start=\"5\">\n>   <li>Consider the treap $T$ immediately after <code>TREAP-INSERT</code> has\n>   inserted node $x$. Let $C$ be the length of the right spine of the left\n>   subtree of $x$. Let $D$ be the length of the left spine of the right subtree\n>   of $x$. Prove that the total number of rotations that were performed during\n>   the insertion of $x$ is equal to $C + D$.\n> </ol>\n>\n> We will now calculate the expected values for $C$ and $D$. Without loss of\n> generality, we assume that the keys are $1, 2, \\ldots, n$, since we are\n> comparing them only to one another.\n>\n> For nodes $x$ and $y$ in treap $T$, where $y \\ne x$, let $k = x.key$ and $i =\n> y.key$. We define indicator random variables:\n>\n> $$ X_{ik} = I\\\\{y \\text{ is in the right spine of the left subtree of } x\\\\} $$\n>\n> <ol type=\"a\" start=\"6\">\n>   <li>Show that $X_{ik} = 1$ if and only if $y.priority > x.priority$, $y.key\n>   < x.key$, and, for every $z$ such that $y.key < z.key < x.key$, we have\n>   $y.priority < z.priority$.\n>   <li>Show that\n>   $$\n>      \\begin{aligned}\n>        \\Pr\\{X_{ik} = 1\\} &= \\frac{(k - i - 1)!}{(k - i + 1)!} \\\\\\\\\n>                          &= \\frac{1}{(k - i + 1)(k - i)}\n>      \\end{aligned}\n>   $$\n>   <li>Show that\n>   $$ \\E[C] = \\sum_{j=1}^{k-1} \\frac{1}{j(j + 1)} = 1 - \\frac{1}{k} $$\n>   <li>Use a symmetry argument to show that\n>   $$ \\E[D] = 1 - \\frac{1}{n - k + 1} $$\n>   <li>Conclude that the expected number of rotations performed when inserting\n>   a node into a treap is less than 2.\n> </ol>\n\n### a. unique treaps\n\nIf we take any tree elements, and attempt to arrange them in a treap\n\n* their priorities will determine which element is the root (the one with the\n  smallest priority), and\n* their keys will determine whether they are the left or right child of their\n  parent\n\nOr to put it another way:\n\n1. the element with the lowest priority will be the root\n2. the elements with smaller keys will be in the left subtree\n3. the elements with larger keys will be in the right subtree\n4. there is only one unique way to pick the root, and the elements of each\n   subtree\n5. this argument can be applied recursively for each subtree\n\n### b. expected height\n\nTaking the easy way out, we already know from the text that the expected height\nof a randomly built search tree is $\\Theta(\\lg n)$. The argument from Chapter\n12.4 applies here full force.\n\n### c. explain `TREAP-INSERT`\n\nIt first inserts the node in the tree by finding a leaf position to put it in.\nAfter that, it compares the priority with that of the parent. If it's higher,\nwe're done. If it's lower, we need to perform a rotation to put the newly\ninserted element in the place of the parent and then continue with the rest of\nthe ancestors.\n\nInstead of pseudocode, there is a Python implementation below.\n\n### d. expected running time\n\nThe algorithm is linear to the height of the tree (it performs at most a single\nrotation for each ancestor), which is $\\Theta(\\lg n)$.\n\n### e. number of rotations after insertion\n\nLet $l$ be the right spine of the left subtree and $r$ be the left spine of the\nright subtree.\n\nObserve that:\n\n1. Both $l$ and $r$ start with zero elements.\n2. Each rotation add a single element to $r$ and $l$. Specifically, left\n   rotations increase $l$ with one element (the parent) and right rotations\n   increase $r$ with one element (the parent)\n\n### f. when is a node in the right spine of the left subtree\n\nNecessity:\n\nIf $y$ is in the right spine of the left subtree of $x$, then:\n\n* $y$ needs to have a smaller key, that is $y.key < x.key$\n* $y$ needs to have a larger priority, that is $y.priority > x.priority$\n* all the elements on the spine are smaller than it, (otherwise it won't be on a\n  right spine), and if there are larger elements than $y$ but smaller than $x$,\n  they need to have larger priority than $y$, otherwise one of them would be its\n  parent, and $y$ would be a left child, thus not on the right spine\n\nSufficiency:\n\nIf the following tree conditions hold:\n\n1. $y.priority > x.priority$\n2. $y.key < x.key$\n3. for every $z$ such that $y.key < z.key < x.key$: $y.priority < z.priority$\n\nWe know that $y$ is in the left subtree of $x$ (because of (1) and (2)), and all\nit's ancestors up until $x$ are smaller than it (because of (3)), and therefore\nit is the right child of its parent, which is the right child of its parent, and\nso on.\n\n### g. probability of $X_{ik} = 1$\n\nWe leverage the knowledge of the previous point, and then we apply some\ncounting.\n\nWe already know that $i < k$, but there may be some elements between $i$ and\n$k$. From (f) we know that (1) their priority needs to be larger than that of\neither $x$ or $y$, and that $x$ have to have the smaller priority than $y$.\n\nThere are in total $k - i + 1$ elements to consider. We can model the\nprobability of their priority by arranging them in order from the smallest to\nthe largest priority. There are thus $(k - i + 1)!$ possible ways to arrange the\npriorities (this is the denominator). For the ones that satisfy the conditions\nin (f), we are looking for $x$ being the first, $y$ being the second, and $(k -\ni - 1)!$ possible ways to arrange the rest (the numerator).\n\n### h. expectation of $C$\n\nSo, the expectation $\\E[C]$ is $X_{12} + X_{13} + \\ldots + X_{k-1,k}$, that is:\n\n$$\n    \\begin{aligned}\n      \\E[C] &= \\sum_{i=1}^{k-1} \\frac{1}{(k - i + 1)(k - i)} \\\\\\\\\n            &= \\sum_{j=1}^{k-1} \\frac{1}{j(j+1)} && \\text{(let } j = k - i \\text{)} \\\\\\\\\n            &= \\sum_{j=1}^{k-1} \\left( \\frac{1}{j(j+1)} - \\frac{j}{j(j+1)} + \\frac{j}{j(j+1)} \\right) \\\\\\\\\n            &= \\sum_{j=1}^{k-1} \\left( \\frac{j + 1}{j(j+1)} - \\frac{j}{j(j+1)} \\right) \\\\\\\\\n            &= \\sum_{j=1}^{k-1} \\left( \\frac{1}{j} - \\frac{1}{j+1} \\right) \\\\\\\\\n            &= \\sum_{j=1}^{k-1} \\frac{1}{j} - \\sum_{j=1}^{k-1} \\frac{1}{j+1} \\\\\\\\\n            &= 1 + \\sum_{j=2}^{k-1} \\frac{1}{j} - \\sum_{j=1}^{k-2} \\frac{1}{j+1} - \\frac{1}{k - 1 + 1} && \\text{(by taking one element out each sum)} \\\\\\\\\n            &= 1 + \\sum_{j=2}^{k-1} \\frac{1}{j} - \\sum_{j=2}^{k-1} \\frac{1}{j} - \\frac{1}{k} && \\text{(by letting } j = j + 1 \\text{ in the second sum)} \\\\\\\\\n            &= 1 - \\frac{1}{k} && \\text{(by letting the sums cancel each other out)}\n    \\end{aligned}\n$$\n\n### i. symmetry for $\\E[D]$\n\nThe same approach holds here, symmetrically. The only thing we need to consider,\nis that instead of looking at $1, 2, \\ldots, k$, we have to look at $k, k + 1,\n\\ldots, n$. There are $n - k + 1$ elements in that sequence, and if we apply the\nsame math, we get the expectation:\n\n$$ \\E[D] = 1 - \\frac{1}{n - k + 1} $$\n\n### j. conclusion\n\nThe expected number of rotations, is then:\n\n$$\n    \\E[C + D] = \\E[C] + \\E[D] = 1 - \\frac{1}{k} + 1 - \\frac{1}{n - k - 1} < 2 = \\O(1)\n$$\n"
  },
  {
    "path": "other/clrs/13/problems/04.py",
    "content": "from collections import deque\n\n\nclass Node:\n    def __init__(self, key, priority, left=None, right=None):\n        self.key = key\n        self.priority = priority\n        self.left = left\n        self.right = right\n\n    def __str__(self):\n        def dump(node):\n            if not node:\n                return \"NIL\"\n            else:\n                return f\"{node.key}:{node.priority}({dump(node.left)}, {dump(node.right)})\"\n\n        return dump(self)\n\n    def left_rotate(self):\n        child = self.right\n        assert(child)\n        self.right = child.left\n        child.left = self\n\n        return child\n\n    def right_rotate(self):\n        child = self.left\n        assert(child)\n        self.left = child.right\n        child.right = self\n\n        return child\n\n    __repr__ = __str__\n\n\nclass Treap:\n    def __init__(self):\n        self.root = None\n\n    def __str__(self):\n        if not self.root:\n            return \"NIL\"\n        else:\n            return str(self.root)\n\n    __repr__ = __str__\n\n    def nodes(self):\n        if not self.root:\n            return\n\n        remaining = deque()\n        remaining.append(self.root)\n\n        while remaining:\n            node = remaining.popleft()\n            if node.left:\n                remaining.append(node.left)\n            if node.right:\n                remaining.append(node.right)\n            yield node\n\n    def insert(self, key, priority=None):\n        def insert_node(subtree, node):\n            if not subtree:\n                return node\n            elif node.key < subtree.key:\n                subtree.left = insert_node(subtree.left, node)\n                if subtree.priority > subtree.left.priority:\n                    subtree = subtree.right_rotate()\n                return subtree\n            else:\n                subtree.right = insert_node(subtree.right, node)\n                if subtree.priority > subtree.right.priority:\n                    subtree = subtree.left_rotate()\n                return subtree\n\n        new = Node(key, priority=priority)\n        self.root = insert_node(self.root, new)\n\n    def search(self, key):\n        node = self.root\n\n        while node:\n            if node.key == key:\n                return node\n            elif key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n"
  },
  {
    "path": "other/clrs/13/problems/04.test.py",
    "content": "import unittest\nimport os.path as path\nimport random\n\nfilename = path.join(path.dirname(__file__), '04.py')\nexec(open(filename).read())\n\n\nclass TreapTest(unittest.TestCase):\n    def assertBinarySearchTreeProperties(self, tree):\n        for node in tree.nodes():\n            if node.left:\n                self.assertTrue(node.left.key < node.key)\n            if node.right:\n                self.assertTrue(node.right.key > node.key)\n\n    def assertTreapProperties(self, treap):\n        for node in treap.nodes():\n            if node.left:\n                self.assertTrue(node.priority < node.left.priority)\n            if node.right:\n                self.assertTrue(node.priority < node.right.priority)\n\n    def testInsertion(self):\n        treap = Treap()\n        treap.insert('B', priority=7)\n        treap.insert('H', priority=5)\n        treap.insert('G', priority=4)\n\n        self.assertIsNotNone(treap.search('B'))\n        self.assertIsNotNone(treap.search('H'))\n        self.assertIsNotNone(treap.search('G'))\n\n    def testSameTreapWithExample(self):\n        nodes = [\n            ('G', 4), ('B', 7), ('A', 10), ('E', 23), ('H', 5), ('K', 65),\n            ('I', 73), ('C', 25), ('D', 9), ('F', 2)\n        ]\n\n        def make_treap(nodes):\n            treap = Treap()\n            for (key, priority) in nodes:\n                treap.insert(key, priority=priority)\n            return treap\n\n\n        treap = make_treap(nodes)\n        first = str(treap)\n\n        for _ in range(100):\n            random.shuffle(nodes)\n            another = str(make_treap(nodes))\n            self.assertEqual(first, another)\n\n    def testRandomTreap(self):\n        k = 300\n\n        elements = list(range(k))\n        priorities = list(range(k))\n        random.shuffle(elements)\n        random.shuffle(priorities)\n\n        treap = Treap()\n        for (key, priority) in zip(elements, priorities):\n            treap.insert(key, priority=priority)\n\n        for n in elements:\n            self.assertIsNotNone(treap.search(n))\n\n        self.assertBinarySearchTreeProperties(treap)\n        self.assertTreapProperties(treap)\n\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/01/01.markdown",
    "content": "> Show how $\\text{OS-SELECT}(T.root, 10)$ operates on the red-black tree $T$\n> of Figure 14.1.\n\nIt does the following:\n\n```plain\n1. k = 26; i = 10; r = 13; goes into the elseif in line 5; follows left child\n2. k = 17; i = 10; r = 8;  goes into the else in line 6; follows right child;\n3. k = 21; i = 2;  r = 3;  goes into the elseif in line 5; follows left child;\n4. k = 19; i = 2;  r = 1;  goes into the else in line 6; follows right child;\n5. k = 20; i = 1;  r = 1;  returns 20\n```\n"
  },
  {
    "path": "other/clrs/14/01/02.markdown",
    "content": "> Show how $\\text{OS-RANK}(T, x)$ operates on the red-black tree $T$ of Figure\n> 14.1 and the node $x$ with $x.key = 35$.\n\nIt does the following:\n\n```\nstarts with\n\ny.key = 35\nr = 1\n\nthen goes in the while loop:\n1. y.key = 35; r = 1; goes up, adds nothing\n2. y.key = 38; r = 1; goes up, adds rank of left sibling plus one\n3. y.key = 30; r = 3; goes up, adds nothing\n4. y.key = 41; r = 3; goes up, adds rank of left sibling plus one\n5. y.key = 20; r = 16; returns 16\n```\n"
  },
  {
    "path": "other/clrs/14/01/03.markdown",
    "content": "> Write a non-recursive version of `OS-SELECT`\n\nHere's the Python code:\n\n```python\ndef select(node, i):\n    while node:\n        rank = node.left.size + 1\n\n        if i == rank:\n            return node\n        elif i < rank:\n            node = node.left\n        else:\n            i -= rank\n            node = node.right\n```\n\nBelow is the whole thing.\n"
  },
  {
    "path": "other/clrs/14/01/03.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nNIL_KEY = object()\n\n\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\n\nclass Node:\n    def __init__(self, color, key, parent, left, right, tree, size):\n        self.color = color\n        self.key = key\n        self.parent = parent\n        self.left = left\n        self.right = right\n        self.tree = tree\n        self.size = size\n\n    def sexp(self):\n        if self.isNil():\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.key}, {self.left}, {self.right})\"\n\n    __str__ = sexp\n\n    def black_height(self):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def isNil(self):\n        return self.key is NIL_KEY\n\n    def isNotNil(self):\n        return not self.isNil()\n\n    def __bool__(self):\n        return self.isNotNil()\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    __getitem__ = child\n    __setitem__ = set_child\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def rotate(self, direction):\n        child = self.other(direction)\n        self[other(direction)] = child[direction]\n\n        if child[direction]:\n            child[direction].parent = self\n\n        child.parent = self.parent\n\n        if not self.parent:\n            self.tree.root = child\n        elif self is self.parent[direction]:\n            self.parent[direction] = child\n        else:\n            self.parent[other(direction)] = child\n\n        child[direction] = self\n        self.parent = child\n\n        child.size = self.size\n        self.size = self.left.size + self.right.size + 1\n\n    def left_rotate(self):\n        self.rotate('left')\n\n    def right_rotate(self):\n        self.rotate('right')\n\n    def transplant(self, other):\n        if not self.parent:\n            self.tree.root = other\n        elif self is self.parent.left:\n            self.parent.left = other\n        else:\n            self.parent.right = other\n        other.parent = self.parent\n\n    def set(self, parent=None, left=None, right=None, color=None):\n        if color:\n            self.color = color\n        if left is not None:\n            self.left = left\n        if right is not None:\n            self.right = right\n        if parent is not None:\n            self.parent = parent\n\n    def minimum(self):\n        node = self\n\n        while node.left:\n            node = node.left\n\n        return node\n\n    def select(self, i):\n        node = self\n\n        while node:\n            rank = node.left.size + 1\n            if i == rank:\n                return node\n            elif i < rank:\n                node = node.left\n            else:\n                i -= rank\n                node = node.right\n\n        assert(False)\n\n    def rank(self):\n        rank = self.left.size + 1\n\n        node = self\n\n        while node.parent:\n            if node == node.parent.right:\n                rank += node.parent.left.size + 1\n            node = node.parent\n\n        return rank\n\n\nnil = Node(Color.BLACK, NIL_KEY, None, None, None, None, 0)\nnil.parent = nil\nnil.left = nil\nnil.right = nil\n\n\nclass Tree:\n    def __init__(self):\n        self.root = nil\n\n    def __str__(self):\n        return self.root.sexp()\n\n    def search(self, key):\n        node = self.root\n\n        while node:\n            if node.key == key:\n                return node\n            elif key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def select(self, i):\n        return self.root.select(i)\n\n    def insert(self, key):\n        new = Node(Color.RED, key, None, None, None, self, 1)\n        parent = nil\n        node = self.root\n        while node:\n            node.size += 1\n\n            parent = node\n            if new.key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        new.parent = parent\n\n        if not parent:\n            self.root = new\n        elif new.key < parent.key:\n            parent.left = new\n        else:\n            parent.right = new\n\n        new.set(left=nil, right=nil, color=Color.RED)\n\n        self.insert_fixup(new)\n\n    def insert_fixup(self, node):\n        while node.parent.isRed():\n            if node.parent is node.parent.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            if direction == 'left' or direction == 'right':\n                uncle = node.parent.parent[other(direction)]\n                if uncle.isRed():\n                    node.parent.color = Color.BLACK\n                    uncle.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node = node.parent.parent\n                else:\n                    if node is node.parent[other(direction)]:\n                        node = node.parent\n                        node.rotate(direction)\n                    node.parent.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node.parent.parent.rotate(other(direction))\n\n        self.root.color = Color.BLACK\n\n    def delete(self, key):\n        def decrease_ancestor_sizes(node):\n            while node:\n                node.size -= 1\n                node = node.parent\n\n        deleted = self.search(key)\n        y = deleted\n        y_original_color = y.color\n\n        if not deleted.left:\n            decrease_ancestor_sizes(deleted)\n            extra_black = deleted.right\n            deleted.transplant(deleted.right)\n        elif not deleted.right:\n            decrease_ancestor_sizes(deleted)\n            extra_black = deleted.left\n            deleted.transplant(deleted.left)\n        else:\n            y = deleted.right.minimum()\n            y_original_color = y.color\n            extra_black = y.right\n\n            decrease_ancestor_sizes(y)\n\n            if y.parent is deleted:\n                extra_black.parent = y\n            else:\n                y.transplant(y.right)\n                y.right = deleted.right\n                y.right.parent = y\n\n            deleted.transplant(y)\n            y.left = deleted.left\n            y.left.parent = y\n            y.color = deleted.color\n            y.size = y.left.size + y.right.size + 1\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(extra_black)\n\n    def delete_fixup(self, node):\n        while node is not self.root and node.isBlack():\n            if node is node.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            sibling = node.parent[other(direction)]\n\n            if sibling.isRed():\n                sibling.color = Color.BLACK\n                node.parent.color = Color.RED\n                node.parent.rotate(direction)\n                sibling = node.parent[other(direction)]\n\n            if sibling.left.isBlack() and sibling.right.isBlack():\n                sibling.color = Color.RED\n                node = node.parent\n            else:\n                if sibling[other(direction)].isBlack():\n                    sibling[direction].color = Color.BLACK\n                    sibling.color = Color.RED\n                    sibling.rotate(other(direction))\n                    sibling = node.parent[other(direction)]\n\n                sibling.color = node.parent.color\n                node.parent.color = Color.BLACK\n                sibling[other(direction)].color = Color.BLACK\n                sibling.parent.rotate(direction)\n                node = self.root\n\n        node.color = Color.BLACK\n"
  },
  {
    "path": "other/clrs/14/01/03.test.py",
    "content": "import unittest\nimport os.path as path\nimport random\n\nfilename = path.join(path.dirname(__file__), '03.py')\nexec(open(filename).read())\n\n\nclass OrderStatisticTreeTest(unittest.TestCase):\n    def test_rank_when_inserting(self):\n        k = 500\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in range(1, k + 1):\n            self.assertEqual(tree.select(n).key, n)\n            self.assertEqual(tree.search(n).rank(), n)\n\n    def test_rank_when_deleting(self):\n        k = 1000\n        m = 500\n\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        random.shuffle(numbers)\n        remaining = numbers[0:m]\n\n        for n in numbers[m:]:\n            tree.delete(n)\n\n        remaining.sort()\n\n        for (i, n) in enumerate(remaining):\n            i += 1\n            self.assertEqual(tree.select(i).key, n)\n            self.assertEqual(tree.search(n).rank(), i)\n\n    def generate(self, m, n):\n        numbers = list(range(m))\n        random.shuffle(numbers)\n        return numbers[0:n]\n\n    def assertContains(self, tree, numbers):\n        for n in numbers:\n            self.assertIsNotNone(tree.search(n), f\"should contain {n}\")\n            self.assertEqual(tree.search(n).key, n)\n\n    def assertProperties(self, tree):\n        heights = set()\n        for n in tree.nodes():\n            if not n.left or not n.right:\n                heights.add(n.black_height())\n\n            if n.color == Color.RED:\n                self.assertEqual(n.left.color, Color.BLACK)\n                self.assertEqual(n.right.color, Color.BLACK)\n\n        self.assertEqual(len(heights), 1)\n        self.assertEqual(tree.root.color, Color.BLACK)\n\n    def test_insertions(self):\n        numbers = self.generate(300, 100)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertContains(tree, numbers)\n\n    def test_properties(self):\n        numbers = self.generate(300, 100)\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertProperties(tree)\n\n    def test_deletion(self):\n        numbers = self.generate(1000, 500)\n        removed = numbers[:]\n        random.shuffle(removed)\n        removed = removed[0:250]\n        remaining = list(set(numbers) - set(removed))\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in removed:\n            tree.delete(n)\n\n        self.assertContains(tree, remaining)\n\n        for n in removed:\n            self.assertIsNone(tree.search(n))\n\n        self.assertProperties(tree)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/01/04.markdown",
    "content": "> Write a recursive procedure `OS-KEY-RANK(T, k)` that takes as input an ordered\n> statistic tree $T$ and a key $k$ and returns the rank $k$ in the dynamic set\n> represented by $T$. Assume that the keys of $T$ are distinct.\n\nIn order for the function to be recursive, $T$ needs to be a pointer to a node,\nnot a tree. Otherwise, it won't be recursive.\n\nHere's the python version:\n\n```python\ndef key_rank(node, key):\n    if node.key == key:\n        return node.left.size + 1\n    elif key < node.key:\n        return node.left.key_rank(key)\n    else:\n        return node.left.size + 1 + node.right.key_rank(key)\n```\n\nThere is a full version below\n"
  },
  {
    "path": "other/clrs/14/01/04.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nNIL_KEY = object()\n\n\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\n\nclass Node:\n    def __init__(self, color, key, parent, left, right, tree, size):\n        self.color = color\n        self.key = key\n        self.parent = parent\n        self.left = left\n        self.right = right\n        self.tree = tree\n        self.size = size\n\n    def sexp(self):\n        if self.isNil():\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.key}, {self.left}, {self.right})\"\n\n    __str__ = sexp\n\n    def black_height(self):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def isNil(self):\n        return self.key is NIL_KEY\n\n    def isNotNil(self):\n        return not self.isNil()\n\n    def __bool__(self):\n        return self.isNotNil()\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    __getitem__ = child\n    __setitem__ = set_child\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def rotate(self, direction):\n        child = self.other(direction)\n        self[other(direction)] = child[direction]\n\n        if child[direction]:\n            child[direction].parent = self\n\n        child.parent = self.parent\n\n        if not self.parent:\n            self.tree.root = child\n        elif self is self.parent[direction]:\n            self.parent[direction] = child\n        else:\n            self.parent[other(direction)] = child\n\n        child[direction] = self\n        self.parent = child\n\n        child.size = self.size\n        self.size = self.left.size + self.right.size + 1\n\n    def left_rotate(self):\n        self.rotate('left')\n\n    def right_rotate(self):\n        self.rotate('right')\n\n    def transplant(self, other):\n        if not self.parent:\n            self.tree.root = other\n        elif self is self.parent.left:\n            self.parent.left = other\n        else:\n            self.parent.right = other\n        other.parent = self.parent\n\n    def set(self, parent=None, left=None, right=None, color=None):\n        if color:\n            self.color = color\n        if left is not None:\n            self.left = left\n        if right is not None:\n            self.right = right\n        if parent is not None:\n            self.parent = parent\n\n    def minimum(self):\n        node = self\n\n        while node.left:\n            node = node.left\n\n        return node\n\n    def select(self, i):\n        node = self\n\n        while node:\n            rank = node.left.size + 1\n            if i == rank:\n                return node\n            elif i < rank:\n                node = node.left\n            else:\n                i -= rank\n                node = node.right\n\n        assert(False)\n\n    def rank(self):\n        rank = self.left.size + 1\n\n        node = self\n\n        while node.parent:\n            if node == node.parent.right:\n                rank += node.parent.left.size + 1\n            node = node.parent\n\n        return rank\n\n    def key_rank(self, key):\n        if self.key == key:\n            return self.left.size + 1\n        elif key < self.key:\n            return self.left.key_rank(key)\n        else:\n            return self.left.size + 1 + self.right.key_rank(key)\n\n\nnil = Node(Color.BLACK, NIL_KEY, None, None, None, None, 0)\nnil.parent = nil\nnil.left = nil\nnil.right = nil\n\n\nclass Tree:\n    def __init__(self):\n        self.root = nil\n\n    def __str__(self):\n        return self.root.sexp()\n\n    def search(self, key):\n        node = self.root\n\n        while node:\n            if node.key == key:\n                return node\n            elif key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def key_rank(self, key):\n        return self.root.key_rank(key)\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def select(self, i):\n        return self.root.select(i)\n\n    def insert(self, key):\n        new = Node(Color.RED, key, None, None, None, self, 1)\n        parent = nil\n        node = self.root\n        while node:\n            node.size += 1\n\n            parent = node\n            if new.key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        new.parent = parent\n\n        if not parent:\n            self.root = new\n        elif new.key < parent.key:\n            parent.left = new\n        else:\n            parent.right = new\n\n        new.set(left=nil, right=nil, color=Color.RED)\n\n        self.insert_fixup(new)\n\n    def insert_fixup(self, node):\n        while node.parent.isRed():\n            if node.parent is node.parent.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            if direction == 'left' or direction == 'right':\n                uncle = node.parent.parent[other(direction)]\n                if uncle.isRed():\n                    node.parent.color = Color.BLACK\n                    uncle.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node = node.parent.parent\n                else:\n                    if node is node.parent[other(direction)]:\n                        node = node.parent\n                        node.rotate(direction)\n                    node.parent.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node.parent.parent.rotate(other(direction))\n\n        self.root.color = Color.BLACK\n\n    def delete(self, key):\n        def decrease_ancestor_sizes(node):\n            while node:\n                node.size -= 1\n                node = node.parent\n\n        deleted = self.search(key)\n        y = deleted\n        y_original_color = y.color\n\n        if not deleted.left:\n            decrease_ancestor_sizes(deleted)\n            extra_black = deleted.right\n            deleted.transplant(deleted.right)\n        elif not deleted.right:\n            decrease_ancestor_sizes(deleted)\n            extra_black = deleted.left\n            deleted.transplant(deleted.left)\n        else:\n            y = deleted.right.minimum()\n            y_original_color = y.color\n            extra_black = y.right\n\n            decrease_ancestor_sizes(y)\n\n            if y.parent is deleted:\n                extra_black.parent = y\n            else:\n                y.transplant(y.right)\n                y.right = deleted.right\n                y.right.parent = y\n\n            deleted.transplant(y)\n            y.left = deleted.left\n            y.left.parent = y\n            y.color = deleted.color\n            y.size = y.left.size + y.right.size + 1\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(extra_black)\n\n    def delete_fixup(self, node):\n        while node is not self.root and node.isBlack():\n            if node is node.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            sibling = node.parent[other(direction)]\n\n            if sibling.isRed():\n                sibling.color = Color.BLACK\n                node.parent.color = Color.RED\n                node.parent.rotate(direction)\n                sibling = node.parent[other(direction)]\n\n            if sibling.left.isBlack() and sibling.right.isBlack():\n                sibling.color = Color.RED\n                node = node.parent\n            else:\n                if sibling[other(direction)].isBlack():\n                    sibling[direction].color = Color.BLACK\n                    sibling.color = Color.RED\n                    sibling.rotate(other(direction))\n                    sibling = node.parent[other(direction)]\n\n                sibling.color = node.parent.color\n                node.parent.color = Color.BLACK\n                sibling[other(direction)].color = Color.BLACK\n                sibling.parent.rotate(direction)\n                node = self.root\n\n        node.color = Color.BLACK\n"
  },
  {
    "path": "other/clrs/14/01/04.test.py",
    "content": "import unittest\nimport os.path as path\nimport random\n\nfilename = path.join(path.dirname(__file__), '04.py')\nexec(open(filename).read())\n\n\nclass OrderStatisticTreeTest(unittest.TestCase):\n    def test_key_rank(self):\n        k = 1000\n        m = 500\n\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        random.shuffle(numbers)\n        remaining = numbers[0:m]\n\n        for n in numbers[m:]:\n            tree.delete(n)\n\n        remaining.sort()\n\n        for (i, n) in enumerate(remaining):\n            self.assertEqual(tree.key_rank(n), i + 1)\n\n    def test_rank_when_inserting(self):\n        k = 500\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in range(1, k + 1):\n            self.assertEqual(tree.select(n).key, n)\n            self.assertEqual(tree.search(n).rank(), n)\n\n    def test_rank_when_deleting(self):\n        k = 1000\n        m = 500\n\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        random.shuffle(numbers)\n        remaining = numbers[0:m]\n\n        for n in numbers[m:]:\n            tree.delete(n)\n\n        remaining.sort()\n\n        for (i, n) in enumerate(remaining):\n            i += 1\n            self.assertEqual(tree.select(i).key, n)\n            self.assertEqual(tree.search(n).rank(), i)\n\n    def generate(self, m, n):\n        numbers = list(range(m))\n        random.shuffle(numbers)\n        return numbers[0:n]\n\n    def assertContains(self, tree, numbers):\n        for n in numbers:\n            self.assertIsNotNone(tree.search(n), f\"should contain {n}\")\n            self.assertEqual(tree.search(n).key, n)\n\n    def assertProperties(self, tree):\n        heights = set()\n        for n in tree.nodes():\n            if not n.left or not n.right:\n                heights.add(n.black_height())\n\n            if n.color == Color.RED:\n                self.assertEqual(n.left.color, Color.BLACK)\n                self.assertEqual(n.right.color, Color.BLACK)\n\n        self.assertEqual(len(heights), 1)\n        self.assertEqual(tree.root.color, Color.BLACK)\n\n    def test_insertions(self):\n        numbers = self.generate(300, 100)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertContains(tree, numbers)\n\n    def test_properties(self):\n        numbers = self.generate(300, 100)\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertProperties(tree)\n\n    def test_deletion(self):\n        numbers = self.generate(1000, 500)\n        removed = numbers[:]\n        random.shuffle(removed)\n        removed = removed[0:250]\n        remaining = list(set(numbers) - set(removed))\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in removed:\n            tree.delete(n)\n\n        self.assertContains(tree, remaining)\n\n        for n in removed:\n            self.assertIsNone(tree.search(n))\n\n        self.assertProperties(tree)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/01/05.markdown",
    "content": "> Given an element $x$ in an $n$-node order-statistic tree and a natural number\n> $i$, how can we determine the $i$th successor of $x$ in the linear order of\n> the tree in $\\O(\\lg n)$ time?\n\nHere's the code:\n\n```python\ndef nth_successor(node, i):\n    while i > node.right.size:\n        if node.parent.left is node:\n            i -= 1 + node.right.size\n            node = node.parent\n        else:\n            i += 1 + node.left.size\n            node = node.parent\n\n    if i == 0:\n        return node\n\n    return node.right.select(i)\n```\n\nThe code first determines whether the successor is in the right subtree, or\nwhether it's somewhere along the parents. It navigates the tree up until it\nidentifies a node, which contains the $i$-th successor in its right subtree,\nwhile updating $i$. Once it identifies one, it uses `SELECT` to find the node\nwith the specific rank.\n\nThe time is $\\O(\\lg n)$, because the height of the three is $\\O(\\lg n)$, and the\nalgorithm traverses that length at most twice – once on the way up, and then\nonce for `SELECT`.\n"
  },
  {
    "path": "other/clrs/14/01/05.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nNIL_KEY = object()\n\n\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\n\nclass Node:\n    def __init__(self, color, key, parent, left, right, tree, size):\n        self.color = color\n        self.key = key\n        self.parent = parent\n        self.left = left\n        self.right = right\n        self.tree = tree\n        self.size = size\n\n    def sexp(self):\n        if self.isNil():\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.key}, {self.left}, {self.right})\"\n\n    __str__ = sexp\n\n    def black_height(self):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def isNil(self):\n        return self.key is NIL_KEY\n\n    def isNotNil(self):\n        return not self.isNil()\n\n    def __bool__(self):\n        return self.isNotNil()\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    __getitem__ = child\n    __setitem__ = set_child\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def rotate(self, direction):\n        child = self.other(direction)\n        self[other(direction)] = child[direction]\n\n        if child[direction]:\n            child[direction].parent = self\n\n        child.parent = self.parent\n\n        if not self.parent:\n            self.tree.root = child\n        elif self is self.parent[direction]:\n            self.parent[direction] = child\n        else:\n            self.parent[other(direction)] = child\n\n        child[direction] = self\n        self.parent = child\n\n        child.size = self.size\n        self.size = self.left.size + self.right.size + 1\n\n    def left_rotate(self):\n        self.rotate('left')\n\n    def right_rotate(self):\n        self.rotate('right')\n\n    def transplant(self, other):\n        if not self.parent:\n            self.tree.root = other\n        elif self is self.parent.left:\n            self.parent.left = other\n        else:\n            self.parent.right = other\n        other.parent = self.parent\n\n    def set(self, parent=None, left=None, right=None, color=None):\n        if color:\n            self.color = color\n        if left is not None:\n            self.left = left\n        if right is not None:\n            self.right = right\n        if parent is not None:\n            self.parent = parent\n\n    def minimum(self):\n        node = self\n\n        while node.left:\n            node = node.left\n\n        return node\n\n    def select(self, i):\n        node = self\n\n        while node:\n            rank = node.left.size + 1\n            if i == rank:\n                return node\n            elif i < rank:\n                node = node.left\n            else:\n                i -= rank\n                node = node.right\n\n        assert(False)\n\n    def rank(self):\n        rank = self.left.size + 1\n\n        node = self\n\n        while node.parent:\n            if node == node.parent.right:\n                rank += node.parent.left.size + 1\n            node = node.parent\n\n        return rank\n\n    def key_rank(self, key):\n        if self.key == key:\n            return self.left.size + 1\n        elif key < self.key:\n            return self.left.key_rank(key)\n        else:\n            return self.left.size + 1 + self.right.key_rank(key)\n\n    def nth_successor(self, n):\n        node = self\n\n        while n > node.right.size:\n            if node.parent.left is node:\n                n -= 1 + node.right.size\n                node = node.parent\n            else:\n                n += 1 + node.left.size\n                node = node.parent\n\n        if n == 0:\n            return node\n\n        return node.right.select(n)\n\nnil = Node(Color.BLACK, NIL_KEY, None, None, None, None, 0)\nnil.parent = nil\nnil.left = nil\nnil.right = nil\n\n\nclass Tree:\n    def __init__(self):\n        self.root = nil\n\n    def __str__(self):\n        return self.root.sexp()\n\n    def search(self, key):\n        node = self.root\n\n        while node:\n            if node.key == key:\n                return node\n            elif key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def key_rank(self, key):\n        return self.root.key_rank(key)\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def select(self, i):\n        return self.root.select(i)\n\n    def insert(self, key):\n        new = Node(Color.RED, key, None, None, None, self, 1)\n        parent = nil\n        node = self.root\n        while node:\n            node.size += 1\n\n            parent = node\n            if new.key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        new.parent = parent\n\n        if not parent:\n            self.root = new\n        elif new.key < parent.key:\n            parent.left = new\n        else:\n            parent.right = new\n\n        new.set(left=nil, right=nil, color=Color.RED)\n\n        self.insert_fixup(new)\n\n    def insert_fixup(self, node):\n        while node.parent.isRed():\n            if node.parent is node.parent.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            if direction == 'left' or direction == 'right':\n                uncle = node.parent.parent[other(direction)]\n                if uncle.isRed():\n                    node.parent.color = Color.BLACK\n                    uncle.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node = node.parent.parent\n                else:\n                    if node is node.parent[other(direction)]:\n                        node = node.parent\n                        node.rotate(direction)\n                    node.parent.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node.parent.parent.rotate(other(direction))\n\n        self.root.color = Color.BLACK\n\n    def delete(self, key):\n        def decrease_ancestor_sizes(node):\n            while node:\n                node.size -= 1\n                node = node.parent\n\n        deleted = self.search(key)\n        y = deleted\n        y_original_color = y.color\n\n        if not deleted.left:\n            decrease_ancestor_sizes(deleted)\n            extra_black = deleted.right\n            deleted.transplant(deleted.right)\n        elif not deleted.right:\n            decrease_ancestor_sizes(deleted)\n            extra_black = deleted.left\n            deleted.transplant(deleted.left)\n        else:\n            y = deleted.right.minimum()\n            y_original_color = y.color\n            extra_black = y.right\n\n            decrease_ancestor_sizes(y)\n\n            if y.parent is deleted:\n                extra_black.parent = y\n            else:\n                y.transplant(y.right)\n                y.right = deleted.right\n                y.right.parent = y\n\n            deleted.transplant(y)\n            y.left = deleted.left\n            y.left.parent = y\n            y.color = deleted.color\n            y.size = y.left.size + y.right.size + 1\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(extra_black)\n\n    def delete_fixup(self, node):\n        while node is not self.root and node.isBlack():\n            if node is node.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            sibling = node.parent[other(direction)]\n\n            if sibling.isRed():\n                sibling.color = Color.BLACK\n                node.parent.color = Color.RED\n                node.parent.rotate(direction)\n                sibling = node.parent[other(direction)]\n\n            if sibling.left.isBlack() and sibling.right.isBlack():\n                sibling.color = Color.RED\n                node = node.parent\n            else:\n                if sibling[other(direction)].isBlack():\n                    sibling[direction].color = Color.BLACK\n                    sibling.color = Color.RED\n                    sibling.rotate(other(direction))\n                    sibling = node.parent[other(direction)]\n\n                sibling.color = node.parent.color\n                node.parent.color = Color.BLACK\n                sibling[other(direction)].color = Color.BLACK\n                sibling.parent.rotate(direction)\n                node = self.root\n\n        node.color = Color.BLACK\n"
  },
  {
    "path": "other/clrs/14/01/05.test.py",
    "content": "import unittest\nimport os.path as path\nimport random\n\nfilename = path.join(path.dirname(__file__), '05.py')\nexec(open(filename).read())\n\n\nclass OrderStatisticTreeTest(unittest.TestCase):\n    def test_nth_successor(self):\n        k = 200\n        m = 100\n\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        random.shuffle(numbers)\n        remaining = numbers[0:m]\n\n        for n in numbers[m:]:\n            tree.delete(n)\n\n        remaining.sort()\n\n        for (i, n) in enumerate(remaining):\n            for j in range(i + 1, len(remaining) - i):\n                self.assertEqual(tree.search(n).nth_successor(j).key, remaining[i + j])\n\n    def test_key_rank(self):\n        k = 1000\n        m = 500\n\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        random.shuffle(numbers)\n        remaining = numbers[0:m]\n\n        for n in numbers[m:]:\n            tree.delete(n)\n\n        remaining.sort()\n\n        for (i, n) in enumerate(remaining):\n            self.assertEqual(tree.key_rank(n), i + 1)\n\n    def test_rank_when_inserting(self):\n        k = 500\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in range(1, k + 1):\n            self.assertEqual(tree.select(n).key, n)\n            self.assertEqual(tree.search(n).rank(), n)\n\n    def test_rank_when_deleting(self):\n        k = 1000\n        m = 500\n\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        random.shuffle(numbers)\n        remaining = numbers[0:m]\n\n        for n in numbers[m:]:\n            tree.delete(n)\n\n        remaining.sort()\n\n        for (i, n) in enumerate(remaining):\n            i += 1\n            self.assertEqual(tree.select(i).key, n)\n            self.assertEqual(tree.search(n).rank(), i)\n\n    def generate(self, m, n):\n        numbers = list(range(m))\n        random.shuffle(numbers)\n        return numbers[0:n]\n\n    def assertContains(self, tree, numbers):\n        for n in numbers:\n            self.assertIsNotNone(tree.search(n), f\"should contain {n}\")\n            self.assertEqual(tree.search(n).key, n)\n\n    def assertProperties(self, tree):\n        heights = set()\n        for n in tree.nodes():\n            if not n.left or not n.right:\n                heights.add(n.black_height())\n\n            if n.color == Color.RED:\n                self.assertEqual(n.left.color, Color.BLACK)\n                self.assertEqual(n.right.color, Color.BLACK)\n\n        self.assertEqual(len(heights), 1)\n        self.assertEqual(tree.root.color, Color.BLACK)\n\n    def test_insertions(self):\n        numbers = self.generate(300, 100)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertContains(tree, numbers)\n\n    def test_properties(self):\n        numbers = self.generate(300, 100)\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertProperties(tree)\n\n    def test_deletion(self):\n        numbers = self.generate(1000, 500)\n        removed = numbers[:]\n        random.shuffle(removed)\n        removed = removed[0:250]\n        remaining = list(set(numbers) - set(removed))\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in removed:\n            tree.delete(n)\n\n        self.assertContains(tree, remaining)\n\n        for n in removed:\n            self.assertIsNone(tree.search(n))\n\n        self.assertProperties(tree)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/01/06.markdown",
    "content": "> Observe that whenever we reference the $size$ attribute of a node in either\n> `OS-SELECT` or `OS-RANK`, we use it only to compute a rank. Accordingly,\n> suppose we store in each node its rank in the subtree of which it is the root.\n> Show how to maintain this information during insertion and deletion. (Remember\n> that those two operations can cause rotations).\n\nFirst, let's notice that `node.rank = node.left.size + 1`. Since one is actually\na function of the other, we can use that to calculate the new rank. We need to:\n\n* Update the code doing the rotation, where a slight asymmetry gets introduced.\n* Update the code that goes down the tree when inserting to change rank\n  accordingly.\n* Update the rank of the node that gets moved to the deleted position with the\n  rank of the deleted node.\n* Update the code that goes up the tree when deleting to change rank\n  accordingly.\n\nSpecifically for rotations, referring to Figure 13.2, notice that:\n\n* On a left rotation, the rank of $y$ decreases by the rank of $x$ ($\\alpha$\n  gets removed from $y$'s left subtree)\n* On a right rotation, the rank of $y$ increases by the rank of $x$ ($\\alpha$\n  gets added to $y$'s left subtree)\n\nAll the changes can be found in the code below.\n"
  },
  {
    "path": "other/clrs/14/01/06.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nNIL_KEY = object()\n\n\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\n\nclass Node:\n    def __init__(self, color, key, parent, left, right, tree, rank=0):\n        self.color = color\n        self.key = key\n        self.parent = parent\n        self.left = left\n        self.right = right\n        self.tree = tree\n        self.rank = rank\n\n    def sexp(self):\n        if self.isNil():\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.key}, r={self.rank}, {self.left}, {self.right})\"\n\n    __str__ = sexp\n\n    def black_height(self):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def isNil(self):\n        return self.key is NIL_KEY\n\n    def isNotNil(self):\n        return not self.isNil()\n\n    def __bool__(self):\n        return self.isNotNil()\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    __getitem__ = child\n    __setitem__ = set_child\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def rotate(self, direction):\n        child = self.other(direction)\n        self[other(direction)] = child[direction]\n\n        if child[direction]:\n            child[direction].parent = self\n\n        child.parent = self.parent\n\n        if not self.parent:\n            self.tree.root = child\n        elif self is self.parent[direction]:\n            self.parent[direction] = child\n        else:\n            self.parent[other(direction)] = child\n\n        child[direction] = self\n        self.parent = child\n\n        if direction == 'left':\n            child.rank += self.rank\n        else:\n            self.rank -= child.rank\n\n    def depth(self):\n        n = 0\n        node = self\n\n        while node:\n            n += 1\n            node = node.parent\n\n        return n\n\n    def left_rotate(self):\n        self.rotate('left')\n\n    def right_rotate(self):\n        self.rotate('right')\n\n    def transplant(self, other):\n        if not self.parent:\n            self.tree.root = other\n        elif self is self.parent.left:\n            self.parent.left = other\n        else:\n            self.parent.right = other\n        other.parent = self.parent\n\n    def set(self, parent=None, left=None, right=None, color=None):\n        if color:\n            self.color = color\n        if left is not None:\n            self.left = left\n        if right is not None:\n            self.right = right\n        if parent is not None:\n            self.parent = parent\n\n    def minimum(self):\n        node = self\n\n        while node.left:\n            node = node.left\n\n        return node\n\n    def select(self, i):\n        node = self\n\n        while node.rank != i:\n            if node.rank < i:\n                i -= node.rank\n                node = node.right\n            else:\n                node = node.left\n\n        return node\n\n    def rank_in_tree(self):\n        rank = self.rank\n        node = self\n\n        while node.parent:\n            if node.parent.right is node:\n                rank += node.parent.rank\n            node = node.parent\n\n        return rank\n\n\nnil = Node(Color.BLACK, NIL_KEY, None, None, None, None, -1)\nnil.parent = nil\nnil.left = nil\nnil.right = nil\n\n\nclass Tree:\n    def __init__(self):\n        self.root = nil\n\n    def __str__(self):\n        return self.root.sexp()\n\n    def display(self):\n        height = max([node.depth() for node in self.nodes()])\n\n        w = 7\n        p = 2\n\n        level = 0\n        nodes = [self.root]\n        while level < height:\n            cells = (height - 1) ** 2\n            print(\" \" * ((height - level) * 5), (\" \" * p).join((f\"{node.key:>d} / {node.rank:>d}\" if node else \"  NIL  \") for node in nodes))\n            next_level = []\n            for node in nodes:\n                next_level += [node.left, node.right]\n            level += 1\n            nodes = next_level\n\n        print(f\"-- {height} ------\")\n\n    def search(self, key):\n        node = self.root\n\n        while node:\n            if node.key == key:\n                return node\n            elif key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def select(self, i):\n        return self.root.select(i)\n\n    def insert(self, key):\n        new = Node(Color.RED, key, None, None, None, self, 1)\n        parent = nil\n        node = self.root\n        while node:\n            parent = node\n            if new.key < node.key:\n                node.rank += 1\n                node = node.left\n            else:\n                node = node.right\n\n        new.parent = parent\n\n        if not parent:\n            self.root = new\n        elif new.key < parent.key:\n            parent.left = new\n        else:\n            parent.right = new\n\n        new.set(left=nil, right=nil, color=Color.RED)\n\n        self.insert_fixup(new)\n\n    def insert_fixup(self, node):\n        while node.parent.isRed():\n            if node.parent is node.parent.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            if direction == 'left' or direction == 'right':\n                uncle = node.parent.parent[other(direction)]\n                if uncle.isRed():\n                    node.parent.color = Color.BLACK\n                    uncle.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node = node.parent.parent\n                else:\n                    if node is node.parent[other(direction)]:\n                        node = node.parent\n                        node.rotate(direction)\n                    node.parent.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node.parent.parent.rotate(other(direction))\n\n        self.root.color = Color.BLACK\n\n    def delete(self, key):\n        def decrease_ancestor_ranks(node):\n            while node:\n                if node.parent and node.parent.left is node:\n                    node.parent.rank -= 1\n                node = node.parent\n\n        deleted = self.search(key)\n        y = deleted\n        y_original_color = y.color\n\n        if not deleted.left:\n            decrease_ancestor_ranks(deleted)\n            extra_black = deleted.right\n            deleted.transplant(deleted.right)\n        elif not deleted.right:\n            decrease_ancestor_ranks(deleted)\n            extra_black = deleted.left\n            deleted.transplant(deleted.left)\n        else:\n            y = deleted.right.minimum()\n            y_original_color = y.color\n            extra_black = y.right\n\n            decrease_ancestor_ranks(y)\n\n            if y.parent is deleted:\n                extra_black.parent = y\n            else:\n                y.transplant(y.right)\n                y.right = deleted.right\n                y.right.parent = y\n\n            deleted.transplant(y)\n            y.left = deleted.left\n            y.left.parent = y\n            y.color = deleted.color\n            y.rank = deleted.rank\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(extra_black)\n\n    def delete_fixup(self, node):\n        while node is not self.root and node.isBlack():\n            if node is node.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            sibling = node.parent[other(direction)]\n\n            if sibling.isRed():\n                sibling.color = Color.BLACK\n                node.parent.color = Color.RED\n                node.parent.rotate(direction)\n                sibling = node.parent[other(direction)]\n\n            if sibling.left.isBlack() and sibling.right.isBlack():\n                sibling.color = Color.RED\n                node = node.parent\n            else:\n                if sibling[other(direction)].isBlack():\n                    sibling[direction].color = Color.BLACK\n                    sibling.color = Color.RED\n                    sibling.rotate(other(direction))\n                    sibling = node.parent[other(direction)]\n\n                sibling.color = node.parent.color\n                node.parent.color = Color.BLACK\n                sibling[other(direction)].color = Color.BLACK\n                sibling.parent.rotate(direction)\n                node = self.root\n\n        node.color = Color.BLACK\n"
  },
  {
    "path": "other/clrs/14/01/06.test.py",
    "content": "import unittest\nimport os.path as path\nimport random\n\nfilename = path.join(path.dirname(__file__), '06.py')\nexec(open(filename).read())\n\n\nclass OrderStatisticTreeTest(unittest.TestCase):\n    def test_rank_when_inserting(self):\n        k = 500\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in range(1, k + 1):\n            self.assertEqual(tree.select(n).key, n)\n            self.assertEqual(tree.search(n).rank_in_tree(), n)\n\n    def test_rank_when_deleting(self):\n        k = 1000\n        m = 500\n\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        random.shuffle(numbers)\n        remaining = numbers[0:m]\n\n        for n in numbers[m:]:\n            tree.delete(n)\n\n        remaining.sort()\n\n        for (i, n) in enumerate(remaining):\n            i += 1\n            self.assertEqual(tree.select(i).key, n)\n            self.assertEqual(tree.search(n).rank_in_tree(), i)\n\n    def generate(self, m, n):\n        numbers = list(range(m))\n        random.shuffle(numbers)\n        return numbers[0:n]\n\n    def assertContains(self, tree, numbers):\n        for n in numbers:\n            self.assertIsNotNone(tree.search(n), f\"should contain {n}\")\n            self.assertEqual(tree.search(n).key, n)\n\n    def assertProperties(self, tree):\n        heights = set()\n        for n in tree.nodes():\n            if not n.left or not n.right:\n                heights.add(n.black_height())\n\n            if n.color == Color.RED:\n                self.assertEqual(n.left.color, Color.BLACK)\n                self.assertEqual(n.right.color, Color.BLACK)\n\n        self.assertEqual(len(heights), 1)\n        self.assertEqual(tree.root.color, Color.BLACK)\n\n    def test_insertions(self):\n        numbers = self.generate(300, 100)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertContains(tree, numbers)\n\n    def test_properties(self):\n        numbers = self.generate(300, 100)\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertProperties(tree)\n\n    def test_deletion(self):\n        numbers = self.generate(1000, 500)\n        removed = numbers[:]\n        random.shuffle(removed)\n        removed = removed[0:250]\n        remaining = list(set(numbers) - set(removed))\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in removed:\n            tree.delete(n)\n\n        self.assertContains(tree, remaining)\n\n        for n in removed:\n            self.assertIsNone(tree.search(n))\n\n        self.assertProperties(tree)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/01/07.markdown",
    "content": "> Show how to use an order-statistic tree to count the number of inversions (see\n> Problem 2-4) in an array of size $n$ in time $\\O(n \\lg n)$.\n\nWe can use one simple trick!\n\nWe create a new tree, and insert the elements from the array in reverse; that\nis, we insert the last element first, then the element before the last, and so\non. If the array is sorted, we expect each new node to have rank 1, as it will\nbe the minimal node in the tree. If it doesn't, it means that there are\n$node.rank - 1$ elements in the array that are after $node.key$, but smaller in\nvalue.\n\nThis gives the number of inversions.\n\nHere's a Python snippet:\n\n```python\ndef inversions(array):\n    tree = Tree()\n    count = 0\n\n    for n in reversed(array):\n        count += tree.insert(n).rank() - 1\n\n    return count\n```\n"
  },
  {
    "path": "other/clrs/14/01/07.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\ndef inversions(array):\n    tree = Tree()\n    count = 0\n\n    for n in reversed(array):\n        count += tree.insert(n).rank() - 1\n\n    return count\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nNIL_KEY = object()\n\n\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\n\nclass Node:\n    def __init__(self, color, key, parent, left, right, tree, size):\n        self.color = color\n        self.key = key\n        self.parent = parent\n        self.left = left\n        self.right = right\n        self.tree = tree\n        self.size = size\n\n    def sexp(self):\n        if self.isNil():\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.key}, {self.left}, {self.right})\"\n\n    __str__ = sexp\n\n    def black_height(self):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def isNil(self):\n        return self.key is NIL_KEY\n\n    def isNotNil(self):\n        return not self.isNil()\n\n    def __bool__(self):\n        return self.isNotNil()\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    __getitem__ = child\n    __setitem__ = set_child\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def rotate(self, direction):\n        child = self.other(direction)\n        self[other(direction)] = child[direction]\n\n        if child[direction]:\n            child[direction].parent = self\n\n        child.parent = self.parent\n\n        if not self.parent:\n            self.tree.root = child\n        elif self is self.parent[direction]:\n            self.parent[direction] = child\n        else:\n            self.parent[other(direction)] = child\n\n        child[direction] = self\n        self.parent = child\n\n        child.size = self.size\n        self.size = self.left.size + self.right.size + 1\n\n    def left_rotate(self):\n        self.rotate('left')\n\n    def right_rotate(self):\n        self.rotate('right')\n\n    def transplant(self, other):\n        if not self.parent:\n            self.tree.root = other\n        elif self is self.parent.left:\n            self.parent.left = other\n        else:\n            self.parent.right = other\n        other.parent = self.parent\n\n    def set(self, parent=None, left=None, right=None, color=None):\n        if color:\n            self.color = color\n        if left is not None:\n            self.left = left\n        if right is not None:\n            self.right = right\n        if parent is not None:\n            self.parent = parent\n\n    def minimum(self):\n        node = self\n\n        while node.left:\n            node = node.left\n\n        return node\n\n    def select(self, i):\n        node = self\n\n        while node:\n            rank = node.left.size + 1\n            if i == rank:\n                return node\n            elif i < rank:\n                node = node.left\n            else:\n                i -= rank\n                node = node.right\n\n        assert(False)\n\n    def rank(self):\n        rank = self.left.size + 1\n\n        node = self\n\n        while node.parent:\n            if node == node.parent.right:\n                rank += node.parent.left.size + 1\n            node = node.parent\n\n        return rank\n\n\nnil = Node(Color.BLACK, NIL_KEY, None, None, None, None, 0)\nnil.parent = nil\nnil.left = nil\nnil.right = nil\n\n\nclass Tree:\n    def __init__(self):\n        self.root = nil\n\n    def __str__(self):\n        return self.root.sexp()\n\n    def search(self, key):\n        node = self.root\n\n        while node:\n            if node.key == key:\n                return node\n            elif key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def rank(self, key):\n        return self.search(key).rank()\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def select(self, i):\n        return self.root.select(i)\n\n    def insert(self, key):\n        new = Node(Color.RED, key, None, None, None, self, 1)\n        parent = nil\n        node = self.root\n        while node:\n            node.size += 1\n\n            parent = node\n            if new.key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        new.parent = parent\n\n        if not parent:\n            self.root = new\n        elif new.key < parent.key:\n            parent.left = new\n        else:\n            parent.right = new\n\n        new.set(left=nil, right=nil, color=Color.RED)\n\n        self.insert_fixup(new)\n\n        return new\n\n    def insert_fixup(self, node):\n        while node.parent.isRed():\n            if node.parent is node.parent.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            if direction == 'left' or direction == 'right':\n                uncle = node.parent.parent[other(direction)]\n                if uncle.isRed():\n                    node.parent.color = Color.BLACK\n                    uncle.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node = node.parent.parent\n                else:\n                    if node is node.parent[other(direction)]:\n                        node = node.parent\n                        node.rotate(direction)\n                    node.parent.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node.parent.parent.rotate(other(direction))\n\n        self.root.color = Color.BLACK\n\n    def delete(self, key):\n        def decrease_ancestor_sizes(node):\n            while node:\n                node.size -= 1\n                node = node.parent\n\n        deleted = self.search(key)\n        y = deleted\n        y_original_color = y.color\n\n        if not deleted.left:\n            decrease_ancestor_sizes(deleted)\n            extra_black = deleted.right\n            deleted.transplant(deleted.right)\n        elif not deleted.right:\n            decrease_ancestor_sizes(deleted)\n            extra_black = deleted.left\n            deleted.transplant(deleted.left)\n        else:\n            y = deleted.right.minimum()\n            y_original_color = y.color\n            extra_black = y.right\n\n            decrease_ancestor_sizes(y)\n\n            if y.parent is deleted:\n                extra_black.parent = y\n            else:\n                y.transplant(y.right)\n                y.right = deleted.right\n                y.right.parent = y\n\n            deleted.transplant(y)\n            y.left = deleted.left\n            y.left.parent = y\n            y.color = deleted.color\n            y.size = y.left.size + y.right.size + 1\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(extra_black)\n\n    def delete_fixup(self, node):\n        while node is not self.root and node.isBlack():\n            if node is node.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            sibling = node.parent[other(direction)]\n\n            if sibling.isRed():\n                sibling.color = Color.BLACK\n                node.parent.color = Color.RED\n                node.parent.rotate(direction)\n                sibling = node.parent[other(direction)]\n\n            if sibling.left.isBlack() and sibling.right.isBlack():\n                sibling.color = Color.RED\n                node = node.parent\n            else:\n                if sibling[other(direction)].isBlack():\n                    sibling[direction].color = Color.BLACK\n                    sibling.color = Color.RED\n                    sibling.rotate(other(direction))\n                    sibling = node.parent[other(direction)]\n\n                sibling.color = node.parent.color\n                node.parent.color = Color.BLACK\n                sibling[other(direction)].color = Color.BLACK\n                sibling.parent.rotate(direction)\n                node = self.root\n\n        node.color = Color.BLACK\n"
  },
  {
    "path": "other/clrs/14/01/07.test.py",
    "content": "import unittest\nimport os.path as path\nimport random\n\nfilename = path.join(path.dirname(__file__), '07.py')\nexec(open(filename).read())\n\n\ndef count_inversions(numbers):\n    count = 0\n    for i in range(0, len(numbers)):\n        for j in range(i + 1, len(numbers)):\n            if numbers[i] > numbers[j]:\n                count += 1\n    return count\n\n\nclass OrderStatisticTreeTest(unittest.TestCase):\n    def test_inversions(self):\n        numbers = [n * 2 for n in range(0, 100)]\n        random.shuffle(numbers)\n        self.assertEqual(inversions(numbers), count_inversions(numbers))\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/01/08.markdown",
    "content": "> $\\star$ Consider $n$ chords on a circle, each defined by its endpoints.\n> Describe an $\\O(n \\lg n)$-time algorithm to determine the number of pairs of\n> chords that intersect inside the circle. (For example, if the $n$ chords are\n> all diameters that meet at the center, then the correct answer is $\\binom n\n> 2$.) Assume that no two chords share an endpoint.\n\nIt's an interesting algorithm:\n\n```python\ndef count_chords(chords):\n    points = []\n\n    for (start, end) in chords:\n        if start > end:\n            start, end = end, start\n\n        points.append({'kind': 'start', 'x': start})\n        points.append({'kind': 'end', 'x': end, 'start': start})\n\n    points = sorted(points, key=lambda point: point['x'])\n\n    tree = Tree()\n    count = 0\n\n    for point in points:\n        if point['kind'] == 'start':\n            tree.insert(point['x'])\n        else:\n            assert point['kind'] == 'end'\n\n            count += tree.size() - tree.search(point['start']).rank()\n            tree.delete(point['start'])\n\n    return count\n```\n\nFirst, we sort all the points, all while keeping track of whether they are the\nstart or the end of an interval, and how to look up the start from the end\npoint. This takes $\\O(n \\lg n)$ time because of the sort. We can now iterate the\npoints in order.\n\nNext, we need to consider the following invariant:\n\n> If $a$ and $b$ are the start and end of a chord, then it intersects with all\n> chords that have start $s$ such that $a < s < b$ and end $e$ such that $e >\n> b$.\n\nThat is, every chord that starts between the two endpoints of another will\nintersect with it, if it's endpoint is outside this range. Note that this holds\ntrue in the other direction as well ($s < a < e < b$), but this will\ndouble-count the intersection. Thus, we interested only in counting pairs $(a,\nb)$ and $(s, e)$, such that $a < s < b < e$.\n\nThe way we can do that is by iterating over the points and doing the following:\n\n* If we encounter a start point, we insert it into the tree ($\\O(\\lg n)$)\n* If we encounter an end point, we look up the rank of the start point ($\\O(\\lg\n  n)$) and use it to determine how many chords start after it, but have not\n  ended yet, and add it up. Then we remove the start point from the tree\n  ($\\O(\\lg n)$).\n\nEach step is at most an $\\O(\\lg n)$ operation, and since we perform $2n$ of\nthem, the total time is $\\O(n \\lg n)$.\n"
  },
  {
    "path": "other/clrs/14/01/08.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\ndef count_chords(chords):\n    points = []\n\n    for (start, end) in chords:\n        if start > end:\n            start, end = end, start\n\n        points.append({'kind': 'start', 'x': start})\n        points.append({'kind': 'end', 'x': end, 'start': start})\n\n    points = sorted(points, key=lambda point: point['x'])\n\n    tree = Tree()\n    count = 0\n\n    for point in points:\n        if point['kind'] == 'start':\n            tree.insert(point['x'])\n        else:\n            assert point['kind'] == 'end'\n\n            count += tree.size() - tree.search(point['start']).rank()\n            tree.delete(point['start'])\n\n    return count\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nNIL_KEY = object()\n\n\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\n\nclass Node:\n    def __init__(self, color, key, parent, left, right, tree, size):\n        self.color = color\n        self.key = key\n        self.parent = parent\n        self.left = left\n        self.right = right\n        self.tree = tree\n        self.size = size\n\n    def sexp(self):\n        if self.isNil():\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.key}, {self.left}, {self.right})\"\n\n    __str__ = sexp\n\n    def black_height(self):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def isNil(self):\n        return self.key is NIL_KEY\n\n    def isNotNil(self):\n        return not self.isNil()\n\n    def __bool__(self):\n        return self.isNotNil()\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    __getitem__ = child\n    __setitem__ = set_child\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def rotate(self, direction):\n        child = self.other(direction)\n        self[other(direction)] = child[direction]\n\n        if child[direction]:\n            child[direction].parent = self\n\n        child.parent = self.parent\n\n        if not self.parent:\n            self.tree.root = child\n        elif self is self.parent[direction]:\n            self.parent[direction] = child\n        else:\n            self.parent[other(direction)] = child\n\n        child[direction] = self\n        self.parent = child\n\n        child.size = self.size\n        self.size = self.left.size + self.right.size + 1\n\n    def left_rotate(self):\n        self.rotate('left')\n\n    def right_rotate(self):\n        self.rotate('right')\n\n    def transplant(self, other):\n        if not self.parent:\n            self.tree.root = other\n        elif self is self.parent.left:\n            self.parent.left = other\n        else:\n            self.parent.right = other\n        other.parent = self.parent\n\n    def set(self, parent=None, left=None, right=None, color=None):\n        if color:\n            self.color = color\n        if left is not None:\n            self.left = left\n        if right is not None:\n            self.right = right\n        if parent is not None:\n            self.parent = parent\n\n    def minimum(self):\n        node = self\n\n        while node.left:\n            node = node.left\n\n        return node\n\n    def select(self, i):\n        node = self\n\n        while node:\n            rank = node.left.size + 1\n            if i == rank:\n                return node\n            elif i < rank:\n                node = node.left\n            else:\n                i -= rank\n                node = node.right\n\n        assert(False)\n\n    def rank(self):\n        rank = self.left.size + 1\n\n        node = self\n\n        while node.parent:\n            if node == node.parent.right:\n                rank += node.parent.left.size + 1\n            node = node.parent\n\n        return rank\n\n\nnil = Node(Color.BLACK, NIL_KEY, None, None, None, None, 0)\nnil.parent = nil\nnil.left = nil\nnil.right = nil\n\n\nclass Tree:\n    def __init__(self):\n        self.root = nil\n\n    def __str__(self):\n        return self.root.sexp()\n\n    def size(self):\n        return self.root.size\n\n    def search(self, key):\n        node = self.root\n\n        while node:\n            if node.key == key:\n                return node\n            elif key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def select(self, i):\n        return self.root.select(i)\n\n    def insert(self, key):\n        new = Node(Color.RED, key, None, None, None, self, 1)\n        parent = nil\n        node = self.root\n        while node:\n            node.size += 1\n\n            parent = node\n            if new.key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        new.parent = parent\n\n        if not parent:\n            self.root = new\n        elif new.key < parent.key:\n            parent.left = new\n        else:\n            parent.right = new\n\n        new.set(left=nil, right=nil, color=Color.RED)\n\n        self.insert_fixup(new)\n\n    def insert_fixup(self, node):\n        while node.parent.isRed():\n            if node.parent is node.parent.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            if direction == 'left' or direction == 'right':\n                uncle = node.parent.parent[other(direction)]\n                if uncle.isRed():\n                    node.parent.color = Color.BLACK\n                    uncle.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node = node.parent.parent\n                else:\n                    if node is node.parent[other(direction)]:\n                        node = node.parent\n                        node.rotate(direction)\n                    node.parent.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node.parent.parent.rotate(other(direction))\n\n        self.root.color = Color.BLACK\n\n    def delete(self, key):\n        def decrease_ancestor_sizes(node):\n            while node:\n                node.size -= 1\n                node = node.parent\n\n        deleted = self.search(key)\n        y = deleted\n        y_original_color = y.color\n\n        if not deleted.left:\n            decrease_ancestor_sizes(deleted)\n            extra_black = deleted.right\n            deleted.transplant(deleted.right)\n        elif not deleted.right:\n            decrease_ancestor_sizes(deleted)\n            extra_black = deleted.left\n            deleted.transplant(deleted.left)\n        else:\n            y = deleted.right.minimum()\n            y_original_color = y.color\n            extra_black = y.right\n\n            decrease_ancestor_sizes(y)\n\n            if y.parent is deleted:\n                extra_black.parent = y\n            else:\n                y.transplant(y.right)\n                y.right = deleted.right\n                y.right.parent = y\n\n            deleted.transplant(y)\n            y.left = deleted.left\n            y.left.parent = y\n            y.color = deleted.color\n            y.size = y.left.size + y.right.size + 1\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(extra_black)\n\n    def delete_fixup(self, node):\n        while node is not self.root and node.isBlack():\n            if node is node.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            sibling = node.parent[other(direction)]\n\n            if sibling.isRed():\n                sibling.color = Color.BLACK\n                node.parent.color = Color.RED\n                node.parent.rotate(direction)\n                sibling = node.parent[other(direction)]\n\n            if sibling.left.isBlack() and sibling.right.isBlack():\n                sibling.color = Color.RED\n                node = node.parent\n            else:\n                if sibling[other(direction)].isBlack():\n                    sibling[direction].color = Color.BLACK\n                    sibling.color = Color.RED\n                    sibling.rotate(other(direction))\n                    sibling = node.parent[other(direction)]\n\n                sibling.color = node.parent.color\n                node.parent.color = Color.BLACK\n                sibling[other(direction)].color = Color.BLACK\n                sibling.parent.rotate(direction)\n                node = self.root\n\n        node.color = Color.BLACK\n"
  },
  {
    "path": "other/clrs/14/01/08.test.py",
    "content": "import unittest\nimport os.path as path\nimport random\n\nfilename = path.join(path.dirname(__file__), '08.py')\nexec(open(filename).read())\n\n\ndef naive_chord_count(chords):\n    count = 0\n\n    for i in range(len(chords)):\n        for j in range(i + 1, len(chords)):\n            (ia, ib) = chords[i]\n            (ja, jb) = chords[j]\n\n            if ib < ia:\n                ia, ib = ib, ia\n\n            if jb < ja:\n                ja, jb = jb, ja\n\n            if ia <= ja <= ib <= jb or ja <= ia <= jb <= ib:\n                count += 1\n\n    return count\n\n\nclass OrderStatisticTreeTest(unittest.TestCase):\n    def test_diameters(self):\n        def generate_diameters(n):\n            chords = None\n\n            while True:\n                chords = []\n                seen = set()\n\n                for i in range(n):\n                    start = random.random()\n                    end = 0.5 + start\n                    if end >= 1:\n                        end -= 1.0\n\n                    seen.add(start)\n                    seen.add(end)\n\n                    chords.append((start, end))\n\n                if len(seen) == n * 2:\n                    break\n\n            return chords\n\n        n = 50\n        chords = generate_diameters(n)\n\n        self.assertEqual(naive_chord_count(chords), (n * (n - 1)) / 2)\n        self.assertEqual(count_chords(chords), (n * (n - 1)) / 2)\n\n    def test_random_circle(self):\n        def generate_chords(n):\n            chords = None\n\n            while True:\n                chords = []\n                seen = set()\n\n                for i in range(n):\n                    start = random.random()\n                    end = random.random()\n\n                    seen.add(start)\n                    seen.add(end)\n\n                    chords.append((start, end))\n\n                if len(seen) == n * 2:\n                    break\n\n            return chords\n\n        n = 100\n        for _ in range(100):\n            chords = generate_chords(n)\n            self.assertEqual(count_chords(chords), naive_chord_count(chords))\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/02/01.markdown",
    "content": "> Show, by adding pointers to the nodes, how to support each of the dynamic-set\n> queries `MINIMUM`, `MAXIMUM`, `SUCCESSOR`, and `PREDECESSOR` in $\\O(1)$\n> worst-case time on an augmented order-statistic tree. The asymptotic\n> performance of other operations on order-statistic trees should not be\n> affected.\n\nThere's no dark magic here. Nodes just form a doubly-linked list with successor\nand predecessor being the pointers in both directions, and minimum and maximum\nbeing the start end end. Every time we insert a node, it's gonna be the\npredecessor or successor of its parent (depending on whether it's on the left or\nright). We're then just doing a simple linked list insertion/deletion.\n\nThe code below is not as polished as it could be, the problem is not\nparticularly hard either.\n"
  },
  {
    "path": "other/clrs/14/02/01.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nNIL_KEY = object()\n\n\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\n\nclass Node:\n    def __init__(self, color, key, parent, left, right, tree, size, pred, succ):\n        self.color = color\n        self.key = key\n        self.parent = parent\n        self.left = left\n        self.right = right\n        self.tree = tree\n        self.size = size\n        self.predecessor = pred\n        self.successor = succ\n\n    def sexp(self):\n        if self.isNil():\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.key}, {self.left}, {self.right})\"\n\n    __str__ = sexp\n\n    def black_height(self):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def isNil(self):\n        return self.key is NIL_KEY\n\n    def isNotNil(self):\n        return not self.isNil()\n\n    def __bool__(self):\n        return self.isNotNil()\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    __getitem__ = child\n    __setitem__ = set_child\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def rotate(self, direction):\n        child = self.other(direction)\n        self[other(direction)] = child[direction]\n\n        if child[direction]:\n            child[direction].parent = self\n\n        child.parent = self.parent\n\n        if not self.parent:\n            self.tree.root = child\n        elif self is self.parent[direction]:\n            self.parent[direction] = child\n        else:\n            self.parent[other(direction)] = child\n\n        child[direction] = self\n        self.parent = child\n\n        child.size = self.size\n        self.size = self.left.size + self.right.size + 1\n\n    def left_rotate(self):\n        self.rotate('left')\n\n    def right_rotate(self):\n        self.rotate('right')\n\n    def transplant(self, other):\n        if not self.parent:\n            self.tree.root = other\n        elif self is self.parent.left:\n            self.parent.left = other\n        else:\n            self.parent.right = other\n        other.parent = self.parent\n\n    def set(self, parent=None, left=None, right=None, color=None, succ=None, pred=None):\n        if color:\n            self.color = color\n        if left is not None:\n            self.left = left\n        if right is not None:\n            self.right = right\n        if parent is not None:\n            self.parent = parent\n        if succ is not None:\n            self.successor = succ\n        if pred is not None:\n            self.predecessor = pred\n\n    def minimum(self):\n        node = self\n\n        while node.left:\n            node = node.left\n\n        return node\n\n    def select(self, i):\n        node = self\n\n        while node:\n            rank = node.left.size + 1\n            if i == rank:\n                return node\n            elif i < rank:\n                node = node.left\n            else:\n                i -= rank\n                node = node.right\n\n        assert(False)\n\n    def rank(self):\n        rank = self.left.size + 1\n\n        node = self\n\n        while node.parent:\n            if node == node.parent.right:\n                rank += node.parent.left.size + 1\n            node = node.parent\n\n        return rank\n\n\nnil = Node(Color.BLACK, NIL_KEY, None, None, None, None, 0, None, None)\nnil.parent = nil\nnil.left = nil\nnil.right = nil\n\n\nclass Tree:\n    def __init__(self):\n        self.root = nil\n        self.minimum = nil\n        self.maximum = nil\n\n    def __str__(self):\n        return self.root.sexp()\n\n    def search(self, key):\n        node = self.root\n\n        while node:\n            if node.key == key:\n                return node\n            elif key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def select(self, i):\n        return self.root.select(i)\n\n    def insert(self, key):\n        new = Node(Color.RED, key, None, None, None, self, 1, None, None)\n        parent = nil\n        node = self.root\n        while node:\n            node.size += 1\n\n            parent = node\n            if new.key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        new.parent = parent\n\n        if not parent:\n            self.root = new\n        elif new.key < parent.key:\n            parent.left = new\n        else:\n            parent.right = new\n\n        new.set(left=nil, right=nil, color=Color.RED)\n\n        if not new.parent:\n            self.minimum = new\n            self.maximum = new\n        elif new.parent.left is new:\n            new.successor = new.parent\n            new.predecessor = new.parent.predecessor\n\n            new.successor.predecessor = new\n            if new.predecessor:\n                new.predecessor.successor = new\n\n            if self.minimum is new.parent:\n                self.minimum = new\n        else:\n            new.predecessor = new.parent\n            new.successor = new.parent.successor\n\n            new.predecessor.successor = new\n            if new.successor:\n                new.successor.predecessor = new\n\n            if self.maximum is new.parent:\n                self.maximum = new\n\n        self.insert_fixup(new)\n\n        return new\n\n    def insert_fixup(self, node):\n        while node.parent.isRed():\n            if node.parent is node.parent.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            if direction == 'left' or direction == 'right':\n                uncle = node.parent.parent[other(direction)]\n                if uncle.isRed():\n                    node.parent.color = Color.BLACK\n                    uncle.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node = node.parent.parent\n                else:\n                    if node is node.parent[other(direction)]:\n                        node = node.parent\n                        node.rotate(direction)\n                    node.parent.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node.parent.parent.rotate(other(direction))\n\n        self.root.color = Color.BLACK\n\n    def delete(self, key):\n        def decrease_ancestor_sizes(node):\n            while node:\n                node.size -= 1\n                node = node.parent\n\n        deleted = self.search(key)\n        y = deleted\n        y_original_color = y.color\n\n        if not deleted.left:\n            decrease_ancestor_sizes(deleted)\n            extra_black = deleted.right\n            deleted.transplant(deleted.right)\n        elif not deleted.right:\n            decrease_ancestor_sizes(deleted)\n            extra_black = deleted.left\n            deleted.transplant(deleted.left)\n        else:\n            y = deleted.right.minimum()\n            y_original_color = y.color\n            extra_black = y.right\n\n            decrease_ancestor_sizes(y)\n\n            if y.parent is deleted:\n                extra_black.parent = y\n            else:\n                y.transplant(y.right)\n                y.right = deleted.right\n                y.right.parent = y\n\n            deleted.transplant(y)\n            y.left = deleted.left\n            y.left.parent = y\n            y.color = deleted.color\n            y.size = y.left.size + y.right.size + 1\n\n        if self.minimum is deleted:\n            self.minimum = deleted.successor\n        if self.maximum is deleted:\n            self.maximum = deleted.predecessor\n        if deleted.predecessor:\n            deleted.predecessor.successor = deleted.successor\n        if deleted.successor:\n            deleted.successor.predecessor = deleted.predecessor\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(extra_black)\n\n    def delete_fixup(self, node):\n        while node is not self.root and node.isBlack():\n            if node is node.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            sibling = node.parent[other(direction)]\n\n            if sibling.isRed():\n                sibling.color = Color.BLACK\n                node.parent.color = Color.RED\n                node.parent.rotate(direction)\n                sibling = node.parent[other(direction)]\n\n            if sibling.left.isBlack() and sibling.right.isBlack():\n                sibling.color = Color.RED\n                node = node.parent\n            else:\n                if sibling[other(direction)].isBlack():\n                    sibling[direction].color = Color.BLACK\n                    sibling.color = Color.RED\n                    sibling.rotate(other(direction))\n                    sibling = node.parent[other(direction)]\n\n                sibling.color = node.parent.color\n                node.parent.color = Color.BLACK\n                sibling[other(direction)].color = Color.BLACK\n                sibling.parent.rotate(direction)\n                node = self.root\n\n        node.color = Color.BLACK\n"
  },
  {
    "path": "other/clrs/14/02/01.test.py",
    "content": "import unittest\nimport os.path as path\nimport random\n\nfilename = path.join(path.dirname(__file__), '01.py')\nexec(open(filename).read())\n\n\nclass OrderStatisticTreeTest(unittest.TestCase):\n    def test_things(self):\n        tree = Tree()\n\n        two = tree.insert(2)\n\n        self.assertEqual(tree.minimum, two)\n        self.assertEqual(tree.maximum, two)\n\n        three = tree.insert(3)\n        self.assertEqual(tree.minimum, two)\n        self.assertEqual(tree.maximum, three)\n        self.assertEqual(tree.minimum.successor, three)\n\n        one = tree.insert(1)\n        self.assertEqual(tree.minimum, one)\n        self.assertEqual(tree.minimum.successor, two)\n        self.assertEqual(tree.minimum.successor.successor, three)\n\n    def test_rank_when_inserting(self):\n        k = 500\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in range(1, k + 1):\n            self.assertEqual(tree.select(n).key, n)\n            self.assertEqual(tree.search(n).rank(), n)\n\n    def test_rank_when_deleting(self):\n        k = 1000\n        m = 500\n\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        random.shuffle(numbers)\n        remaining = numbers[0:m]\n\n        for n in numbers[m:]:\n            tree.delete(n)\n\n        remaining.sort()\n\n        for (i, n) in enumerate(remaining):\n            i += 1\n            self.assertEqual(tree.select(i).key, n)\n            self.assertEqual(tree.search(n).rank(), i)\n\n    def generate(self, m, n):\n        numbers = list(range(m))\n        random.shuffle(numbers)\n        return numbers[0:n]\n\n    def assertContains(self, tree, numbers):\n        for n in numbers:\n            self.assertIsNotNone(tree.search(n), f\"should contain {n}\")\n            self.assertEqual(tree.search(n).key, n)\n\n    def assertProperties(self, tree):\n        heights = set()\n        for n in tree.nodes():\n            if not n.left or not n.right:\n                heights.add(n.black_height())\n\n            if n.color == Color.RED:\n                self.assertEqual(n.left.color, Color.BLACK)\n                self.assertEqual(n.right.color, Color.BLACK)\n\n        self.assertEqual(len(heights), 1)\n        self.assertEqual(tree.root.color, Color.BLACK)\n\n    def assertForwardWalk(self, tree, numbers):\n        prev = None\n        node = tree.minimum\n\n        for n in sorted(numbers):\n            self.assertEqual(n, node.key)\n            prev = node\n            node = node.successor\n\n        self.assertEqual(prev, tree.maximum)\n\n    def assertBackwardWalk(self, tree, numbers):\n        prev = None\n        node = tree.maximum\n\n        for n in reversed(sorted(numbers)):\n            self.assertEqual(n, node.key)\n            prev = node\n            node = node.predecessor\n\n        self.assertEqual(prev, tree.minimum)\n\n    def test_insertions(self):\n        numbers = self.generate(300, 100)\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertContains(tree, numbers)\n        self.assertForwardWalk(tree, numbers)\n        self.assertBackwardWalk(tree, numbers)\n\n    def test_properties(self):\n        numbers = self.generate(300, 100)\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertProperties(tree)\n        self.assertForwardWalk(tree, numbers)\n        self.assertBackwardWalk(tree, numbers)\n\n    def test_deletion(self):\n        numbers = self.generate(1000, 500)\n        removed = numbers[:]\n        random.shuffle(removed)\n        removed = removed[0:250]\n        remaining = list(set(numbers) - set(removed))\n\n        tree = Tree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in removed:\n            tree.delete(n)\n\n        self.assertContains(tree, remaining)\n\n        for n in removed:\n            self.assertIsNone(tree.search(n))\n\n        self.assertProperties(tree)\n        self.assertForwardWalk(tree, remaining)\n        self.assertBackwardWalk(tree, remaining)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/02/02.markdown",
    "content": "> Can we maintain the black-heights of nodes in a red-black tree as attributes\n> in the nodes of the tree without affecting the asymptotic performance of any\n> of the red-black tree operations? Show how, or argue why not. How about\n> maintaining the depth of nodes?\n\nWe can maintain the black heights, although we need to be careful with the\nvarious recoloring that's happening when we're going up the tree on insertion\nand deletion. Then it's quite simple to do it when rotations happen. I'm not\ngoing to show it, as I don't think it's that interesting.\n\nDepth won't work, because if we remove the root, we may need to update the depth\nof all $n$ nodes.\n"
  },
  {
    "path": "other/clrs/14/02/03.markdown",
    "content": "> $\\star$ Let $\\otimes$ be an associative binary operator, and let $a$ be an\n> attribute maintained in each node of a red-black tree. Suppose that we want to\n> include in each node $x$ an additional attribute $f$ such that $x.f = x_1.a\n> \\otimes x_2.a \\otimes \\cdots \\otimes x_m.a$, where $x_1, x_2, \\ldots, x_m$ is\n> the inorder listing of nodes in the subtree rooted at $x$. Show how to update\n> the $f$ attributes in $\\O(1)$ times after a rotation. Modify your argument\n> slightly to apply it to the $size$ attribute in order-statistic trees.\n\nI'm uncertain about why the star on this exercise.\n\nFundamentally, the problem is nicely aligned so that\n\n$$ x.f = x.left.f \\otimes x.a \\otimes x.right.f $$\n\n...for every $x$ in the tree. In order to get it to work, we need to:\n\n* Recalculate $f$ for each parent of a newly inserted node (before the fixup)\n* Recalculate $f$ for each parent of the newly deleted node (before the fixup)\n* Recalculate $f$ on each rotation, but first recalculating it for the lower\n  node, and then the upper\n\nFor tracking the size, we just have that $a = 1$ for each node other than the\nsentinel $nil$ (where $a = 0$) and $\\otimes = +$.\n\n"
  },
  {
    "path": "other/clrs/14/02/04.markdown",
    "content": "> $\\star$ We wish to augment red-black trees with an operation `RB-ENUMERATE(x,\n> a, b)` that outputs all keys $k$ such that $a \\le k \\le b$ in a red-black tree\n> rooted at $x$. Describe how to implement `RB-ENUMERATE` in $\\Theta(m + \\lg n)$\n> time, where $m$ is the number of keys that are output and $n$ is the number of\n> internal nodes in the tree. (_Hint_: You do not need to add new attributes to\n> the red-black tree.)\n\nI'd write it in code, but I feel I've done that before.\n\nFundamentally, there are two bits:\n\n* We find $a$ in $\\O(\\lg n)$ time.\n\n* We perform an in-order tree walk, but we start from $a$ instead of the minimum\n  element, and we terminate after we find $b$. As per Exercise 12.2-7, we can do\n  that in $m$ time.\n\nAs a reminder, the in-order tree walk can be accomplished without extra storage\nif we keep track of where in the tree we are, and where we are coming from.\nExercise 10.4-5 implements an algorithm for that. We need to modify it slightly\nto work in-order as opposed to depth-first.\n"
  },
  {
    "path": "other/clrs/14/03/01.markdown",
    "content": "> Write pseudocode for `LEFT-ROTATE` that operates on nodes in an interval tree\n> and updates the max attributes in $\\O(1)$ time.\n\nThis is pretty basic – we just update the `max` on the lower node and then update\nthe `max` on the upper node. We set `max` to be `max(node.max,\nnode.left.interval.high, node.right.interval.high)` where we need to be careful\nto exclude nil values.\n"
  },
  {
    "path": "other/clrs/14/03/01.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\nclass Interval:\n    def __init__(self, low, high):\n        assert low <= high\n        self.low = low\n        self.high = high\n\n    def __eq__(self, other):\n        return isinstance(other, Interval) and self.low == other.low and \\\n            self.high == other.high\n\n    def __contains__(self, n):\n        return self.low <= n <= self.high\n\n    def __repr__(self):\n        return f\"Interval({self.low}, {self.high})\"\n\n    __str__ = __repr__\n\n    def overlaps(self, other):\n        return self.low <= other.high and other.low <= self.high\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nNIL_KEY = object()\n\n\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\ndef max_maybe(*args):\n    return max([arg for arg in args if arg is not None])\n\nclass Node:\n    def __init__(self, color, interval, parent, left, right, max, tree):\n        self.color = color\n        self.interval = interval\n        self.parent = parent\n        self.left = left\n        self.right = right\n        self.tree = tree\n        self.max = max\n\n    def sexp(self):\n        if self.isNil():\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.interval}, max={self.max}, {self.left}, {self.right})\"\n\n    __str__ = sexp\n\n    def black_height(self):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def isNil(self):\n        return self.interval is NIL_KEY\n\n    def isNotNil(self):\n        return not self.isNil()\n\n    def __bool__(self):\n        return self.isNotNil()\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    __getitem__ = child\n    __setitem__ = set_child\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def rotate(self, direction):\n        child = self.other(direction)\n        self[other(direction)] = child[direction]\n\n        if child[direction]:\n            child[direction].parent = self\n\n        child.parent = self.parent\n\n        if not self.parent:\n            self.tree.root = child\n        elif self is self.parent[direction]:\n            self.parent[direction] = child\n        else:\n            self.parent[other(direction)] = child\n\n        child[direction] = self\n        self.parent = child\n\n        self.max = max_maybe(\n            self.interval.high,\n            self.left.max if self.left else None,\n            self.right.max if self.right else None,\n        )\n\n        child.max = max_maybe(\n            child.interval.high,\n            child.left.max if child.left else None,\n            child.right.max if child.right else None,\n        )\n\n    def left_rotate(self):\n        self.rotate('left')\n\n    def right_rotate(self):\n        self.rotate('right')\n\n    def transplant(self, other):\n        if not self.parent:\n            self.tree.root = other\n        elif self is self.parent.left:\n            self.parent.left = other\n        else:\n            self.parent.right = other\n        other.parent = self.parent\n\n    def set(self, parent=None, left=None, right=None, color=None):\n        if color:\n            self.color = color\n        if left is not None:\n            self.left = left\n        if right is not None:\n            self.right = right\n        if parent is not None:\n            self.parent = parent\n\n    def minimum(self):\n        node = self\n\n        while node.left:\n            node = node.left\n\n        return node\n\n\nnil = Node(Color.BLACK, NIL_KEY, None, None, None, None, None)\nnil.parent = nil\nnil.left = nil\nnil.right = nil\n\n\nclass IntervalTree:\n    def __init__(self):\n        self.root = nil\n\n    def __str__(self):\n        return self.root.sexp()\n\n    def find(self, interval):\n        node = self.root\n\n        while node:\n            if node.interval == interval:\n                return node\n            elif interval.low < node.interval.low:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def search(self, interval):\n        node = self.root\n\n        while node:\n            if interval.overlaps(node.interval):\n                return node\n            elif node.left and node.left.max >= interval.low:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def insert(self, interval):\n        new = Node(Color.RED, interval, None, None, None, interval.high, self)\n        parent = nil\n        node = self.root\n        while node:\n            parent = node\n            if new.interval.low < node.interval.low:\n                node = node.left\n            else:\n                node = node.right\n\n        new.parent = parent\n\n        if not parent:\n            self.root = new\n        elif new.interval.low < parent.interval.low:\n            parent.left = new\n        else:\n            parent.right = new\n\n        new.set(left=nil, right=nil, color=Color.RED)\n\n        self.max_fixup(parent)\n\n        self.insert_fixup(new)\n\n    def max_fixup(self, node):\n        while node:\n            node.max = max_maybe(\n                node.interval.high,\n                node.left.max if node.left else None,\n                node.right.max if node.right else None\n            )\n\n            node = node.parent\n\n    def insert_fixup(self, node):\n        while node.parent.isRed():\n            if node.parent is node.parent.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            if direction == 'left' or direction == 'right':\n                uncle = node.parent.parent[other(direction)]\n                if uncle.isRed():\n                    node.parent.color = Color.BLACK\n                    uncle.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node = node.parent.parent\n                else:\n                    if node is node.parent[other(direction)]:\n                        node = node.parent\n                        node.rotate(direction)\n                    node.parent.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node.parent.parent.rotate(other(direction))\n\n        self.root.color = Color.BLACK\n\n    def delete(self, interval):\n        deleted = self.find(interval)\n        y = deleted\n        y_original_color = y.color\n\n        if not deleted.left:\n            extra_black = deleted.right\n            deleted.transplant(deleted.right)\n            self.max_fixup(deleted)\n        elif not deleted.right:\n            extra_black = deleted.left\n            deleted.transplant(deleted.left)\n            self.max_fixup(deleted)\n        else:\n            y = deleted.right.minimum()\n            y_original_color = y.color\n            extra_black = y.right\n\n            todo = None\n\n            if y.parent is deleted:\n                extra_black.parent = y\n            else:\n                todo = y.parent\n                y.transplant(y.right)\n                y.right = deleted.right\n                y.right.parent = y\n\n            deleted.transplant(y)\n            y.left = deleted.left\n            y.left.parent = y\n            y.color = deleted.color\n\n            self.max_fixup(todo or y)\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(extra_black)\n\n    def delete_fixup(self, node):\n        while node is not self.root and node.isBlack():\n            if node is node.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            sibling = node.parent[other(direction)]\n\n            if sibling.isRed():\n                sibling.color = Color.BLACK\n                node.parent.color = Color.RED\n                node.parent.rotate(direction)\n                sibling = node.parent[other(direction)]\n\n            if sibling.left.isBlack() and sibling.right.isBlack():\n                sibling.color = Color.RED\n                node = node.parent\n            else:\n                if sibling[other(direction)].isBlack():\n                    sibling[direction].color = Color.BLACK\n                    sibling.color = Color.RED\n                    sibling.rotate(other(direction))\n                    sibling = node.parent[other(direction)]\n\n                sibling.color = node.parent.color\n                node.parent.color = Color.BLACK\n                sibling[other(direction)].color = Color.BLACK\n                sibling.parent.rotate(direction)\n                node = self.root\n\n        node.color = Color.BLACK\n"
  },
  {
    "path": "other/clrs/14/03/01.test.py",
    "content": "import unittest\nimport random\nimport os.path as path\n\nfilename = path.join(path.dirname(__file__), '01.py')\nexec(open(filename).read())\n\n\nclass IntervalTest(unittest.TestCase):\n    def test_contains(self):\n        interval = Interval(5, 10)\n        self.assertTrue(7 in interval)\n        self.assertTrue(5 in interval)\n        self.assertTrue(10 in interval)\n        self.assertTrue(4 not in interval)\n        self.assertTrue(11 not in interval)\n\n    def test_overlaps(self):\n        self.assertTrue(Interval(5, 10).overlaps(Interval(2, 7)))\n        self.assertTrue(Interval(5, 10).overlaps(Interval(7, 9)))\n        self.assertTrue(Interval(5, 10).overlaps(Interval(7, 13)))\n\n        self.assertFalse(Interval(5, 10).overlaps(Interval(1, 4)))\n        self.assertFalse(Interval(5, 10).overlaps(Interval(11, 15)))\n\n\nclass IntervalTreeTest(unittest.TestCase):\n    def test_simple_interval_tree(self):\n        tree = IntervalTree()\n        three_to_five = Interval(3, 5)\n        seven_to_nine = Interval(7, 9)\n        eleven_to_thirteen = Interval(11, 13)\n\n        def point(n):\n            return Interval(n, n)\n\n        tree.insert(three_to_five)\n        tree.insert(seven_to_nine)\n        tree.insert(eleven_to_thirteen)\n\n        self.assertIsNone(tree.search(point(1)))\n        self.assertIsNone(tree.search(point(2)))\n\n        self.assertIs(tree.search(point(4)).interval, three_to_five)\n        self.assertIs(tree.search(point(3)).interval, three_to_five)\n        self.assertIs(tree.search(point(5)).interval, three_to_five)\n\n        self.assertIsNone(tree.search(point(6)))\n\n        self.assertIs(tree.search(point(7)).interval, seven_to_nine)\n        self.assertIs(tree.search(point(8)).interval, seven_to_nine)\n        self.assertIs(tree.search(point(9)).interval, seven_to_nine)\n\n        self.assertIsNone(tree.search(point(10)))\n\n        self.assertIs(tree.search(point(11)).interval, eleven_to_thirteen)\n        self.assertIs(tree.search(point(12)).interval, eleven_to_thirteen)\n        self.assertIs(tree.search(point(13)).interval, eleven_to_thirteen)\n\n        self.assertIsNone(tree.search(point(14)))\n        self.assertIsNone(tree.search(point(15)))\n\n        self.assertProperties(tree)\n\n    def test_overlapping(self):\n        tree = IntervalTree()\n        tree.insert(Interval(5, 6))\n        tree.insert(Interval(1, 20))\n        tree.insert(Interval(10, 12))\n\n        self.assertIsNotNone(tree.search(Interval(18, 19)))\n\n        self.assertProperties(tree)\n\n    def test_properties(self):\n        k = 20000\n        n = 800\n        w = 50\n        d = 300\n        starts = list(range(0, k))\n        random.shuffle(starts)\n        starts = starts[0:n]\n        intervals = []\n\n        tree = IntervalTree()\n\n        for low in starts:\n            high = low + random.randint(0, min(w, k - low))\n            interval = Interval(low, high)\n            intervals.append(interval)\n            tree.insert(interval)\n            self.assertProperties(tree)\n\n        self.assertProperties(tree)\n\n        random.shuffle(intervals)\n        intervals = intervals[0:d]\n\n        for interval in intervals:\n            tree.delete(interval)\n            self.assertProperties(tree)\n\n\n    def assertProperties(self, tree):\n        def check_max(node):\n            numbers = [node.interval.high]\n\n            if node.left:\n                numbers.append(check_max(node.left))\n                self.assertTrue(node.left.interval.low < node.interval.low)\n\n            if node.right:\n                numbers.append(check_max(node.right))\n                self.assertTrue(node.interval.low < node.right.interval.low)\n\n            self.assertEqual(node.max, max(numbers))\n\n            return node.max\n\n        if tree.root:\n            check_max(tree.root)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/03/02.markdown",
    "content": "> Rewrite the code for `INTERVAL-SEARCH` so that it works properly when all\n> intervals are open.\n\nThis is pretty minor, and I'm not gonna bother doing the full thing. We need to\ndo to things to the code in Exercise 14.3-1:\n\n* change the definition of `overlaps` to exclude the boundary conditions, that\n  is, change `<=` to `<` in the comparisons;\n* use `>` instead of `>=` when comparing `node.left.max` and `interval.low` in\n  `Tree.search`.\n"
  },
  {
    "path": "other/clrs/14/03/03.markdown",
    "content": "> Describe an efficient algorithm that, given an interval $i$, returns an\n> interval overlapping $i$ that has the minimum low endpoint, or $T.nil$ if no\n> such interval exists.\n\nThe existing algorithm is almost there – the only addition it needs to be made\nis that in case the current node overlaps with the supplied interval, instead of\nreturning immediately, we need to keep track of the match, and continue left.\nMatches in the left subtree will have smaller low endpoints.\n\nTo keep it simple, we can just keep track of the matches, updating them only\nwhen the lower bound is smaller than the current match.\n"
  },
  {
    "path": "other/clrs/14/03/04.markdown",
    "content": "> Given an interval tree $T$ and an interval $i$, describe how to list all\n> intervals in $T$ that overlap $i$ in $\\O(\\min(n, k \\lg n))$ time, where $k$ is\n> the number of intervals in the output list. (_Hint:_ One simple method makes\n> several queries, modifying the tree between queries. A slightly more\n> complicated method does not modify the tree).\n\nThe simple method would be to remove the interval and search again, until an\ninterval is no longer present.\n\nI struggle to formally establish an upper bound. Intuitively, if $k = n$, that\nis, all intervals overlap with the one that is being searched for, it will\nalways be the root, and removing the root would be a constant operating,\nestablishing $\\O(n)$ complexity. I'm not sure how to reason about this when $k <\nn$ but $n < k \\lg n$. Should pan out, but no idea why.\n\nAn algorithm that does not modify the tree is doable, but the upper bound still\nevades me. Let's explore it nonetheless.\n\nOnce we visit a node, we can check whether it overlaps and add its interval to\nthe result if it does. We're then in a situation in which we may have to explore\nboth branches of the tree. Letting $x$ be the node, we have the following\nconstraints to work with:\n\n* $x.left$ will not contain overlapping intervals if $x.left.max < i.low$.\n* $x.right$ will not contain overlapping intervals unless $[x.int.low,\n  x.right.max]$ overlaps with $i$.\n\nWe can use this to avoid visiting some of the nodes in the tree. The resulting\nalgorithm will certainly be $\\O(n)$, because it does not visit a node more than\nonce. Whether it is $\\O(k \\lg n)$, I have no idea.\n\n```python\ndef search(tree, interval):\n    result = []\n\n    def collect(node):\n        if node.interval.overlaps(interval):\n            result.append(node.interval)\n\n        if node.left and interval.low <= node.left.max:\n            collect(node.left)\n\n        if node.right and Interval(node.interval.low,\n                node.right.max).overlaps(interval):\n            collect(node.right)\n\n    collect(tree.root)\n\n    return result\n```\n"
  },
  {
    "path": "other/clrs/14/03/04.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\nclass Interval:\n    def __init__(self, low, high):\n        assert low <= high\n        self.low = low\n        self.high = high\n\n    def __eq__(self, other):\n        return isinstance(other, Interval) and self.low == other.low and \\\n            self.high == other.high\n\n    def __hash__(self):\n        return hash((self.low, self.high))\n\n    def __contains__(self, n):\n        return self.low <= n <= self.high\n\n    def __repr__(self):\n        return f\"Interval({self.low}, {self.high})\"\n\n    __str__ = __repr__\n\n    def overlaps(self, other):\n        return self.low <= other.high and other.low <= self.high\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nNIL_KEY = object()\n\n\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\ndef max_maybe(*args):\n    return max([arg for arg in args if arg is not None])\n\nclass Node:\n    def __init__(self, color, interval, parent, left, right, max, tree):\n        self.color = color\n        self.interval = interval\n        self.parent = parent\n        self.left = left\n        self.right = right\n        self.tree = tree\n        self.max = max\n\n    def sexp(self):\n        if self.isNil():\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.interval}, max={self.max}, {self.left}, {self.right})\"\n\n    __str__ = sexp\n\n    def black_height(self):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def isNil(self):\n        return self.interval is NIL_KEY\n\n    def isNotNil(self):\n        return not self.isNil()\n\n    def __bool__(self):\n        return self.isNotNil()\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    __getitem__ = child\n    __setitem__ = set_child\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def rotate(self, direction):\n        child = self.other(direction)\n        self[other(direction)] = child[direction]\n\n        if child[direction]:\n            child[direction].parent = self\n\n        child.parent = self.parent\n\n        if not self.parent:\n            self.tree.root = child\n        elif self is self.parent[direction]:\n            self.parent[direction] = child\n        else:\n            self.parent[other(direction)] = child\n\n        child[direction] = self\n        self.parent = child\n\n        self.max = max_maybe(\n            self.interval.high,\n            self.left.max if self.left else None,\n            self.right.max if self.right else None,\n        )\n\n        child.max = max_maybe(\n            child.interval.high,\n            child.left.max if child.left else None,\n            child.right.max if child.right else None,\n        )\n\n    def left_rotate(self):\n        self.rotate('left')\n\n    def right_rotate(self):\n        self.rotate('right')\n\n    def transplant(self, other):\n        if not self.parent:\n            self.tree.root = other\n        elif self is self.parent.left:\n            self.parent.left = other\n        else:\n            self.parent.right = other\n        other.parent = self.parent\n\n    def set(self, parent=None, left=None, right=None, color=None):\n        if color:\n            self.color = color\n        if left is not None:\n            self.left = left\n        if right is not None:\n            self.right = right\n        if parent is not None:\n            self.parent = parent\n\n    def minimum(self):\n        node = self\n\n        while node.left:\n            node = node.left\n\n        return node\n\n\nnil = Node(Color.BLACK, NIL_KEY, None, None, None, None, None)\nnil.parent = nil\nnil.left = nil\nnil.right = nil\n\n\nclass IntervalTree:\n    def __init__(self):\n        self.root = nil\n\n    def __str__(self):\n        return self.root.sexp()\n\n    def find(self, interval):\n        node = self.root\n\n        while node:\n            if node.interval == interval:\n                return node\n            elif interval.low < node.interval.low:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def search(self, interval):\n        node = self.root\n\n        while node:\n            if interval.overlaps(node.interval):\n                return node\n            elif node.left and node.left.max >= interval.low:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def search_all(self, interval):\n        result = []\n\n        def collect(node):\n            if node.interval.overlaps(interval):\n                result.append(node.interval)\n\n            if node.left and interval.low <= node.left.max:\n                collect(node.left)\n\n            if node.right and Interval(node.interval.low,\n                    node.right.max).overlaps(interval):\n                collect(node.right)\n\n        collect(self.root)\n\n        return result\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def insert(self, interval):\n        new = Node(Color.RED, interval, None, None, None, interval.high, self)\n        parent = nil\n        node = self.root\n        while node:\n            parent = node\n            if new.interval.low < node.interval.low:\n                node = node.left\n            else:\n                node = node.right\n\n        new.parent = parent\n\n        if not parent:\n            self.root = new\n        elif new.interval.low < parent.interval.low:\n            parent.left = new\n        else:\n            parent.right = new\n\n        new.set(left=nil, right=nil, color=Color.RED)\n\n        self.max_fixup(parent)\n\n        self.insert_fixup(new)\n\n    def max_fixup(self, node):\n        while node:\n            node.max = max_maybe(\n                node.interval.high,\n                node.left.max if node.left else None,\n                node.right.max if node.right else None\n            )\n\n            node = node.parent\n\n    def insert_fixup(self, node):\n        while node.parent.isRed():\n            if node.parent is node.parent.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            if direction == 'left' or direction == 'right':\n                uncle = node.parent.parent[other(direction)]\n                if uncle.isRed():\n                    node.parent.color = Color.BLACK\n                    uncle.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node = node.parent.parent\n                else:\n                    if node is node.parent[other(direction)]:\n                        node = node.parent\n                        node.rotate(direction)\n                    node.parent.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node.parent.parent.rotate(other(direction))\n\n        self.root.color = Color.BLACK\n\n    def delete(self, interval):\n        deleted = self.find(interval)\n        y = deleted\n        y_original_color = y.color\n\n        if not deleted.left:\n            extra_black = deleted.right\n            deleted.transplant(deleted.right)\n            self.max_fixup(deleted)\n        elif not deleted.right:\n            extra_black = deleted.left\n            deleted.transplant(deleted.left)\n            self.max_fixup(deleted)\n        else:\n            y = deleted.right.minimum()\n            y_original_color = y.color\n            extra_black = y.right\n\n            todo = None\n\n            if y.parent is deleted:\n                extra_black.parent = y\n            else:\n                todo = y.parent\n                y.transplant(y.right)\n                y.right = deleted.right\n                y.right.parent = y\n\n            deleted.transplant(y)\n            y.left = deleted.left\n            y.left.parent = y\n            y.color = deleted.color\n\n            self.max_fixup(todo or y)\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(extra_black)\n\n    def delete_fixup(self, node):\n        while node is not self.root and node.isBlack():\n            if node is node.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            sibling = node.parent[other(direction)]\n\n            if sibling.isRed():\n                sibling.color = Color.BLACK\n                node.parent.color = Color.RED\n                node.parent.rotate(direction)\n                sibling = node.parent[other(direction)]\n\n            if sibling.left.isBlack() and sibling.right.isBlack():\n                sibling.color = Color.RED\n                node = node.parent\n            else:\n                if sibling[other(direction)].isBlack():\n                    sibling[direction].color = Color.BLACK\n                    sibling.color = Color.RED\n                    sibling.rotate(other(direction))\n                    sibling = node.parent[other(direction)]\n\n                sibling.color = node.parent.color\n                node.parent.color = Color.BLACK\n                sibling[other(direction)].color = Color.BLACK\n                sibling.parent.rotate(direction)\n                node = self.root\n\n        node.color = Color.BLACK\n"
  },
  {
    "path": "other/clrs/14/03/04.test.py",
    "content": "import unittest\nimport random\nimport os.path as path\n\n\nfilename = path.join(path.dirname(__file__), '04.py')\nexec(open(filename).read())\n\n\nclass IntervalTreeTest(unittest.TestCase):\n    def test_search_all(self):\n        tree = IntervalTree()\n        three_to_five = Interval(3, 5)\n        seven_to_nine = Interval(7, 9)\n        eleven_to_thirteen = Interval(11, 13)\n\n        tree.insert(three_to_five)\n        tree.insert(seven_to_nine)\n        tree.insert(eleven_to_thirteen)\n\n\n        self.assertEqual(set(tree.search_all(Interval(3, 8))),\n                         {three_to_five, seven_to_nine})\n\n        self.assertEqual(set(tree.search_all(Interval(7, 10))),\n                         {seven_to_nine})\n\n        self.assertEqual(set(tree.search_all(Interval(7, 12))),\n                         {seven_to_nine, eleven_to_thirteen})\n\n        self.assertEqual(set(tree.search_all(Interval(1, 15))),\n                         {three_to_five, seven_to_nine, eleven_to_thirteen})\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/03/05.markdown",
    "content": "> Suggest modifications to the interval-tree procedures to support the new\n> operation `INTERVAL-SEARCH-EXACTLY(T, i)`, where $T$ is an interval tree and\n> $i$ is an interval. The operation should return a pointer to a node $x$ in $T$\n> such that $x.int.low = i.low$ and $x.int.high = i.high$, or $T.nil$ if $T$\n> contains no such code. All operations including `INTERVAL-SEARCH-EXACTLY`\n> should run in $\\O(\\lg n)$ time on a $n$-node interval tree.\n\nThis only presents a problem if there are intervals with matching $low$ values –\notherwise, it's just a basic binary tree search, looking at $low$ for the key.\nThe solutions of the previous exercises assume that the low endpoints are\ndistinct, so they even provide a function like that.\n\nAssuming that we're not creating a multiset, that is, each interval can be\npresent only once, the trick here is to define a total order on the intervals –\n$i_1 < i_2$ if and only if $(i_1.low, i_1.high) < (i_2.low, i_2.high)$ where the\ncomparison is \"lexicographical\". That is, as long as two intervals have\ndifferent lower bounds, the one that goes more to the left is smaller. If their\nlower bounds match, the one that has less width is the smaller.\n\nWith the ordering defined like that, we simply do a regular search in a BST.\n"
  },
  {
    "path": "other/clrs/14/03/06.markdown",
    "content": "> Show how to maintain a dynamic set $Q$ of numbers that supports the operation\n> `MIN-GAP`, which gives the magnitude of the difference of the two closes\n> numbers in $Q$. For example, if $Q = \\\\{ 1, 5, 9, 15, 18, 22 \\\\}$, then\n> `MIN-GAP(Q)` returns $18 - 15 = 3$, since $15$ and $18$ are the two closest\n> numbers in $Q$. Make the operations `INSERT`, `DELETE`, `SEARCH` and `MIN-GAP`\n> as efficient as possible, and analyze their running times.\n\nThis should be formulaic.\n\nWe store the following extra attributes in each node:\n\n* `minimum` of the subtree rooted at the node\n* `maximum` of the subtree rooted at the node\n* `gap` (minimal one) for the subtree root at the node\n\nWe can calculate the extra attributes for each node in the following way:\n\n* The minimum is the left subtree's minimum if it exist, or the key of the node\n  if it doesn't.\n* The maximum is the right subtree's maximum if it exists, or the key of the\n  node if it doesn't.\n* There are four candidates for the min gap, whichever is smallest is fine.\n  1. The left subtree's min gap, if there is a left node\n  2. The right subtree's min gap, if there is a right node\n  3. `node.key - node.left.maximum`, if there is a left node\n  4. `node.right.minimum - node.key`, if there is a right node\n\nTo maintain invariants, we need to recalculate the extras when:\n\n* We do a rotation\n* We insert a node, starting with the inserted node\n* We delete a node, starting with the lowest node we've moved\n\nThis results in the code below.\n"
  },
  {
    "path": "other/clrs/14/03/06.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nNIL_KEY = object()\n\n\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\n\nclass Extra:\n    def __init__(self, minimum, maximum, gap):\n        self.minimum = minimum\n        self.maximum = maximum\n        self.gap = gap\n\n\nclass Node:\n    def __init__(self, color, key, parent, left, right, extra, tree):\n        self.color = color\n        self.key = key\n        self.parent = parent\n        self.left = left\n        self.right = right\n        self.extra = extra\n        self.tree = tree\n\n    def sexp(self):\n        if self.isNil():\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.key}, {self.left}, {self.right})\"\n\n    __str__ = sexp\n\n    def black_height(self):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def isNil(self):\n        return self.key is NIL_KEY\n\n    def isNotNil(self):\n        return not self.isNil()\n\n    def __bool__(self):\n        return self.isNotNil()\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    __getitem__ = child\n    __setitem__ = set_child\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def rotate(self, direction):\n        child = self.other(direction)\n        self[other(direction)] = child[direction]\n\n        if child[direction]:\n            child[direction].parent = self\n\n        child.parent = self.parent\n\n        if not self.parent:\n            self.tree.root = child\n        elif self is self.parent[direction]:\n            self.parent[direction] = child\n        else:\n            self.parent[other(direction)] = child\n\n        child[direction] = self\n        self.parent = child\n\n        self.recalculate()\n        child.recalculate()\n\n    def left_rotate(self):\n        self.rotate('left')\n\n    def right_rotate(self):\n        self.rotate('right')\n\n    def transplant(self, other):\n        if not self.parent:\n            self.tree.root = other\n        elif self is self.parent.left:\n            self.parent.left = other\n        else:\n            self.parent.right = other\n        other.parent = self.parent\n\n    def set(self, parent=None, left=None, right=None, color=None):\n        if color:\n            self.color = color\n        if left is not None:\n            self.left = left\n        if right is not None:\n            self.right = right\n        if parent is not None:\n            self.parent = parent\n\n    def minimum(self):\n        node = self\n\n        while node.left:\n            node = node.left\n\n        return node\n\n    def maximum(self):\n        node = self\n\n        while node.right:\n            node = node.right\n\n        return node\n\n    def recalculate(self):\n        self.extra.minimum = self.left.extra.minimum if self.left else self.key\n        self.extra.maximum = self.right.extra.maximum if self.right else self.key\n\n        self.extra.gap = min(n for n in [\n            self.left.extra.gap if self.left else None,\n            self.right.extra.gap if self.right else None,\n            self.key - self.left.extra.maximum if self.left else None,\n            self.right.extra.minimum - self.key if self.right else None,\n            float('inf')\n          ] if n is not None)\n\n\nnil = Node(Color.BLACK, NIL_KEY, None, None, None, None, None)\nnil.parent = nil\nnil.left = nil\nnil.right = nil\n\n\nclass MinGapTree:\n    def __init__(self):\n        self.root = nil\n\n    def __str__(self):\n        return self.root.sexp()\n\n    def min_gap(self):\n        return self.root.extra.gap\n\n    def search(self, key):\n        node = self.root\n\n        while node:\n            if node.key == key:\n                return node\n            elif key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def insert(self, key):\n        extra = Extra(minimum=float('inf'), maximum=float('-inf'), gap=float('inf'))\n        new = Node(Color.RED, key, None, None, None, extra, self)\n        parent = nil\n        node = self.root\n        while node:\n            parent = node\n            if new.key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        new.parent = parent\n\n        if not parent:\n            self.root = new\n        elif new.key < parent.key:\n            parent.left = new\n        else:\n            parent.right = new\n\n        new.set(left=nil, right=nil, color=Color.RED)\n\n        self.extras_fixup(new)\n\n        self.insert_fixup(new)\n\n    def insert_fixup(self, node):\n        while node.parent.isRed():\n            if node.parent is node.parent.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            if direction == 'left' or direction == 'right':\n                uncle = node.parent.parent[other(direction)]\n                if uncle.isRed():\n                    node.parent.color = Color.BLACK\n                    uncle.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node = node.parent.parent\n                else:\n                    if node is node.parent[other(direction)]:\n                        node = node.parent\n                        node.rotate(direction)\n                    node.parent.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node.parent.parent.rotate(other(direction))\n\n        self.root.color = Color.BLACK\n\n    def delete(self, key):\n        deleted = self.search(key)\n        y = deleted\n        y_original_color = y.color\n\n        if not deleted.left:\n            extra_black = deleted.right\n            deleted.transplant(deleted.right)\n            self.extras_fixup(deleted)\n        elif not deleted.right:\n            extra_black = deleted.left\n            deleted.transplant(deleted.left)\n            self.extras_fixup(deleted)\n        else:\n            y = deleted.right.minimum()\n            y_original_color = y.color\n            extra_black = y.right\n            to_fix = y\n\n            if y.parent is deleted:\n                extra_black.parent = y\n            else:\n                to_fix = y.parent\n                y.transplant(y.right)\n                y.right = deleted.right\n                y.right.parent = y\n\n            deleted.transplant(y)\n            y.left = deleted.left\n            y.left.parent = y\n            y.color = deleted.color\n\n            self.extras_fixup(to_fix)\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(extra_black)\n\n    def delete_fixup(self, node):\n        while node is not self.root and node.isBlack():\n            if node is node.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            sibling = node.parent[other(direction)]\n\n            if sibling.isRed():\n                sibling.color = Color.BLACK\n                node.parent.color = Color.RED\n                node.parent.rotate(direction)\n                sibling = node.parent[other(direction)]\n\n            if sibling.left.isBlack() and sibling.right.isBlack():\n                sibling.color = Color.RED\n                node = node.parent\n            else:\n                if sibling[other(direction)].isBlack():\n                    sibling[direction].color = Color.BLACK\n                    sibling.color = Color.RED\n                    sibling.rotate(other(direction))\n                    sibling = node.parent[other(direction)]\n\n                sibling.color = node.parent.color\n                node.parent.color = Color.BLACK\n                sibling[other(direction)].color = Color.BLACK\n                sibling.parent.rotate(direction)\n                node = self.root\n\n        node.color = Color.BLACK\n\n    def extras_fixup(self, node):\n        while node:\n            node.recalculate()\n            node = node.parent\n"
  },
  {
    "path": "other/clrs/14/03/06.test.py",
    "content": "import unittest\nimport random\nfrom os import path\n\n\nfilename = path.join(path.dirname(__file__), '06.py')\nexec(open(filename).read())\n\n\nclass MinGapTreeTest(unittest.TestCase):\n    def test_example_from_book(self):\n        tree = MinGapTree()\n        numbers = [1, 5, 9, 15, 18, 22]\n        random.shuffle(numbers)\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertEqual(tree.min_gap(), 3)\n\n        tree.delete(15)\n        self.assertEqual(tree.min_gap(), 4)\n\n        tree.delete(18)\n        self.assertEqual(tree.min_gap(), 4)\n\n        tree.delete(5)\n        self.assertEqual(tree.min_gap(), 8)\n\n        tree.delete(9)\n        self.assertEqual(tree.min_gap(), 21)\n\n    def generate(self, m, n):\n        numbers = list(range(m))\n        random.shuffle(numbers)\n        return numbers[0:n]\n\n    def assertContains(self, tree, numbers):\n        for n in numbers:\n            self.assertIsNotNone(tree.search(n), f\"should contain {n}\")\n            self.assertEqual(tree.search(n).key, n)\n\n    def assertProperties(self, tree):\n        heights = set()\n        for n in tree.nodes():\n            if not n.left or not n.right:\n                heights.add(n.black_height())\n\n            if n.color == Color.RED:\n                self.assertEqual(n.left.color, Color.BLACK)\n                self.assertEqual(n.right.color, Color.BLACK)\n\n            self.assertEqual(n.minimum().key, n.extra.minimum)\n            self.assertEqual(n.maximum().key, n.extra.maximum)\n\n        self.assertEqual(len(heights), 1)\n        self.assertEqual(tree.root.color, Color.BLACK)\n\n    def test_insertions(self):\n        numbers = self.generate(300, 100)\n\n        tree = MinGapTree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertContains(tree, numbers)\n\n    def test_properties(self):\n        numbers = self.generate(300, 100)\n        tree = MinGapTree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertProperties(tree)\n\n    def test_deletion(self):\n        numbers = self.generate(1000, 500)\n        removed = numbers[:]\n        random.shuffle(removed)\n        removed = removed[0:250]\n        remaining = list(set(numbers) - set(removed))\n\n        tree = MinGapTree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in removed:\n            tree.delete(n)\n\n        self.assertContains(tree, remaining)\n\n        for n in removed:\n            self.assertIsNone(tree.search(n))\n\n        self.assertProperties(tree)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/03/07.markdown",
    "content": "> $\\star$ VLSI databases commonly represent an integrated circuit as a list of\n> rectangles. Assume that each rectangle is rectilinearly oriented (sides\n> parallel to the x- and y-axes), so that we represent a rectangle by its\n> minimum and maximum x- and y-coordinates. Give an $\\O(n \\lg n)$-time algorithm\n> to decide whether or not a set of $n$ rectangles so represented contains two\n> rectangles that overlap. Your algorithm need not report all intersecting\n> pairs, but it must report that an overlap exists if one rectangle entirely\n> covers another, even if the boundary lines do not intersect. (_Hint:_ Move a\n> \"sweep\" line across the set of rectangles.)\n\nThis bears similarity to Exercise 14.1-8, only we need an interval tree, instead\nof a order statistic tree.\n\nThe algorithm is the following:\n\n1. We create an array of the left and right edges of each rectangle, tracking\n   the type of edge (left vs right), it's position and the rectangle it refers\n   to – $\\O(n)$ time\n2. We sort the array, ordering left edges before right edges – $\\O(n \\lg n)$\n   time\n3. We create an empty interval tree\n4. We iterate the array – $\\O(n)$ time\n   1. If we encounter a left edge, we construct an interval `[rect.top,\n      rect.bottom]`. We search of it in the interval tree ($\\O(\\lg n)$). If it's\n      present, we can return an overlap. If it's not, we insert it ($\\O(\\lg n)$)\n      and continue\n   2. If we encounter a right edge, we remove the rectangle from the interval\n      tree\n5. If we successfully iterate the array without breaking out, we return no\n   overlap\n"
  },
  {
    "path": "other/clrs/14/03/07.py",
    "content": "from enum import Enum\nfrom collections import deque\n\ndef overlap(rectangles):\n    tree = IntervalTree()\n    edges = []\n    intervals = {}\n\n    for rectangle in rectangles:\n        edges.append({'side': 'left', 'key': rectangle.left, 'rect': rectangle})\n        edges.append({'side': 'right', 'key': rectangle.right, 'rect': rectangle})\n\n    edges.sort(key=lambda r: (r['key'], 0 if r['side'] == 'left' else 1))\n\n    for edge in edges:\n        if edge['side'] == 'left':\n            interval = Interval(edge['rect'].top, edge['rect'].bottom)\n\n            if tree.search(interval):\n                return True\n\n            intervals[edge['rect']] = interval\n            tree.insert(interval)\n        else:\n            assert edge['side'] == 'right'\n            tree.delete(intervals[edge['rect']])\n\n    return False\n\nclass Rectangle:\n    def __init__(self, top, bottom, left, right):\n        assert(top < bottom)\n        assert(left < right)\n\n        self.top = top\n        self.bottom = bottom\n        self.left = left\n        self.right = right\n\n    def overlaps(self, other):\n        return self.top <= other.bottom and other.top <= self.bottom and \\\n            self.left <= other.right and other.left <= self.right\n\n    def __repr__(self):\n        return f\"Rectangle(left={self.left}, right={self.right}, top={self.top}, bottom={self.bottom})\"\n\n\nclass Interval:\n    def __init__(self, low, high):\n        assert low <= high\n        self.low = low\n        self.high = high\n\n    def __eq__(self, other):\n        return isinstance(other, Interval) and self.low == other.low and \\\n            self.high == other.high\n\n    def __contains__(self, n):\n        return self.low <= n <= self.high\n\n    def __repr__(self):\n        return f\"Interval({self.low}, {self.high})\"\n\n    __str__ = __repr__\n\n    def overlaps(self, other):\n        return self.low <= other.high and other.low <= self.high\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nNIL_KEY = object()\n\n\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\ndef max_maybe(*args):\n    return max([arg for arg in args if arg is not None])\n\nclass Node:\n    def __init__(self, color, interval, parent, left, right, max, tree):\n        self.color = color\n        self.interval = interval\n        self.parent = parent\n        self.left = left\n        self.right = right\n        self.tree = tree\n        self.max = max\n\n    def sexp(self):\n        if self.isNil():\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.interval}, max={self.max}, {self.left}, {self.right})\"\n\n    __str__ = sexp\n\n    def black_height(self):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def isNil(self):\n        return self.interval is NIL_KEY\n\n    def isNotNil(self):\n        return not self.isNil()\n\n    def __bool__(self):\n        return self.isNotNil()\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    __getitem__ = child\n    __setitem__ = set_child\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def rotate(self, direction):\n        child = self.other(direction)\n        self[other(direction)] = child[direction]\n\n        if child[direction]:\n            child[direction].parent = self\n\n        child.parent = self.parent\n\n        if not self.parent:\n            self.tree.root = child\n        elif self is self.parent[direction]:\n            self.parent[direction] = child\n        else:\n            self.parent[other(direction)] = child\n\n        child[direction] = self\n        self.parent = child\n\n        self.max = max_maybe(\n            self.interval.high,\n            self.left.max if self.left else None,\n            self.right.max if self.right else None,\n        )\n\n        child.max = max_maybe(\n            child.interval.high,\n            child.left.max if child.left else None,\n            child.right.max if child.right else None,\n        )\n\n    def left_rotate(self):\n        self.rotate('left')\n\n    def right_rotate(self):\n        self.rotate('right')\n\n    def transplant(self, other):\n        if not self.parent:\n            self.tree.root = other\n        elif self is self.parent.left:\n            self.parent.left = other\n        else:\n            self.parent.right = other\n        other.parent = self.parent\n\n    def set(self, parent=None, left=None, right=None, color=None):\n        if color:\n            self.color = color\n        if left is not None:\n            self.left = left\n        if right is not None:\n            self.right = right\n        if parent is not None:\n            self.parent = parent\n\n    def minimum(self):\n        node = self\n\n        while node.left:\n            node = node.left\n\n        return node\n\n\nnil = Node(Color.BLACK, NIL_KEY, None, None, None, None, None)\nnil.parent = nil\nnil.left = nil\nnil.right = nil\n\n\nclass IntervalTree:\n    def __init__(self):\n        self.root = nil\n\n    def __str__(self):\n        return self.root.sexp()\n\n    def find(self, interval):\n        node = self.root\n\n        while node:\n            if node.interval == interval:\n                return node\n            elif interval.low < node.interval.low:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def search(self, interval):\n        node = self.root\n\n        while node:\n            if interval.overlaps(node.interval):\n                return node\n            elif node.left and node.left.max >= interval.low:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def insert(self, interval):\n        new = Node(Color.RED, interval, None, None, None, interval.high, self)\n        parent = nil\n        node = self.root\n        while node:\n            parent = node\n            if new.interval.low < node.interval.low:\n                node = node.left\n            else:\n                node = node.right\n\n        new.parent = parent\n\n        if not parent:\n            self.root = new\n        elif new.interval.low < parent.interval.low:\n            parent.left = new\n        else:\n            parent.right = new\n\n        new.set(left=nil, right=nil, color=Color.RED)\n\n        self.max_fixup(parent)\n\n        self.insert_fixup(new)\n\n    def max_fixup(self, node):\n        while node:\n            node.max = max_maybe(\n                node.interval.high,\n                node.left.max if node.left else None,\n                node.right.max if node.right else None\n            )\n\n            node = node.parent\n\n    def insert_fixup(self, node):\n        while node.parent.isRed():\n            if node.parent is node.parent.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            if direction == 'left' or direction == 'right':\n                uncle = node.parent.parent[other(direction)]\n                if uncle.isRed():\n                    node.parent.color = Color.BLACK\n                    uncle.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node = node.parent.parent\n                else:\n                    if node is node.parent[other(direction)]:\n                        node = node.parent\n                        node.rotate(direction)\n                    node.parent.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node.parent.parent.rotate(other(direction))\n\n        self.root.color = Color.BLACK\n\n    def delete(self, interval):\n        deleted = self.find(interval)\n        y = deleted\n        y_original_color = y.color\n\n        if not deleted.left:\n            extra_black = deleted.right\n            deleted.transplant(deleted.right)\n            self.max_fixup(deleted)\n        elif not deleted.right:\n            extra_black = deleted.left\n            deleted.transplant(deleted.left)\n            self.max_fixup(deleted)\n        else:\n            y = deleted.right.minimum()\n            y_original_color = y.color\n            extra_black = y.right\n\n            todo = y\n\n            if y.parent is deleted:\n                extra_black.parent = y\n            else:\n                todo = y.parent\n                y.transplant(y.right)\n                y.right = deleted.right\n                y.right.parent = y\n\n            deleted.transplant(y)\n            y.left = deleted.left\n            y.left.parent = y\n            y.color = deleted.color\n\n            self.max_fixup(todo)\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(extra_black)\n\n    def delete_fixup(self, node):\n        while node is not self.root and node.isBlack():\n            if node is node.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            sibling = node.parent[other(direction)]\n\n            if sibling.isRed():\n                sibling.color = Color.BLACK\n                node.parent.color = Color.RED\n                node.parent.rotate(direction)\n                sibling = node.parent[other(direction)]\n\n            if sibling.left.isBlack() and sibling.right.isBlack():\n                sibling.color = Color.RED\n                node = node.parent\n            else:\n                if sibling[other(direction)].isBlack():\n                    sibling[direction].color = Color.BLACK\n                    sibling.color = Color.RED\n                    sibling.rotate(other(direction))\n                    sibling = node.parent[other(direction)]\n\n                sibling.color = node.parent.color\n                node.parent.color = Color.BLACK\n                sibling[other(direction)].color = Color.BLACK\n                sibling.parent.rotate(direction)\n                node = self.root\n\n        node.color = Color.BLACK\n"
  },
  {
    "path": "other/clrs/14/03/07.test.py",
    "content": "import unittest\nimport random\nfrom os import path\n\n\nfilename = path.join(path.dirname(__file__), '07.py')\nexec(open(filename).read())\n\n\ndef overlapper(rectangles):\n    for i in range(0, len(rectangles) - 1):\n        one, *others = rectangles[i:]\n        for other in others:\n            if other.overlaps(one):\n                return one\n\n    return None\n\n\nclass OverlapingRectanglesTest(unittest.TestCase):\n    def test_simple_cases(self):\n        self.assertFalse(\n            overlap([\n                Rectangle(left=0, right=10, top=0, bottom=10),\n                Rectangle(left=20, right=30, top=0, bottom=10),\n            ])\n        )\n\n        self.assertTrue(\n            overlap([\n                Rectangle(left=0, right=10, top=0, bottom=10),\n                Rectangle(left=5, right=15, top=5, bottom=15),\n            ])\n        )\n\n    def test_randomly_generated(self):\n        n = 100\n        s = 1000\n        m = 150\n\n        rectangles = []\n        for i in range(0, n):\n            left = random.randint(0, s - 2)\n            right = random.randint(left + 1, min(s, left + m))\n            top = random.randint(0, s - 2)\n            bottom = random.randint(top + 1, min(s, top + m))\n            rectangle = Rectangle(left=left, right=right, top=top, bottom=bottom)\n            rectangles.append(rectangle)\n\n        while target := overlapper(rectangles):\n            self.assertTrue(overlap(rectangles))\n            rectangles.remove(target)\n\n        self.assertFalse(overlap(rectangles))\n\n        random.shuffle(rectangles)\n\n        while len(rectangles):\n            self.assertFalse(overlap(rectangles))\n            rectangles.pop()\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/misc/augmentable_tree.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nNIL_KEY = object()\n\n\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\n\nclass Node:\n    def __init__(self, color, key, parent, left, right, tree):\n        self.color = color\n        self.key = key\n        self.parent = parent\n        self.left = left\n        self.right = right\n        self.tree = tree\n\n    def sexp(self):\n        if self.isNil():\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.key}, {self.left}, {self.right})\"\n\n    def __str__(self):\n        return self.sexp()\n\n    def black_height(self):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def isNil(self):\n        return self.key is NIL_KEY\n\n    def isNotNil(self):\n        return not self.isNil()\n\n    def __bool__(self):\n        return self.isNotNil()\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    __getitem__ = child\n    __setitem__ = set_child\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def rotate(self, direction):\n        child = self.other(direction)\n        self[other(direction)] = child[direction]\n\n        if child[direction]:\n            child[direction].parent = self\n\n        child.parent = self.parent\n\n        if not self.parent:\n            self.tree.root = child\n        elif self is self.parent[direction]:\n            self.parent[direction] = child\n        else:\n            self.parent[other(direction)] = child\n\n        child[direction] = self\n        self.parent = child\n\n        self.tree.recalculate_node(self)\n        self.tree.recalculate_node(child)\n\n    def left_rotate(self):\n        self.rotate('left')\n\n    def right_rotate(self):\n        self.rotate('right')\n\n    def transplant(self, other):\n        if not self.parent:\n            self.tree.root = other\n        elif self is self.parent.left:\n            self.parent.left = other\n        else:\n            self.parent.right = other\n        other.parent = self.parent\n\n    def set(self, parent=None, left=None, right=None, color=None):\n        if color:\n            self.color = color\n        if left is not None:\n            self.left = left\n        if right is not None:\n            self.right = right\n        if parent is not None:\n            self.parent = parent\n\n    def minimum(self):\n        node = self\n\n        while node.left:\n            node = node.left\n\n        return node\n\n\nnil = Node(Color.BLACK, NIL_KEY, None, None, None, None)\nnil.parent = nil\nnil.left = nil\nnil.right = nil\n\n\nclass AugmentableTree:\n    def __init__(self):\n        self.root = nil\n\n    def __str__(self):\n        return self.root.sexp()\n\n    def search(self, key):\n        node = self.root\n\n        while node:\n            if node.key == key:\n                return node\n            elif key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def insert(self, key):\n        new = Node(Color.RED, key, None, None, None, self)\n        self.augment_node(new)\n\n        parent = nil\n        node = self.root\n        while node:\n            parent = node\n            if new.key < node.key:\n                node = node.left\n            else:\n                node = node.right\n\n        new.parent = parent\n\n        if not parent:\n            self.root = new\n        elif new.key < parent.key:\n            parent.left = new\n        else:\n            parent.right = new\n\n        new.set(left=nil, right=nil, color=Color.RED)\n\n        self.recalculate_ancestors(parent)\n\n        self.insert_fixup(new)\n\n    def recalculate_ancestors(self, node):\n        while node:\n            self.recalculate_node(node)\n            node = node.parent\n\n    def insert_fixup(self, node):\n        while node.parent.isRed():\n            if node.parent is node.parent.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            if direction == 'left' or direction == 'right':\n                uncle = node.parent.parent[other(direction)]\n                if uncle.isRed():\n                    node.parent.color = Color.BLACK\n                    uncle.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node = node.parent.parent\n                else:\n                    if node is node.parent[other(direction)]:\n                        node = node.parent\n                        node.rotate(direction)\n                    node.parent.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node.parent.parent.rotate(other(direction))\n\n        self.root.color = Color.BLACK\n\n    def delete(self, key):\n        deleted = self.search(key)\n        y = deleted\n        y_original_color = y.color\n        to_fix = deleted\n\n        if not deleted.left:\n            extra_black = deleted.right\n            deleted.transplant(deleted.right)\n        elif not deleted.right:\n            extra_black = deleted.left\n            deleted.transplant(deleted.left)\n        else:\n            y = deleted.right.minimum()\n            y_original_color = y.color\n            extra_black = y.right\n\n            to_fix = y\n\n            if y.parent is deleted:\n                extra_black.parent = y\n            else:\n                to_fix = y.parent\n                y.transplant(y.right)\n                y.right = deleted.right\n                y.right.parent = y\n\n            deleted.transplant(y)\n            y.left = deleted.left\n            y.left.parent = y\n            y.color = deleted.color\n\n        self.recalculate_ancestors(to_fix)\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(extra_black)\n\n    def delete_fixup(self, node):\n        while node is not self.root and node.isBlack():\n            if node is node.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            sibling = node.parent[other(direction)]\n\n            if sibling.isRed():\n                sibling.color = Color.BLACK\n                node.parent.color = Color.RED\n                node.parent.rotate(direction)\n                sibling = node.parent[other(direction)]\n\n            if sibling.left.isBlack() and sibling.right.isBlack():\n                sibling.color = Color.RED\n                node = node.parent\n            else:\n                if sibling[other(direction)].isBlack():\n                    sibling[direction].color = Color.BLACK\n                    sibling.color = Color.RED\n                    sibling.rotate(other(direction))\n                    sibling = node.parent[other(direction)]\n\n                sibling.color = node.parent.color\n                node.parent.color = Color.BLACK\n                sibling[other(direction)].color = Color.BLACK\n                sibling.parent.rotate(direction)\n                node = self.root\n\n        node.color = Color.BLACK\n"
  },
  {
    "path": "other/clrs/14/misc/augmentable_tree_test.py",
    "content": "import unittest\nfrom augmentable_tree import AugmentableTree, Color\nimport random\n\n\nclass Interval:\n    def __init__(self, low, high):\n        assert low <= high\n        self.low = low\n        self.high = high\n\n    def __eq__(self, other):\n        return isinstance(other, Interval) and self.low == other.low and \\\n            self.high == other.high\n\n    def __lt__(self, other):\n        return self.low < other.low\n\n    def __contains__(self, n):\n        return self.low <= n <= self.high\n\n    def __repr__(self):\n        return f\"Interval({self.low}, {self.high})\"\n\n    __str__ = __repr__\n\n    def overlaps(self, other):\n        return self.low <= other.high and other.low <= self.high\n\n\ndef max_maybe(*args):\n    return max([arg for arg in args if arg is not None])\n\n\nclass IntervalTree(AugmentableTree):\n    def augment_node(self, node):\n        node.interval = node.key\n        node.max = node.interval.high\n\n    def recalculate_node(self, node):\n        node.max = max_maybe(\n            node.interval.high,\n            node.left.max if node.left else None,\n            node.right.max if node.right else None\n        )\n\n    def find(self, interval):\n        node = self.root\n\n        while node:\n            if interval.overlaps(node.interval):\n                return node\n            elif node.left and node.left.max >= interval.low:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n\nclass IntervalTreeTest(unittest.TestCase):\n    def test_simple_interval_tree(self):\n        tree = IntervalTree()\n        three_to_five = Interval(3, 5)\n        seven_to_nine = Interval(7, 9)\n        eleven_to_thirteen = Interval(11, 13)\n\n        def point(n):\n            return Interval(n, n)\n\n        tree.insert(three_to_five)\n        tree.insert(seven_to_nine)\n        tree.insert(eleven_to_thirteen)\n\n        self.assertIsNone(tree.find(point(1)))\n        self.assertIsNone(tree.find(point(2)))\n\n        self.assertIs(tree.find(point(4)).interval, three_to_five)\n        self.assertIs(tree.find(point(3)).interval, three_to_five)\n        self.assertIs(tree.find(point(5)).interval, three_to_five)\n\n        self.assertIsNone(tree.find(point(6)))\n\n        self.assertIs(tree.find(point(7)).interval, seven_to_nine)\n        self.assertIs(tree.find(point(8)).interval, seven_to_nine)\n        self.assertIs(tree.find(point(9)).interval, seven_to_nine)\n\n        self.assertIsNone(tree.find(point(10)))\n\n        self.assertIs(tree.find(point(11)).interval, eleven_to_thirteen)\n        self.assertIs(tree.find(point(12)).interval, eleven_to_thirteen)\n        self.assertIs(tree.find(point(13)).interval, eleven_to_thirteen)\n\n        self.assertIsNone(tree.find(point(14)))\n        self.assertIsNone(tree.find(point(15)))\n\n        self.assertProperties(tree)\n\n    def test_overlapping(self):\n        tree = IntervalTree()\n        tree.insert(Interval(5, 6))\n        tree.insert(Interval(1, 20))\n        tree.insert(Interval(10, 12))\n\n        self.assertIsNotNone(tree.find(Interval(18, 19)))\n\n        self.assertProperties(tree)\n\n    def test_properties(self):\n        k = 20000\n        n = 800\n        w = 50\n        d = 300\n        starts = list(range(0, k))\n        random.shuffle(starts)\n        starts = starts[0:n]\n        intervals = []\n\n        tree = IntervalTree()\n\n        for low in starts:\n            high = low + random.randint(0, min(w, k - low))\n            interval = Interval(low, high)\n            intervals.append(interval)\n            tree.insert(interval)\n            self.assertProperties(tree)\n\n        self.assertProperties(tree)\n\n        random.shuffle(intervals)\n        intervals = intervals[0:d]\n\n        for interval in intervals:\n            tree.delete(interval)\n            self.assertProperties(tree)\n\n\n    def assertProperties(self, tree):\n        def check_max(node):\n            numbers = [node.interval.high]\n\n            if node.left:\n                numbers.append(check_max(node.left))\n                self.assertTrue(node.left.interval.low < node.interval.low)\n\n            if node.right:\n                numbers.append(check_max(node.right))\n                self.assertTrue(node.interval.low < node.right.interval.low)\n\n            self.assertEqual(node.max, max(numbers))\n\n            return node.max\n\n        if tree.root:\n            check_max(tree.root)\n\n\ndef node_size(node):\n    return node.size if node else 0\n\ndef select_node(node, i):\n    while node:\n        rank = node_size(node.left) + 1\n        if i == rank:\n            return node\n        elif i < rank:\n            node = node.left\n        else:\n            i -= rank\n            node = node.right\n\n    assert(False)\n\ndef rank_node(node):\n    rank = node_size(node.left) + 1\n\n    while node.parent:\n        if node == node.parent.right:\n            rank += node_size(node.parent.left) + 1\n        node = node.parent\n\n    return rank\n\n\nclass OrderStatisticTree(AugmentableTree):\n    def augment_node(self, node):\n        node.rank = lambda: rank_node(node)\n        node.select = lambda i: select_node(node, i)\n        node.size = 1\n\n    def recalculate_node(self, node):\n        node.size = 1 + node_size(node.left) + node_size(node.right)\n\n    def select(self, i):\n        return select_node(self.root, i)\n\n\nclass OrderStatisticTreeTest(unittest.TestCase):\n    def test_rank_when_inserting(self):\n        k = 500\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = OrderStatisticTree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in range(1, k + 1):\n            self.assertEqual(tree.select(n).key, n)\n            self.assertEqual(tree.search(n).rank(), n)\n\n    def test_rank_when_deleting(self):\n        k = 1000\n        m = 500\n\n        numbers = list(range(1, k + 1))\n        random.shuffle(numbers)\n\n        tree = OrderStatisticTree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        random.shuffle(numbers)\n        remaining = numbers[0:m]\n\n        for n in numbers[m:]:\n            tree.delete(n)\n\n        remaining.sort()\n\n        for (i, n) in enumerate(remaining):\n            i += 1\n            self.assertEqual(tree.select(i).key, n)\n            self.assertEqual(tree.search(n).rank(), i)\n\n    def generate(self, m, n):\n        numbers = list(range(m))\n        random.shuffle(numbers)\n        return numbers[0:n]\n\n    def assertContains(self, tree, numbers):\n        for n in numbers:\n            self.assertIsNotNone(tree.search(n), f\"should contain {n}\")\n            self.assertEqual(tree.search(n).key, n)\n\n    def assertProperties(self, tree):\n        heights = set()\n        for n in tree.nodes():\n            if not n.left or not n.right:\n                heights.add(n.black_height())\n\n            if n.color == Color.RED:\n                self.assertEqual(n.left.color, Color.BLACK)\n                self.assertEqual(n.right.color, Color.BLACK)\n\n        self.assertEqual(len(heights), 1)\n        self.assertEqual(tree.root.color, Color.BLACK)\n\n    def test_insertions(self):\n        numbers = self.generate(300, 100)\n\n        tree = OrderStatisticTree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertContains(tree, numbers)\n\n    def test_properties(self):\n        numbers = self.generate(300, 100)\n        tree = OrderStatisticTree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        self.assertProperties(tree)\n\n    def test_deletion(self):\n        numbers = self.generate(1000, 500)\n        removed = numbers[:]\n        random.shuffle(removed)\n        removed = removed[0:250]\n        remaining = list(set(numbers) - set(removed))\n\n        tree = OrderStatisticTree()\n\n        for n in numbers:\n            tree.insert(n)\n\n        for n in removed:\n            tree.delete(n)\n\n        self.assertContains(tree, remaining)\n\n        for n in removed:\n            self.assertIsNone(tree.search(n))\n\n        self.assertProperties(tree)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/misc/interval_tree.py",
    "content": "from enum import Enum\nfrom collections import deque\n\n\nclass Interval:\n    def __init__(self, low, high):\n        assert low <= high\n        self.low = low\n        self.high = high\n\n    def __eq__(self, other):\n        return isinstance(other, Interval) and self.low == other.low and \\\n            self.high == other.high\n\n    def __contains__(self, n):\n        return self.low <= n <= self.high\n\n    def __repr__(self):\n        return f\"Interval({self.low}, {self.high})\"\n\n    __str__ = __repr__\n\n    def overlaps(self, other):\n        return self.low <= other.high and other.low <= self.high\n\n\nclass Color(Enum):\n    RED = 1\n    BLACK = 2\n\n\nNIL_KEY = object()\n\n\ndef other(direction):\n    if direction == 'left':\n        return 'right'\n    elif direction == 'right':\n        return 'left'\n    else:\n        assert(False)\n\ndef max_maybe(*args):\n    return max([arg for arg in args if arg is not None])\n\nclass Node:\n    def __init__(self, color, interval, parent, left, right, max, tree):\n        self.color = color\n        self.interval = interval\n        self.parent = parent\n        self.left = left\n        self.right = right\n        self.tree = tree\n        self.max = max\n\n    def sexp(self):\n        if self.isNil():\n            return 'NIL'\n\n        color = 'R' if self.color == Color.RED else 'B'\n\n        return f\"{color}({self.interval}, max={self.max}, {self.left}, {self.right})\"\n\n    __str__ = sexp\n\n    def black_height(self):\n        node = self\n        height = 0\n\n        while node is not nil:\n            if node.color == Color.BLACK:\n                height += 1\n            node = node.parent\n\n        return height\n\n    def isRed(self):\n        return self.color == Color.RED\n\n    def isBlack(self):\n        return self.color == Color.BLACK\n\n    def isNil(self):\n        return self.interval is NIL_KEY\n\n    def isNotNil(self):\n        return not self.isNil()\n\n    def __bool__(self):\n        return self.isNotNil()\n\n    def child(self, direction):\n        if direction == 'left':\n            return self.left\n        elif direction == 'right':\n            return self.right\n        else:\n            assert(False)\n\n    def set_child(self, direction, child):\n        if direction == 'left':\n            self.left = child\n        elif direction == 'right':\n            self.right = child\n        else:\n            assert(False)\n\n    __getitem__ = child\n    __setitem__ = set_child\n\n    def other(self, direction):\n        return self.child(other(direction))\n\n    def rotate(self, direction):\n        child = self.other(direction)\n        self[other(direction)] = child[direction]\n\n        if child[direction]:\n            child[direction].parent = self\n\n        child.parent = self.parent\n\n        if not self.parent:\n            self.tree.root = child\n        elif self is self.parent[direction]:\n            self.parent[direction] = child\n        else:\n            self.parent[other(direction)] = child\n\n        child[direction] = self\n        self.parent = child\n\n        self.max = max_maybe(\n            self.interval.high,\n            self.left.max if self.left else None,\n            self.right.max if self.right else None,\n        )\n\n        child.max = max_maybe(\n            child.interval.high,\n            child.left.max if child.left else None,\n            child.right.max if child.right else None,\n        )\n\n    def left_rotate(self):\n        self.rotate('left')\n\n    def right_rotate(self):\n        self.rotate('right')\n\n    def transplant(self, other):\n        if not self.parent:\n            self.tree.root = other\n        elif self is self.parent.left:\n            self.parent.left = other\n        else:\n            self.parent.right = other\n        other.parent = self.parent\n\n    def set(self, parent=None, left=None, right=None, color=None):\n        if color:\n            self.color = color\n        if left is not None:\n            self.left = left\n        if right is not None:\n            self.right = right\n        if parent is not None:\n            self.parent = parent\n\n    def minimum(self):\n        node = self\n\n        while node.left:\n            node = node.left\n\n        return node\n\n\nnil = Node(Color.BLACK, NIL_KEY, None, None, None, None, None)\nnil.parent = nil\nnil.left = nil\nnil.right = nil\n\n\nclass IntervalTree:\n    def __init__(self):\n        self.root = nil\n\n    def __str__(self):\n        return self.root.sexp()\n\n    def find(self, interval):\n        node = self.root\n\n        while node:\n            if node.interval == interval:\n                return node\n            elif interval.low < node.interval.low:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def search(self, interval):\n        node = self.root\n\n        while node:\n            if interval.overlaps(node.interval):\n                return node\n            elif node.left and node.left.max >= interval.low:\n                node = node.left\n            else:\n                node = node.right\n\n        return None\n\n    def nodes(self):\n        items = deque()\n\n        if self.root:\n            items.append(self.root)\n\n        while items:\n            node = items.popleft()\n\n            yield node\n\n            if node.left:\n                items.append(node.left)\n\n            if node.right:\n                items.append(node.right)\n\n    def insert(self, interval):\n        new = Node(Color.RED, interval, None, None, None, interval.high, self)\n        parent = nil\n        node = self.root\n        while node:\n            parent = node\n            if new.interval.low < node.interval.low:\n                node = node.left\n            else:\n                node = node.right\n\n        new.parent = parent\n\n        if not parent:\n            self.root = new\n        elif new.interval.low < parent.interval.low:\n            parent.left = new\n        else:\n            parent.right = new\n\n        new.set(left=nil, right=nil, color=Color.RED)\n\n        self.max_fixup(parent)\n\n        self.insert_fixup(new)\n\n    def max_fixup(self, node):\n        while node:\n            node.max = max_maybe(\n                node.interval.high,\n                node.left.max if node.left else None,\n                node.right.max if node.right else None\n            )\n\n            node = node.parent\n\n    def insert_fixup(self, node):\n        while node.parent.isRed():\n            if node.parent is node.parent.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            if direction == 'left' or direction == 'right':\n                uncle = node.parent.parent[other(direction)]\n                if uncle.isRed():\n                    node.parent.color = Color.BLACK\n                    uncle.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node = node.parent.parent\n                else:\n                    if node is node.parent[other(direction)]:\n                        node = node.parent\n                        node.rotate(direction)\n                    node.parent.color = Color.BLACK\n                    node.parent.parent.color = Color.RED\n                    node.parent.parent.rotate(other(direction))\n\n        self.root.color = Color.BLACK\n\n    def delete(self, interval):\n        deleted = self.find(interval)\n        y = deleted\n        y_original_color = y.color\n        to_fix = deleted\n\n        if not deleted.left:\n            extra_black = deleted.right\n            deleted.transplant(deleted.right)\n        elif not deleted.right:\n            extra_black = deleted.left\n            deleted.transplant(deleted.left)\n        else:\n            y = deleted.right.minimum()\n            y_original_color = y.color\n            extra_black = y.right\n\n            to_fix = y\n\n            if y.parent is deleted:\n                extra_black.parent = y\n            else:\n                to_fix = y.parent\n                y.transplant(y.right)\n                y.right = deleted.right\n                y.right.parent = y\n\n            deleted.transplant(y)\n            y.left = deleted.left\n            y.left.parent = y\n            y.color = deleted.color\n\n        self.max_fixup(to_fix)\n\n        if y_original_color == Color.BLACK:\n            self.delete_fixup(extra_black)\n\n    def delete_fixup(self, node):\n        while node is not self.root and node.isBlack():\n            if node is node.parent.left:\n                direction = 'left'\n            else:\n                direction = 'right'\n\n            sibling = node.parent[other(direction)]\n\n            if sibling.isRed():\n                sibling.color = Color.BLACK\n                node.parent.color = Color.RED\n                node.parent.rotate(direction)\n                sibling = node.parent[other(direction)]\n\n            if sibling.left.isBlack() and sibling.right.isBlack():\n                sibling.color = Color.RED\n                node = node.parent\n            else:\n                if sibling[other(direction)].isBlack():\n                    sibling[direction].color = Color.BLACK\n                    sibling.color = Color.RED\n                    sibling.rotate(other(direction))\n                    sibling = node.parent[other(direction)]\n\n                sibling.color = node.parent.color\n                node.parent.color = Color.BLACK\n                sibling[other(direction)].color = Color.BLACK\n                sibling.parent.rotate(direction)\n                node = self.root\n\n        node.color = Color.BLACK\n"
  },
  {
    "path": "other/clrs/14/misc/interval_tree_test.py",
    "content": "import unittest\nfrom interval_tree import IntervalTree, Color, Interval\nimport random\n\n\nclass IntervalTest(unittest.TestCase):\n    def test_contains(self):\n        interval = Interval(5, 10)\n        self.assertTrue(7 in interval)\n        self.assertTrue(5 in interval)\n        self.assertTrue(10 in interval)\n        self.assertTrue(4 not in interval)\n        self.assertTrue(11 not in interval)\n\n    def test_overlaps(self):\n        self.assertTrue(Interval(5, 10).overlaps(Interval(2, 7)))\n        self.assertTrue(Interval(5, 10).overlaps(Interval(7, 9)))\n        self.assertTrue(Interval(5, 10).overlaps(Interval(7, 13)))\n\n        self.assertFalse(Interval(5, 10).overlaps(Interval(1, 4)))\n        self.assertFalse(Interval(5, 10).overlaps(Interval(11, 15)))\n\n\nclass IntervalTreeTest(unittest.TestCase):\n    def test_simple_interval_tree(self):\n        tree = IntervalTree()\n        three_to_five = Interval(3, 5)\n        seven_to_nine = Interval(7, 9)\n        eleven_to_thirteen = Interval(11, 13)\n\n        def point(n):\n            return Interval(n, n)\n\n        tree.insert(three_to_five)\n        tree.insert(seven_to_nine)\n        tree.insert(eleven_to_thirteen)\n\n        self.assertIsNone(tree.search(point(1)))\n        self.assertIsNone(tree.search(point(2)))\n\n        self.assertIs(tree.search(point(4)).interval, three_to_five)\n        self.assertIs(tree.search(point(3)).interval, three_to_five)\n        self.assertIs(tree.search(point(5)).interval, three_to_five)\n\n        self.assertIsNone(tree.search(point(6)))\n\n        self.assertIs(tree.search(point(7)).interval, seven_to_nine)\n        self.assertIs(tree.search(point(8)).interval, seven_to_nine)\n        self.assertIs(tree.search(point(9)).interval, seven_to_nine)\n\n        self.assertIsNone(tree.search(point(10)))\n\n        self.assertIs(tree.search(point(11)).interval, eleven_to_thirteen)\n        self.assertIs(tree.search(point(12)).interval, eleven_to_thirteen)\n        self.assertIs(tree.search(point(13)).interval, eleven_to_thirteen)\n\n        self.assertIsNone(tree.search(point(14)))\n        self.assertIsNone(tree.search(point(15)))\n\n        self.assertProperties(tree)\n\n    def test_overlapping(self):\n        tree = IntervalTree()\n        tree.insert(Interval(5, 6))\n        tree.insert(Interval(1, 20))\n        tree.insert(Interval(10, 12))\n\n        self.assertIsNotNone(tree.search(Interval(18, 19)))\n\n        self.assertProperties(tree)\n\n    def test_properties(self):\n        k = 20000\n        n = 800\n        w = 50\n        d = 300\n        starts = list(range(0, k))\n        random.shuffle(starts)\n        starts = starts[0:n]\n        intervals = []\n\n        tree = IntervalTree()\n\n        for low in starts:\n            high = low + random.randint(0, min(w, k - low))\n            interval = Interval(low, high)\n            intervals.append(interval)\n            tree.insert(interval)\n            self.assertProperties(tree)\n\n        self.assertProperties(tree)\n\n        random.shuffle(intervals)\n        intervals = intervals[0:d]\n\n        for interval in intervals:\n            tree.delete(interval)\n            self.assertProperties(tree)\n\n\n    def assertProperties(self, tree):\n        def check_max(node):\n            numbers = [node.interval.high]\n\n            if node.left:\n                numbers.append(check_max(node.left))\n                self.assertTrue(node.left.interval.low < node.interval.low)\n\n            if node.right:\n                numbers.append(check_max(node.right))\n                self.assertTrue(node.interval.low < node.right.interval.low)\n\n            self.assertEqual(node.max, max(numbers))\n\n            return node.max\n\n        if tree.root:\n            check_max(tree.root)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/misc/order_statistic_tree.py",
    "content": "from augmentable_tree import AugmentableTree\n\ndef node_size(node):\n    return node.size if node else 0\n\ndef select_node(node, i):\n    while node:\n        rank = node_size(node.left) + 1\n        if i == rank:\n            return node\n        elif i < rank:\n            node = node.left\n        else:\n            i -= rank\n            node = node.right\n\n    assert(False)\n\ndef rank_node(node):\n    rank = node_size(node.left) + 1\n\n    while node.parent:\n        if node == node.parent.right:\n            rank += node_size(node.parent.left) + 1\n        node = node.parent\n\n    return rank\n\n\nclass OrderStatisticTree(AugmentableTree):\n    def augment_node(self, node):\n        node.rank = lambda: rank_node(node)\n        node.select = lambda i: select_node(node, i)\n        node.size = 1\n\n    def recalculate_node(self, node):\n        node.size = 1 + node_size(node.left) + node_size(node.right)\n\n    def select(self, i):\n        return select_node(self.root, i)\n"
  },
  {
    "path": "other/clrs/14/problems/01.markdown",
    "content": "# Point of maximum overlap\n\n> Suppose that we wish to keep track of a **point of maximum overlap** in a set\n> of intervals – a point with the largest number of intervals in the set that\n> overlaps it.\n>\n> <ol type=\"a\">\n>   <li>Show that there will always be a point of maximum overlap that is an\n>   endpoint of one of the segments.\n>   <li>Design a data structure that efficiently supports the operations\n>   <code>INTERVAL-INSERT</code>, <code>INTERVAL-DELETE</code>, and\n>   <code>FIND-POM</code>, which returns a point of maximum overlap.\n>   (<em>Hint:</em> Keep a red-black tree of all the endpoints. Associate a\n>   value of +1 with each left endpoint, and associate a value of -1 with each\n>   right endpoint. Augment each node of the tree with some extra information to\n>   maintain the point of maximum overlap.)\n> </ol>\n\n## Maximum overlap at an endpoint\n\nThis is a bit obvious, so as usual, proving it is tricky.\n\nLet $x$ be a maximum overlap point and $S$ be set of the intervals that overlap\naround $x$. Let $I_S$ the intersection of all intervals in $S$, that is:\n\n$$ I_S = \\bigcup\\_{X \\in S} X $$\n\nIf we let $I_S = (a, b)$, that is, for $a$ and $b$ to be the endpoints of the\nintersection, they are also points of maximum overlap. Furthermore, they are the\nendpoint of one of the intervals in $S$ (otherwise $I_S$ would not end there).\n\n## Data structure\n\nAs hinted, the data structure is a red-black tree, where each key is associated\nwith a weight (-1 or 1) depending on whether it's the start or end of an\ninterval. If we represent each set of intervals as a list of -1s and 1s in the\norder of the endpoints, then the largest number of overlapping interval is the\nmaximum of the sums of each sublist.\n\nIf there are duplicate endpoints, we need to order the 1s before the -1s.\n\nA list would not get good performance, however, so we model it as a tree:\n\n* The tree is an ordering of 1s and -1s of all the endpoints.\n* We're looking for a maximum sum of sequential endpoints, and an endpoint that\n  generates it.\n\nNote that each node represent a sublist of the endpoints, that is, there are no\nelements between the minimum and the maximum of the subtree in the full list of\nendpoints that are not present in the subtree.\n\nWe can calculate this efficiently by storing three properties on each node:\n\n1. The sum of all the weights in the subtree rooted at a node.\n2. The maximum weight in attainable by a prefix of the tree\n3. The element that creates this maximum weight\n\nThe first is obvious, and the third is calculated by the second. So the question\nis how we keep calculate the maximum overlap at a subtree, given that we have it\nfor its children.\n\nThere are essentially three cases:\n\n* The maximum overlap is achieved in a suffix of the left subtree\n* The maximum overlap is achieved by entire left subtree plus the endpoint of\n  the node\n* The maximum overlap is achieved by entire left subtree plus the endpoint of\n  the node plus a prefix in the right subtree\n\nThey result in three different things we need to check, which is implemented in\nthe code below\n"
  },
  {
    "path": "other/clrs/14/problems/01.py",
    "content": "import sys, os\nsys.path.append(os.path.join(os.path.dirname(__file__), '..', 'misc'))\n\nfrom augmentable_tree import AugmentableTree\n\nclass Endpoint:\n    def __init__(self, value, weight): self.value, self.weight = value, weight\n    def __lt__(self, other): return (self.value, -self.weight) < (other.value, -other.weight)\n    def __eq__(self, other): return (self.value, self.weight) == (other.value, other.weight)\n    def isLow(self): return self.weight == 1\n\n\ndef weight(node):\n    return node.weight if node else 0\n\n\ndef optimal(node):\n    return node.optimal if node else (0, None)\n\n\nclass OverlapTree(AugmentableTree):\n    def __init__(self, intervals = []):\n        super(OverlapTree, self).__init__()\n\n        for interval in intervals:\n            self.insert_interval(interval)\n\n    def augment_node(self, node):\n        node.optimal = (1, node.key.value) if node.key.isLow() else (0, None)\n        node.weight = node.key.weight\n        node.sexp = lambda: self.print_node(node)\n\n    def recalculate_node(self, node):\n        node.weight = node.key.weight + weight(node.left) + weight(node.right)\n\n        right_optimal = optimal(node.right)\n\n        candidates = [\n            optimal(node.left),\n            (weight(node.left) + node.key.weight, node.key.value),\n            (weight(node.left) + node.key.weight + right_optimal[0], right_optimal[1] or node.key.value),\n        ]\n\n        node.optimal = max(candidates, key=lambda t: t[0])\n\n    def max_overlap(self):\n        return optimal(self.root)[1]\n\n    def insert_interval(self, interval):\n        self.insert(Endpoint(interval.low, 1))\n        self.insert(Endpoint(interval.high, -1))\n\n    def delete_interval(self, interval):\n        self.delete(Endpoint(interval.low, 1))\n        self.delete(Endpoint(interval.high, -1))\n\n"
  },
  {
    "path": "other/clrs/14/problems/01.test.py",
    "content": "import unittest\nimport random\nfrom collections import defaultdict\n\nOverlapTree = __import__('01').OverlapTree\n\nclass Interval:\n    def __init__(self, low, high):\n        self.low = low\n        self.high = high\n\n    def elements(self):\n        return range(self.low, self.high + 1)\n\n\ndef naive_max_overlap(intervals):\n    counts = defaultdict(lambda: 0)\n\n    for interval in intervals:\n        for number in interval.elements():\n            counts[number] += 1\n\n    count = max(counts.values())\n    answer = min(key for key, value in counts.items() if value == count)\n\n    return answer\n\nclass OverlapTreeTest(unittest.TestCase):\n    def test_simple_case(self):\n        intervals = [\n            Interval(0, 6),\n            Interval(3, 7),\n            Interval(4, 10)\n        ]\n\n        tree = OverlapTree(intervals)\n\n        self.assertEqual(naive_max_overlap(intervals), 4)\n        self.assertEqual(tree.max_overlap(), 4)\n\n    def test_random_case(self):\n        n = 100\n        numbers = list(range(0, n * 2))\n        random.shuffle(numbers)\n        intervals = []\n\n        tree = OverlapTree()\n\n        while numbers:\n            low, high = numbers.pop(), numbers.pop()\n            if low > high:\n                low, high = high, low\n\n            interval = Interval(low, high)\n            intervals.append(interval)\n            tree.insert_interval(interval)\n\n        while intervals:\n            endpoint = naive_max_overlap(intervals)\n            self.assertEqual(tree.max_overlap(), endpoint)\n\n            interval, = [i for i in intervals if i.low == endpoint]\n            intervals.remove(interval)\n            tree.delete_interval(interval)\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/14/problems/02.markdown",
    "content": "# Josephus permutation\n\n> We define the **Josephus problem** as follows. Suppose that $n$ people form a\n> circle and that we are given a positive integer $m \\le n$. Beginning with a\n> designated first person, we proceed around the circle, removing every $m$th\n> person. After each person is removed, counting continues around the circle\n> that remains. This process continues until we have removed all $n$ people. The\n> order in which the people are removed from the circle defines the\n> **$(n,m)$-Josephus permutation** of integers $1, 2, \\ldots, n$. For example,\n> the $(7, 3)$-Josephus permutation is $\\langle 3, 6, 2, 7, 5, 1, 4 \\rangle$.\n>\n> <ol type=\"a\">\n>   <li>Suppose that $m$ is a constant. Describe an $\\O(n)$-time algorithm that,\n>   given an integer $n$, outputs the $(n, m)$-Josephus permutation.\n>   <li>Suppose that $m$ is not a constant. Describe an $\\O(n \\lg n)$-time\n>   algorithm that, given all integers $n$ and $m$, outputs the $(n,\n>   m)$-Josephus permutation.\n> </ol>\n\n## Constant $m$\n\nThis is a very evil way to spell \"an $\\O(mn)$-time algorithm\". I honestly got\nstuck here, until I realized that the point was to have a simpler algorithm that\ndoes not take $m$ into account.\n\nThus, it's simple:\n\n1. Put all the numbers in a linked list and make it circular\n2. Start with the first number and loop until you empty the list\n3. Output the current number, remove it from the list, an advance $m$ times.\n\nAt some point you end up removing the last number, which means we're done. It's\nnot that hard to implement, so I would not bother.\n\n## $\\O(n \\lg n)$ time\n\nEasy-peasy.\n\nFirst of all, we need to use an order statistic tree. Then, we simply start with\nselecting the $m$-th element, output it, delete it, and then look $m$ elements\nahead, wrapping around with some modulo arithmetic and accounting for the\ndeleted element.\n\nPython code below. Note that the index awkwardness is due to the 1-based\nindexing of our ranks. Note as well that we don't just need `OS-SELECT`, but\nalso the size property of the tree/root.\n"
  },
  {
    "path": "other/clrs/14/problems/02.py",
    "content": "import sys, os\nsys.path.append(os.path.join(os.path.dirname(__file__), '..', 'misc'))\n\nfrom order_statistic_tree import OrderStatisticTree\n\ndef josephus(n, m):\n    tree = OrderStatisticTree()\n\n    for i in list(range(1, n + 1)):\n        tree.insert(i)\n\n    current = 1\n    result = []\n\n    while tree.root:\n        current = (current + m - 2) % tree.root.size + 1\n        node = tree.select(current)\n        result.append(node.key)\n        tree.delete(node.key)\n\n    return tuple(result)\n\n\n"
  },
  {
    "path": "other/clrs/14/problems/02.test.py",
    "content": "import unittest\nimport random\nfrom collections import defaultdict\n\n\njosephus = __import__('02').josephus\n\n\ndef naive_josephus(n, m):\n    items = list(range(1, n + 1))\n    current = 0\n    result = []\n\n    while items:\n        current = (current + m - 1) % len(items)\n        result.append(items[current])\n        del items[current]\n\n    return tuple(result)\n\n\nclass JosephusTest(unittest.TestCase):\n    def test_simple_permutation(self):\n        self.assertEqual(josephus(7, 3), (3, 6, 2, 7, 5, 1, 4))\n\n    def test_permutations(self):\n        n = 50\n        for m in range(1, n):\n            self.assertEqual(josephus(n, m), naive_josephus(n, m))\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/15/01/01.markdown",
    "content": "> Show that equation (15.4) follows from equation (15.3) and the initial\n> condition $T(0) = 1$.\n\nLet's first prove the rather obvious:\n\n$$ A(n) = \\sum_{i=0}^{n} 2^i = 2^{n+1} - 1 $$\n\nWe do this by induction. It's clear that $A(0) = 2^0 = 1 = 2^1 - 1$ and even\n$A(1) = 2^0 + 2^1 = 1 + 2 = 3 = 2^2 - 1$. Assuming it holds for numbers up to\n$n$, if we look at $A(n + 1)$, we get:\n\n$$ A(n+1) = \\sum_{i}^{n+1} 2^i = 2^{n+1} + A(n) = 2^{n+1} + 2^{n+1} - 1 =\n2^{n+2} - 1 $$\n\nWe now use induction again. Looking then at (15.3) and (15.4), it clearly holds\nwhen $T(0) = 1$. Then let's $T(n) = 2^n$ up to an $n$, and then look at:\n\n$$ T(n+1) = 1 + \\sum_{j=0}^{n} T(j) = 1 + \\sum_{j=0}^{n} 2^n = 1 + 2^{n+1} - 1 =\n2^{n+1} $$\n"
  },
  {
    "path": "other/clrs/15/01/02.markdown",
    "content": "> Show, by means of counterexample, that the following \"greedy\" strategy does\n> not always determine an optimal way to cut rods. Define the **density** of a\n> rod of length $i$ to be $p_i / i$, that is, its value per inch. The greedy\n> strategy for a rod of length $n$ cuts off a first piece of length $i$, where\n> $1 \\le i \\le n$, having maximum density. It then continues by applying the\n> greedy strategy to the remaining piece of length $n - i$.\n\nLet us have the following options of rod length.\n\n| Length  |  5 |  4 | 1 |\n|---------|---:|---:|--:|\n| Cost    | 10 |  7 | 1 |\n| Density |  2 | 1¾ | 1 |\n\nLet's look at a rod of length 8. The greedy algorithm will choose $5 + 1 + 1 +\n1$ with value $13$. In comparison, if we just cut it $4 + 4$, we are going to\nget value $14$.\n\n"
  },
  {
    "path": "other/clrs/15/01/03.markdown",
    "content": "> Consider a modification of the rod-cutting problem in which, in addition to a\n> price $p_i$ for each rod, each cut incurs a fixed cost $c$. The revenue\n> associated with a solution is now the sum of the prices of the pieces minus\n> the costs of making the cuts. Give a dynamic-programming algorithm to solve\n> this modified problem.\n\nThe algorithm is pretty straightforward, and outlined below – you subtract $c$\nfrom the calculation whenever there is a cut to be made.\n\nBut more importantly, it reduces to the original problem – if we subtract $c$\nfrom each $p_i$ and then add $c$ back to the result, we get the same value and\nthe same cuts.\n"
  },
  {
    "path": "other/clrs/15/01/03.py",
    "content": "def cut_rod(length, prices, cut_cost=0):\n    values = [-1] * (length + 1)\n    choices = [-1] * (length + 1)\n    values[0] = 0\n\n    for j in range(1, length + 1):\n        max_cut = min(len(prices), j + 1)\n        max_value = -1\n        for i in range(1, max_cut):\n            value = prices[i] + values[j - i] - (0 if j - i == 0 else cut_cost)\n            if max_value < value:\n                max_value = value\n                choices[j] = i\n\n        values[j] = max_value\n\n    n = length\n    cuts = []\n    while n > 0:\n        cuts.append(choices[n])\n        n -= choices[n]\n\n    return (values[length], cuts)\n"
  },
  {
    "path": "other/clrs/15/01/03.test.py",
    "content": "import unittest\n\ncut_rod = __import__('03').cut_rod\n\n\nclass RodCuttingTest(unittest.TestCase):\n    def setUp(self):\n        self.prices = [0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30]\n\n    def test_cutting_without_a_cost(self):\n        self.assertEqual(cut_rod(1, self.prices), (1, [1]))\n        self.assertEqual(cut_rod(2, self.prices), (5, [2]))\n        self.assertEqual(cut_rod(3, self.prices), (8, [3]))\n        self.assertEqual(cut_rod(4, self.prices), (10, [2, 2]))\n        self.assertEqual(cut_rod(5, self.prices), (13, [2, 3]))\n        self.assertEqual(cut_rod(6, self.prices), (17, [6]))\n        self.assertEqual(cut_rod(7, self.prices), (18, [1, 6]))\n        self.assertEqual(cut_rod(8, self.prices), (22, [2, 6]))\n        self.assertEqual(cut_rod(9, self.prices), (25, [3, 6]))\n        self.assertEqual(cut_rod(10, self.prices), (30, [10]))\n        self.assertEqual(cut_rod(40, self.prices), (120, [10, 10, 10, 10]))\n\n    def test_cutting_with_a_cost(self):\n        prices = [0, 3, 5, 2, 5]\n        self.assertEqual(cut_rod(4, prices, 2), (8, [2, 2]))\n\n    def test_equivalence_to_costless(self):\n        prices = [0, 3, 5, 2, 5, 6, 9, 9, 12]\n        cost = 2\n        adjusted_prices = [p - cost for p in prices]\n        adjusted_prices[0] = 0\n\n        for i in range(1, 100):\n            self.assertEqual(\n                    cut_rod(i, prices, cost)[0],\n                    cut_rod(i, adjusted_prices)[0] + cost\n            )\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/15/01/04.markdown",
    "content": "> Modify `MEMOIZED-CUT-ROD` to return not only the value but the actual\n> solution, too.\n"
  },
  {
    "path": "other/clrs/15/01/04.py",
    "content": "def memoized_cut_rod(length, prices):\n    values = [-1] * (length + 1)\n    choices = [-1] * (length + 1)\n\n    def cut(n):\n        if values[n] >= 0:\n            return values[n]\n\n        if n == 0:\n            values[0] = 0\n        else:\n            cut_options = range(1, min(len(prices), n + 1))\n            max_value = -1\n            for i in cut_options:\n                value = prices[i] + cut(n - i)\n\n                if max_value < value:\n                    max_value = value\n                    choices[n] = i\n\n            values[n] = max_value\n\n        return values[n]\n\n    value = cut(length)\n    cuts = []\n\n    while length > 0:\n        cuts.append(choices[length])\n        length -= choices[length]\n\n    return (value, cuts)\n"
  },
  {
    "path": "other/clrs/15/01/04.test.py",
    "content": "import unittest\n\ncut_rod = __import__('04').memoized_cut_rod\n\n\nclass MemoizedRodCuttingTest(unittest.TestCase):\n    def setUp(self):\n        self.prices = [0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30]\n\n    def test_cutting_without_a_cost(self):\n        self.assertEqual(cut_rod(1, self.prices), (1, [1]))\n        self.assertEqual(cut_rod(2, self.prices), (5, [2]))\n        self.assertEqual(cut_rod(3, self.prices), (8, [3]))\n        self.assertEqual(cut_rod(4, self.prices), (10, [2, 2]))\n        self.assertEqual(cut_rod(5, self.prices), (13, [2, 3]))\n        self.assertEqual(cut_rod(6, self.prices), (17, [6]))\n        self.assertEqual(cut_rod(7, self.prices), (18, [1, 6]))\n        self.assertEqual(cut_rod(8, self.prices), (22, [2, 6]))\n        self.assertEqual(cut_rod(9, self.prices), (25, [3, 6]))\n        self.assertEqual(cut_rod(10, self.prices), (30, [10]))\n        self.assertEqual(cut_rod(40, self.prices), (120, [10, 10, 10, 10]))\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/15/01/05.dot",
    "content": "digraph {\n  node[shape=circle];\n\n  subgraph {\n    r5_5[label=5];\n    r4_4[label=4]; r4_3[label=3];\n    r3_3_1[label=3]; r3_2_1[label=2]; r3_2_2[label=2]; r3_1_2[label=1];\n    r2_2_1[label=2]; r2_1_1[label=1]; r2_1_2[label=1]; r2_0_2[label=0]; r2_1_3[label=1]; r2_0_3[label=0];\n    r1_1[label=1]; r1_0[label=0];\n\n    r5_5 -> r4_4; r5_5 -> r4_3;\n    r4_4 -> r3_3_1; r4_4 -> r3_2_1; r4_3 -> r3_2_2; r4_3 -> r3_1_2;\n    r3_3_1 -> r2_2_1; r3_3_1 -> r2_1_1; r3_2_1 -> r2_1_2; r3_2_1 -> r2_0_2; r3_2_2 -> r2_1_3; r3_2_2 -> r2_0_3;\n    r2_2_1 -> r1_1; r2_2_1 -> r1_0;\n  }\n\n  subgraph {\n    5; 4; 3; 2; 1; 0;\n\n    5 -> 4; 5 -> 3; 4 -> 3; 4 -> 2; 3 -> 2; 3 -> 1; 2 -> 1; 2 -> 0;\n  }\n}\n"
  },
  {
    "path": "other/clrs/15/01/05.markdown",
    "content": "> The Fibonacci numbers are defined by recurrence (3.22). Give a $\\O(n)$-time\n> dynamic-programming algorithm to compute the $n$th Fibonacci number. Draw the\n> subproblem graph. How many vertices and edges are in the graph?\n\nWe don't really need a dynamic programming approach, do we? Anyway, let's\nimplement one.\n\nThe subproblem graph is pretty trivial to draw, and I was going to skip the\nwhole dot exercise, but then I drew it on paper, and there is a pretty\ninteresting property. Specifically, the non-optimal version for solving $n$ has\n$F_n$ vertices, where $F_i$ is the $i$-th Fibonacci number.\n\nThe other is pretty straightforward, although graphviz doesn't render it\nperfectly.\n"
  },
  {
    "path": "other/clrs/15/01/05.py",
    "content": "def fibonacci(n):\n    results = [0] * (n + 1)\n    results[1] = 1\n\n    for i in range(2, n + 1):\n        results[i] = results[i - 1] + results[i - 2]\n\n    return results[n]\n"
  },
  {
    "path": "other/clrs/15/01/05.test.py",
    "content": "import unittest\n\nfibonacci = __import__('05').fibonacci\n\n\nclass FibonacciTest(unittest.TestCase):\n    def test_cutting_without_a_cost(self):\n        self.assertEqual(fibonacci(1), 1)\n        self.assertEqual(fibonacci(2), 1)\n        self.assertEqual(fibonacci(3), 2)\n        self.assertEqual(fibonacci(4), 3)\n        self.assertEqual(fibonacci(5), 5)\n        self.assertEqual(fibonacci(6), 8)\n        self.assertEqual(fibonacci(7), 13)\n        self.assertEqual(fibonacci(8), 21)\n        self.assertEqual(fibonacci(9), 34)\n        self.assertEqual(fibonacci(10), 55)\n        self.assertEqual(fibonacci(11), 89)\n        self.assertEqual(fibonacci(12), 144)\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/15/02/01.markdown",
    "content": "> Find an optimal parenthesization of a matrix-chain product whose sequence of\n> dimensions is $\\langle 5, 10, 3, 12, 5, 50, 6 \\rangle$.\n"
  },
  {
    "path": "other/clrs/15/02/01.py",
    "content": "import sys\n\nsizes = [30, 35, 15, 5, 10, 20, 25]\n\n\ndef subscript(n):\n    chars = \"₀₁₂₃₄₅₆₇₈₉\"\n    result = []\n    while n:\n        rem = n % 10\n        n //= 10\n        result.append(chars[rem])\n\n    return ''.join(reversed(result))\n\n\ndef order(dimensions):\n    n = len(dimensions) - 1\n    memo = [[-1] * n for _ in range(n)]\n    choices = [[-1] * n for _ in range(n)]\n    for i in range(0, n):\n        memo[i][i] = 0\n\n    for length in range(1, n):\n        for start in range(0, n - length):\n            end = start + length\n            cheapest = sys.maxsize\n            for split in range(start, end):\n                cost = memo[start][split] + memo[split + 1][end] + \\\n                    dimensions[start] * dimensions[split + 1] * \\\n                    dimensions[end + 1]\n\n                if cost < cheapest:\n                    cheapest = cost\n                    memo[start][end] = cost\n                    choices[start][end] = split\n\n    def optimal(i, j):\n        if i == j:\n            return \"A\" + subscript(i)\n        else:\n            left = optimal(i, choices[i][j])\n            right = optimal(choices[i][j] + 1, j)\n            return f\"({left}{right})\"\n\n    return (memo[0][n - 1], optimal(0, n - 1))\n"
  },
  {
    "path": "other/clrs/15/02/01.run.py",
    "content": "order = __import__('01').order\n\ndimensions = [5, 10, 3, 12, 5, 50, 6]\nprint(order(dimensions)[1])\n"
  },
  {
    "path": "other/clrs/15/02/02.markdown",
    "content": "> Give a recursive algorithm `MATRIX-CHAIN-MULTIPLY(A, s, i, j)` that actually\n> performs the optimal matrix-chain multiplication, given the sequence of\n> matrices $\\langle A_1, A_2, \\ldots, A_n \\rangle$, the $s$ table computed\n> `MATRIX-CHAIN-ORDER`, and the indices $i$ and $j$. (The initial call would be\n> `MATRIX-CHAIN-MULTIPLY(A, s, 1, n)`.)\n\nUnless I'm missing something really clever, this is either super trivial, or a\nbig annoyance in managing memory.\n\nThe best way to do it is to just modify `PRINT-OPTIMAL-PARENS` to do the\nmultiplication. The recursive structure of the algorithm is the same.\n"
  },
  {
    "path": "other/clrs/15/02/03.markdown",
    "content": "> Use the substitution method to show that the solution to the recurrence (15.6)\n> is $\\Omega(2^n)$.\n\nThe recurrence is:\n\n$$\n  P(n) =\n  \\begin{cases}\n    1 & \\text{if } n = 1, \\\\\\\\\n    \\sum_{k=1}^{n-1} P(k) P(n - k) & \\text{if } n \\ge 2\n  \\end{cases}\n$$\n\nOur guess is that $P(m) \\ge c \\cdot 2^m$.\n\nTrying to quantify $P(n)$, we get:\n\n$$\n  \\begin{aligned}\n      P(n) &= \\sum_{k=1}^{n-1} P(k) P(n - k) \\\\\\\\\n           &\\ge \\sum_{k=1}^{n-1} c \\cdot 2^k \\cdot c \\cdot 2^{n-k} \\\\\\\\\n           &= c^2 \\sum_{k=1}^{n-1} 2^k 2^{n-k} \\\\\\\\\n           &= c^2 \\sum_{k=1}^{n-1} 2^n \\\\\\\\\n           &= c^2 (n - 1) 2^n \\\\\\\\\n           &\\ge c \\cdot 2^{n}\n  \\end{aligned}\n$$\n\n(when $c \\ge 1$ and $n \\ge 2$)\n"
  },
  {
    "path": "other/clrs/15/02/04.markdown",
    "content": "> Describe the subproblem graph for matrix-chain multiplication with an input\n> chain of length $n$. How many vertices does it have? How many edges does it\n> have, and which edges are they?\n\nAssuming this is the efficient algorithm, the graph has vertices $v_{ij}$ where $i\n\\le j$. There are $1 + 2 + \\ldots + n$ of them, which is $\\frac{n(n+1)}{2}$, a\nboring old formula.\n\nAs for edges, each vertex has two edges, $(v_{ij}, v_{ik})$ and $(v_{ij},\nv_{k+1,j})$ for each $k$ such that $i \\le k < j$. The sum is:\n\n$$ \\sum_{i=1}^n \\sum_{j=i}^n 2 (j - i) $$\n\nThis is probably expandable, but I'm not that hard-working.\n"
  },
  {
    "path": "other/clrs/15/02/05.markdown",
    "content": "> Let $R(i, j)$ be the number of times the table entry $m[i, j]$ is referenced\n> while computing other table entries in a call of `MATRIX-CHAIN-ORDER`. Show\n> that the total number of references for the entire table is\n>\n> $$ \\sum_{i=1}^n \\sum_{j=i}^n R(i, j) = \\frac{n^3 - n}{3} $$\n>\n> (_Hint:_ You may find equation (A.3) useful.)\n\nLet's observe the following about the loops:\n\n* The third loop ($k$) references $m$ twice.\n* The body of the third loop gets executed $j - i = l - 1$ times.\n* The body of the second loop gets executed $n - l + 1$ times.\n* The body of the first loop gets execute $n - 1$ times, with $l$ moving from\n  $2$ to $n$.\n\nThus, it's the following sum:\n\n$$ \\sum_{l=2}^n 2(l - 1)(n - l + 1) $$\n\nNow let's simplify:\n\n$$\n  \\begin{aligned}\n    \\sum_{l=2}^n 2(l - 1)(n - l + 1) &=\n        \\sum_{l=1}^{n-1} 2l(n - l) \\\\\\\\\n      &= 2n \\sum_{l=1}^{n-1} l - 2 \\sum_{l=1}^{n-1} l^2 \\\\\\\\\n      &= 2n \\frac{(n-1)n}{2} - 2\\frac{(n - 1)((n - 1) + 1)(2(n - 1) + 1)}{6} \\\\\\\\\n      &= n^3 - n^2 - \\frac{n(n - 1)(2n - 1)}{3} \\\\\\\\\n      &= \\frac{1}{3} \\left( 3n^3 - 3n^2 - 2n^3 + n^2 + 2n^2 -n \\right) \\\\\\\\\n      &= \\frac{1}{2} \\left( n^3 - n \\right) \\\\\\\\\n      &= \\frac{n^3 - n}{3}\n  \\end{aligned}\n$$\n\nI'm also struggling to figure out how this is different than the previous\nexercise.\n"
  },
  {
    "path": "other/clrs/15/02/06.markdown",
    "content": "> Show that a full parenthesization of an $n$-element expression has exactly $n\n> - 1$ pairs of parentheses.\n\nIt clearly holds for $n = 1$ and $n = 2$. So using induction, if we have an\n$n$-element expression, where $n \\ge 2$, that is fully parenthesized, by\ndefinition it is the product of two fully parenthesized expression of smaller\nlength. Let $a$ be the length of the left one, and $b$ be the length of the\nright one. By the inductive step we know that the left has $a - 1$ pairs and the\nright has $b - 1$. Adding one more pair, we get $1 + a - 1 + b - 1 = a + b - 1 =\nn - 1$.\n"
  },
  {
    "path": "other/clrs/15/03/01.markdown",
    "content": "> Which is a more efficient way to determine the optimal number of\n> multiplications in a matrix-chain multiplication problem: enumerating all the\n> ways of parenthesizing the product and computing the number of multiplications\n> for each, or running `RECURSIVE-MATRIX-CHAIN`? Justify your answer.\n\nObviously the dynamic programming approach.\n\nTo keep it simple, if there is a split on $k$, the dynamic programming approach\nwould calculate the possible parenthesizations of $A_k A_{k+1} \\ldots A_j$ only\nonce, while when enumerating, we'll calculate them once for each possible\nparenthesization of $A_i A_{i + 1} \\ldots A_{k - 1}$.\n\nIn fact, I fail to see how the original slow algorithm is not doing just that –\nenumerating all the ways in which the multiplication can be parenthesized.\n"
  },
  {
    "path": "other/clrs/15/03/02.markdown",
    "content": "> Draw the recursion tree for the `MERGE-SORT` procedure from Section 2.3.1 on\n> an array of 16 elements. Explain why memoization fails to speed up a good\n> divide-and-conquer algorithm such as `MERGE-SORT`.\n\nBecause there is no subproblem overlap. Whenever merge sort splits an array, it\nproduces unique partitions that don't occur anywhere else.\n\nI'm not gonna draw the tree, because it's kinda obvious once you've read the\nchapter.\n"
  },
  {
    "path": "other/clrs/15/03/03.markdown",
    "content": "> Consider a variant of the matrix-chain multiplication problem in which the\n> goal is to parenthesize the sequence of matrices so as to maximize, rather\n> than minimize, the number of scalar multiplications. Does this problem exhibit\n> optimal substructure?\n\nYes it does.\n\nIt changes the calculation, but the two important properties remain – there is\nan overlap of the subproblems and they are independent.\n"
  },
  {
    "path": "other/clrs/15/03/04.markdown",
    "content": "> As stated, in dynamic programming we first solve the subproblems and then\n> choose which of them to use in an optimal solution to the problem. Professor\n> Capulet clains that we do not always need to solve all the subproblems in\n> order to find an optimal solution. She suggests that we can find an optimal\n> solution to the matrix-chain multiplication problem by always choosing the\n> matrix $A_k$ at which to split the subproduct $A_i A_{i+1} \\ldots A_j$ (by\n> selecting $k$ to minimize the quantity $p_{i-1} p_k p_j$) _before_ solving the\n> subproblems. Find an instance of the matrix-chain multiplication problem for\n> which this greedy approach yields a suboptimal solution.\n\nAn example would be a matrix chain $10 \\times 4 \\times 3 \\times 2$, where:\n\n$$\n\\begin{aligned}\n  A_1 & \\in \\mathbb{R}^{10} \\times \\mathbb{R}^4 \\\\\\\\\n  A_2 & \\in \\mathbb{R}^4 \\times \\mathbb{R}^3 \\\\\\\\\n  A_3 & \\in \\mathbb{R}^3 \\times \\mathbb{R}^2 \\\\\\\\\n\\end{aligned}\n$$\n\nThe first choice would be whether to first multiply $A_1 A_2$ or $A_2 A_3$.\nLooking just at $p_{i-1} p_k p_j$, the options will be \n\n$$\n\\begin{aligned}\n  C_1 &= p_1 p_2 p_4 = 10 \\cdot 4 \\cdot 2 &= 80 \\\\\\\\\n  C_2 &= p_1 p_3 p_4 = 10 \\cdot 3 \\cdot 2 &= 60 \\\\\\\\\n\\end{aligned}\n$$\n\nWith this information, ~~Juliet~~ Professor Capulet would opt in for the second\noption. Yet, this would be premature!\n\nIn the second case, she will have to continue with then multiplying $A_1 A_2$\nwith $10 \\cdot 4 \\cdot 3 = 120$ additional scalar operations, bringing the tally\nto $180$.\n\nIf she instead, chilled a bit and waited to see how things would play out, she\nwould discover that in the other option there would be only $4 \\cdot 3 \\cdot 2 =\n24$ more scalar operations to peform, in a total of $104$.\n"
  },
  {
    "path": "other/clrs/15/03/04.py",
    "content": "import sys\n\nsizes = [30, 35, 15, 5, 10, 20, 25]\n\n\ndef subscript(n):\n    chars = \"₀₁₂₃₄₅₆₇₈₉\"\n    result = []\n    while n:\n        rem = n % 10\n        n //= 10\n        result.append(chars[rem])\n\n    return ''.join(reversed(result))\n\n\ndef optimal(choices, i, j):\n    if i == j:\n        return \"A\" + subscript(i + 1)\n    else:\n        left = optimal(choices, i, choices[i][j])\n        right = optimal(choices, choices[i][j] + 1, j)\n        return f\"({left}{right})\"\n\n\ndef order(dimensions):\n    n = len(dimensions) - 1\n    memo = [[-1] * n for _ in range(n)]\n    choices = [[-1] * n for _ in range(n)]\n    for i in range(0, n):\n        memo[i][i] = 0\n\n    for length in range(1, n):\n        for start in range(0, n - length):\n            end = start + length\n            cheapest = sys.maxsize\n            for split in range(start, end):\n                cost = memo[start][split] + memo[split + 1][end] + \\\n                    dimensions[start] * dimensions[split + 1] * \\\n                    dimensions[end + 1]\n\n                if cost < cheapest:\n                    cheapest = cost\n                    memo[start][end] = cost\n                    choices[start][end] = split\n\n    return (memo[0][n - 1], optimal(choices, 0, n - 1))\n\n\ndef greedy(dimensions):\n    n = len(dimensions) - 1\n    memo = [[-1] * n for _ in range(n)]\n    choices = [[-1] * n for _ in range(n)]\n\n    for i in range(0, n):\n        memo[i][i] = 0\n\n    for length in range(1, n):\n        for start in range(0, n - length):\n            end = start + length\n            cheapest = sys.maxsize\n            for split in range(start, end):\n                cost = dimensions[start] * dimensions[split + 1] * \\\n                    dimensions[end + 1]\n\n                if cost < cheapest:\n                    cheapest = cost\n                    memo[start][end] = cost + memo[start][split] + \\\n                        memo[split + 1][end]\n\n                    choices[start][end] = split\n\n    return (memo[0][n - 1], optimal(choices, 0, n - 1))\n"
  },
  {
    "path": "other/clrs/15/03/04.run.py",
    "content": "solution = __import__('04')\n\nexample = [10, 4, 3, 2]\n\n\ndef report(message, answers):\n    multiplications, order = answers\n\n    print(f\"{message}: {order} with {multiplications} scalar multiplications\")\n\n\nreport(\"wise decision\", solution.order(example))\nreport(\"poor decision\", solution.greedy(example))\n"
  },
  {
    "path": "other/clrs/15/03/05.markdown",
    "content": "> Suppose that in the rod-cutting problem of Section 15.1, we also had limit\n> $l_i$ on the number of pieces of length $i$ that we are allowed to produce,\n> for $i = 1, 2, \\ldots, n$. Show that the optimal-substructure property\n> described in Section 15.1 no longer holds.\n\nA bit obviously, but the subproblems stop being independent now. When choosing a\ncut, we have to balance the remaining number of cuts to add up to at most a\ngiven number.\n\nI think this could be solved with tweaking the algorithm to use a table for\nmemoization instead of an array, so we have both the rod length and the maximum\nnumber of cuts. Nobody is asking me to implement it, however, so I'll opt out\nnot to.\n"
  },
  {
    "path": "other/clrs/15/03/06.markdown",
    "content": "> Imagine that you wish to exchange one currency for another. You realize that\n> instead of directly exchanging one currency for another, you might be better\n> of making a series of trades through other currencies, winding up with the\n> currency you want. Suppose that you can trade $n$ different currencies,\n> numbered $1, 2, \\ldots, n$, where you start with currency $1$ and wish to wind\n> up with currency $n$. You are given, for each pair of currencies $i$ and $j$,\n> an exchange rate $r_{ij}$, meaning that if you start with $d$ units of\n> currency $i$, you can trade for $dr_{ij}$ units of currency $j$. A sequence of\n> trades may entail a commission, which depends on the number of trades you\n> make. Let $c_k$ be the commission that you are charged when you make $k$\n> trades. Show that, if $c_k = 0$ for all $k = 1, 2, \\ldots, n$, then the\n> problems of finding the best sequence of exchanges from currency $1$ to\n> currency $n$ exhibits optimal substructure. The show that if commissions $c_k$\n> are arbitrary values, then the problem of finding the best sequence of\n> exchanges from currency $1$ to currency $n$ does not necessarily exhibit\n> optimal substructure.\n\nIf $c_k = 0$, we can use the reasoning from the chapter. Let $t = 1\n\\rightsquigarrow a_1 \\rightsquigarrow a_2 \\rightsquigarrow \\ldots\n\\rightsquigarrow j$ be the optimal trade. If we pick any $a_k$, then both $p = 1\n\\rightsquigarrow a_1 \\rightsquigarrow \\ldots \\rightsquigarrow a_k$ and $q = a_k\n\\rightsquigarrow a_{k+1} \\rightsquigarrow \\ldots \\rightsquigarrow j$ are optimal\ntrades. If we assume otherwise, then there is a sequence $p'$ that is better\nthan $p$, and we can use it trade $p' \\rightsquigarrow q$, which would be a\nbetter trade than $t$, which is a contradiction.\n\nNow let's look at when commissions become a problem. Let's have 4 currencies,\nwith the following trades:\n\n```generate-dot\ndigraph {\n  rankdir=\"LR\";\n\n  node[shape=circle];\n  edge[weight=2];\n  1 -> 2 [label=\"x2\"];\n  2 -> 3 [label=\"x2\"];\n  3 -> 4 [label=\"x2\"];\n\n  edge[weight=1];\n  1 -> 3 [label=\"x3\"];\n}\n```\n\nLet's assume that unmarked trades are just not good enough. Let's also have:\n\n$$ c_0 = 0, c_1 = 1, c_2 = 2, c_3 = 50, c_4 = 50, \\ldots $$\n\nThat is, the first two trades are cheap, but then it gets problematic. Let's\nassume we have $10$ units of currency $1$ and look at some optimal ways to trade\n$x \\rightsquigarrow y$:\n\n$$\n\\begin{aligned}\n  1 \\rightsquigarrow 4 &= 1 \\rightarrow 3 \\rightarrow 4\n    = 10 \\cdot 3 \\cdot 2 - c_1 - c_2 = 60 - 1 - 2 &= 57 \\\\\\\\\n  1 \\rightsquigarrow 3 &= 1 \\rightarrow 2 \\rightarrow 3\n    = 10 \\cdot 2 \\cdot 2 - c_1 - c_2 = 40 - 1 - 2 &= 37 \\\\\\\\\n  3 \\rightsquigarrow 4 &= 3 \\rightarrow 4\n    = 10 \\cdot 2 - c_1 = 20 - 1 &= 19 \\\\\\\\\n\\end{aligned}\n$$\n\nThe optimal way to trade $1 \\rightsquigarrow 3$ would be to go through $2$\nyielding $37$, instead of directly, yielding $29$. But if we combine that with\nthe optimal way to go $3 \\rightsquigarrow 4$, we get:\n\n$$\n  1 \\rightarrow 2 \\rightarrow 3 \\rightarrow 4 = 10 \\cdot 2 \\cdot 2 \\cdot 2 - c_1\n  - c_2 - c_3 = 80 - 1 - 2 - 50 = 27\n$$\n\nWhich is much less than $57$ if we just perform 2 trades.\n"
  },
  {
    "path": "other/clrs/15/04/01.markdown",
    "content": "> Determine an LCS of $\\langle 1, 0, 0, 1, 0, 1, 0, 1 \\rangle$ and $\\langle 0,\n> 1, 0, 1, 1, 1, 0, 1, 1, 0 \\rangle$.\n"
  },
  {
    "path": "other/clrs/15/04/01.py",
    "content": "def lcs(x, y):\n    m = len(x)\n    n = len(y)\n\n    longest = [[0] * (n + 1) for _ in range(m + 1)]\n    choices = [[' '] * (n + 1) for _ in range(m + 1)]\n\n    for i in range(m):\n        for j in range(n):\n            if x[i] == y[j]:\n                longest[i + 1][j + 1] = longest[i][j] + 1\n                choices[i + 1][j + 1] = '↖︎'\n            elif longest[i][j + 1] >= longest[i + 1][j]:\n                longest[i + 1][j + 1] = longest[i][j + 1]\n                choices[i + 1][j + 1] = '↑'\n            else:\n                longest[i + 1][j + 1] = longest[i + 1][j]\n                choices[i + 1][j + 1] = '←'\n\n    result = []\n    a, b = m, n\n\n    while a != 0 and b != 0:\n        choice = choices[a][b]\n        if choice == '↖︎':\n            result.append(x[a - 1])\n            a -= 1\n            b -= 1\n        elif choice == '↑':\n            a -= 1\n        elif choice == '←':\n            b -= 1\n\n    result.reverse()\n\n    return result\n"
  },
  {
    "path": "other/clrs/15/04/01.run.py",
    "content": "solution = __import__('01')\n\na = [1, 0, 0, 1, 0, 1, 0, 1]\nb = [0, 1, 0, 1, 1, 1, 0, 1, 1, 0]\n\nprint(solution.lcs(a, b))\n"
  },
  {
    "path": "other/clrs/15/04/02.markdown",
    "content": "> Give pseudocode to reconstruct an LCS from the completed $c$ table and the\n> original sequences $X = \\langle x_1, x_2, \\ldots, x_m \\rangle$ and $Y =\n> \\langle y_1, y_2, \\ldots, y_n \\rangle$ in $O(m + n)$ time, without using the b\n> table.\n"
  },
  {
    "path": "other/clrs/15/04/02.py",
    "content": "def lcs(x, y):\n    m = len(x)\n    n = len(y)\n\n    longest = [[0] * (n + 1) for _ in range(m + 1)]\n\n    for i in range(m):\n        for j in range(n):\n            if x[i] == y[j]:\n                longest[i + 1][j + 1] = longest[i][j] + 1\n            elif longest[i][j + 1] >= longest[i + 1][j]:\n                longest[i + 1][j + 1] = longest[i][j + 1]\n            else:\n                longest[i + 1][j + 1] = longest[i + 1][j]\n\n    result = []\n    a, b = m, n\n\n    while a != 0 and b != 0:\n        if longest[a - 1][b - 1] >= longest[a - 1][b] and longest[a - 1][b - 1] >= longest[a][b - 1]:\n            result.append(x[a - 1])\n            a -= 1\n            b -= 1\n        elif longest[a - 1][b] >= longest[a][b - 1]:\n            a -= 1\n        else:\n            b -= 1\n\n    result.reverse()\n\n    return result\n"
  },
  {
    "path": "other/clrs/15/04/02.test.py",
    "content": "import unittest\n\nlcs = __import__('02').lcs\n\n\nclass LongestCommonSubsequenceTest(unittest.TestCase):\n    def test_lcs(self):\n        a = ['A', 'B', 'C', 'B', 'D', 'A', 'B']\n        b = ['B', 'D', 'C', 'A', 'B', 'A']\n\n        self.assertEqual(lcs(a, b), ['B', 'C', 'B', 'A'])\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/15/04/03.markdown",
    "content": "> Give a memoized version of `LCS-LENGTH` that runs in $\\O(mn)$ time.\n"
  },
  {
    "path": "other/clrs/15/04/03.py",
    "content": "def lcs(x, y):\n    m = len(x)\n    n = len(y)\n\n    cache = {}\n\n    def longest(a, b):\n        if a == 0 or b == 0:\n            return 0\n\n        if (a, b) in cache:\n            return cache[(a, b)]\n\n        result = None\n\n        if x[a - 1] == y[b - 1]:\n            result = 1 + longest(a - 1, b - 1)\n        else:\n            result = max(longest(a - 1, b), longest(a, b - 1))\n\n        cache[(a, b)] = result\n        return result\n\n    result = []\n    a, b = m, n\n\n    while a != 0 and b != 0:\n        if x[a - 1] == y[b - 1]:\n            result.append(x[a - 1])\n            a -= 1\n            b -= 1\n        elif longest(a - 1, b) >= longest(a, b - 1):\n            a -= 1\n        else:\n            b -= 1\n\n    result.reverse()\n\n    return result\n"
  },
  {
    "path": "other/clrs/15/04/03.test.py",
    "content": "import unittest\n\nlcs = __import__('03').lcs\n\n\nclass LongestCommonSubsequenceTest(unittest.TestCase):\n    def test_lcs(self):\n        a = list(\"CGATAATTGAGA\")\n        b = list(\"GTTCCTAATA\")\n\n        self.assertEqual(lcs(a, b), list(\"CTAATA\"))\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/15/04/04.markdown",
    "content": "> Show how to compute the length of an LCS using only $2 \\cdot \\min(m, n)$\n> entries in the $c$ table plus $\\O(1)$ additional space. Then show how to do\n> the same thing, but using $\\min(m, n)$ entries plus $\\O(1)$ additional space.\n\nWe just need to make a few observations:\n\n1. In order to go for $\\min(m, n)$, we need to make sure that $n$ is the smaller\n   numbers, that is, exchange the strings if the second is longer.\n2. Every time we calculate a row in $c$, we only consult the previous row and\n   the current row up to the point at which we've built it. Therefore, we don't\n   need to keep track of rows other than the previous.\n3. When calculating the value in a row for index $j$, we only ever consult the\n   previous row for index $j - 1$. Therefore, we can just keep track of a single\n   array, with indices lower than $j$ referring to the current row, and indices\n   higher or equal than $j$ referring to the previous row. Since we need $j - 1$\n   to calculate $j$, we keep track of it separately.\n"
  },
  {
    "path": "other/clrs/15/04/04.py",
    "content": "def lcs_twice(x, y):\n    if len(x) < len(y):\n        x, y = y, x\n\n    m = len(x)\n    n = len(y)\n\n    previous = [0] * (n + 1)\n\n    for i in range(m):\n        current = [0] + [None] * n\n\n        for j in range(n):\n            if x[i] == y[j]:\n                current[j + 1] = previous[j] + 1\n            elif previous[j + 1] >= current[j]:\n                current[j + 1] = previous[j + 1]\n            else:\n                current[j + 1] = current[j]\n\n        previous = current\n\n    return previous[n]\n\ndef lcs_once_plus_const(x, y):\n    if len(x) < len(y):\n        x, y = y, x\n\n    m = len(x)\n    n = len(y)\n\n    row = [0] * (n + 1)\n\n    for i in range(m):\n        prev = 0\n\n        for j in range(n):\n            next = row[j + 1]\n\n            if x[i] == y[j]:\n                row[j + 1] = prev + 1\n            elif row[j + 1] < row[j]:\n                row[j + 1] = row[j]\n\n            prev = next\n\n    return row[n]\n"
  },
  {
    "path": "other/clrs/15/04/04.test.py",
    "content": "import unittest\n\nlcs = __import__('04')\n\n\nclass LongestCommonSubsequenceTest(unittest.TestCase):\n    def test_example_one(self):\n        a = ['A', 'B', 'C', 'B', 'D', 'A', 'B']\n        b = ['B', 'D', 'C', 'A', 'B', 'A']\n\n        self.assertEqual(lcs.lcs_once_plus_const(a, b), len(['B', 'C', 'B', 'A']))\n        self.assertEqual(lcs.lcs_twice(a, b), len(['B', 'C', 'B', 'A']))\n\n    def test_example_two(self):\n        a = list(\"CGATAATTGAGA\")\n        b = list(\"GTTCCTAATA\")\n\n        self.assertEqual(lcs.lcs_once_plus_const(a, b), len(\"CTAATA\"))\n        self.assertEqual(lcs.lcs_twice(a, b), len(\"CTAATA\"))\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/15/04/05.markdown",
    "content": "> Given an $\\O(n^2)$-time algorithm to find the longest monotonically increasing\n> subsequence of a sequence of $n$ numbers.\n"
  },
  {
    "path": "other/clrs/15/04/05.py",
    "content": "def mono(items):\n    best = [1] * len(items)\n    choices = [None] * len(items)\n\n    for j in range(1, len(items)):\n        for i in range(0, j):\n            if items[i] <= items[j] and best[j] <= best[i] + 1:\n                best[j] = best[i] + 1\n                choices[j] = i\n\n    n = max(range(0, len(items)), key=lambda x: (best[x], x))\n\n    result = []\n\n    while n is not None:\n        result.append(items[n])\n        n = choices[n]\n\n    result.reverse()\n\n    return result\n"
  },
  {
    "path": "other/clrs/15/04/05.test.py",
    "content": "import unittest\n\nmono = __import__('05').mono\n\n\nclass LongestMonotonicallyIncreasingSubsequenceTest(unittest.TestCase):\n    def test_examples(self):\n        self.assertEqual(\n            mono([1, 2, 3, 10, 11, 4, 5, 8, 6, 7, 1]),\n            [1, 2, 3, 4, 5, 6, 7]\n        )\n\n        self.assertEqual(\n            mono([8, 2, 4, 2]),\n            [2, 2]\n        )\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/15/04/06.markdown",
    "content": "> $\\star$ Give an $\\O(n \\lg n)$-time algorithm to find the longest monotonically\n> increasing subsequence of a sequence of $n$ numbers. (_Hint:_ Observe that the\n> last element of a candidate subsequence of length $i$ is at least as large as\n> the last element of a candidate subsequence of length $i - 1$. Maintain\n> candidate subsequences by linking them through the input sequence.)\n\nThis is a bit weird to explain. There are three parts to it.\n\n1. We can hold an array, `longest`, that stores at position $i$ the so-far\n   longest subsequence with length $i$.\n\n2. Every time we process an element from the input sequence we can update\n   `longest` with that element. If we map `longest` to the last element of each\n   sequence, it's going to maintain an invariant of being sorted.\n\n3. Since longest is sorted, we can use binary search to figure out where to put\n   the next element from the input sequence.\n"
  },
  {
    "path": "other/clrs/15/04/06.py",
    "content": "def mono(items):\n    last = 0\n    longest = [None] * len(items)\n    longest[0] = dict(value=items[0], prev=None)\n\n    def find_place(value):\n        lo, hi = 0, last + 1\n\n        while lo < hi:\n            mid = (lo + hi) // 2\n\n            if longest[mid]['value'] <= value:\n                lo = mid + 1\n            else:\n                hi = mid\n\n        return (lo, longest[lo - 1] if lo > 0 else None)\n\n    for i in range(1, len(items)):\n        (index, prev) = find_place(items[i])\n        longest[index] = dict(value=items[i], prev=prev)\n        last = max(last, index)\n\n    result = []\n    node = longest[last]\n\n    while node:\n        result.append(node['value'])\n        node = node['prev']\n\n    result.reverse()\n\n    return result\n"
  },
  {
    "path": "other/clrs/15/04/06.test.py",
    "content": "import unittest\nimport random\n\nmono = __import__('06').mono\n\n\ndef quadratic(items):\n    best = [1] * len(items)\n    choices = [None] * len(items)\n\n    for j in range(1, len(items)):\n        for i in range(0, j):\n            if items[i] <= items[j] and best[j] <= best[i] + 1:\n                best[j] = best[i] + 1\n                choices[j] = i\n\n    n = max(range(0, len(items)), key=lambda x: (best[x], x))\n\n    result = []\n\n    while n is not None:\n        result.append(items[n])\n        n = choices[n]\n\n    result.reverse()\n\n    return result\n\n\nclass FasterLongestMonotonicallyIncreasingSubsequenceTest(unittest.TestCase):\n    def test_examples(self):\n        self.assertEqual(\n            mono([1, 2, 8, 9, 3, 4, 5]),\n            [1, 2, 3, 4, 5]\n        )\n\n        self.assertEqual(\n            mono([1, 2, 3, 10, 11, 4, 5, 8, 6, 7, 1]),\n            [1, 2, 3, 4, 5, 6, 7]\n        )\n\n        self.assertEqual(mono([6, 6, 0, 4]), [0, 4])\n\n        self.assertEqual(mono([1, 2, 3, 4]), [1, 2, 3, 4])\n\n    def test_comparison(self):\n        k = 500\n        n = 20\n        random.seed(0)\n        for a in range(n):\n            sequence = list(map(lambda _: random.randint(0, 9), range(k)))\n            self.assertEqual(len(quadratic(sequence)), len(mono(sequence)))\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "other/clrs/15/05/01.markdown",
    "content": "> Write pseudocode for the procedure `CONSTRUCT-OPTIMAL-BST(root)` which, given\n> the table $root$, outputs the structure of an optimal binary search tree. For\n> the example in Figure 15.10, your procedure should print the structure\n>\n> * $k_2$ is the root\n> * $k_1$ is the left child of $k_2$\n> * $d_0$ is the left child of $k_1$\n> * $d_1$ is the right child of $k_1$\n> * $k_5$ is the right child of $k_2$\n> * $k_4$ is the left child of $k_5$\n> * $k_3$ is the left child of $k_4$\n> * $d_2$ is the left child of $k_3$\n> * $d_3$ is the right child of $k_3$\n> * $d_4$ is the right child of $k_4$\n> * $d_5$ is the right child of $k_5$\n>\n> corresponding to the optimal binary search tree shown in Figure 15.9(b).\n\nThis problem is not very compatible with my brain. The code is a bit messy, but\nit is what it is.\n"
  },
  {
    "path": "other/clrs/15/05/01.py",
    "content": "import math\n\ndef table(h, w):\n    return [[None] * (w + 1) for _ in range(h + 1)]\n\ndef optimal(p, q):\n    n = len(q) - 1\n    e = table(n + 1, n)\n    w = table(n + 1, n)\n    root = table(n, n)\n\n    for i in range(1, n + 2):\n        e[i][i - 1] = q[i - 1]\n        w[i][i - 1] = q[i - 1]\n\n    for l in range(1, n + 1):\n        for i in range(1, n - l + 2):\n            j = i + l - 1\n            e[i][j] = math.inf\n            w[i][j] = w[i][j - 1] + p[j] + q[j]\n            for r in range(i, j + 1):\n                t = e[i][r - 1] + e[r + 1][j] + w[i][j]\n                if t < e[i][j]:\n                    e[i][j] = t\n                    root[i][j] = r\n\n    return (e, root)\n\n\ndef dump_tree(root):\n    next_d = -1\n\n    def d():\n        nonlocal next_d\n        next_d += 1\n        return f\"d{next_d}\"\n\n    def is_empty(start, end):\n        return start == 0 or end == 0 or start == end + 1\n\n    def collect(start, end):\n        split = root[start][end]\n\n        if is_empty(start, split - 1):\n            print(f\"{d()} is the left child of k{split}\")\n        else:\n            print(f'k{root[start][split - 1]} if left child of k{split}')\n            collect(start, split - 1)\n\n        if is_empty(split + 1, end):\n            print(f\"{d()} is the right child of k{split}\")\n        else:\n            print(f'k{root[split + 1][end]} is right child of k{split}')\n            collect(split + 1, end)\n\n    print(f\"k{root[1][len(root) - 1]} is the root\")\n\n    collect(1, len(root) - 1)\n\n"
  },
  {
    "path": "other/clrs/15/05/01.run.py",
    "content": "module = __import__('01')\n\np = [None, 0.15, 0.10, 0.05, 0.10, 0.20]\nq = [0.05, 0.10, 0.05, 0.05, 0.05, 0.10]\n\na, root = module.optimal(p, q)\n\nmodule.dump_tree(root)\n"
  },
  {
    "path": "other/clrs/15/05/02.markdown",
    "content": "> Determine the cost and structure of an optimal binary search tree for a set of\n> $n = 7$ keys with the following probabilities:\n>\n> | $i$   | 0    | 1    | 2    | 3    | 4    | 5    | 6    | 7    |\n> |:------|:-----|:-----|:-----|:-----|:-----|:-----|:-----|:-----|\n> | $p_i$ |      | 0.04 | 0.06 | 0.08 | 0.02 | 0.10 | 0.12 | 0.14 |\n> | $q_i$ | 0.06 | 0.06 | 0.06 | 0.06 | 0.05 | 0.05 | 0.05 | 0.05 |\n\n\n"
  },
  {
    "path": "other/clrs/15/05/02.py",
    "content": "import math\n\ndef table(h, w):\n    return [[None] * (w + 1) for _ in range(h + 1)]\n\ndef optimal(p, q):\n    n = len(q) - 1\n    e = table(n + 1, n)\n    w = table(n + 1, n)\n    root = table(n, n)\n\n    for i in range(1, n + 2):\n        e[i][i - 1] = q[i - 1]\n        w[i][i - 1] = q[i - 1]\n\n    for l in range(1, n + 1):\n        for i in range(1, n - l + 2):\n            j = i + l - 1\n            e[i][j] = math.inf\n            w[i][j] = w[i][j - 1] + p[j] + q[j]\n            for r in range(i, j + 1):\n                t = e[i][r - 1] + e[r + 1][j] + w[i][j]\n                if t < e[i][j]:\n                    e[i][j] = t\n                    root[i][j] = r\n\n    return (e, root)\n\n\ndef dump_tree(root):\n    next_d = -1\n\n    def d():\n        nonlocal next_d\n        next_d += 1\n        return f\"d{next_d}\"\n\n    def is_empty(start, end):\n        return start == 0 or end == 0 or start == end + 1\n\n    def collect(start, end):\n        split = root[start][end]\n\n        if is_empty(start, split - 1):\n            print(f\"{d()} is the left child of k{split}\")\n        else:\n            print(f'k{root[start][split - 1]} if left child of k{split}')\n            collect(start, split - 1)\n\n        if is_empty(split + 1, end):\n            print(f\"{d()} is the right child of k{split}\")\n        else:\n            print(f'k{root[split + 1][end]} is right child of k{split}')\n            collect(split + 1, end)\n\n    print(f\"k{root[1][len(root) - 1]} is the root\")\n\n    collect(1, len(root) - 1)\n\n"
  },
  {
    "path": "other/clrs/15/05/02.run.py",
    "content": "module = __import__('02')\n\np = [None, 0.04, 0.06, 0.08, 0.02, 0.10, 0.12, 0.14]\nq = [0.06, 0.06, 0.06, 0.06, 0.05, 0.05, 0.05, 0.05]\n\n_, root = module.optimal(p, q)\n\nmodule.dump_tree(root)\n"
  },
  {
    "path": "other/clrs/15/05/03.markdown",
    "content": "> Suppose that instead of maintaining the table $w[i, j]$, we computed the value\n> of $w(i, j)$ directly from equation (15.12) in line 9 of `OPTIMAL-BST` and\n> used this computed value in line 11. How would this change affect the\n> asymptotic running time of `OPTIMAL-BST`?\n\nIt will make line 9 linear instead of constant, but it will not increase the\noverall asymptotic time, since it's not in the innermost loop. Thus, it will\nremain $O(n^3)$.\n"
  },
  {
    "path": "other/clrs/15/05/04.markdown",
    "content": "> $\\star$ Knuth [212] has shown that there are always roots of optimal subtrees\n> such that $root[i, j - 1] \\le root[i, j] \\le [root[i + 1, j]$ for all $1 \\le i\n> < j \\le n$. Use this fact to modify the `OPTIMAL-BST` procedure to run in\n> $\\Theta(n^2)$ time.\n\nI'm not sure that is completely true, and I find this problem quite boring.\nThus, I'm going to only leave [this Stack Overflow link][link].\n\n[link]: https://stackoverflow.com/questions/16987670/dynamic-programming-why-knuths-improvement-to-optimal-binary-search-tree-on2\n"
  },
  {
    "path": "other/clrs/C/01/01.markdown",
    "content": "> How many $k$-substrings does an $n$-string have? (Consider identical\n> $k$-substrings at different positions to be different.) How many substrings\n> does and $n$-string have in total?\n\nThere are $S_k = n - k + 1$ possible substrings of length $k$ (one starting at\nthe first position, one and the second, etc.)\n\nIn total there are:\n\n$$ \\begin{aligned}\n   S &= S_1 + S_2 + \\ldots + S_n \\\\\\\\\n     &= \\sum_{i=1}^{n}S_i \\\\\\\\\n     &= \\sum_{i=1}^{n}(n - i + 1) \\\\\\\\\n     &= \\sum_{i=1}^{n}n - \\sum_{i=1}^{n}i + \\sum_{i=1}^{n}1 \\\\\\\\\n     &= n^2 - n(n + 1)/2 + n \\\\\\\\\n     &= n^2 - n^2/2 - n/2 + n \\\\\\\\\n     &= n(n + 1)/2 \\qquad \\text{(Duh!)}\n     \\end{aligned}$$\n\nObvious proof is obvious.\n"
  },
  {
    "path": "other/clrs/C/01/02.markdown",
    "content": "> An $n$-input, $m$-output **boolean function** is a function from\n> $\\\\{TRUE,FALSE\\\\}^n$ to $\\\\{TRUE,FALSE\\\\}^m$. How many $n$-input 1-output\n> boolean functions are there? How many $n$-input, $m$-output boolean functions\n> are there?\n\nThere are $2^n$ possible inputs. We can represent the possible binary functions\ncompletely as binary numbers of $2^n$ digits. There $2^{2^n}$ of those.\n\nIf there are $2^m$ possible outputs, we can represent the functions as numbers\nof $2^n$ digits in base $2^m$. This makes the answer of the second question:\n\n$$ (2^m)^{2^n} $$\n"
  },
  {
    "path": "other/clrs/C/01/03.markdown",
    "content": "> In how many ways can $n$ professors sit around a circular conference table?\n> Consider two seatings to be the same if one can be rotated to form the other.\n\nIf we pick a chair as the first one and a direction, in which the chairs are\nincreasing, there are $n!$ ways to seat the professors. However, an arrangement\n$\\\\{1, 2, \\ldots, n\\\\}$ is identical to $\\\\{2, 3, \\ldots, n, 1\\\\}$ and there\nare $n$ of those identical arrangements (one starting on each professor). Since\nidentical arrangements are in groups of size $n$, the total number of seatings\nis $n!/n = (n-1)!$.\n"
  },
  {
    "path": "other/clrs/C/01/04.markdown",
    "content": "> In how many ways can we choose three distinct numbers from the set\n> $\\\\{1,2,\\ldots,99\\\\}$ so that their sum is even?\n\nThere are 49 even numbers and 50 odd in that set. To get an even number, we\neither need two odd and one even or three even.\n\n$$ \\langle \\text{2 odd, 1 even} \\rangle = 49\\frac{50!}{2! \\cdot 48!} = \\frac{50 \\cdot 49^2}{2} \\\\\\\\\n   \\langle \\text{3 even} \\rangle = \\frac{49!}{3! \\cdot 46!} = \\frac{49 \\cdot 48 \\cdot 47}{6} \\\\\\\\\n   \\langle \\text{even sum} \\rangle = \\frac{49 \\cdot 48 \\cdot 47}{6} + \\frac{50 \\cdot 49^2}{2}\n     = 78449\n$$\n"
  },
  {
    "path": "other/clrs/C/01/05.markdown",
    "content": "> Prove the identity\n>\n> $$ \\binom{n}{k} = \\frac{n}{k}\\binom{n-1}{k-1}$$\n>\n> for $0 < k \\le n$.\n\n$$ \\binom{n}{k} = \\frac{n!}{k!(n-k)!} = \\frac{n}{k}\\frac{(n-1)!}{(k-1)!(n-1-(k-1))!}\n                = \\frac{n}{k}\\binom{n-1}{k-1}$$\n"
  },
  {
    "path": "other/clrs/C/01/06.markdown",
    "content": "> Prove the identity\n>\n> $$ \\binom{n}{k} = \\frac{n}{n-k}\\binom{n-1}{k} $$\n>\n> for $0 \\le k < n$.\n\n$$ \\binom{n}{k} = \\frac{n!}{k!(n-k)!} = \\frac{n}{n-k}\\frac{(n-1)!}{k!(n-1-k)!}\n                = \\frac{n}{n-k}\\binom{n-1}{k} $$\n"
  },
  {
    "path": "other/clrs/C/01/07.markdown",
    "content": "> To choose $k$ objects from $n$, you can make one of the objects distinguished\n> and consider whether the distinguished object is chosen. Use this approach to\n> prove that:\n>\n> $$ \\binom{n}{k} = \\binom{n-1}{k} + \\binom{n-1}{k-1} $$\n\nGiven the distinguished object is chosen, there are $\\binom{n-1}{k-1}$ ways to\nchoose the others. If it is not chosen, there are $\\binom{n-1}{k}$ ways to\nchoose the objects. Adding those together yields the equality above.\n\n$$ \\begin{aligned}\n   \\binom{n-1}{k} + \\binom{n-1}{k-1}\n     &= \\frac{(n-1)!}{k!(n-1-k)!} + \\frac{(n-1)!}{(k-1)!(n-1-k+1)!} \\\\\\\\\n     &= \\frac{(n-1-k+1)(n-1)!}{k!(n-1-k+1)!} + \\frac{k(n-1)!}{k!(n-1-k+1)!} \\\\\\\\\n     &= \\frac{(n-1-k+1+k)(n-1)!}{k!(n-1-k+1)!} \\\\\\\\\n     &= \\frac{n!}{k!(n-k)!} \\\\\\\\\n     &= \\binom{n}{k}\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/C/01/08.markdown",
    "content": "> Using the result of exercise C.1-7, make a table for $n = 0, 1, \\ldots, 6$\n> and $0 \\le k \\le n$ of the binomial coefficients $\\binom{n}{k}$ with\n> $\\binom{0}{0}$ at the top, $\\binom{1}{0}$ and $\\binom{1}{1}$ on the next line,\n> and so forth. Such a table of binomial coefficients is called **Pascal's\n> triangle**.\n\n$$ 1 \\\\\\\\\n   1 \\quad 1 \\\\\\\\\n   1 \\quad 2 \\quad 1 \\\\\\\\\n   1 \\quad 3 \\quad 3  \\quad 1 \\\\\\\\\n   1 \\quad 4 \\quad 6  \\quad 4  \\quad 1 \\\\\\\\\n   1 \\quad 5 \\quad 10 \\quad 10 \\quad 5  \\quad 1 \\\\\\\\\n   1 \\quad 6 \\quad 15 \\quad 20 \\quad 15 \\quad 6  \\quad 1 \\\\\\\\\n   1 \\quad 7 \\quad 21 \\quad 35 \\quad 35 \\quad 21 \\quad 7 \\quad 1\n$$\n"
  },
  {
    "path": "other/clrs/C/01/09.markdown",
    "content": "> Prove that\n>\n> $$ \\sum_{i=1}^ni = \\binom{n+1}{2} $$\n\n$$ \\sum_{i=1}^n = \\frac{n(n+1)}{2} = \\frac{(n+1)!}{2!(n+1-2)!} = \\binom{n+1}{2} $$\n\nInteresting. The second diagonals of Pascal's triangle appear to be the\narithmetic series.\n"
  },
  {
    "path": "other/clrs/C/01/10.markdown",
    "content": "> Show that for any $n \\ge 0$ and $0 \\le k \\le m$, the expression\n> $\\binom{n}{k}$ achieves its maximum value when $k = \\lfloor n/2 \\rfloor$ or\n> $k = \\lceil n/2 \\rceil$.\n\nIt's evident in Pascal's triangle, yet anyway. There are $k$ multipliers in the\ndenominator of:\n\n$$ \\binom{n}{k} = \\frac{n!}{k!(n-k)!} $$\n\nIt's a question of minizing them. For $n/2 - k < i < n/2$, there would be $i$\npairs of the type $i(n-i)$. Those pairs are strictly greater than $i^2$. They\nare minized when $i$ is $n/2$ or the nearest integer.\n\nIt's not bullet-proof, but it works.\n"
  },
  {
    "path": "other/clrs/C/01/11.markdown",
    "content": "> $\\star$ Argue that for any integers $n \\ge 0, j \\ge 0, k \\ge 0$ and $j + k \\le n$,\n>\n> $$ \\binom{n}{j+k} \\le \\binom{n}{j}\\binom{n-j}{k} $$\n>\n> Provide both an algebraic proof and an argument based on a method for\n> choosing $j + k$ items out of $n$. Give an example in which equality does not\n> hold.\n\nFirst, let's establish that, $j!k! \\le (j+k)!$. Both sides have the same number\nof terms, but the right side has $k$ terms more - $(j+1)(j+2)\\ldots(j+k)$ -\nthat are greater than the corresponding terms on the left side\n$1\\cdot2\\cdot\\ldots k$.\n\nThus:\n\n$$ \\binom{n}{j} \\binom{n-j}{k}\n   = \\frac{n!}{j!(n-j)!} \\frac{(n-j)!}{k!(n-j-k)!}\n   = \\frac{n!}{j!k!(n-j-k)!}\n   \\ge \\frac{n!}{(j+k)!(n-j-k)!}\n   = \\binom{n}{j+k}\n$$\n\nAs for the argument, the right side is the number of ways in which we can:\n\n1. Choose $j$ elements out of $n$\n2. Choose $k$ elements out of the remaining $n-j$ elements\n\nThere are more ways to do that than just choosing $j+k$ elements out of $n$,\nbecause this implies some ordering in the choice. For example, if $j = k = 1$,\nthere are two ways to pick two elements (each one first) with this approach,\nbut only one otherwise.\n\nIf $n = 4, j = k = 1$, then equality does not hold.\n"
  },
  {
    "path": "other/clrs/C/01/12.markdown",
    "content": "> $\\star$ Use induction on all integers $k$ such that $0 \\le k \\le n/2$ to\n> prove inequality (C.6) and use equation (C.3) to extend it to all integers\n> $k$ such that $0 \\le k \\le n$.\n\nThanks to [this answer](http://math.stackexchange.com/questions/533170/prove-an-upper-bound-for-the-binomials/533258?noredirect=1#533258), first we rearrange the inequality:\n\n$$ \\binom{n}{k} \\le \\frac{n^n}{k^k(n-k)^{n-k}} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\frac{k^k}{k!} \\cdot \\frac{(n-k)^{n-k}}{(n-k)!} \\le \\frac{n^n}{n!} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\frac{k^k}{k!} \\cdot \\frac{m^m}{m!} \\le \\frac{(k+m)^{k+m}}{(k+m)!}$$\n\nWhere $m = n-k$. Then we need to know that $\\Big(1 + \\frac{1}{n}\\Big)^n$ is\nmonotonous. This is not that surprising, because:\n\n$$\\lim_{x \\to +\\infty}\\Big(1 + \\frac{1}{n}\\Big)^n = e$$\n\nFinally, we go like this:\n\n$$ \\begin{aligned}\n   \\frac{k^k}{k!} \\cdot \\frac{(m+1)^{m+1}}{(m+1)!}\n     &=   \\frac{k^k}{k!} \\cdot \\frac{(m+1)^m}{m!} \\\\\\\\\n     &=   \\frac{k^k}{k!} \\cdot \\frac{m^m}{m!} \\Bigg(1+\\frac{1}{m}\\Bigg)^m \\\\\\\\\n     &\\le \\frac{(k+m)^{k+m}}{(k+m)!}\\Bigg(1+\\frac{1}{m}\\Bigg)^m & \\text{(inductive hypothesis)} \\\\\\\\\n     &\\le \\frac{(k+m)^{k+m}}{(k+m)!}\\Bigg(1+\\frac{1}{k+m}\\Bigg)^{k+m} & \\text{(monotonicity)} \\\\\\\\\n     &=   \\frac{(k+m+1)^{k+m}}{(k+m)!}\n     &=   \\frac{(k+m+1)^{k+m+1}}{(k+m+1)!}\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/C/01/13.markdown",
    "content": "> $\\star$ Use Stirling's approximation to prove that\n>\n> $$ \\binom{2n}{n} = \\frac{2^{2n}}{\\sqrt{\\pi n}}(1 + \\mathcal{O}(1/n)) $$\n\nSo:\n\n$$ \\begin{aligned}\n   \\binom{2n}{n} &= \\frac{(2n)!}{n!(2n-n)!} = \\frac{(2n)!}{(n!)^2} \\\\\\\\\n     &= \\frac{\\sqrt{2 \\pi 2 n}\\big(\\frac{2n}{e}\\big)^{2n}\\Big(1 + \\Theta(\\frac{1}{n})\\Big)}\n            {2 \\pi n \\big(\\frac{n}{e}\\big)^{2n}\\Big(1 + \\Theta(\\frac{1}{n})\\Big)^2} \\\\\\\\\n     &= \\frac{1}{\\sqrt{\\pi n}} \\frac{2^{2n}n^{2n}}{n^{2n}}(1 + \\mathcal{O}(1/n)) \\\\\\\\\n     &= \\frac{2^{2n}}{\\sqrt{\\pi n}}(1 + \\mathcal{O}(1/n))\n   \\end{aligned} $$\n\nThere is a little hand-waving at the end, but it is good enough.\n"
  },
  {
    "path": "other/clrs/C/01/14.markdown",
    "content": "> $\\star$ By differentiating the entropy function $H(\\lambda)$, show that it\n> achieves its maximum value at $\\lambda = 1/2$. What is $H(1/2)$?\n\nPhew, it took me a while to figure out that I've forgotten calculus:\n\n$$ H(\\lambda) = -\\lambda\\lg{\\lambda} - (1 - \\lambda)\\lg(1 - \\lambda) \\\\\\\\\n   \\begin{aligned}\n     H'(\\lambda) &= -\\lg{\\lambda} - \\frac{\\lambda 1}{\\lambda \\ln2} + \\lg(1 - \\lambda) - \\frac{(1-\\lambda)}{(1-\\lambda)(-1)\\ln2} \\\\\\\\\n           &= \\lg\\frac{1 - \\lambda}{\\lambda} - \\lg{e} + \\lg{e} \\\\\\\\\n           &= \\lg\\frac{1 - \\lambda}{\\lambda}\n   \\end{aligned} $$\n\nLet's find a critical point:\n\n$$\nH'(\\lambda) = 0 \\\\\\\\\n\\Downarrow \\\\\\\\\n\\lg\\frac{1 - \\lambda}{\\lambda} = 0 \\\\\\\\\n\\Downarrow \\\\\\\\\n\\frac{1-\\lambda}{\\lambda} = 1 \\\\\\\\\n\\Downarrow \\\\\\\\\n\\lambda = 1/2\n$$\n\nBecause $H'(1/4) = \\lg{3} > 0$ and $H'(3/4) = \\lg(1/3) < 0$, we know that it is a maxima.\n\n$$ H(1/2) = - \\lg(1/2)/2 -\\lg(1/2)/2 = - \\lg{1/2} = 1 $$\n"
  },
  {
    "path": "other/clrs/C/01/15.markdown",
    "content": "> $\\star$ Show that for any integer $n \\ge 0$,\n>\n> $$ \\sum_{k=0}^n\\binom{n}{k}k = n2^{n-1} $$\n\n$$ \\sum_{k=0}^n\\binom{n}{k}k\n   = \\sum_{k=1}^n\\binom{n}{k}k\n   = \\sum_{k=1}^n\\frac{nk}{k}\\binom{n-1}{k-1}\n   = n\\sum_{k=1}^n\\binom{n-1}{k-1}\n   = n\\sum_{k=0}^n\\binom{n-1}{k}\n   = n2^{n-1} $$\n"
  },
  {
    "path": "other/clrs/C/02/01.markdown",
    "content": "> Professor Rosencrantz flips a fair coin. Professor Guildenstern flips a fair\n> coin twice. What is the probability that Professor Rosencrantz obtains more\n> heads than professor Guildenstern?\n\nLet us call $G_n$ and $R_n$ the number of heads each professor has. The answer\nis:\n\n$$ \\Pr\\\\{R_n = 1\\\\}.\\Pr\\\\{G_n = 0\\\\} = \\frac{1}{2}.\\frac{1}{4} = \\frac{1}{8} $$\n"
  },
  {
    "path": "other/clrs/C/02/02.markdown",
    "content": "> Prove **Boole's inequality**: For any finite or countably infinte sequence of\n> events $A_1, A_2, \\ldots$,\n>\n> $$ \\Pr\\\\{A_1 \\cup A_2 \\cup \\ldots \\\\} \\le \\Pr\\\\{A_1\\\\} + \\Pr\\\\{A_2\\\\} + \\ldots $$\n\n$$ \\begin{aligned}\n   \\Pr\\\\{A_1 \\cup A_2 \\cup \\cdots\\\\} &=\n                             \\Pr\\\\{A_1\\\\} +\n                             \\Pr\\\\{A_2 \\cup A_3 \\cup \\cdots\\\\} -\n                             \\Pr\\\\{A_1 \\cap (A_2 \\cup A_3 \\cup \\cdots)\\\\} \\\\\\\\\n                       & \\le \\Pr\\\\{A_1\\\\} + \\Pr\\\\{A_2 \\cup A_3 \\cup \\cdots\\\\} \\\\\\\\\n                       & \\le \\Pr\\\\{A_1\\\\} + \\Pr\\\\{A_2\\\\} + \\Pr\\\\{A_3 \\cup A_4 \\cup \\cdots\\\\}\n   \\end{aligned} $$\n\nStrictly speaking, we should use some induction, but you get the idea.\n"
  },
  {
    "path": "other/clrs/C/02/03.markdown",
    "content": "> Suppose we shuffle a deck of 10 cards, each bearing a distinct number from 1\n> to 10, to mix the cards thoroughly. We then remove three cards, one at a\n> time, from the deck. What is the probability that we select the three cards\n> in sorted (increasing) order?\n\nThere are $n!/(n-k)!$ ways to pick $k$ cards. Out of those, only $\\binom{n}{k}$\nare ascending. Thus the probability is:\n\n$$ \\binom{n}{k} \\div \\frac{n!}{(n-k)!} = \\frac{n!(n-k)!}{k!(n-k)!n!} = \\frac{1}{k!} $$\n\nFor three cards, this is $1/6$.\n\nI tried approaching this with probabilities, but it was way harder than just\ncounting. Also, I wrote a small ruby program to verify my result ;)\n"
  },
  {
    "path": "other/clrs/C/02/04.markdown",
    "content": "> Prove that\n>\n> $$ \\Pr\\\\{A | B\\\\} + \\Pr\\\\{\\overline A | B\\\\} = 1 $$\n\nVery obvious if you think about it, but anyway:\n\n$$ \\begin{aligned}\n   \\Pr\\\\{A|B\\\\} + \\Pr\\\\{\\overline A | B\\\\}\n           &= \\frac{\\Pr\\\\{A \\cap B\\\\}}{\\Pr\\\\{B\\\\}} +\n              \\frac{\\Pr\\\\{\\overline A \\cap B\\\\}}{\\Pr\\\\{B\\\\}} \\\\\\\\\n           &= \\frac{\\Pr\\\\{A \\cap B\\\\} + \\Pr\\\\{\\overline A \\cap B\\\\}}{\\Pr\\\\{B\\\\}} \\\\\\\\\n           &= \\frac{\\Pr\\\\{(\\overline A \\cap B) \\cup (A \\cap B)\\\\}}{\\Pr\\\\{B\\\\}} \\\\\\\\\n           &= \\frac{\\Pr\\\\{(A \\cup \\overline A) \\cap B)}{\\Pr\\\\{B\\\\}} \\\\\\\\\n           &= \\frac{\\Pr\\\\{B\\\\}}{\\Pr\\\\{B\\\\}} \\\\\\\\\n           &= 1\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/C/02/05.markdown",
    "content": "> Prove that for any collection of events $A_1,A_2,\\ldots,A_n$\n>\n> $$ \\Pr\\\\{A_1 \\cap A_2 \\cap \\cdots \\cap A_n\\\\} = \\Pr\\\\{A_1\\\\} \\cdot \\Pr\\\\{A_2 | A_1\\\\} \\cdot \n>    \\Pr\\\\{A_3 | A_1 \\cap A_2\\\\} \\cdots \\Pr\\\\{A_n | A_1 \\cap A_2 \\cap \\cdots \\cap A_{n-1}\\\\} $$\n\nThis is nice\n\n$$ \n    \\begin{aligned}\n    \\Pr\\\\{A_1 \\cap A_2 \\cap \\cdots\\\\}\n     &= \\Pr\\\\{A_n | A_1 \\cap \\cdots \\cap A_{n-1}\\\\} \\cdot\n        \\Pr\\\\{A_1 \\cap \\cdots \\cap A_{n-1}\\\\} \\\\\\\\\n     &= \\Pr\\\\{A_n | A_1 \\cap \\cdots \\cap A_{n-1}\\\\} \\cdot\n        \\Pr\\\\{A_{n-1} | A_1 \\cap \\cdots \\cap A_{n-2}\\\\} \\cdot\n        \\Pr\\\\{A_1 \\cap \\cdots \\cap A_{n-2}\\\\} \\\\\\\\\n     &= \\ldots \\\\\\\\\n     &= \\Pr\\\\{A_n | A_1 \\cap \\cdots \\cap A_{n-1}\\\\} \\cdots\n        \\Pr\\\\{A_3 | A_1 \\cap A_2\\\\} \\cdot\n        \\Pr\\\\{A_2 | A_1\\\\} \\cdot\n        \\Pr\\\\{A_1\\\\}\n   \\end{aligned}\n$$\n"
  },
  {
    "path": "other/clrs/C/02/06.markdown",
    "content": "> $\\star$ Describe a procedure that takes as input two integers $a$ and $b$\n> such that $0 < a < b$ and, using fair coin flips, produces as output heads\n> with probability $a/b$ and tails with probability $(b-a)/b$. Give a bound on\n> the expected number of coin flips, which should be $\\mathcal{O}(1)$. (Hint:\n> represent $a/b$ in binary.)\n\nThis is actually tricky. Fortunatelly, [this answer][answer] helper me.\n\n[answer]: http://math.stackexchange.com/questions/63207/produce-output-with-certain-probability-using-fair-coin-flips\n\nYou represent $a/b$ as binary. Then you start flipping coins and expect each\nflip to match a digit (0 for heads, 1 for tails). If you expect a 0, but get 1,\nyou return tail. If you expect 1 and get a 0, you return heads. Otherwise, you\nkeep doing it.\n\nTo put it otherwise, just the flips produce a random number in binary. If you\nexpect 0, but get 1, then you have produced a number greated than $a/b$.\nOtherwise, you have produced a number less than it.\n\nThe probability of terminating is $1/2$ at each flip. The expected number of\nthrows is:\n\n$$ \\sum_{r=1}^{\\infty}\\frac{r}{2^r}\n   = \\frac{1/2}{1/4}\n   = 2 $$\n\nDon't know when this came from? Well, for $k < 1$:\n\n$$ \\sum_{k=0}^{\\infty}kx^k = \\frac{x}{(1 - x)^2} $$\n\nHow do you get that, you ask? You just integrate this sum:\n\n$$ \\sum_{k=0}^{\\infty}x^k = \\frac{1}{1-x} $$\n\nMindblowing.\n"
  },
  {
    "path": "other/clrs/C/02/07.markdown",
    "content": "> $\\star$ Show how to construct a set of $n$ events that are pairwise\n> independent but such that no subset of $k > 2$ of them is mutually\n> independent.\n\nGet a dice with $n^2$ sides (you can actually construct one of those). Assign\nthe numbers $1 \\ldots n$ to $n$ colors, non of which is black. Use each color\nto paint $n-1$ sides, paint one side striped with all colors, and paint the\nrest black. Here's a table:\n\n|         |  1  |  2  |  3  | ... | n |\n|:-------:|:---:|:---:|:---:|:---:|:-:|\n|  **1**  |  1  |  2  |  3  | ... | n |\n|  **2**  |  1  |  2  |  3  | ... | n |\n|  **3**  |  1  |  2  |  3  | ... | n |\n|   ...   | ... | ... | ... | ... | n |\n| **n-1** |  1  |  2  |  3  | ... | n |\n|  **n**  | all |  -  |  -  | ... | - |\n\nCounting the side painted with all colors, there are $(n-1 + 1)/n^2 = 1/n$ ways\nto get each color. For any two colors, there are $1/n^2$ ways, which satisfies\nthe equation for independence. However, for $k$ colors, the chances are too\n$1/n^2$, where they should be $1/n^k$ if that event was independent.\n\nThus, each pair is independent, but each subset with three or more elements is\nnot.\n\nI'm actually quite proud of this solution.\n\nThere is an [interesting article](http://www.pme-math.org/journal/issues/PMEJ.Vol.9.No.9.pdf)\nin the Pi Mu Epsilon Journal, vol 9, 1993\n"
  },
  {
    "path": "other/clrs/C/02/08.markdown",
    "content": "> $\\star$ Two events $A$ and $B$ are **conditionally independent**, given $C$,\n> if\n>\n> $$ \\Pr\\\\{A \\cap B | C\\\\} = \\Pr\\\\{A | C\\\\} \\cdot \\Pr\\\\{B | C\\\\} $$\n>\n> Give a simple but nontrivial example of two events that are not independent\n> but are conditionally independent given a third event.\n\nTwo people use the same coin.\n\n* **A** - person 1 tosses heads\n* **B** - person 2 tosses heads\n* **C** - the coin is biased (falls heads only) - happens one in three times\n\nThus:\n\n$$\n\\Pr\\\\{A\\\\} = \\frac 1 3 \\cdot 1 + \\frac 2 3 \\cdot \\frac 1 2 = \\frac 2 3 \\\\\\\\\n\\Pr\\\\{B\\\\} = \\frac 1 3 \\cdot 1 + \\frac 2 3 \\cdot \\frac 1 2 = \\frac 2 3 \\\\\\\\\n\\Pr\\\\{A \\cap B\\\\} = \\frac 1 3 \\cdot 1 + \\frac 2 3 \\cdot \\frac 1 4 = \\frac 1 2\n$$\n\nThe two events are not independent, because:\n\n$$ \\frac 2 3 = \\Pr\\\\{A \\cap B\\\\} \\neq \\Pr\\\\{A\\\\} \\cdot \\Pr\\\\{B\\\\} = \\frac 4 9 $$\n\nHowever, they are conditionally independent, because:\n\n$$ 1 = \\Pr\\\\{A \\cap B | C \\\\} = \\Pr\\\\{A | C\\\\} \\cdot \\Pr\\\\{B | C\\\\} = 1 $$\n"
  },
  {
    "path": "other/clrs/C/02/09.markdown",
    "content": "> $\\star$ You are a contestant in a game show in which a prize is hidden behind\n> one of three curtains. You will win the prize if you select the correct\n> curtain. After you have picked one curtain but before the curtain is lifted,\n> the emcee lifts one of the other curtains, knowing that it will reveal an\n> empty stage, and asks if you would like to switch from your current selection\n> to the remaining curtain. How would your chances change if you switch? (This\n> question is the celebrated **Monty Hall problem**, named after a game-show\n> host who often presented contestants with just this dilemma.)\n\nThis is [very popular](http://en.wikipedia.org/wiki/Monty_Hall_problem).\n\nIf you are always given this choice and take it:\n\n* If you picked the right curtain (probability $1/3$), you will switch to an\n  empty stage\n* If you picked a wrong curtain (probability $2/3$), you will switch to the\n  prize (that's the only option, since the other empty stage is shown)\n\nEffectively, you interchange success and failure. That way, the probability to\nwin is $2/3$ and you should always take it (if the choice is given to you in an\nunbiased fashion).\n"
  },
  {
    "path": "other/clrs/C/02/10.markdown",
    "content": "> $\\star$ A prison warden has randomly picked one prisoner among three to go\n> free. The other two will be executed. The guard knows which one will go free\n> but is forbidden to give any prisoner information regarding his status. Let\n> us call the prisoners X, Y and Z. Prisoner X asks the guard privately which\n> of Y or Z will be executed, arguing that since he already knows that at least\n> one of them must die, the guard won't be revealing any information about his\n> own status. The guard tells X that Y is to be executed. Prisoner X feels\n> happier now, since he figures that either he or prisoner Z will go free,\n> which means that his probability of going free is now $1/2$. Is he right, or\n> are his chances still $1/3$? Explain.\n\nObviously the event took place before prisoner X obtained that knowledge and\nthis should not impact his chances in anyway.\n\nBut words are cheap, let's use math:\n\n* **y** is the event of the guard saying prisoner Y will be executed\n* **X**, **Y** and **Z** are the events of each prisoner going free\n* If X is going free, the guard has a 50% of saying Y is executed\n\n$$\n\\Pr\\\\{y|X\\\\} = \\frac 1 2 \\\\\\\\\n\\Pr\\\\{y\\\\} = \\Pr\\\\{y \\cap X\\\\} + \\Pr\\\\{y \\cap Y\\\\} + \\Pr\\\\{y \\cap Z\\\\} = \\frac 1 3 \\cdot \\frac 1 2 + \\frac 1 3 \\cdot 0 + \\frac 1 3 \\cdot 1 = \\frac 1 6 + \\frac 1 3 = \\frac 1 2 \\\\\\\\\n\\Pr\\\\{X|y\\\\} = \\frac{\\Pr\\\\{y|X\\\\} \\cdot \\Pr\\\\{X\\\\}}{\\Pr\\\\{y\\\\}} = \\frac{\\frac 1 2 \\cdot \\frac 1 3}{\\frac 1 2} = \\frac 1 3\n$$\n\nThis one is also [very popular](http://en.wikipedia.org/wiki/Three_Prisoners_problem)\n"
  },
  {
    "path": "other/clrs/C/03/01.markdown",
    "content": "> Suppose we roll two ordinary, 6-sided dice. What is the expectation of the\n> sum of two values showing? What is the expectation of the maximum of two\n> values showing?\n\nThe expectation of the sum is:\n\n$$ \\begin{aligned}\n     \\E[X] &= \\sum_{x=2}^{12}x\\Pr\\\\{X = x\\\\} \\\\\\\\\n           &=  2 \\cdot \\frac 1 36 +\n               3 \\cdot \\frac 2 36 +\n               4 \\cdot \\frac 3 36 +\n               5 \\cdot \\frac 4 36 +\n               6 \\cdot \\frac 5 36 +\n               7 \\cdot \\frac 6 36 +\n               8 \\cdot \\frac 5 36 +\n               9 \\cdot \\frac 4 36 +\n              10 \\cdot \\frac 3 36 +\n              11 \\cdot \\frac 2 36 +\n              12 \\cdot \\frac 1 36 \\\\\\\\\n           &= 7\n   \\end{aligned}$$\n\nThe result is as expected, the probabilities are obtained by just counting them.\n\nAs for the maximum, a table helps illustrate the probabilities:\n\n|       | 1 | 2 | 3 | 4 | 5 | 6 |\n|:-----:|:-:|:-:|:-:|:-:|:-:|:-:|\n| **1** | 1 | 2 | 3 | 4 | 5 | 6 |\n| **2** | 2 | 2 | 3 | 4 | 5 | 6 |\n| **3** | 3 | 3 | 3 | 4 | 5 | 6 |\n| **4** | 4 | 4 | 4 | 4 | 5 | 6 |\n| **5** | 5 | 5 | 5 | 5 | 5 | 6 |\n| **6** | 6 | 6 | 6 | 6 | 6 | 6 |\n\nThere is a nice geometrical interpretation here. In any case, the chance of $n$\nbeing the maximum of two dice is $(2n-1)/36$. Thus:\n\n$$ \\E[Y]\n   = \\sum_{i=1}^{6}i\\Pr\\\\{Y = i\\\\}\n   = \\sum_{i=1}^{6}\\Bigg(i \\cdot \\frac{2i - 1}{36}\\Bigg)\n   = \\frac{2\\sum{i^2} - \\sum{i}}{36}\n   = \\frac{(6 \\cdot 7 \\cdot 13)/6 - (6 \\cdot 7)/2}{36}\n   = \\frac{161}{36} = 4.47\\ldots $$\n"
  },
  {
    "path": "other/clrs/C/03/02.markdown",
    "content": "> An array $A[1\\ldots n]$ contains $n$ distinct numbers that are randomly\n> ordered, with each permutation of the $n$ numbers equally likely. What is the\n> expectation of the index of the maximum element in the array? What is the\n> expectation of the minimum element of the array?\n\nThe expectation of the max element having an index $i$ is $\\Pr\\\\{X = i\\\\} = \\frac 1 n$.\n\n$$ \\E[X] = \\sum_{i=1}^n i \\cdot \\Pr\\\\{X = i\\\\}\n         = \\sum_{i=1}^n i \\cdot \\frac 1 n\n         = \\frac 1 n \\sum_{i=1}^n i\n         = \\frac 1 n \\frac{n(n+1)}{2}\n         = \\frac{n+1}{2} $$\n\nNot a surprising result.\n\nCurious: the same logic applies for the minimum element. Thus, the expectation\nfor the index of the minimum element is the same.\n"
  },
  {
    "path": "other/clrs/C/03/03.markdown",
    "content": "> A carnival game consists of three dice in a cage. A player can be a dollar on\n> any of the numbers 1 through 6. The cage is shaken, and the payoff is as\n> follows. If the player's number doesn't appear on any of the dice, he loses\n> his dollar. Otherwise, if his number appears on exactly $k$ of the three\n> dice, for $k = 1, 2, 3$, he keeps his dollar and wins $k$ more dollars. What\n> is the expected gain from playing the carnival game once?\n\nHere are the probabilities:\n\n$$ \\Pr\\\\{X = 3\\\\} = 1/216 \\\\\\\\\n   \\Pr\\\\{X = 2\\\\} = 3(6/216) - 3(1/126) = 5/216 \\\\\\\\\n   \\Pr\\\\{X = 1\\\\} = 3(36/216) - 3(11/216) = 75/216 \\\\\\\\\n   \\Pr\\\\{X = 1\\\\} = 125/216 $$\n\n(There are 36 ways that a specific die is $k$, but in 10 of them one of the\nother die is also $k$ and in one of them both are).\n\nHere's the calculation:\n\n$$ \\begin{aligned}\n   \\E[X] &= -1 \\cdot \\Pr\\\\{X = 0\\\\} +\n             1 \\cdot \\Pr\\\\{X = 1\\\\} +\n             2 \\cdot \\Pr\\\\{X = 2\\\\} +\n             3 \\cdot \\Pr\\\\{X = 3\\\\} \\\\\\\\\n         &= - 1 \\cdot \\frac{125}{216}\n            + 1 \\cdot \\frac{75}{216}\n            + 2 \\cdot \\frac{15}{216}\n            + 3 \\cdot \\frac{1}{216} \\\\\\\\\n         &= - \\frac{17}{216} \\\\\\\\\n         &= -0.07\\ldots\n   \\end{aligned} $$\n\nTurns out you loose ever so slightly. This did not match my intuition.\n"
  },
  {
    "path": "other/clrs/C/03/04.markdown",
    "content": "> Argue that if $X$ and $Y$ are nonnegative random variables, then\n>\n> $$ \\E[\\max(X, Y)] \\le \\E[X] + \\E[Y] $$\n\nThere is a hidden assumption that $X$ and $Y$ are on the same domain\n(otherwise, you can't define $\\max(X, Y)$). The expectations can be expanded as\nthis:\n\n$$ \\E[\\max(X, Y)] = \\sum n \\cdot \\max(\\Pr\\\\{X = n\\\\}, \\Pr\\\\{Y = n\\\\}) \\\\\\\\\n   \\E[X] = \\sum n \\Pr\\\\{X = n\\\\} \\qquad\n   \\E[X] = \\sum n \\Pr\\\\{Y = n\\\\} $$\n\nEach of the summands in the first formula appears in either $\\E[X]$ or $\\E[Y]$.\nTheir sum contains twice as many, all nonnegative. That makes it equal or\ngreater.\n"
  },
  {
    "path": "other/clrs/C/03/05.markdown",
    "content": "> $\\star$ Let $X$ and $Y$ be independent random variables. Prove that $f(X)$\n> and $g(Y)$ are independent for any choice of functions $f$ and $g$.\n\n**(UNSOLVED)** This is so intuitively obvious, that I have a hard time wanting to\ndo it. On the other hand, intuition disagrees with many things in probability\nthoery. Either way, I have no clue what to do with $\\Pr\\\\{f(X)\\\\}$, so I don't\nknow how to prove it.\n"
  },
  {
    "path": "other/clrs/C/03/06.markdown",
    "content": "> $\\star$ Let $X$ be a nonnegative random variable, and suppose that $E[Y]$ is\n> well defined. Prove **Markov's inequality**:\n>\n> $$ \\Pr\\\\{X \\ge t\\\\} \\le \\E[X]/t $$\n>\n> for all $t > 0$.\n\n$$ \\begin{aligned}\n   \\E[X] &= \\sum_{x}x \\cdot \\Pr\\\\{X \\ge t\\\\} \\\\\\\\\n         &= \\sum_{x < t}x \\cdot \\Pr\\\\{X = x\\\\} + \\sum_{x \\ge t} x \\cdot \\Pr\\\\{X = x\\\\} \\\\\\\\\n         & \\ge \\sum_{x < t}x \\cdot \\Pr\\\\{X = x\\\\} + \\sum_{x \\ge t} t \\cdot \\Pr\\\\{X = x\\\\} \\\\\\\\\n         & \\ge t \\sum_{x \\ge t} \\Pr\\\\{X = x\\\\} \\\\\\\\\n         &= t \\cdot \\Pr\\\\{X \\ge t\\\\}\n   \\end{aligned} $$\n\nChaning $x$ with $t$ in one of the sum works, since that is the sum where $x\n\\ge t$.\n\nThus follows:\n\n$$ \\E[X] \\ge t \\cdot \\Pr\\\\{X \\ge t\\\\} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\Pr\\\\{X \\ge t\\\\} \\le \\E[X]/t $$\n"
  },
  {
    "path": "other/clrs/C/03/07.markdown",
    "content": "> Let $S$ be a sample space, and let $X$ and $X'$ be random variables such that\n> $X(s) \\ge X'(s)$ for all $s \\in S$. Prove that for any real constant $t$,\n>\n> $$ \\Pr\\\\{X \\ge t\\\\} \\ge \\Pr\\\\{X' \\ge t\\\\} $$\n\nBoth of them, expanded, are:\n\n$$ \\Pr\\\\{X \\ge t\\\\} = \\sum_{s \\in S:X(s) \\ge t}\\Pr\\\\{s\\\\} \\\\\\\\\n   \\Pr\\\\{X' \\ge t\\\\} = \\sum_{s \\in S:X'(s) \\ge t}\\Pr\\\\{s\\\\} $$\n\nEach term of the second sum is present in the first sum, because $X(s) \\ge\nX'(s)$. This makes them at least equal. There might be additional terms in the\nfirst sum (when $X(s) \\ge t > X'(s)$. Thus it can also be greater.\n"
  },
  {
    "path": "other/clrs/C/03/08.markdown",
    "content": "> Which is larger: The expectation of the square of a random variable, or the\n> square of its expectation?\n\nWe know that:\n\n$$ \\E[f(X)] \\ge f(\\E[X]) $$\n\nIf $f(x) = x^2$:\n\n$$ \\E[X^2] \\ge \\E^2[X] $$\n\nThe expectation of the square is larger.\n"
  },
  {
    "path": "other/clrs/C/03/09.markdown",
    "content": "> Show that for any random variable $X$ that takes on only the values $0$ and\n> $1$, we have $\\Var[X] = \\E[X]\\E[1-X]$.\n\nLet's first calculate the expectations:\n\n$$ \\E[X] = 0 \\cdot \\Pr\\\\{X = 0\\\\} + 1 \\cdot \\Pr\\\\{X = 1\\\\} = \\Pr\\\\{X = 1\\\\} \\\\\\\\\n   \\E[1-X] = \\Pr\\\\{X = 0\\\\} \\\\\\\\\n   \\E[X]\\E[1-X] = \\Pr\\\\{X = 0\\\\} \\cdot \\Pr\\\\{X = 1\\\\} $$\n\nNow - the variance:\n\n$$ \\Var[X] = \\E[X^2] - \\E^2[X] = \\Pr\\\\{X = 1\\\\} - (\\Pr\\\\{X = 1\\\\})^2\n           = \\Pr\\\\{X = 1\\\\} (1 - \\Pr\\\\{X = 1\\\\})\n           = \\Pr\\\\{X = 0\\\\} \\cdot Pr\\\\{X = 1\\\\} $$\n"
  },
  {
    "path": "other/clrs/C/03/10.markdown",
    "content": "> Prove that $\\Var[\\alpha X] = \\alpha^2 \\Var[X]$ from the definition (C.27) of\n> variance.\n\nEasy. We just use the linearity of expectation:\n\n$$ \\Var[\\alpha X] = \\E[\\alpha^2 X^2] - \\E^2[\\alpha X]\n                  = \\alpha^2 \\E[X^2] - \\alpha^2\\E[X]\n                  = \\alpha^2 (\\E[X^2] - \\E^2[X])\n                  = \\alpha^2 \\Var[X] $$\n"
  },
  {
    "path": "other/clrs/C/04/01.markdown",
    "content": "> Verify axiom 2 of the probability axioms for the geometric distribution.\n\n$$ \\sum_{k=1}^{\\infty} \\Pr\\\\{X = k\\\\}\n   = \\sum_{k=1}^{\\infty} q^{k-1}p\n   = p \\sum_{k=0}^{\\infty} q^k\n   = p \\frac{1}{1-q}\n   = \\frac{p}{p}\n   = 1 $$\n"
  },
  {
    "path": "other/clrs/C/04/02.markdown",
    "content": "> How many times on average must we flip 6 fair coins before we obtain 3 heads\n> and 3 tails?\n\nThe $\\binom{6}{3}$ ways to have three heads and three tails. Thus:\n\n$$ \\Pr\\\\{\\text{3H3T}\\\\}\n     = \\binom{6}{3} / 2^6\n     = 5/16 $$\n\nAs for the expectation:\n\n$$ \\E[\\text{3H3T}] = \\frac{1}{\\Pr\\\\{\\text{3H3T}\\\\}} = \\frac{16}{5} = 3.2 $$\n\nThis can be verified by the following line of Ruby:\n\n    1_000_000.times.map { 1.upto(2**32).take_while { 6.times.map { rand(2) }.count(1) != 3 }.last.to_i.succ }.inject(:+) / 1_000_000.to_f\n"
  },
  {
    "path": "other/clrs/C/04/03.markdown",
    "content": "> Show that $b(k;n,p) = b(n-k;n,q)$, where $q = 1 - p$.\n\n$$ b(k;n,p) = \\binom{n}{k} p^k q^{n-k}\n            = \\binom{n}{n-k} p^k q^{n-k}\n            = \\binom{n}{n-k} q^{n-k} p^k\n            = b(n-k;n,q) $$\n"
  },
  {
    "path": "other/clrs/C/04/04.markdown",
    "content": "> Show that value of the maximum of the binomial distribution $b(k;n,p)$ is\n> approximately $1/\\sqrt{2 \\pi n p q}$ where $q = 1 - p$.\n\nThere is a lot of calculation to be performed here, but this is essentially an\napplication of the [de Moivre-Laplace theorem][de-moivre-laplace]. It's too\ncomplex for me to want to bother to write it down.\n\n[de-moivre-laplace]: http://en.wikipedia.org/wiki/De_Moivre%E2%80%93Laplace_theorem\n"
  },
  {
    "path": "other/clrs/C/04/05.markdown",
    "content": "> $\\star$ Show that the probability of no successes in $n$ Bernoulli trials,\n> each with probability $p = 1/n$, is approximately $1/e$. Show that the\n> probability of exactly one success is also $1/e$\n\nThe probability of no successes of $n$ trials is:\n\n$$ b(0;n,p) = \\binom{n}{k} p^k q^{n-k}\n            = \\binom{n}{0} q^n\n            = (1-p)^n\n            = \\Big(1 - \\frac{1}{n}\\Big)^n\n            = \\frac{1}{\\Big(1-\\frac{1}{n}\\Big)^{-n}}\n$$\n\nThe probability of one success of $n$ trials is:\n\n\n$$ b(1;n,p) = \\binom{n}{1} \\frac{1}{n} \\bigg(1 - \\frac{1}{n}\\bigg)^{n-1}\n            = \\frac{1}{\\Big(1-\\frac{1}{n}\\Big)^{-(n-1)}}\n$$\n\nWe know that:\n\n$$ e = \\lim_{n \\to \\infty}\\bigg(1 + \\frac{1}{n}\\bigg)^n\n     = \\lim_{n \\to \\infty}\\bigg(1 - \\frac{1}{n}\\bigg)^{-n} $$\n\nWe can just substitute in the examples above and get approximately $1/e$.\n"
  },
  {
    "path": "other/clrs/C/04/06.markdown",
    "content": "> $\\star$ Professor Rosencrantz flips a fair coin $n$ times, and so does\n> Professor Guildenstern. Show that the probability that they get the same\n> number of heads is $\\binom{2n}{n}/4^n$. (Hint: For Professor Rosencrantz,\n> call a head a success; for Professor Guildenstern, call a tail a success.)\n> Use your argument to verify the identity\n>\n> $$ \\sum_{k=0}^n\\binom{n}{k}^2 = \\binom{2n}{n} $$\n\nLet's do what the hint says: call tails for Professor Guildenstern a success\nand heads - failure. They have the same numbers of heads when they have\n$k + (n - k) = n$ successes out of $2n$ trials.\n\n$$ \\Pr\\\\{R=G\\\\} = b(n;2n;1/2)\n                = \\binom{2n}{n} \\frac{1}{2^n} \\frac{1}{2^n}\n                = \\binom{2}{n}/4^n $$\n\nAlternatively, we can just calculate the probability and see what happens:\n\n$$ \\begin{aligned}\n   \\Pr\\\\{R=G\\\\} &= \\sum_{k=0}^n \\Pr\\\\{R=k\\\\}\\Pr\\\\{G=n-k\\\\} \\\\\\\\\n                &= \\sum_{k=0}^n \\binom{n}{k} \\cdot \\frac{1}{2^n} \\cdot\n                               \\binom{n}{n-k} \\cdot \\frac{1}{2^n} \\\\\\\\\n                &= \\frac{1}{4^n} \\sum_{k=0}^n \\binom{n}{k} \\binom{n}{n-k} \\\\\\\\\n                &= \\frac{1}{4^n} \\sum_{k=0}^n \\binom{n}{k}^2\n  \\end{aligned} $$\n\nThose are two ways we can express the same value. This let's us verify the\nidentity.\n"
  },
  {
    "path": "other/clrs/C/04/07.markdown",
    "content": "> $\\star$ Show that for $0 \\le k \\le n$,\n>\n> $$ b(k;n,1/2) \\le 2^{nH(k/n)-n} $$\n>\n> where $H(x)$ is the entropy function (C.7)\n\n$$ b(k;n,1/2) =   \\binom{n}{k}\\frac{1}{2^n}\n              =   \\binom{n}{n\\frac{k}{n}}\\frac{1}{2^n}\n              \\le \\frac{2^{nH(k/n)}}{2^n}\n              =   2^{nH(k/n) - n} $$\n"
  },
  {
    "path": "other/clrs/C/04/08.markdown",
    "content": "> $\\star$ Consider $n$ Bernoulli trials, where $i = 1, 2, \\ldots, n$, the $i$th\n> trial has probability $p_i$ of success, and let $X$ be the random variable\n> denoting the total number of successes. Let $p \\ge p_i$ for all $i = 1, 2,\n> \\ldots, n$. Prove that $1 \\le k \\le n$,\n>\n> $$ \\Pr\\\\{X < k\\\\} \\ge \\sum_{i=0}^{k-1}b(i;n,p) $$\n\nLet's create another set of Bernoulli trials $Y$, each with probability $p$.\n\n$$ \\Pr\\\\{Y < k\\\\} = 1 - \\Pr\\\\{Y \\ge k\\\\} \\le 1 - \\Pr\\\\{X \\ge k\\\\} = \\Pr\\\\{X < k\\\\} $$\n\nThe inequality follows from exercise C.4-9. That's right. We haven't done it\nyet, but we're using it. That's because I'm the Doctor!\n"
  },
  {
    "path": "other/clrs/C/04/09.markdown",
    "content": "> $\\star$ Let $X$ be the random variable for the total number of successes, in\n> a set $A$ of $n$ Bernoulli trials, where the $i$th trial has a probability\n> $p_i$ of success, and let $X'$ be the random variable for the total number of\n> successes in a second set $A'$ of $n$ Bernoulli trials, where the $i$th trial\n> has a probability $p_i' \\ge p_i$ of success. Prove that $o \\le k \\le n$,\n>\n> $$ \\Pr\\\\{X' \\ge k\\\\} \\ge \\Pr\\\\{X \\ge k\\\\} $$\n>\n> (Hint: Show how to obtain the Bernoulli trials in $A'$ by an experiment\n> involving the trials of $A$, and use the result of exercise C.3-7)\n\nLet $Y_1, Y_2, \\ldots Y_n$ be indicator random variables for the events in $A$.\n\nLet $Z_1, Z_2, \\ldots Z_n$ be new random variables, such that:\n\n* If $Y_i = 1$ then $Z_i = 1$\n* If $Y_i = 0$ then $Z_i = 1$ with probability $\\frac{p_i' - p_i}{1-p_i}$\n\nLet's calculate $\\Pr\\\\{Z_i\\\\}$:\n\n$$ \\Pr\\\\{Z_i\\\\} = p_i \\Pr\\\\{Y_i = 1\\\\} + (1 - p_i) \\cdot \\frac{p_i' - p_i}{1-p_i}\n                = p_i + p_i' - p_i\n                = p_i' $$\n\nSince we know that $p_i' \\ge p_i$, we can do the following:\n\n$$ \\Pr\\\\{X' \\ge k\\\\} = \\Pr\\\\{Z_1 + Z_2 + \\ldots + Z_n\\\\}\n                   \\ge \\Pr\\\\{Y_1 + Y_2 + \\ldots + Y_n\\\\}\n                     = \\Pr\\\\{X \\ge k\\\\} $$\n\nThe last part can also be proven by exercise C.3-7.\n"
  },
  {
    "path": "other/clrs/C/05/01.markdown",
    "content": "> $\\star$ Which is less likely: obtaining no heads when you flip a coin $n$\n> times, or obtaining fewer than $n$ heads when you flip the coin $4n$ times?\n\n**(UNSOLVED)** I can't figure out how to compare them, but testing with Ruby\nyields that it is less likely to get less than $n$ heads in $4n$ flips.\n"
  },
  {
    "path": "other/clrs/C/05/02.markdown",
    "content": "> $\\star$ Prove corollaries C.6 and C.7\n\nLet $Y$ be a random variable, indicating the number of failures.\n\nFor C.6 (using C.4):\n\n$$ \\Pr\\\\{X > k\\\\} = \\Pr\\\\{Y < n-k\\\\}\n                  < \\frac{(n-k)p}{nq - n + k}b(n-k;n,q)\n                  = \\frac{(n-k)p}{k-np}\\binom{n}{n-k}q^{n-k}p^k\n                  = \\frac{(n-k)p}{k-np}b(k;n,p) $$\n\nFor C.7 (using C.5):\n\n$$ \\Pr\\\\{Y < n - k\\\\} < \\frac{1}{2} \\Pr\\\\{Y < n - k + 1\\\\} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\Pr\\\\{X > k\\\\} < \\frac{1}{2} \\Pr\\\\{X > k - 1\\\\} $$\n"
  },
  {
    "path": "other/clrs/C/05/03.markdown",
    "content": "> $\\star$ Show that\n>\n> $$ \\sum_{i=0}^{k-1}\\binom{n}{i}a^i < (a+1)^n \\frac{k}{na - k(a+1)}b(k;n,a/(a+1)) $$\n>\n> for all $a > 0$ and all $k$ such that $0 < k < na/(a+1)$.\n\n\n$$ \\begin{aligned}\n   (a+1)^n \\frac{k}{na - k(a+1)}b(k;n,a/(a+1))\n       &= (a+1)^n \\frac{k \\frac{1}{a+1}}{\\frac{na-ak-a}{a+1}} b(k;n,a/(a+1)) & \\text{(C.4)} \\\\\\\\\n       &> (a+1)^n \\sum_{i=0}^{k-1}b(i;n,a/(a+1)) \\\\\\\\\n       &= (a+1)^n \\sum_{i=0}^{k-1}\\binom{n}{i}\\frac{a^i}{(a+1)^i}\\frac{1}{(a+i)^{n-i}} \\\\\\\\\n       &= (a+1)^n \\frac{1}{(a+1)^n} \\sum_{i=0}^{k-1}\\binom{n}{i}a^i \\\\\\\\\n       &= \\sum_{i=0}^{k-1}\\binom{n}{i}a^i\n       \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/C/05/04.markdown",
    "content": "> $\\star$ Prove that if $0 < k < np$, where $0 < p < 1$ and $q = 1 - p$, then\n>\n> $$ \\sum_{i=0}^{k-1}p^iq^{n-i} < \\frac{kq}{np-k}\n>                                 \\bigg(\\frac{np}{k}\\bigg)^k\n>                                 \\bigg(\\frac{nq}{n-k}\\bigg)^{n-k} $$\n\n$$ \\begin{aligned}\n   \\sum_{i=0}^{k-1}p^iq^{n-i} &= \\Pr\\\\{X < k\\\\} & \\text{(C.4)} \\\\\\\\\n                              &< \\frac{kq}{np - k} b(k;n,p) & \\text{(C.1)} \\\\\\\\\n                              &< \\frac{kq}{np - k} \\bigg(\\frac{np}{k}\\bigg)^k\n                                                   \\bigg(\\frac{nq}{n-k}\\bigg)^{n-k}\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/C/05/05.markdown",
    "content": "> $\\star$ Show that the conditions of theorem C.8 imply that\n>\n> $$ \\Pr\\\\{\\mu - X \\ge r\\\\} \\le \\bigg(\\frac{(n - \\mu)e}{r}\\bigg)^r $$\n>\n> Similarly, show that the conditions of corollary C.9 imply that\n>\n> $$ \\Pr\\\\{np - X \\ge r\\\\} \\le \\bigg(\\frac{nqe}{r}\\bigg)^r $$\n\nThis is tricky. Let's introduce a new random variable $Y = n - X$.\n\n$$ \\nu = E[Y] = E[n - X] = n - E[x] = n - \\mu $$\n\nUsing theorem C.8, we get:\n\n$$ \\Pr\\\\{Y - \\nu > r\\\\} \\le \\bigg(\\frac{\\nu e}{r}\\bigg)^r \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\Pr\\\\{\\mu - X \\ge r\\\\} \\le \\bigg(\\frac{(n - \\mu)e}{r}\\bigg)^r\n$$\n\nIt's similar with the other one, where $qn = (1-p)n = n - np$:\n\n$$ \\Pr\\\\{np - X\\\\}\n   = \\Pr\\\\{n - X - n + np\\\\}\n   = \\Pr\\\\{Y - qn > r\\\\}\n   \\le \\bigg(\\frac{nqe}{r}\\bigg)^r $$\n\n"
  },
  {
    "path": "other/clrs/C/05/06.markdown",
    "content": "> $\\star$ Consider a sequence of $n$ Bernoulli trials, where in the $i$th\n> trial, for $i = 1, 2, \\ldots, n$, success occurs with probability $p_i$ and\n> failure occurs with probability $q_i = 1 - p_i$. Let $X$ be the random\n> variable describing the total number of successes, and let $\\mu = \\E[X]$.\n> Show that for $r \\ge 0$,\n>\n> $$ \\Pr\\\\{X - \\mu \\ge r\\\\} \\le e^{-r^2/2n} $$\n>\n> (Hint: Prove that $p_i e^{\\alpha q_i} + q_i e^{-\\alpha p_i} \\le e^{\\alpha^2/2}$.\n> Then follow the outline of the proof of Theorem C.8, using this inequality in\n> place of inequality (C.45).)\n\nThis is tricky. I spent quite a while and I don't like it. Anyway, let's first\nprove the hint.\n\nLet:\n\n$$ f(x) = e^{x^2/2} - (pe^{qx} + qe^{-px}) $$\n\nWe want to prove that it is monotoneously increasing when $x \\ge 0$. It is not\nvery easy to show that $f'(x) > 0$, so let's show that $f'(x)$ is also\nmonotoneously increasing by solving $f''(x) > 0$.\n\n$$ f'(x) = xe^{x^2/2} - pq(qe^{qx} - pe^{-px}) \\\\\\\\\n   f''(x) = e^{x^2/2} + x^2 e^{x^2/2} - pq(qe^{qx} + pe^{-px}) > 0 \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\text{(} x^2 e^{x^2/2} \\text{ is positive)} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   e^{x^2/2} > pq(qe^{qx} + pe^{-px}) \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\text{(} pq < \\frac{1}{4} \\text{ from } x(1-x) - 1/4 < 0 \\text{)} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   e^{x^2/2} > \\frac{1}{4}(qe^{qx} + pe^{-px}) \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\text{(} p < 1, q < 1 \\text{)} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   4e^{x^2/2} > e^{qx} + e^{-px} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   \\text{(} e^{qx} + e^{-px} = e^{-px} (e^x + 1) < e^x + 1 \\text{)} \\\\\\\\\n   \\Downarrow \\\\\\\\\n   4e^{x^2/2} > e^x + 1 \\\\\\\\\n   \\Downarrow \\\\\\\\\n   (e^{x^2/2} > 1) \\\\\\\\\n   \\Downarrow \\\\\\\\\n   3e^{x^2/2} > e^x \\\\\\\\\n   \\Downarrow \\\\\\\\\n   3e^{x^2/2 - x} > 1 \\\\\\\\\n   \\Downarrow \\\\\\\\\n   3e^{\\frac{(x-1)^2}{2} - \\frac{1}{2}} > 1 \\\\\\\\\n   \\Downarrow \\\\\\\\\n   3 > \\sqrt{e}\n$$\n\nSince $f''(0) = 0$, then $f'(x)$ is increasing for $x \\ge 0$.\n\nSince $f'(0) = 0$, then $f(x)$ is increasing for $x \\ge 0$.\n\nSince $f(0) = 0$, then $f(x) \\ge 0$, hence the inequality holds.\n\nWe can just substitute it in the expectation:\n\n$$ \\begin{aligned}\n   \\E[e^{\\alpha (X_i - p_i)}] &=   e^{\\alpha(1-p_i)}p_i + e^{\\alpha(0-p_i)}q_i \\\\\\\\\n                              &=   p_i e^{\\alpha q_i} + q_i e^{- \\alpha p_i} \\\\\\\\\n                              &\\le e^{\\alpha^2/2}\n   \\end{aligned} $$\n\nThen:\n\n$$ \\begin{aligned}\n   \\E[e^{\\alpha(X - \\mu)}] &=  \\prod_{i=1}^n \\E[e^{\\alpha(X_i - p_i)}] \\\\\\\\\n                           &\\le \\prod_{i=1}^n \\exp(\\alpha^2 / 2) \\\\\\\\\n                           &= \\exp(n \\alpha^2/2)\n   \\end{aligned} $$\n\nAnd:\n\n$$ \\begin{aligned}\n   \\Pr\\\\{X - \\mu \\ge r\\\\} &\\le \\exp(n \\alpha^2/2)/\\exp(- \\alpha r) \\\\\\\\\n                          &=   \\exp(n\\alpha^2/2 - \\alpha r) \\\\\\\\\n                          &=   \\exp\\bigg(\\frac{n r^2}{2 n^2} - \\frac{r^2}{n}\\bigg) \\\\\\\\\n                          &=   \\exp\\bigg(-\\frac{r^2}{2n}\\bigg)\n   \\end{aligned} $$\n"
  },
  {
    "path": "other/clrs/C/05/07.markdown",
    "content": "> $\\star$ Show that choosing $\\alpha = \\ln(r/\\mu)$ minimizes the right-hand\n> side of inequality (C.47).\n\nThis is simple. Let:\n\n$$ f(x) = \\exp(mu e^{\\alpha} - r) $$\n\nLet's explore it's critical points:\n\n$$ f'(x) = \\exp(\\mu e^{\\alpha} - r)(\\mu e^{\\alpha} - r) = 0$$\n\nThis has a solution for $\\alpha = \\ln(r/\\mu)$. It's easy to see that left of\nthis point $f'(x)$ is negative and right of it it is positive. Thus, it is a\nlocal minima.\n"
  },
  {
    "path": "other/clrs/C/problems/01.markdown",
    "content": "## Balls and bins\n\n> In this problem, we investigate the effect of various assumptions on the\n> number of ways of placing $n$ balls into $b$ distinct bins.\n>\n> 1. Suppose that the $n$ balls are distinct and their order within a bin does\n>    not matter. Argue that the number of ways of placing the balls in the bins\n>    is $b^n$.\n> 2. Suppose that the balls are distinct and that the balls in each bin are\n>    ordered. Prove that there are exactly $(b + n - 1)!/(b - 1)!$ ways to\n>    place the balls in the bins. (Hint: Consider the number of ways of\n>    arranging $n$ distinct balls and $b-1$ indistinguishable stricks in a\n>    row).\n> 3. Suppose that the balls are identical, and hence their order within a bin\n>    does not matter. Show that the number of ways of placing the balls in the\n>    bins is $\\binom{b+n-1}{n}$. (Hint: Of the arrangements in part (b), how\n>    many are repeated if the balls are made identical?)\n> 4. Suppose that the balls are identical and that no bin may contain more than\n>    one balls, so that $n \\le b$. Show that the number of ways of placing the\n>    balls is $\\binom{b}{n}$.\n> 5. Suppose that the balls are identical and that no bin may be left empty.\n>    Assuming that $n \\ge b$, show that the number of ways of placing the balls\n>    is $\\binom{n-1}{b-1}$.\n\n### Distinct balls, unordered\n\nThere are $b$ ways to place the first ball, then $b$ ways to place the second\nand so on. There are $n$ balls, so the total number of ways is $b^n$.\n\n### Distinct balls, ordered\n\nAs the hint indicates, this is isomporhic to arranging $n + b - 1$ items, out\nof which $b - 1$ are separators. The balls before the first separator go in the\nfirst bin, those between the first and the second go in the second bin, etc.\nThere are $(n + b - 1)!$ ways to do that, but since the order of the separators\ndoes not matter, $(b - 1)!$ out of those are duplicated. Thus the answer is\n$(b + n - 1)!/(b - 1)!$.\n\n### Identical balls, unordered\n\nThere are $(b + n - 1)!/(b - 1)!$ ways if the balls are distinct. If they are\nmade identical, $n!$ of the arrangements are repeated for each position of the\nseparators. We get $\\frac{(b + n - 1)!}{n!(b - 1)!} = \\binom{b + n - 1}{n}$\narrangements.\n\n### Identical balls, max 1 per bin\n\nThis is reduced to selecting $n$ of the $b$ bins to put balls in, which is the\ndefinition of binomial coefficients - $\\binom{b}{n}$.\n\n### Identical balls, no bin left empty\n\nThis is fun. First, we put a ball in each bin and we're left with $n - b$ balls\nto put in $b$ bins. Now lets use part (c) - substituting $n - b$ for $n$, we\nget:\n\n$$ \\binom{b + n - b - 1}{n - b} = \\binom{n - 1}{n - b}\n                                = \\binom{n - 1}{n - 1 - n + b}\n                                = \\binom{n - 1}{b - 1} $$\n"
  },
  {
    "path": "other/clrs/Gemfile",
    "content": "source 'https://rubygems.org'\n\ngem 'coderay'\ngem 'nokogiri'\ngem 'rake'\ngem 'redcarpet'\ngem 'sassc'\ngem 'shotgun'\ngem 'sinatra'\ngem 'tilt'\n"
  },
  {
    "path": "other/clrs/Rakefile",
    "content": "require_relative 'build/build'\n\ndesc 'Build all the static files'\ntask :build do\n  Generator.generate\nend\n\ndesc 'Clean all the compiled things'\ntask :clean do\n  Pathname(__FILE__).dirname.join('target/compiled').rmtree\n  Pathname(__FILE__).dirname.join('target/bin').rmtree\nend\n\ndesc 'Start a local server for files'\ntask :server do\n  system 'rackup'\nend\n\ndesc 'Copies all the files to ita.skanev.com'\ntask :deploy => :build do\n  system 'scp -r target/compiled/* ita.skanev.com:~/www'\nend\n\nnamespace :test do\n  desc 'Run the tests for an exercise'\n  task :exercise, :chapter, :section, :number do |t, args|\n    exercise = Exercise.new ChapterNumber.new(args[:chapter]), args[:section], args[:number]\n    exercise.run_tests\n  end\n\n  desc 'Run the tests of a problem'\n  task :problem, :chapter, :number do |t, args|\n    problem = Problem.new ChapterNumber.new(args[:chapter]), args[:number]\n    problem.run_tests\n  end\nend\n\nnamespace :run do\n  desc 'Run the code of an exercise'\n  task :exercise, :chapter, :section, :number do |t, args|\n    exercise = Exercise.new ChapterNumber.new(args[:chapter]), args[:section], args[:number]\n    exercise.run_all\n  end\n\n  desc 'Run the code of a problem'\n  task :problem, :chapter, :number do |t, args|\n    problem = Problem.new ChapterNumber.new(args[:chapter]), args[:number]\n    problem.run_all\n  end\nend\n"
  },
  {
    "path": "other/clrs/build/app.rb",
    "content": "require 'sinatra'\nrequire 'pathname'\n\nrequire_relative 'build'\n\nset :root, File.dirname(__FILE__)\nset :public_folder, Proc.new { File.join(root, 'public') }\nset :views, Proc.new { File.join(root, 'views') }\n\nget '/' do\n  catalog = Catalog.new SOLUTION_ROOT\n  Renderer.render_catalog catalog\nend\n\nget '/index.?:format?' do\n  catalog = Catalog.new SOLUTION_ROOT\n  Renderer.render_catalog catalog\nend\n\nget '/:chapter/problems/:number.png' do\n  problem = Problem.new ChapterNumber.new(params[:chapter]), params[:number]\n\n  content_type 'image/png'\n  Graph.render_png problem.graph_path\nend\n\nget '/:chapter/problems/:number.svg' do\n  problem = Problem.new ChapterNumber.new(params[:chapter]), params[:number]\n\n  content_type 'image/svg+xml'\n  Graph.render_svg problem.graph_path\nend\n\nget '/:chapter/problems/:number.?:format?' do\n  catalog = Catalog.new SOLUTION_ROOT\n  problem = Problem.new ChapterNumber.new(params[:chapter]), params[:number]\n\n  Renderer.render_problem problem, catalog\nend\n\nget '/:chapter/:section/:number.png' do\n  exercise = Exercise.new ChapterNumber.new(params[:chapter]), params[:section], params[:number]\n\n  content_type 'image/png'\n  Graph.render_png exercise.graph_path\nend\n\nget '/:chapter/:section/:number.drawing.:index.svg' do\n  exercise = Exercise.new ChapterNumber.new(params[:chapter]), params[:section], params[:number]\n\n  content_type 'image/svg+xml'\n  Graph.render_drawing exercise.draw_path, params[:index]\nend\n\nget '/:chapter/:section/:number.svg' do\n  exercise = Exercise.new ChapterNumber.new(params[:chapter]), params[:section], params[:number]\n\n  content_type 'image/svg+xml'\n  Graph.render_svg exercise.graph_path\nend\n\n\nget '/:chapter/:section/:number.?:format?' do\n  catalog = Catalog.new SOLUTION_ROOT\n  exercise = Exercise.new ChapterNumber.new(params[:chapter]), params[:section], params[:number]\n\n  Renderer.render_exercise exercise, catalog\nend\n\nget '/css/clrs.css' do\n  content_type 'text/css'\n  Renderer.render_css\nend\n"
  },
  {
    "path": "other/clrs/build/build.rb",
    "content": "require 'pathname'\nrequire 'fileutils'\nrequire 'open3'\n\nrequire 'tilt'\nrequire 'redcarpet'\nrequire 'sassc'\nrequire 'nokogiri'\nrequire 'coderay'\n\nrequire_relative 'lib/chapter_number'\nrequire_relative 'lib/catalog'\nrequire_relative 'lib/solution'\nrequire_relative 'lib/exercise'\nrequire_relative 'lib/problem'\nrequire_relative 'lib/renderer'\nrequire_relative 'lib/generator'\nrequire_relative 'lib/graph'\nrequire_relative 'lib/runtimes'\nrequire_relative 'lib/runtimes/c'\nrequire_relative 'lib/runtimes/python'\n\nSOLUTION_ROOT = Pathname(__FILE__).dirname.join('..').expand_path\nVIEWS_ROOT    = Pathname(__FILE__).dirname.join('views/').expand_path\nPUBLIC_ROOT   = Pathname(__FILE__).dirname.join('public/').expand_path\nEXT_ROOT      = Pathname(__FILE__).dirname.join('ext').expand_path\n"
  },
  {
    "path": "other/clrs/build/ext/debug_helpers.h",
    "content": "#include <stdio.h>\n\nvoid fprint_array(FILE *stream, int array[], int length) {\n  fprintf(stream, \"[\");\n  for (int i = 0; i < length; i++) {\n    fprintf(stream, \"%d\", array[i]);\n    if (i < length - 1) {\n      fprintf(stream, \", \");\n    }\n  }\n  fprintf(stream, \"]\");\n}\n"
  },
  {
    "path": "other/clrs/build/ext/drawing.py",
    "content": "import sys\nimport re\nfrom collections import deque\nfrom subprocess import Popen, PIPE, STDOUT\n\nunique = 0\n\n\ndef unique_number():\n    global unique\n    unique += 1\n    return unique\n\n\nclass RedBlackTrees:\n    class Node:\n        def __init__(self, value, left=None, right=None, label=None, extra=[]):\n            self.id = unique_number()\n            self.value = value\n            self.label = label or value\n            self.left = left\n            self.right = right\n            self.extra = extra\n\n        def dot(self, nils=True):\n            def nil_node(n):\n                return f'nil{n}[shape=point];'\n\n            nodes = []\n            edges = []\n\n            lines = []\n            lines.append(\"graph {\")\n            lines.append(\"  node[shape=circle, style=filled];\")\n            lines.append(\"\")\n\n            nodes.append(self.node())\n\n            for item in self.bfs():\n                if item.left:\n                    nodes.append(item.left.node())\n                    edges.append(f\"{item.name()} -- {item.left.name()};\")\n                elif nils:\n                    n = unique_number()\n                    nodes.append(nil_node(n))\n                    edges.append(f\"{item.name()} -- nil{n};\")\n\n                if item.right:\n                    nodes.append(item.right.node())\n                    edges.append(f\"{item.name()} -- {item.right.name()};\")\n                elif nils:\n                    n = unique_number()\n                    nodes.append(nil_node(n))\n                    edges.append(f\"{item.name()} -- nil{n};\")\n\n            for node in nodes:\n                lines.append(f\"  {node}\")\n\n            lines.append(\"\")\n\n            for edge in edges:\n                lines.append(f\"  {edge}\")\n\n            lines.append(\"}\")\n            lines.append(\"\")\n\n            return \"\\n\".join(lines)\n\n        def name(self):\n            return f\"n{self.id}\"\n\n        def node(self):\n            attrs = \", \".join([f\"label=\\\"{self.label}\\\"\",\n                               *self.attributes(),\n                               *self.extra])\n            return f\"{self.name()}[{attrs}];\"\n\n        def bfs(self):\n            queue = deque()\n            queue.append(self)\n\n            while queue:\n                item = queue.popleft()\n                yield item\n                if item.left:\n                    queue.append(item.left)\n                if item.right:\n                    queue.append(item.right)\n\n    class Red(Node):\n        def attributes(self):\n            return ['fillcolor=red', 'fontcolor=white']\n\n    class Black(Node):\n        def attributes(self):\n            return ['fillcolor=black', 'fontcolor=white']\n\n    class Gray(Node):\n        def attributes(self):\n            return ['fillcolor=gray', 'fontcolor=white']\n\n\ndef svg(dot):\n    with Popen(['dot', '-Tsvg'], stdin=PIPE, stdout=PIPE, stderr=STDOUT) as p:\n        output = p.communicate(bytes(dot, 'utf-8'))[0]\n        return output.decode()\n\n\ndef process(drawings):\n    command = sys.argv[1]\n    if command == 'list':\n        for (i, drawing) in enumerate(drawings):\n            number = '{:02d}'.format(i + 1)\n            name = re.sub('^.*?(\\d+)/(\\d+|problems)/(\\d+)\\.draw.py', f'\\\\1/\\\\2/\\\\3.drawing.{number}.svg', sys.argv[0])\n            print(\"{} {} {} {}\".format(number, name, 'true' if drawing['display'] else 'false', drawing['name']))\n    elif command == 'draw':\n        index = int(sys.argv[2]) - 1\n        dot = drawings[index]['dot']\n        print(svg(dot))\n    elif command == 'debug':\n        index = int(sys.argv[2]) - 1\n        dot = drawings[index]['dot']\n        print(dot)\n    else:\n        raise f\"Uknown commands: {repr(sys.argv)}\"\n"
  },
  {
    "path": "other/clrs/build/ext/test.h",
    "content": "#include <stdio.h>\n#include <stdarg.h>\n#include <setjmp.h>\n\n#include \"debug_helpers.h\"\n\n/*\n * A small testing library I'm writing for the Introduction to Algorithms\n * study group. It will probably be expanded as we go.\n */\n\n/*\n * State and initialization.\n */\n\nconst char *test_current_name;\nconst char *test_last_assert_file;\nint test_last_assert_line;\nint test_failures;\nint test_runs;\njmp_buf test_on_fail;\n\nvoid test_initialize() {\n  test_current_name = \"\";\n  test_last_assert_file = \"\";\n  test_last_assert_line = -1;\n  test_runs = 0;\n  test_failures = 0;\n}\n\n/*\n * Reporting test runs\n */\n\nvoid test_report_assertion_error(const char *assertion_name) {\n  fprintf(stderr, \"%s:%d: %s (%s)\\n\",\n    test_current_name,\n    test_last_assert_line,\n    assertion_name,\n    test_last_assert_file\n  );\n}\n\nint test_report_results() {\n  if (test_runs == 0) {\n    fprintf(stderr, \"No tests were ran ;(\\n\");\n    return -1;\n  }\n\n  if (test_failures) {\n    fprintf(stderr, \"\\n\");\n    printf(\"FAILURE %d test(s), %d failure(s)\\n\", test_runs, test_failures);\n    return 1;\n  }\n\n  printf(\"OK %d test(s)\\n\", test_runs);\n  return 0;\n}\n\n/*\n * Running a test\n */\n\nvoid run_test(const char *name, void (*code)()) {\n  test_current_name = name;\n  test_last_assert_file = \"\";\n  test_last_assert_line = -1;\n\n  test_runs++;\n\n  if (setjmp(test_on_fail)) {\n    test_failures++;\n  } else {\n    code();\n  }\n}\n\nvoid abort_test() {\n  longjmp(test_on_fail, 1);\n}\n\n/*\n * Assertions\n */\n\n#define ASSERT_SAME_ARRAYS(a, b) \\\n  test_last_assert_file = __FILE__; \\\n  test_last_assert_line = __LINE__; \\\n  assert_same_arrays(a, b, sizeof(a) / sizeof(a[1]), sizeof(b) / sizeof(b[1]))\n\n#define ASSERT_SAME_ARRAYS_S(a, b, s) \\\n  test_last_assert_file = __FILE__; \\\n  test_last_assert_line = __LINE__; \\\n  assert_same_arrays(a, b, s, s)\n\nvoid assert_same_arrays(int a[], int b[], int l1, int l2) {\n  if (l1 != l2)\n    goto report_failure;\n\n  for (int i = 0; i < l1; i++)\n    if (a[i] != b[i])\n      goto report_failure;\n\n  return;\n\nreport_failure:\n  test_report_assertion_error(\"assert_same_arrays\");\n  fprintf(stderr, \"    expected \");\n  fprint_array(stderr, a, l1);\n  fprintf(stderr, \"\\n    to equal \");\n  fprint_array(stderr, b, l2);\n  fprintf(stderr, \"\\n\");\n  abort_test();\n}\n\n#define ASSERT_EQUALS(a, b) \\\n  test_last_assert_file = __FILE__; \\\n  test_last_assert_line = __LINE__; \\\n  assert_equals(a, b)\n\nvoid assert_equals(int a, int b) {\n  if (a != b) {\n    test_report_assertion_error(\"assert_equals\");\n    fprintf(stderr, \"    expected %d\\n\", a);\n    fprintf(stderr, \"    to equal %d\\n\", b);\n    fprintf(stderr, \"\\n\");\n    abort_test();\n  }\n}\n\n#define ASSERT_EQUALS(a, b) \\\n  test_last_assert_file = __FILE__; \\\n  test_last_assert_line = __LINE__; \\\n  assert_equals(a, b)\n\nvoid assert_true(int v) {\n    if (!v) {\n        test_report_assertion_error(\"assert_true\");\n        fprintf(stderr, \"expected a truth\\n\");\n        fprintf(stderr, \"\\n\");\n        abort_test();\n    }\n}\n\nvoid assert_false(int v) {\n    if (v) {\n        test_report_assertion_error(\"assert_false\");\n        fprintf(stderr, \"expected a falsity\\n\");\n        fprintf(stderr, \"\\n\");\n        abort_test();\n    }\n}\n\n#define ASSERT_TRUE(a) \\\n  test_last_assert_file = __FILE__; \\\n  test_last_assert_line = __LINE__; \\\n  assert_true(a)\n\n#define ASSERT_FALSE(a) \\\n  test_last_assert_file = __FILE__; \\\n  test_last_assert_line = __LINE__; \\\n  assert_false(a)\n\nvoid assert_null(void *v) {\n    if (v) {\n        test_report_assertion_error(\"assert_null\");\n        fprintf(stderr, \"expected null\\n\");\n        fprintf(stderr, \"\\n\");\n        abort_test();\n    }\n}\n\nvoid assert_not_null(void *v) {\n    if (!v) {\n        test_report_assertion_error(\"assert_not_null\");\n        fprintf(stderr, \"expected not null\\n\");\n        fprintf(stderr, \"\\n\");\n        abort_test();\n    }\n}\n\n#define ASSERT_NULL(a) \\\n  test_last_assert_file = __FILE__; \\\n  test_last_assert_line = __LINE__; \\\n  assert_null(a)\n\n#define ASSERT_NOT_NULL(a) \\\n  test_last_assert_file = __FILE__; \\\n  test_last_assert_line = __LINE__; \\\n  assert_not_null(a)\n\nvoid fail(const char *message, ...) {\n    va_list args;\n    va_start(args, message);\n\n    test_report_assertion_error(\"fail\");\n\n    fprintf(stderr, \"Failure:\\n  \");\n    vfprintf(stderr, message, args);\n    fprintf(stderr, \"\\n\");\n\n    abort_test();\n}\n\n#define FAIL(...) \\\n  test_last_assert_file = __FILE__; \\\n  test_last_assert_line = __LINE__; \\\n  fail(__VA_ARGS__)\n\n/*\n * Defining tests\n */\n\n#define TEST(NAME) \\\n  void NAME##_test_code(); \\\n  void run_##NAME() { run_test(#NAME, &NAME##_test_code); } \\\n  void NAME##_test_code()\n"
  },
  {
    "path": "other/clrs/build/lib/catalog.rb",
    "content": "class Catalog\n  Chapter = Struct.new(:number, :sections, :problems)\n  Section = Struct.new(:number, :exercises)\n  Position = Struct.new(:before, :after)\n\n  class << self\n    def locate\n      new Pathname(__FILE__).join('../../..')\n    end\n  end\n\n  def initialize(root_dir)\n    @root = root_dir\n  end\n\n  def chapters\n    @chapters ||= find_chapters\n  end\n\n  def solutions\n    load_solutions_and_positions\n    @solutions\n  end\n\n  def positions\n    load_solutions_and_positions\n    @positions\n  end\n\n  def previous(solution)\n    positions[solution.name].before\n  end\n\n  def next(solution)\n    positions[solution.name].after\n  end\n\n  private\n\n  def load_solutions_and_positions\n    return if @solutions && @positions\n\n    @solutions = {}\n    @positions = {}\n\n    solutions = chapters.flat_map { |chapter| chapter.sections.flat_map(&:exercises) + chapter.problems }\n\n    before = nil\n\n    solutions.each do |solution|\n      name = solution.name\n      @positions[before.name].after = solution if before\n      @solutions[name] = solution\n      @positions[name] = Position.new before, nil\n      before = solution\n    end\n\n    @solutions\n  end\n\n  def find_chapters\n    Dir.chdir @root do\n      dirs = glob('.', '[0-9][0-9]').to_a + glob('.', '[ABCD]').to_a\n\n      dirs.map do |dir|\n        number   = ChapterNumber.new dir\n        sections = find_sections number\n        problems = find_problems number\n\n        Chapter.new number, sections, problems\n      end\n    end\n  end\n\n  def find_sections(chapter)\n    glob chapter, '[0-9][0-9]' do |number|\n      exercises = find_exercises chapter, number\n      Section.new number.to_i, exercises\n    end\n  end\n\n  def find_exercises(chapter, section)\n    glob \"#{chapter}/#{section}\", '[0-9][0-9]', 'markdown' do |number|\n      Exercise.new chapter, section, number\n    end\n  end\n\n  def find_problems(chapter)\n    dir = Pathname(\"#{chapter}/problems\")\n    return [] unless dir.exist?\n\n    glob dir, '[0-9][0-9]', 'markdown' do |number|\n      Problem.new chapter, number\n    end\n  end\n\n  def glob(dir, pattern, extension = nil, &block)\n    pattern = \"#{pattern}.#{extension}\" if extension\n    matches = Dir.chdir(dir) { Dir.glob(pattern) }\n    matches = matches.map { |name| name.gsub(/\\.#{extension}$/, '') } if extension\n    matches.sort.map(&block)\n  end\nend\n"
  },
  {
    "path": "other/clrs/build/lib/chapter_number.rb",
    "content": "class ChapterNumber\n  def initialize(name)\n    @name = case name\n      when /^(\\d+)$/ then name.to_i\n      when /^[ABCD]$/ then name\n      else raise \"Invalid chapter name: #{name}\"\n    end\n  end\n\n  def name\n    case @name\n      when Integer then '%02d' % @name\n      when String then @name\n      else raise '???'\n    end\n  end\n\n  def short_name\n    @name.to_s\n  end\n\n  def inspect\n    \"#<Chapter:#{name}>\"\n  end\n\n  alias to_s name\n  alias to_str to_s\nend\n"
  },
  {
    "path": "other/clrs/build/lib/exercise.rb",
    "content": "class Exercise\n  include Solution\n\n  def initialize(chapter, section, number)\n    @chapter = chapter\n    @section = section.to_i\n    @number  = number.to_i\n  end\n\n  def components\n    [@chapter, @section, @number]\n  end\n\n  def name\n    \"#{@chapter.short_name}.#@section.#@number\"\n  end\n\n  def title\n    \"Exercise #{name}\"\n  end\n\n  def location\n    '%s/%02d/%02d' % components\n  end\nend\n"
  },
  {
    "path": "other/clrs/build/lib/generator.rb",
    "content": "module Generator\n  extend self\n\n  def generate\n    catalog = Catalog.new SOLUTION_ROOT\n\n    FileUtils.rm_rf 'target/compiled'\n    FileUtils.mkdir_p 'target/compiled'\n    Dir.chdir 'target/compiled' do\n      copy_static_files\n      generate_css\n      generate_catalog catalog\n      generate_solutions catalog\n    end\n  end\n\n  private\n\n  def copy_static_files\n    FileUtils.cp_r '../../build/public/css', 'css'\n    FileUtils.cp_r '../../build/public/img', 'img'\n  end\n\n  def generate_css\n    write_file 'css/clrs.css', Renderer.render_css\n  end\n\n  def generate_solutions(catalog)\n    catalog.chapters.each do |chapter|\n      chapter.sections.each do |section|\n        section.exercises.each do |exercise|\n          generate_exercise exercise, catalog\n          generate_graph exercise if exercise.graph?\n          generate_drawings exercise if exercise.drawings?\n        end\n      end\n\n      chapter.problems.each do |problem|\n        generate_problem problem, catalog\n        generate_graph problem if problem.graph?\n      end\n    end\n  end\n\n  def generate_catalog(catalog)\n    write_file 'index.html', Renderer.render_catalog(catalog)\n  end\n\n  def generate_exercise(exercise, catalog)\n    write_file \"#{exercise.location}.html\", Renderer.render_exercise(exercise, catalog)\n  end\n\n  def generate_problem(problem, catalog)\n    write_file \"#{problem.location}.html\", Renderer.render_problem(problem, catalog)\n  end\n\n  def generate_drawings(solution)\n    Graph.list_drawings(solution.draw_path).each do |number, file, display|\n      write_file file, Graph.render_drawing(solution.draw_path, number)\n    end\n  end\n\n  def generate_graph(solution)\n    write_file \"#{solution.location}.png\", Graph.render_png(solution.graph_path)\n    write_file \"#{solution.location}.svg\", Graph.render_svg(solution.graph_path)\n  end\n\n  def write_file(filename, content)\n    path = Pathname(filename).dirname\n    FileUtils.mkdir_p path unless path.exist?\n    File.open(filename, 'w') { |file| file.write content }\n  end\nend\n"
  },
  {
    "path": "other/clrs/build/lib/graph.rb",
    "content": "module Graph\n  extend self\n\n  def render_png(pathname)\n    %x[dot -Tpng -Gdpi=144 #{pathname.expand_path.to_s}]\n  end\n\n  def render_svg(pathname)\n    %x[dot -Tsvg #{pathname.expand_path.to_s}]\n  end\n\n  def compile_to_svg(code)\n    input, output, error = Open3.popen3('dot -Tsvg')\n    input.write(code)\n    input.close\n\n    output.read\n  end\n\n  def list_drawings(pathname)\n    run_draw(pathname, 'list').lines.map { |line| line.split(/\\s+/, 4) }\n  end\n\n  def render_drawing(pathname, number)\n    run_draw pathname, 'draw', number\n  end\n\n  private\n\n  def run_draw(pathname, *args)\n    %x[PYTHONPATH=\"#{EXT_ROOT}\" PYTHONDONTWRITEBYTECODE=x python3 #{pathname} #{args.join(' ')}]\n  end\nend\n"
  },
  {
    "path": "other/clrs/build/lib/problem.rb",
    "content": "class Problem\n  include Solution\n\n  def initialize(chapter, number)\n    @chapter = chapter\n    @number  = number.to_i\n  end\n\n  def components\n    [@chapter, @number]\n  end\n\n  def name\n    \"#{@chapter.short_name}.#@number\"\n  end\n\n  def title\n    \"Problem #{name}\"\n  end\n\n  def location\n    '%s/problems/%02d' % components\n  end\nend\n"
  },
  {
    "path": "other/clrs/build/lib/renderer.rb",
    "content": "module Renderer\n  extend self\n\n  def render_catalog(catalog)\n    context = make_context catalog: catalog\n\n    render_view 'layout', context do\n      render_view 'catalog', context\n    end\n  end\n\n  def render_exercise(exercise, catalog = nil)\n    exercise_markdown = File.read exercise.markdown_path\n    context           = make_context catalog: catalog, solution: exercise, exercise: exercise, base: '../../'\n\n    render_view 'layout', context do\n      render_view 'exercise', context do\n        process exercise_markdown\n      end\n    end\n  end\n\n  def render_problem(problem, catalog = nil)\n    problem_markdown = File.read problem.markdown_path\n    context          = make_context catalog: catalog, solution: problem, problem: problem, base: '../../'\n\n    render_view 'layout', context do\n      render_view 'problem', context do\n        process problem_markdown\n      end\n    end\n  end\n\n  def render_code(path, language)\n    code = File.read path\n    CodeRay.scan(code, language).div\n  end\n\n  def render_css\n    scss = File.read PUBLIC_ROOT.join('css/clrs.scss')\n    SassC::Engine.new(scss).render\n  end\n\n  private\n\n  def render_view(name, context, &block)\n    filename = VIEWS_ROOT.join(\"#{name}.erb\").to_s\n    Tilt::ERBTemplate.new(filename).render(context, &block)\n  end\n\n  def make_context(hash = {})\n    Object.new.tap do |context|\n      hash.each do |key, value|\n        context.instance_variable_set :\"@#{key}\", value\n      end\n    end\n  end\n\n  def markdown\n    @markdown ||= Redcarpet::Markdown.new Markdown, tables: true,\n                                                    no_intra_emphasis: true,\n                                                    fenced_code_blocks: true,\n                                                    strikethrough: true\n  end\n\n  def process(markdown_code)\n    markdown_code = markdown_code.gsub(/exercise\\s+([A-D]|\\d+).(\\d+)[-.](\\d+)(?!<\\/a>)/i) { |text| \"[#{text}](/%s/%02d/%02d.html)\" % [ChapterNumber.new($1), $2, $3] }\n    markdown_code = markdown_code.gsub(/problem\\s+([A-D]|\\d+).(\\d+)(?!<\\/a>)/i) { |text| \"[#{text}](/%s/problems/%02d.html)\" % [ChapterNumber.new($1), $2] }\n    markdown.render markdown_code\n  end\n\n  class Markdown < Redcarpet::Render::HTML\n    def postprocess(html)\n      doc = Nokogiri::HTML(html)\n\n      doc.search('table').each do |node|\n        node[:class] = 'table table-bordered table-striped table-compact'\n      end\n\n      doc.search('pre > code.generate-dot').each do |node|\n        node.parent.replace \"<p class=\\\"generated-dot\\\">#{Graph.compile_to_svg node.inner_text}</p>\"\n      end\n\n      doc.search('body').first.inner_html\n    end\n  end\nend\n"
  },
  {
    "path": "other/clrs/build/lib/runtimes/c.rb",
    "content": "module Runtimes\n  module C\n    extend self\n\n    def run_test(location, capture_output = false)\n      test_path   = SOLUTION_ROOT.join(location).sub_ext('.test.c')\n      target_path = SOLUTION_ROOT.join('target/bin').join(location).sub_ext('.test')\n      runner_path = target_path.sub_ext('.c')\n\n      write_test_file test_path, runner_path\n      compile runner_path, target_path\n      execute target_path, capture_output\n    end\n\n    def run(location, capture_output = false)\n      runner_path = SOLUTION_ROOT.join(location).sub_ext('.run.c')\n      target_path = SOLUTION_ROOT.join('target/bin').join(location)\n\n      compile runner_path, target_path\n      execute target_path, capture_output\n    end\n\n    private\n\n    def write_test_file(test_path, runner_path)\n      test_names = File.read(test_path).scan(/^\\W*TEST\\((\\w+)/).flatten\n\n      runner_path.dirname.mkpath\n\n      File.open runner_path, 'w' do |file|\n        file.write <<-END\n#include \"#{test_path.expand_path.to_s}\"\n\nint main() {\n    test_initialize();\nEND\n        test_names.each do |name|\n          file.write \"    run_#{name}();\"\n        end\n\n        file.write <<-END\n    return test_report_results();\n}\n        END\n      end\n    end\n\n    def compile(code_path, target_path)\n      target_path.dirname.mkpath\n\n      opts    = %W[cc -std=c99 #{code_path.to_s} -o #{target_path.to_s}]\n      success = system(*opts)\n\n      raise \"Failed to compile #{code_path.to_s}\" unless success\n    end\n\n    def execute(executable_path, capture_output)\n      if capture_output\n        `#{executable_path.to_s} 2>&1`\n      else\n        system executable_path.to_s\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "other/clrs/build/lib/runtimes/python.rb",
    "content": "module Runtimes\n  module Python\n    extend self\n\n    def run(location, capture_output = false)\n      path = SOLUTION_ROOT.join(location).sub_ext '.run.py'\n      execute path, capture_output\n    end\n\n    def run_test(location, capture_output = false)\n      path = SOLUTION_ROOT.join(location).sub_ext '.test.py'\n      execute path, capture_output\n    end\n\n    private\n\n    def execute(path, capture_output = false)\n      if capture_output\n        `python3 #{path.to_s} 2>&1`\n      else\n        system 'python3', path.to_s\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "other/clrs/build/lib/runtimes.rb",
    "content": "module Runtimes\n  extend self\n\n  def for(language)\n    case language\n      when :c      then Runtimes::C\n      when :python then Runtimes::Python\n      else              raise \"Unknown language #{language}\"\n    end\n  end\nend\n"
  },
  {
    "path": "other/clrs/build/lib/solution.rb",
    "content": "module Solution\n  EXTENSIONS = {c: '.c', python: '.py'}\n\n  def location_path\n    SOLUTION_ROOT.join(location)\n  end\n\n  def extension_exists?(extension)\n    location_path.sub_ext(extension).exist?\n  end\n\n  def markdown_path\n    location_path.sub_ext '.markdown'\n  end\n\n  def graph_path\n    location_path.sub_ext '.dot'\n  end\n\n  def draw_path\n    location_path.sub_ext '.draw.py'\n  end\n\n  def html_url\n    \"#{location}.html\"\n  end\n\n  def languages\n    @languages ||= EXTENSIONS.\n      select { |_, ext| extension_exists? ext }.\n      map { |language, _| language }\n  end\n\n  def test_languages\n    @test_languages ||= EXTENSIONS.\n      select { |_, ext| extension_exists? '.test' + ext }.\n      map { |language, _| language }\n  end\n\n  def run_languages\n    @test_languages ||= EXTENSIONS.\n      select { |_, ext| extension_exists? '.run' + ext }.\n      map { |language, _| language }\n  end\n\n  def code?\n    not languages.empty?\n  end\n\n  def tested?\n    not test_languages.empty?\n  end\n\n  def graph?\n    graph_path.exist?\n  end\n\n  def drawings?\n    draw_path.exist?\n  end\n\n  def code_path(language)\n    location_path.sub_ext EXTENSIONS.fetch(language)\n  end\n\n  def test_path(language)\n    location_path.sub_ext '.test' + EXTENSIONS.fetch(language)\n  end\n\n  def runner_path(language)\n    location_path.sub_ext '.run' + EXTENSIONS.fetch(language)\n  end\n\n  def displayed_drawings\n    Graph.list_drawings(draw_path).select { |_, _, display| display == 'true' }.map { |_, file, _, name| [file, name] }\n  end\n\n  def run(language)\n    Runtimes.for(language).run location\n  end\n\n  def run_test(language)\n    Runtimes.for(language).run_test location\n  end\n\n  def run_and_capture_output(language)\n    Runtimes.for(language).run location, true\n  end\n\n  def run_tests\n    test_languages.each do |language|\n      run_test language\n    end\n  end\n\n  def run_all\n    annotate = run_languages.size > 1\n\n    run_languages.each do |language|\n      puts \"#{language.to_s.upcase}:\" if annotate\n      run language\n      puts if annotate\n    end\n  end\nend\n"
  },
  {
    "path": "other/clrs/build/public/css/clrs.scss",
    "content": "@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;700&family=Merriweather:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&display=swap');\n\n$text-color-l: #333;\n$text-color-d: #eee;\n$link-color-l: #4c94b7;\n$link-color-d: #5d9ec1;\n$blockquote-color-l: #e0e0e0;\n$blockquote-color-d: #333;\n$background-l: #fff;\n$background-d: #000;\n\n$border-color: #c0c0c0;\n\n$column-width: 960px;\n\n@mixin mode-dependent($property, $light, $dark) {\n  #{$property}: $light;\n  //@media (prefers-color-scheme: dark) { & { #{$property}: $dark; } }\n}\n\n@mixin color($light, $dark) { @include mode-dependent(color, $light, $dark); }\n@mixin background-color($light, $dark) { @include mode-dependent(background-color, $light, $dark); }\n\nhtml {\n  @include color($text-color-l, $text-color-d);\n  @include background-color($background-l, $background-d);\n  font-family: Merriweather, serif;\n  font-size: 17px;\n  line-height: 1.8;\n}\n\n.katex-display { margin: 2em 0; }\n.katex-display .katex { line-height: 2.7 !important; }\n\na,\na:visited,\na:hover,\na:active { @include color($link-color-l, $link-color-d); text-decoration: none; }\n\na:hover { text-decoration: underline; }\n\nnav.header {\n  border-bottom: 1px solid #aaa;\n\n  ul.solution-nav {\n    max-width: $column-width;\n    margin: 0 auto;\n    padding: 1ex;\n\n    li { margin: 0; padding: 0; list-style: none; display: inline-block; }\n    li.before { float: left; margin-right: 1em; }\n    li.after { float: right; }\n  }\n}\n\n.container { padding: 0 1em; margin: 0 auto 2em; max-width: $column-width; }\n.container {\n  blockquote {\n    margin: 0;\n    padding: 0 0 0 1em;\n    border-left: 7px solid transparent;\n    @include mode-dependent(border-left-color, $blockquote-color-l, $blockquote-color-d);\n  }\n}\n\npre,\ncode,\nkbd,\nsamp {\n  font-family: 'Fira Code', monospace;\n  font-size: 15px;\n  line-height: 1.2;\n}\n\npre {\n  margin: 1em 0;\n  line-height: 1.4em;\n}\n\narticle.solution {\n  text-align: justify;\n\n  p { margin: 1.5em 0; }\n\n  img { display: block; margin: 1em auto; max-width: $column-width; }\n  ol { padding-left: 30px; }\n  ol li { padding-left: 10px; }\n  ol ::marker {\n    font-weight: bold;\n    text-align: left;\n  }\n}\n\nhr { border: 0; border-bottom: 1px dashed $border-color; margin: 2em 0; }\n\ntable {\n  border-collapse: collapse;\n\n  td,\n  th { padding: 5px 7px; border: 1px solid $border-color; }\n}\n\np.generated-dot svg { display: block; margin-left: auto; margin-right: auto; }\n"
  },
  {
    "path": "other/clrs/build/views/catalog.erb",
    "content": "<h1>Introduction to Algorithms solutions</h1>\n\n<p>Hi!</p>\n<p>\n  Welcome to my solutions to the exercises and problems of Introduction to\n  Algorithms, 3rd edition, lovingly abbreviated as\n  <abbr title=\"Cormen, Leiserson, Rivest, Stein\">CLRS</abbr>.\n</p>\n<p><img src=\"img/cover.jpg\" alt=\"Introduction to Algorithms cover\" /></p>\n<p>\n  Don't trust a single word! While mistakes were not intended, they were surely\n  made. I'm doing this for fun – I have neither the energy nor the patience to\n  double-check everything. If you find an error, please don't contact me to fix\n  it.\n</p>\n<p>\n  This is a journey in progress. I'm neither in a hurry, not hell-bent on\n  getting there. I'll add new solutions over time, but am not adhering to a\n  schedule.\n</p>\n\n<% @catalog.chapters.each do |chapter| %>\n  <h2>Chapter <%= chapter.number %></h2>\n  <table class=\"table table-condensed table-bordered table-compact catalog\">\n    <% max_width = chapter.sections.map(&:exercises).map(&:size).+([chapter.problems.size]).max %>\n    <tbody>\n      <% chapter.sections.each do |section| %>\n        <tr>\n          <th>Section <%= section.number %></th>\n          <% section.exercises.each do |exercise| %>\n            <td>\n              <a href=\"<%= exercise.html_url %>\">\n                <%= exercise.name %>\n              </a>\n            </td>\n          <% end %>\n          <% if section.exercises.size < max_width %>\n            <td colspan=\"<%= max_width - section.exercises.size %>\"></td>\n          <% end %>\n        </tr>\n      <% end %>\n      <% unless chapter.problems.empty? %>\n        <tr>\n          <th>Problems</th>\n          <% chapter.problems.each do |problem| %>\n            <td>\n              <a href=\"<%= problem.html_url %>\">\n                <%= problem.name %>\n              </a>\n            </td>\n          <% end %>\n          <% if chapter.problems.size < max_width %>\n            <td colspan=\"<%= max_width - chapter.problems.size %>\"></td>\n          <% end %>\n        </tr>\n      <% end %>\n    </tbody>\n  </table>\n<% end %>\n"
  },
  {
    "path": "other/clrs/build/views/exercise.erb",
    "content": "<article class=\"solution exercise\">\n  <h1>Exercise <%= @exercise.name %></h1>\n\n  <%= yield %>\n  <% if @exercise.graph? %>\n    <hr />\n    <img src=\"<%= \"#{@exercise.location}.svg\" %>\" />\n  <% end %>\n  <% if @exercise.drawings? %>\n    <% displayed = @exercise.displayed_drawings %>\n    <% if displayed.size > 0 %>\n      <% displayed.each do |file, name| %>\n        <p><%= name %></p>\n        <p><img src=\"<%= file %>\" /></p>\n      <% end %>\n    <% end %>\n  <% end %>\n  <% @exercise.run_languages.each do |language| %>\n    <hr />\n    <h3><%= language.to_s.capitalize %> runner output</h3>\n    <pre><%= @exercise.run_and_capture_output(language) %></pre>\n  <% end %>\n  <% @exercise.languages.each do |language| %>\n    <hr />\n    <h3><%= language.to_s.capitalize %> code</h3>\n    <%= Renderer.render_code @exercise.code_path(language), language %>\n  <% end %>\n</article>\n"
  },
  {
    "path": "other/clrs/build/views/layout.erb",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title><%= @exercise && @exercise.title || @problem && @problem.title || 'Introduction to Algorithms solutions' %> </title>\n\n    <meta charset=\"utf-8\">\n    <% if @base %>\n      <base href=\"<%= @base %>\">\n    <% end %>\n\n    <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css\" integrity=\"sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X\" crossorigin=\"anonymous\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"https://necolas.github.io/normalize.css/latest/normalize.css\" />\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"css/clrs.css\" />\n\n    <script defer src=\"https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.js\" integrity=\"sha384-g7c+Jr9ZivxKLnZTDUhnkOnsh30B4H0rpLUpJ4jAIKs4fnJI+sEnkvrMWph2EDg4\" crossorigin=\"anonymous\"></script>\n    <script defer src=\"https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/auto-render.min.js\" integrity=\"sha384-mll67QQFJfxn0IYznZYonOWZ644AWYC+Pt2cHqMaRhXVrursRwvLnLaebdGIlYNa\" crossorigin=\"anonymous\"></script>\n\n    <script type=\"text/javascript\">\n      document.addEventListener(\"DOMContentLoaded\", function() {\n        renderMathInElement(document.body, {\n          delimiters: [\n            {left: \"$$\", right: \"$$\", display: true},\n            {left: \"$\", right: \"$\", display: false},\n          ],\n          macros: {\n            \"\\\\E\": \"\\\\mathrm{E}\",\n            \"\\\\O\": \"\\\\mathcal{O}\",\n            \"\\\\o\": \"\\\\mathcal{o}\",\n            \"\\\\Var\": \"\\\\mathrm{Var}\",\n          }\n        });\n    });\n    </script>\n  </head>\n\n  <body>\n    <% if @solution && @catalog %>\n      <nav class=\"header\">\n        <ul class=\"solution-nav\">\n          <% if before = @catalog.previous(@solution) %>\n            <li class=\"before\"><a href=\"<%= before.html_url %>\">← <%= before.name %></a></li>\n          <% end %>\n          <% if after = @catalog.next(@solution) %>\n            <li class=\"after\"><a href=\"<%= after.html_url %>\"><%= after.name %> →</a></li>\n          <% end %>\n          <li class=\"index\"><a href=\"index.html\">Solution index</a></li>\n        </ul>\n      </nav>\n    <% end %>\n\n    <div class=\"container\">\n      <%= yield %>\n    </div>\n\n    <script>\n      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\n      ga('create', 'UA-2564866-3', 'skanev.com');\n      ga('send', 'pageview');\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "other/clrs/build/views/problem.erb",
    "content": "<article class=\"solution problem\">\n  <h1>Problem <%= @problem.name %></h1>\n\n  <%= yield %>\n\n  <% if @problem.graph? %>\n    <hr />\n    <img src=\"<%= \"#{@problem.location}.svg\" %>\" />\n  <% end %>\n  <% @problem.run_languages.each do |language| %>\n    <hr />\n    <h3><%= language.to_s.capitalize %> runner output</h3>\n    <pre><%= @problem.run_and_capture_output(language) %></pre>\n  <% end %>\n  <% @problem.languages.each do |language| %>\n    <hr />\n    <h3><%= language.to_s.capitalize %> code</h3>\n    <%= Renderer.render_code @problem.code_path(language), language %>\n  <% end %>\n</article>\n"
  },
  {
    "path": "other/clrs/config.ru",
    "content": "require './build/app'\nrun Sinatra::Application\n"
  },
  {
    "path": "other/clrs/notes/week-01.markdown",
    "content": "# Week 01 (2013-07-09 - 2013-07-16)\n\n## Array indexing\n\nArray indexing in C is 1-based, but in ItA it starts from 1. Translating pseudocode to C is hell.\n\n## Style\n\nI can't figure out the style I want to follow. Apart from the number of spaces, I'm not sure whether to go with descriptive names (like I would normally) or terse names (like the ones in the book). I err on the side of the later, since this is unusual for me.\n\nI find it fascinating, that a lot of my C coding habits are still the ones I had in high school. I'm not particularly hygenic when it comes to writing it.\n\n## Graphviz\n\nI spend a lot of time playing with graphviz and it is a love-hate relationship. You can get a lot of thins draw, but unfortunatelly, you cannot get them drawn beautifully. It's very awkward at times and depends on weird conventions in the language (like catalog_ in the subgraphs). Finally, I managed to segfault it on multiple occasions.\n\n## This needs care\n\nWhen solving problem 2.1, I wrote a buggy version of the solution and it took me a while to figure out where the problem was. It ended up being wrong implementation of insertion sort. I need to write more tests and need to be way more careful when implementing those algorithms.\n"
  },
  {
    "path": "other/clrs/notes/week-02.markdown",
    "content": "# Week 02 (2013-07-16 - 2013-07-23)\n\nThis week had VarnaConf, so I barely had time to do anything. We met,\ndiscussed some stuff and went to the protest. There is not much to add.\n"
  },
  {
    "path": "other/clrs/notes/week-03.markdown",
    "content": "# Week 03 (2013-07-23 - 2013-07-30)\n\n## Questions\n\n* What is the advantage of the \"omega infinity\" notation?\n\n## Making errors\n\nI keep making errors that result into a lot of debugging. Most of the errors\nI've had so far have been off-by-ones. I'm just rediscovering that I need to\nbe very careful when writing this code, in order to avoid both errors and\nspending too much time down the rabbit hole.\n"
  },
  {
    "path": "other/clrs/notes/week-04.markdown",
    "content": "# Week 04 (2013-10-16 - 2013-10-23)\n\n## On week numbers\n\nWe were very bad on keeping it regular in the summer. I had some\nremarks about chapter 4, but I am going to skip them and just\njump ahead in my notes.\n\n## Various remarks\n\n* I had to solve exercise C.4-9 before having an idea about\n  solving C.4-8. I spent an hour on the later. At least I learned\n  about [coupling][coupling]\n* Exercise C.1.9 gives an interesting interpretation of the\n  second diagonal of Pascal's triangle\n* I'm starting to reflect on how much of mathematics is not\n  intuition about logical laws, but symbol manipulation. It is a\n  very interesting distinction.\n* I was mindblown by the sum used to prove exercise C.2.6\n\n[coupling]: http://en.wikipedia.org/wiki/Coupling_%28probability%29\n\n## Doing it twice\n\nFor Appendix C, I first solved everything with pen and paper and then went\nthrough the long and tedious process of entering everything into Markdown and\nLaTeX. The second part was not so much fun, but I got to revisit the exercises\na couple of days after I did them, which helper reinforce my knowledge.\n\nRevisiting what you learned is important.\n\n## Probability\n\nI'm having tons of fun doing probability. Especially things like\nverifying the results of exercise C.4-2 with the following Ruby\nscript:\n\n    n = 1_000_000\n    def try\n      [1].cycle.take_while { rand(2**6).to_s(2).count(\"1\") != 3 }.count + 1\n    end\n\n    p n.times.map { try }.inject(:+) / n.to_f\n\nAnd surprise - the results match!\n"
  },
  {
    "path": "other/clrs/notes/week-05.markdown",
    "content": "# Week 05 (2013-10-23 - 2013-10-30)\n\nThe chapter was simple enough. It was easy to solve and there were not many\nsurprises, apart from the analysis of the streaks expectation. I had a (few)\nunsolved exercise(s), but apart from that everything made sense and was not\nthat hard.\n\nI spent the whole week afterwards just entering the solutions. It was not that\neasy, especially because it concided with OpenFest.\n"
  },
  {
    "path": "other/clrs/notes/week-06.markdown",
    "content": "# Week 06 (2013-11-06 - 2013-11-13)\n\nLast week was OpenFest, so I skipped one week. This week it is heap-sort time!\n\n## Questions\n\n* I'm not really sure why `BUILD-MAX-HEAP` is linear. I understand the math in\n  section 6.3, but it is the weirdest approach ever. I wonder how people come\n  up with that stuff.\n\n## Various remarks\n\n* I really need to learn gdb. While I don't find debugging all that necessary\n  in Ruby, all the minute details appear important in this context. Unit tests\n  are not enough to give you a good tangent.\n* An example of the previous point is exercise 6.2-5. It took me a while to\n  figure out that I was passing `expected` instead of `actual` to `MAX-HEAPIFY`\n  in the unit test.\n* The exercises in this book are extremely well-designed. They complement the\n  material very well and doing them expands your knowledge. For example, the\n  heap sort bounds are explored in exercises.\n* The lower bound of heap-sort was tricky. It was found some 30 years after\n  the algorithms was discovered. Exercise 6.4.5 dwells on it.\n"
  },
  {
    "path": "other/clrs/notes/week-07.markdown",
    "content": "# Week 07 (2013-11-13 - 2013-11-20)\n\n## Various remarks\n\n* It should have been obvious, but I never considered that a reverse-sorted\n  array also produces the worst-case performance in quicksort.\n* Quicksort is quadratic whenever one of the partitions has a constant size.\n* There is a [killer adversary][killer-adversary] comparison algorithm for\n  quicksort - it turns it quadratic in almost any implementation.\n\n[killer-adversary]: http://www.cs.dartmouth.edu/~doug/mdmspe.pdf\n"
  },
  {
    "path": "other/clrs/notes/week-08.markdown",
    "content": "# Week 08 (2013-11-20 - 2013-11-27)\n\n## Various remarks\n\n* The technique for splitting a summation as in exercise 8.1.2 seems to be\n  useful for finding lower bounds\n* Exercises where you have to illustrate the algorithm are actually useful.\n* Nikolay appears to be very fast at solving mathematical problems\n"
  },
  {
    "path": "other/clrs/target/.gitignore",
    "content": "compiled\nbin\n"
  },
  {
    "path": "ruby/understanding-computation/.gitignore",
    "content": "tmp\n"
  },
  {
    "path": "ruby/understanding-computation/03/03.rb",
    "content": "require 'set'\nrequire 'treetop'\n\n$:.unshift File.dirname(__FILE__) + '/lib'\n\nautoload :FARule, 'fa_rule'\nautoload :DFARulebook, 'dfa_rulebook'\nautoload :DFA, 'dfa'\nautoload :DFADesign, 'dfa_design'\nautoload :NFARulebook, 'nfa_rulebook'\nautoload :NFA, 'nfa'\nautoload :NFADesign, 'nfa_design'\nautoload :NFASimulation, 'nfa_simulation'\nautoload :Dot, 'dot'\n\nautoload :Pattern, 'pattern'\nautoload :Empty, 'pattern'\nautoload :Literal, 'pattern'\nautoload :Concatenate, 'pattern'\nautoload :Choose, 'pattern'\nautoload :Repeat, 'pattern'\n\nTreetop.load(File.dirname(__FILE__) + '/lib/grammar')\n"
  },
  {
    "path": "ruby/understanding-computation/03/example.rb",
    "content": "require_relative '03'\nrequire 'fileutils'\n\nmodule Chapter03\n  extend self\n\n  def generate_example(base_path)\n    nfa1 = Pattern.parse('ab(ab)*').to_ast.to_nfa_design\n    dfa1 = nfa1.to_dfa_design\n    nfa2 = Pattern.parse('a(ba)*b').to_ast.to_nfa_design\n    dfa2 = nfa2.to_dfa_design\n    dfa1min = dfa1.minimize\n    dfa2min = dfa2.minimize\n\n    Dir.chdir(base_path) do\n      Dot.draw nfa1, 'nfa1'\n      Dot.draw dfa1, 'dfa1'\n      Dot.draw nfa2, 'nfa2'\n      Dot.draw dfa2, 'dfa2'\n      Dot.draw dfa1min, 'dfa1min'\n      Dot.draw dfa2min, 'dfa2min'\n    end\n\n    FileUtils.cp File.dirname(__FILE__) + '/lib/index.html', base_path.join('index.html')\n  end\nend\n\n"
  },
  {
    "path": "ruby/understanding-computation/03/lib/dfa.rb",
    "content": "class DFA < Struct.new(:current_state, :accept_states, :rulebook)\n  def accepting?\n    accept_states.include?(current_state)\n  end\n\n  def read_character(character)\n    self.current_state = rulebook.next_state(current_state, character)\n  end\n\n  def read_string(string)\n    string.chars.each do |character|\n      read_character character\n    end\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/03/lib/dfa_design.rb",
    "content": "class DFADesign < Struct.new(:start_state, :accept_states, :rulebook)\n  include Dot::Design\n\n  def to_dfa\n    DFA.new(start_state, accept_states, rulebook)\n  end\n\n  def accepts?(string)\n    to_dfa.tap { |dfa| dfa.read_string(string) }.accepting?\n  end\n\n  def reverse\n    new_accept_states = [start_state]\n    new_start_state = Object.new\n\n    start_free_moves = accept_states.map do |state|\n      FARule.new(new_start_state, nil, state)\n    end\n\n    reversed_rules = rulebook.rules.map do |rule|\n      FARule.new(rule.next_state, rule.character, rule.state)\n    end\n\n    new_rulebook = NFARulebook.new(start_free_moves + reversed_rules)\n\n    NFADesign.new(new_start_state, new_accept_states, new_rulebook)\n  end\n\n  def minimize\n    reverse.to_dfa_design.reverse.to_dfa_design\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/03/lib/dfa_rulebook.rb",
    "content": "class DFARulebook < Struct.new(:rules)\n  def next_state(state, character)\n    rule_for(state, character).follow\n  end\n\n  def rule_for(state, character)\n    rules.detect { |rule| rule.applies_to?(state, character) }\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/03/lib/dot.rb",
    "content": "module Dot\n  module Design\n    def to_dot\n      states = rulebook.rules.flat_map(&:states).uniq\n\n      dot = 'digraph NFA {'\n\n      states.each do |state|\n        style = if start_state == state\n          ' [style=filled]'\n        elsif accept_states.include?(state)\n          ' [peripheries=2]'\n        else\n          ''\n        end\n\n        dot << \"#{Dot.repr(state)}#{style};\"\n      end\n\n      rulebook.rules.each do |rule|\n        dot << rule.to_dot\n        dot << ';'\n      end\n      dot << '}'\n    end\n  end\n\n  module Rule\n    def states\n      [state, next_state]\n    end\n\n    def to_dot\n      edge_style = if character\n        \"label=#{character}\"\n      else\n        'style=dashed'\n      end\n\n      \"#{state_repr} -> #{next_state_repr} [#{edge_style}]\"\n    end\n\n    def state_repr\n      repr state\n    end\n\n    def next_state_repr\n      repr next_state\n    end\n\n    private\n\n    def repr(state)\n      Dot.repr(state)\n    end\n  end\n\n  def self.draw(design, file_base, open=false)\n    File.open(\"#{file_base}.dot\", 'w') do |file|\n      file.write design.to_dot\n    end\n\n    system \"dot -Tgif #{file_base}.dot > #{file_base}.gif\"\n    system \"open #{file_base}.gif\" if open\n  end\n\n  def self.repr(state)\n    case state\n    when Integer then state.to_s\n    when Set[], nil then 'None'\n    else gensym(state)\n    end\n  end\n\n  def self.reset_gensym\n    @states = {}\n    @current = 'A'\n  end\n\n  def self.shorten_set(set_of_sets)\n    @sets ||= {}\n    @current_set_name ||= 'AA'\n\n    if @sets.has_key? set_of_sets\n      @sets[set_of_sets]\n    else\n      @sets[set_of_sets] = @current_set_name\n      @current_set_name = @current_set_name.succ\n      @sets[set_of_sets]\n    end\n  end\n\n  def self.gensym(state)\n    if state.is_a?(Set) and state.none? { |i| i.is_a? Set }\n      return '\"' + state.to_a.map { |i| gensym(i) }.sort.join('/') + '\"'\n    end\n\n    key = case state\n      when Set then state\n      else state.object_id\n    end\n\n    @states ||= {}\n    @current ||= 'A'\n\n    if @states[key]\n      @states[key]\n    else\n      @states[key] = @current\n      @current = @current.succ\n      @states[key]\n    end\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/03/lib/fa_rule.rb",
    "content": "class FARule < Struct.new(:state, :character, :next_state)\n  include Dot::Rule\n\n  def applies_to?(state, character)\n    self.state == state and\n      self.character == character\n  end\n\n  def follow\n    next_state\n  end\n\n  def inspect\n    \"#<FARule #{state.inspect} --#{character}--> #{next_state.inspect}>\"\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/03/lib/grammar.treetop",
    "content": "grammar Pattern\n  rule choose\n    first:concatenate_or_empty '|' rest:choose {\n      def to_ast\n        Choose.new(first.to_ast, rest.to_ast)\n      end\n    }\n    /\n    concatenate_or_empty\n  end\n\n  rule concatenate_or_empty\n    concatenate / empty\n  end\n\n  rule concatenate\n    first:repeat rest:concatenate {\n      def to_ast\n        Concatenate.new(first.to_ast, rest.to_ast)\n      end\n    }\n    /\n    repeat\n  end\n\n  rule empty\n    '' {\n      def to_ast\n        Empty.new\n      end\n    }\n  end\n\n  rule repeat\n    brackets '*' {\n      def to_ast\n        Repeat.new(brackets.to_ast)\n      end\n    }\n    /\n    brackets\n  end\n\n  rule brackets\n    '(' choose ')' {\n      def to_ast\n        choose.to_ast\n      end\n    }\n    /\n    literal\n  end\n\n  rule literal\n    [a-z] {\n      def to_ast\n        Literal.new(text_value)\n      end\n    }\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/03/lib/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Understanding Computation - Chapter 03 example</title>\n  </head>\n  <body>\n    <h1>Minimizaiton of finite automata</h1>\n\n    <p>\n      I found Brzozowski's algorithm so unbelievable, that I had actually to\n      run it to be sure that it actually works (spoiler alert: it does). This\n      is what it produces:\n    </p>\n\n    <table border=\"2\">\n      <thead>\n        <tr>\n          <th>Type</th>\n          <th><code>ab(ab)*</code></th>\n          <th><code>a(ba)*b</code></th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>NFA</td>\n          <td><img src=\"nfa1.gif\" alt=\"Nondeterministice Finite Automaton for ab(ab)*\"></td>\n          <td><img src=\"nfa2.gif\" alt=\"Nondeterministice Finite Automaton for a(ba)*b\"></td>\n        </tr>\n        <tr>\n          <td>DFA</td>\n          <td><img src=\"dfa2.gif\" alt=\"Deterministice Finite Automaton for a(ba)*b\"></td>\n          <td><img src=\"dfa1.gif\" alt=\"Deterministice Finite Automaton for ab(ab)*\"></td>\n        </tr>\n        <tr>\n          <td>Minimized DFA</td>\n          <td><img src=\"dfa1min.gif\" alt=\"Minimized Finite Automaton for ab(ab)*\"></td>\n          <td><img src=\"dfa2min.gif\" alt=\"Minimized Finite Automaton for a(ba)*b\"></td>\n        </tr>\n      </tbody>\n    </table>\n\n    <p>I trully find this shocking ;)</p>\n  </body>\n</html>\n"
  },
  {
    "path": "ruby/understanding-computation/03/lib/nfa.rb",
    "content": "class NFA < Struct.new(:current_states, :accept_states, :rulebook)\n  def accepting?\n    (current_states & accept_states).any?\n  end\n\n  def read_character(character)\n    self.current_states = rulebook.next_states(current_states, character)\n  end\n\n  def read_string(string)\n    string.chars.each do |character|\n      read_character(character)\n    end\n  end\n\n  def current_states\n    rulebook.follow_free_moves(super)\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/03/lib/nfa_design.rb",
    "content": "class NFADesign < Struct.new(:start_state, :accept_states, :rulebook)\n  include Dot::Design\n\n  def accepts?(string)\n    to_nfa.tap { |nfa| nfa.read_string(string) }.accepting?\n  end\n\n  def to_nfa(current_states = Set[start_state])\n    NFA.new(current_states, accept_states, rulebook)\n  end\n\n  def to_dfa_design\n    NFASimulation.new(self).to_dfa_design\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/03/lib/nfa_rulebook.rb",
    "content": "class NFARulebook < Struct.new(:rules)\n  def next_states(states, character)\n    states.flat_map { |state| follow_rules_for(state, character) }.to_set\n  end\n\n  def follow_rules_for(state, character)\n    rules_for(state, character).map(&:follow)\n  end\n\n  def rules_for(state, character)\n    rules.select { |rule| rule.applies_to?(state, character) }\n  end\n\n  def follow_free_moves(states)\n    more_states = next_states(states, nil)\n\n    if more_states.subset?(states)\n      states\n    else\n      follow_free_moves(states + more_states)\n    end\n  end\n\n  def alphabet\n    rules.map(&:character).compact.uniq\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/03/lib/nfa_simulation.rb",
    "content": "class NFASimulation < Struct.new(:nfa_design)\n  def next_state(state, character)\n    nfa_design.to_nfa(state).tap do |nfa|\n      nfa.read_character(character)\n    end.current_states\n  end\n\n  def rules_for(state)\n    nfa_design.rulebook.alphabet.map do |character|\n      FARule.new(state, character, next_state(state, character))\n    end\n  end\n\n  def discover_states_and_rules(states)\n    rules = states.flat_map { |state| rules_for(state) }\n    more_states = rules.map(&:follow).to_set\n\n    if more_states.subset?(states)\n      [states, rules]\n    else\n      discover_states_and_rules(states + more_states)\n    end\n  end\n\n  def to_dfa_design\n    start_state   = nfa_design.to_nfa.current_states\n    states, rules = discover_states_and_rules(Set[start_state])\n    accept_states = states.select { |state| nfa_design.to_nfa(state).accepting? }\n\n    DFADesign.new(start_state, accept_states, DFARulebook.new(rules))\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/03/lib/pattern.rb",
    "content": "module Pattern\n  def self.parse(string)\n    PatternParser.new.parse(string)\n  end\n\n  def bracket(outer_precendence)\n    if precendence < outer_precendence\n      '(' + to_s + ')'\n    else\n      to_s\n    end\n  end\n\n  def inspect\n    \"/#{self}/\"\n  end\n\n  def matches?(string)\n    to_nfa_design.accepts?(string)\n  end\nend\n\nclass Empty\n  include Pattern\n\n  def to_s\n    ''\n  end\n\n  def precendence\n    3\n  end\n\n  def to_nfa_design\n    start_state = Object.new\n    accept_states = [start_state]\n    rulebook = NFARulebook.new([])\n\n    NFADesign.new(start_state, accept_states, rulebook)\n  end\nend\n\nclass Literal < Struct.new(:character)\n  include Pattern\n\n  def to_s\n    character\n  end\n\n  def precendence\n    3\n  end\n\n  def to_nfa_design\n    start_state = Object.new\n    accept_state = Object.new\n    rule = FARule.new(start_state, character, accept_state)\n    rulebook = NFARulebook.new([rule])\n\n    NFADesign.new(start_state, [accept_state], rulebook)\n  end\nend\n\nclass Concatenate < Struct.new(:first, :second)\n  include Pattern\n\n  def to_s\n    [first, second].map { |pattern| pattern.bracket(precendence) }.join\n  end\n\n  def precendence\n    1\n  end\n\n  def to_nfa_design\n    first_nfa_design  = first.to_nfa_design\n    second_nfa_design = second.to_nfa_design\n\n    start_state = first_nfa_design.start_state\n    accept_states = second_nfa_design.accept_states\n    rules = first_nfa_design.rulebook.rules + second_nfa_design.rulebook.rules\n    extra_rules = first_nfa_design.accept_states.map do |state|\n      FARule.new(state, nil, second_nfa_design.start_state)\n    end\n\n    rulebook = NFARulebook.new(rules + extra_rules)\n\n    NFADesign.new(start_state, accept_states, rulebook)\n  end\nend\n\nclass Choose < Struct.new(:first, :second)\n  include Pattern\n\n  def to_s\n    [first, second].map { |pattern| pattern.bracket(precendence) }.join('|')\n  end\n\n  def precendence\n    0\n  end\n\n  def to_nfa_design\n    first_nfa_design  = first.to_nfa_design\n    second_nfa_design = second.to_nfa_design\n\n    start_state = Object.new\n    accept_states = first_nfa_design.accept_states + second_nfa_design.accept_states\n    rules = first_nfa_design.rulebook.rules + second_nfa_design.rulebook.rules\n\n    extra_rules = [\n      FARule.new(start_state, nil, first_nfa_design.start_state),\n      FARule.new(start_state, nil, second_nfa_design.start_state)\n    ]\n\n    rulebook = NFARulebook.new(rules + extra_rules)\n\n    NFADesign.new(start_state, accept_states, rulebook)\n  end\nend\n\nclass Repeat < Struct.new(:pattern)\n  include Pattern\n\n  def to_s\n    pattern.bracket(precendence) + '*'\n  end\n\n  def precendence\n    2\n  end\n\n  def to_nfa_design\n    pattern_nfa_design = pattern.to_nfa_design\n\n    start_state = Object.new\n    accept_states = pattern_nfa_design.accept_states + [start_state]\n    rules = pattern_nfa_design.rulebook.rules\n    extra_rules = pattern_nfa_design.accept_states.map { |state|\n      FARule.new(state, nil, pattern_nfa_design.start_state)\n    } + [FARule.new(start_state, nil, pattern_nfa_design.start_state)]\n\n    rulebook = NFARulebook.new(rules + extra_rules)\n\n    NFADesign.new(start_state, accept_states, rulebook)\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/03/rulebooks.rb",
    "content": "require './03'\n\nRULEBOOK_1 = DFARulebook.new([\n  FARule.new(1, 'a', 2), FARule.new(1, 'b', 1),\n  FARule.new(2, 'a', 2), FARule.new(2, 'b', 3),\n  FARule.new(3, 'a', 3), FARule.new(3, 'b', 3)\n])\n\nDFA1 = DFADesign.new(1, [3], RULEBOOK_1)\n\nRULEBOOK_2 = NFARulebook.new([\n  FARule.new(1, 'a', 1), FARule.new(1, 'b', 1), FARule.new(1, 'b', 2),\n  FARule.new(2, 'a', 3), FARule.new(2, 'b', 3),\n  FARule.new(3, 'a', 4), FARule.new(3, 'b', 4)\n])\n\nNFA1 = NFADesign.new(1, [4], RULEBOOK_2)\n\nRULEBOOK_3 = NFARulebook.new([\n  FARule.new(1, nil, 2), FARule.new(1, nil, 4),\n  FARule.new(2, 'a', 3),\n  FARule.new(3, 'a', 2),\n  FARule.new(4, 'a', 5),\n  FARule.new(5, 'a', 6),\n  FARule.new(6, 'a', 4)\n])\n\nNFA2 = NFADesign.new(1, [2, 4], RULEBOOK_3)\n\nPATTERN =\n  Repeat.new(\n    Choose.new(\n      Concatenate.new(Literal.new('a'), Literal.new('b')),\n      Literal.new('a')\n    )\n  )\n\nRULEBOOK_4 = NFARulebook.new([\n  FARule.new(1, 'a', 1), FARule.new(1, 'a', 2), FARule.new(1, nil, 2),\n  FARule.new(2, 'b', 3),\n  FARule.new(3, 'b', 1), FARule.new(3, nil, 2)\n])\n\nNFA3 = NFADesign.new(1, [3], RULEBOOK_4)\n\nDFA2 = NFASimulation.new(NFA3).to_dfa_design\n"
  },
  {
    "path": "ruby/understanding-computation/04/04.rb",
    "content": "require 'set'\n\n$:.unshift File.dirname(__FILE__) + '/lib'\n\nautoload :Stack, 'stack'\nautoload :PDARule, 'pda_rule'\nautoload :PDAConfiguration, 'pda_configuration'\n\nautoload :DPDA, 'dpda'\nautoload :DPDADesign, 'dpda_design'\nautoload :DPDARulebook, 'dpda_rulebook'\n\nautoload :NPDA, 'npda'\nautoload :NPDADesign, 'npda_design'\nautoload :NPDARulebook, 'npda_rulebook'\n\nautoload :LexicalAnalyzer, 'lexical_analyzer'\nautoload :SimpleParser, 'simple_parser'\n"
  },
  {
    "path": "ruby/understanding-computation/04/lib/dpda.rb",
    "content": "class DPDA < Struct.new(:current_configuration, :accept_states, :rulebook)\n  def accepting?\n    accept_states.include?(current_configuration.state)\n  end\n\n  def next_configuration(character)\n    if rulebook.applies_to?(current_configuration, character)\n      rulebook.next_configuration(current_configuration, character)\n    else\n      current_configuration.stuck\n    end\n  end\n\n  def stuck?\n    current_configuration.stuck?\n  end\n\n  def read_character(character)\n    self.current_configuration = next_configuration(character)\n  end\n\n  def read_string(string)\n    string.chars.each do |character|\n      read_character(character) unless stuck?\n    end\n  end\n\n  def current_configuration\n    rulebook.follow_free_moves(super)\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/04/lib/dpda_design.rb",
    "content": "class DPDADesign < Struct.new(:start_state, :bottom_character,\n                              :accept_states, :rulebook)\n  def accepts?(string)\n    to_dpda.tap { |dpda| dpda.read_string(string) }.accepting?\n  end\n\n  def to_dpda\n    start_stack = Stack.new([bottom_character])\n    start_configuration = PDAConfiguration.new(start_state, start_stack)\n    DPDA.new(start_configuration, accept_states, rulebook)\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/04/lib/dpda_rulebook.rb",
    "content": "class DPDARulebook < Struct.new(:rules)\n  def next_configuration(configuration, character)\n    rule_for(configuration, character).follow(configuration)\n  end\n\n  def rule_for(configuration, character)\n    rules.detect { |rule| rule.applies_to?(configuration, character) }\n  end\n\n  def applies_to?(configuration, character)\n    !rule_for(configuration, character).nil?\n  end\n\n  def follow_free_moves(configuration)\n    if applies_to?(configuration, nil)\n      follow_free_moves(next_configuration(configuration, nil))\n    else\n      configuration\n    end\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/04/lib/lexical_analyzer.rb",
    "content": "class LexicalAnalyzer < Struct.new(:string)\n  GRAMMAR = [\n    {token: 'i', pattern: /if/         },\n    {token: 'e', pattern: /else/       },\n    {token: 'w', pattern: /while/      },\n    {token: 'd', pattern: /do-nothing/ },\n    {token: '(', pattern: /\\(/         },\n    {token: ')', pattern: /\\)/         },\n    {token: '{', pattern: /\\{/         },\n    {token: '}', pattern: /\\}/         },\n    {token: ';', pattern: /;/          },\n    {token: '=', pattern: /=/          },\n    {token: '+', pattern: /\\+/         },\n    {token: '*', pattern: /\\*/         },\n    {token: '<', pattern: /</          },\n    {token: 'n', pattern: /[0-9]+/     },\n    {token: 'b', pattern: /true|false/ },\n    {token: 'v', pattern: /[a-z]+/     },\n  ]\n\n  def analyze\n    [].tap do |tokens|\n      while more_tokens?\n        tokens.push(next_token)\n      end\n    end\n  end\n\n  def more_tokens?\n    !string.empty?\n  end\n\n  def next_token\n    rule, match = rule_matching(string)\n    self.string = string_after(match)\n    rule[:token]\n  end\n\n  def rule_matching(string)\n    matches = GRAMMAR.map { |rule| match_at_beginning(rule[:pattern], string) }\n    rules_with_matches = GRAMMAR.zip(matches).reject { |rule, match| match.nil? }\n    rule_with_longest_match(rules_with_matches)\n  end\n\n  def match_at_beginning(pattern, string)\n    /\\A#{pattern}/.match(string)\n  end\n\n  def rule_with_longest_match(rules_with_matches)\n    rules_with_matches.max_by { |rule, match| match.to_s.length }\n  end\n\n  def string_after(match)\n    match.post_match.lstrip\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/04/lib/npda.rb",
    "content": "class NPDA < Struct.new(:current_configurations, :accept_states, :rulebook)\n  def accepting?\n    current_configurations.any? { |config| accept_states.include?(config.state) }\n  end\n\n  def read_character(character)\n    self.current_configurations = rulebook.next_configurations(current_configurations, character)\n  end\n\n  def read_string(string)\n    string.chars.each do |character|\n      read_character(character)\n    end\n  end\n\n  def current_configurations\n    rulebook.follow_free_moves(super)\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/04/lib/npda_design.rb",
    "content": "class NPDADesign < Struct.new(:start_state, :bottom_character, :accept_states, :rulebook)\n  def accepts?(string)\n    to_npda.tap { |npda| npda.read_string(string) }.accepting?\n  end\n\n  def to_npda\n    start_stack = Stack.new([bottom_character])\n    start_configuration = PDAConfiguration.new(start_state, start_stack)\n    NPDA.new(Set[start_configuration], accept_states, rulebook)\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/04/lib/npda_rulebook.rb",
    "content": "class NPDARulebook < Struct.new(:rules)\n  def next_configurations(configurations, character)\n    configurations.flat_map { |config| follow_rules_for(config, character) }.to_set\n  end\n\n  def follow_rules_for(configuration, character)\n    rules_for(configuration, character).map { |rule| rule.follow(configuration) }\n  end\n\n  def rules_for(configuration, character)\n    rules.select { |rule| rule.applies_to?(configuration, character) }\n  end\n\n  def follow_free_moves(configurations)\n    more_configurations = next_configurations(configurations, nil)\n\n    if more_configurations.subset?(configurations)\n      configurations\n    else\n      follow_free_moves(configurations + more_configurations)\n    end\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/04/lib/pda_configuration.rb",
    "content": "class PDAConfiguration < Struct.new(:state, :stack)\n  STUCK_STATE = Object.new\n\n  def stuck\n    PDAConfiguration.new(STUCK_STATE, stack)\n  end\n\n  def stuck?\n    state == STUCK_STATE\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/04/lib/pda_rule.rb",
    "content": "class PDARule < Struct.new(:state, :character, :next_state,\n                           :pop_character, :push_characters)\n  def applies_to?(configuration, character)\n    self.state == configuration.state &&\n      self.pop_character == configuration.stack.top &&\n      self.character == character\n  end\n\n  def follow(configuration)\n    PDAConfiguration.new(next_state, next_stack(configuration))\n  end\n\n  def next_stack(configuration)\n    popped_stack = configuration.stack.pop\n\n    push_characters.reverse.\n      inject(popped_stack) { |stack, character| stack.push(character) }\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/04/lib/simple_parser.rb",
    "content": "module SimpleParser\n  START_RULE = PDARule.new(1, nil, 2, '$', %w[S $])\n  SYMBOL_RULES = [\n    # <statement> ::= <while> | <assign>\n    PDARule.new(2, nil, 2, 'S', %w[W]),\n    PDARule.new(2, nil, 2, 'S', %w[A]),\n\n    # <while> ::= 'w' '(' <expression> ')' '{' <statement> '}'\n    PDARule.new(2, nil, 2, 'W', %w[w ( E ) { S }]),\n\n    # <assign> ::= 'v' '=' <expression>\n    PDARule.new(2, nil, 2, 'A', %w[v = E]),\n\n    # <expression> ::= <less-than>\n    PDARule.new(2, nil, 2, 'E', %w[L]),\n\n    # <less-than> ::= <multiply> '<' <less-than> | <multiply>\n    PDARule.new(2, nil, 2, 'L', %w[M < L]),\n    PDARule.new(2, nil, 2, 'L', %w[M]),\n\n    # <multiply> ::= <term> '*' <multiply> | <term>\n    PDARule.new(2, nil, 2, 'M', %w[T * M]),\n    PDARule.new(2, nil, 2, 'M', %w[T]),\n\n    # <term> ::= 'n' | 'v'\n    PDARule.new(2, nil, 2, 'T', %w[n]),\n    PDARule.new(2, nil, 2, 'T', %w[v]),\n  ]\n  TOKEN_RULES = LexicalAnalyzer::GRAMMAR.map do |rule|\n    PDARule.new(2, rule[:token], 2, rule[:token], [])\n  end\n  STOP_RULE = PDARule.new(2, nil, 3, '$', %w[$])\n\n  RULES = [START_RULE, STOP_RULE] + SYMBOL_RULES + TOKEN_RULES\n  RULEBOOK = NPDARulebook.new(RULES)\n  DESIGN = NPDADesign.new(1, '$', [3], RULEBOOK)\n\n  def self.accepts?(string)\n    token_string = LexicalAnalyzer.new(string).analyze.join\n    puts token_string\n    DESIGN.accepts?(token_string)\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/04/lib/stack.rb",
    "content": "class Stack < Struct.new(:contents)\n  def push(character)\n    Stack.new([character] + contents)\n  end\n\n  def pop\n    Stack.new(contents.drop(1))\n  end\n\n  def top\n    contents.first\n  end\n\n  def inspect\n    \"#<Stack (#{top})#{contents.drop(1).join}>\"\n  end\nend\n"
  },
  {
    "path": "ruby/understanding-computation/04/rulebooks.rb",
    "content": "require_relative '04'\n\nRULEBOOK_1 = DPDARulebook.new([\n  PDARule.new(1, '(', 2, '$', ['b', '$']),\n  PDARule.new(2, '(', 2, 'b', ['b', 'b']),\n  PDARule.new(2, ')', 2, 'b', []),\n  PDARule.new(2, nil, 1, '$', ['$']),\n])\n\nDPA1 = DPDADesign.new(1, '$', [1], RULEBOOK_1)\n\nRULEBOOK_2 = DPDARulebook.new([\n  PDARule.new(1, 'a', 2, '$', ['a', '$']),\n  PDARule.new(1, 'b', 2, '$', ['b', '$']),\n  PDARule.new(2, 'a', 2, 'a', ['a', 'a']),\n  PDARule.new(2, 'b', 2, 'b', ['b', 'b']),\n  PDARule.new(2, 'a', 2, 'b', []),\n  PDARule.new(2, 'b', 2, 'a', []),\n  PDARule.new(2, nil, 1, '$', ['$'])\n])\n\nDPDA2 = DPDADesign.new(1, '$', [1], RULEBOOK_2)\n\nRULEBOOK_3 = DPDARulebook.new([\n  PDARule.new(1, 'a', 1, '$', ['a', '$']),\n  PDARule.new(1, 'a', 1, 'a', ['a', 'a']),\n  PDARule.new(1, 'a', 1, 'b', ['a', 'b']),\n  PDARule.new(1, 'b', 1, '$', ['b', '$']),\n  PDARule.new(1, 'b', 1, 'a', ['b', 'a']),\n  PDARule.new(1, 'b', 1, 'b', ['b', 'b']),\n  PDARule.new(1, 'm', 2, '$', ['$']),\n  PDARule.new(1, 'm', 2, 'a', ['a']),\n  PDARule.new(1, 'm', 2, 'b', ['b']),\n  PDARule.new(2, 'a', 2, 'a', []),\n  PDARule.new(2, 'b', 2, 'b', []),\n  PDARule.new(2, nil, 3, '$', ['$'])\n])\n\nDPDA3 = DPDADesign.new(1, '$', [3], RULEBOOK_3)\n\nRULEBOOK_4 = NPDARulebook.new([\n  PDARule.new(1, 'a', 1, '$', ['a', '$']),\n  PDARule.new(1, 'a', 1, 'a', ['a', 'a']),\n  PDARule.new(1, 'a', 1, 'b', ['a', 'b']),\n  PDARule.new(1, 'b', 1, '$', ['b', '$']),\n  PDARule.new(1, 'b', 1, 'a', ['b', 'a']),\n  PDARule.new(1, 'b', 1, 'b', ['b', 'b']),\n  PDARule.new(1, nil, 2, '$', ['$']),\n  PDARule.new(1, nil, 2, 'a', ['a']),\n  PDARule.new(1, nil, 2, 'b', ['b']),\n  PDARule.new(2, 'a', 2, 'a', []),\n  PDARule.new(2, 'b', 2, 'b', []),\n  PDARule.new(2, nil, 3, '$', ['$'])\n])\n\nNPDA1 = NPDADesign.new(1, '$', [3], RULEBOOK_4)\n"
  },
  {
    "path": "ruby/understanding-computation/Rakefile",
    "content": "require 'fileutils'\nrequire 'pathname'\n\nCURRENT_DIR = Pathname(File.dirname(__FILE__))\n\ndesc \"Generates output for chapter 03\"\ntask '03' do\n  require './03/example'\n  mkdir_p CURRENT_DIR.join('tmp/03')\n  Chapter03.generate_example CURRENT_DIR.join('tmp/03')\nend\n"
  },
  {
    "path": "scala/expr/.gitignore",
    "content": "*.class\n*.log\n\n# sbt specific\ndist/*\ntarget/\nlib_managed/\nsrc_managed/\nproject/boot/\nproject/plugins/project/\n\n"
  },
  {
    "path": "scala/expr/README.markdown",
    "content": "# Expression evaluator\n\nA tiny interpreter for simple arithmetic expressions.\n\n## Description\n\nI wrote this project in order to learn Scala. I enjoy writing this interpreter\nin different languages, because it has a few interesting learning\nopportunities. It contains the following:\n\n* AST structure for expressions (using case classes)\n* A parser for expressions (using `scala.parser.combinators`)\n* An interactive interpreter for arithmetic expressions\n* Expressions can be evaluated concurrently (using `scala.actors`)\n* Functions can be defined in terms of other expressions\n* Functions can be defined in Scala\n\n## Firing it up\n\nIt's as simple as:\n\n    → sbt run\n    Type 'help' for help.\n    > forty_five_degrees = 0.25 * PI\n    > tangent = lambda(x) { sin(x) / cos(x) }\n    > tangent(forty_five_degrees)\n    = 0.9999999999999999\n\nIt almost got it right. You can ask for `help` too:\n\n    > help\n    Usage instructions:\n      * write any expression in order to evaluate it:\n    \n         1 + 2 + 3 + 5 + 7 + 11 + 13\n         X + add(2, 4)\n         1 + 2 - 3 * 4 / 5 ^ 6\n    \n      * assign variables or define functions with =\n    \n         ANSWER = 42\n         add = lambda(X, Y) { X + Y }\n    \n      * other available commands\n    \n         names -- show all defined names\n         exit  -- quit the interpreter\n         help  -- you are looking at it\n\n## How did it go?\n\nWhile reading [Seven Languages in Seven Weeks][1], I realized I cannot reach a\ngood enough understanding of Scala just from the examples. Therefore, I read\n[Programming in Scala][2] and went through some of the code. After that I\nthought it will be fun to write a tiny interpreter, so I can experiment with\nfew features of Scala (pattern matching with extractors and case classes,\nparser combinators and ScalaCheck, to name a few).\n\nAll went fine, until I attempted to evaluate expressions concurrently with\nactors. It took me two days get it working and the activities included plowing\nthrough the `scala.actors` documentation, purchasing a beta version of\n[Actors in Scala][3], reading the papers ([first][4] and [second][5]) on the\nActor implementation and going through most of the code in `scala.actors`.\nI finally got it right, but I'm not convinced that it is the best way to do it.\n\n## Things I learned\n\nIn no specific order:\n\n* Writing tests when learning a language is **very** good idea. I usually end\n  up doing a lot of experiments and having feedback on a key press (as opposed\n  to rerunning) is a huge time-saver.\n* Furthermore, tweaking the environment to shave off a few seconds out of the\n  common activities is priceless. I spent too much time typing stuff in sbt\n  before I automated it in my Vim.\n* Knowledge of the tools surrounding a language is as important as knowledge\n  of the language itself. If I knew more about the Scala incremental compiler,\n  ScalaTest and sbt, I would have been a lot more effective in learning the\n  language. I should take the time to study to whole toolchain involved.\n* Vim is not the best fit for a complex, static typed language like Scala. I\n  was craving for IDE features. Seeing the type of an expression or the\n  available methods would be priceless.\n* Applying an incremental approach to writing code in a new language pays off.\n  I've spent most of the time refactoring code I've gotten to work. It is a\n  great learning opportinuty, since it allows finding out small tricks for\n  DRYing up code in the safety net of tests.\n\n  [1]: http://pragprog.com/titles/btlang/seven-languages-in-seven-weeks\n  [2]: http://www.artima.com/shop/programming_in_scala\n  [3]: http://www.artima.com/shop/actors_in_scala\n  [4]: http://lampwww.epfl.ch/~odersky/papers/jmlc06.pdf\n  [5]: http://lamp.epfl.ch/~phaller/doc/haller07coord.pdf\n"
  },
  {
    "path": "scala/expr/project/build/Expressions.scala",
    "content": "import sbt._\n\nclass ExpressionsProject(info: ProjectInfo) extends DefaultProject(info) {\n  val scalatest = \"org.scalatest\" % \"scalatest\" % \"1.1\"\n  val scalacheck = \"org.scala-tools.testing\" % \"scalacheck_2.7.7\" % \"1.6\"\n  val jline = \"jline\" % \"jline\" % \"0.9.94\"\n}\n"
  },
  {
    "path": "scala/expr/project/build.properties",
    "content": "#Project properties\n#Tue Dec 07 20:35:34 CET 2010\nproject.organization=skanev.com\nproject.name=expressions\nsbt.version=0.7.4\nproject.version=1.0\nbuild.scala.versions=2.7.7\nproject.initialize=false\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/ActorEvaluation.scala",
    "content": "package expr\n\nimport scala.actors.Actor\nimport scala.actors.Actor.{actor, react, reply, loopWhile, mkBody}\n\nimport BinOp._\n\n\nobject ActorEvaluation {\n  def eval(expr: Expr, env: Env) = new ActorEvaluation(env).eval(expr)\n}\n\nclass ActorEvaluation(env: Env) {\n  case class PartialResult(index: Int, num: Double)\n\n  def mapReduce(exprs: List[Expr], index: Int, target: Actor)(reduce: Array[Double] => Double): Unit = {\n    val mapper = actor {\n      val evaluated: Array[Double] = Array.make(exprs.length, 0.0)\n\n      times(exprs.length) {\n        react { case PartialResult(n, value) => evaluated(n) = value }\n      } andThen {\n        target ! PartialResult(index, reduce(evaluated))\n      }\n    }\n\n    for ((e, i) <- exprs.zipWithIndex) evalTo(e, i, mapper)\n  }\n\n  def evalTo(expr: Expr, index: Int, target: Actor): Unit = {\n    def respond(answer: => Double) = actor { target ! PartialResult(index, answer) }\n    def binOp(x: Expr, y: Expr)(op: (Double, Double) => Double) =\n      mapReduce(List(x, y), index, target)(xs => op(xs(0), xs(1)))\n    def function(name: String, args: Seq[Expr]) =\n      mapReduce(args.toList, index, target) { xs => env.function(name).eval(env, xs.toList) }\n\n    expr match {\n      case Num(num) => respond { num }\n      case Name(name) => respond { env.variable(name) }\n      case Call(name, args) => function(name, args)\n      case x + y => binOp(x, y) { _ + _ }\n      case x - y => binOp(x, y) { _ - _ }\n      case x * y => binOp(x, y) { _ * _ }\n      case x / y => binOp(x, y) { _ / _ }\n      case x ^ y => binOp(x, y) { Math.pow(_, _) }\n    }\n  }\n\n  def eval(expr: Expr): Double = {\n    val waiter = actor {\n      var result = 0.0\n      mkBody {\n        react { case PartialResult(-1, num) => result = num }\n      } andThen {\n        react { case 'Eval => reply(result) }\n      }\n    }\n\n    evalTo(expr, -1, waiter)\n    (waiter !? 'Eval) match { case result: Double => result }\n  }\n\n  private def times(n: Int)(body: => Unit) = {\n    var counter = n\n    loopWhile(counter > 0) { counter -= 1; body }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/BadInputException.scala",
    "content": "package expr\n\nclass BadInputException(message: String) extends Exception(message)\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/Callable.scala",
    "content": "package expr\n\ntrait Callable {\n  def eval(env: Env, params: Seq[Double]): Double\n}\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/Env.scala",
    "content": "package expr\n\nobject Env {\n  sealed abstract class Value { def repr: String }\n  case class Variable(val number: Double) extends Value { def repr = number.toString }\n  case class Function(val code: Callable) extends Value { def repr = code.toString }\n\n  def empty = new Env(Map())\n}\n\nclass Env(val mapping: Map[String, Env.Value]) {\n  import Env.{Value, Variable, Function}\n\n  def apply(name: String): Value = mapping(name)\n\n  def extend(name: String, value: Env.Value): Env = new Env(mapping + (name -> value))\n  def extend(name: String, number: Double): Env = extend(name, Variable(number))\n  def extend(name: String, code: Callable): Env = extend(name, Function(code))\n  def extend(pairs: Seq[(String, Double)]): Env = new Env(mapping ++ pairs.map { p => (p._1, Variable(p._2)) })\n\n  def names: Set[String] = Set() ++ mapping.keys\n\n  def variable(name: String): Double = {\n    mapping.get(name) match {\n      case Some(Variable(x)) => x\n      case _ => throw new ExprException(\"Undefined variable: \" + name)\n    }\n  }\n\n  def function(name: String): Callable = {\n    mapping.get(name) match {\n      case Some(Function(lambda)) => lambda\n      case _ => throw new ExprException(\"Undefined function: \" + name)\n    }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/Evaluation.scala",
    "content": "package expr\n\nimport scala.actors.Futures.future\nimport Math.pow\nimport BinOp._\n\nobject Evaluation {\n  def eval(expression: Expr, env: Env): Double = {\n    def e(expr: Expr) = eval(expr, env)\n\n    expression match {\n      case Num(x) => x\n      case Name(x) => env.variable(x)\n      case Call(name, args) => env.function(name).eval(env, args.map(e))\n      case x + y => e(x) + e(y)\n      case x - y => e(x) - e(y)\n      case x * y => e(x) * e(y)\n      case x / y => e(x) / e(y)\n      case x ^ y => pow(e(x), e(y))\n      case _ => error(\"Cannot evaluate expression: \" + expression)\n    }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/Expr.scala",
    "content": "package expr\n\nobject Expr {\n  def parse(input: String) = Parser.parse(input)\n}\n\nsealed abstract class Expr {\n  def +(other: Expr) = BinOp(BinOp.+, this, other)\n  def -(other: Expr) = BinOp(BinOp.-, this, other)\n  def *(other: Expr) = BinOp(BinOp.*, this, other)\n  def ^(other: Expr) = BinOp(BinOp.^, this, other)\n\n  def eval(env: Env) = Evaluation.eval(this, env)\n  def aeval(env: Env) = ActorEvaluation.eval(this, env)\n\n  override def toString = Printer.asString(this)\n}\n\ncase class Num(number: Double) extends Expr\ncase class Name(name: String) extends Expr\ncase class BinOp(op: BinOp.Operator, left: Expr, right: Expr) extends Expr\ncase class Call(name: String, arguments: Seq[Expr]) extends Expr\n\nobject BinOp {\n  sealed abstract class Operator(symbol: String, val precendance: Int) {\n    val operator = this\n\n    def unapply(expr: Expr): Option[(Expr, Expr)] = {\n      expr match {\n        case BinOp(`operator`, left, right) => Some((left, right))\n        case _ => None\n      }\n    }\n\n    override def toString = symbol\n  }\n\n  object ^ extends Operator(\"^\", 1)\n  object / extends Operator(\"/\", 2)\n  object * extends Operator(\"*\", 3)\n  object - extends Operator(\"-\", 4)\n  object + extends Operator(\"+\", 5)\n}\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/ExprException.scala",
    "content": "package expr\n\nclass ExprException(val message: String) extends Exception(message)\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/Lambda.scala",
    "content": "package expr\n\ncase class Lambda(args: List[String], expr: Expr) extends Callable {\n  verifyNoFreeVariables()\n\n  override def toString = \"lambda(%s) { %s }\".format(args.mkString(\", \"), expr.toString)\n\n  override def eval(env: Env, params: Seq[Double]): Double = {\n    verifyArity(params.length)\n    val extended = env.extend(args zip params.toList)\n    expr.eval(extended)\n  }\n\n  private def freeVariables(expr: Expr): Seq[String] = {\n    expr match {\n      case BinOp(_, left, right) => freeVariables(left) ++ freeVariables(right)\n      case Call(_, params) => params.flatMap(freeVariables)\n      case Name(name) if !args.contains(name) => List(name)\n      case _ => List()\n    }\n  }\n\n  private def verifyArity(paramCount: Int) {\n    if (paramCount != args.length)\n      throw new ExprException(\"Lambda expects \" + args.length + \" argument(s), \" +\n          \"but was called with \" + paramCount)\n  }\n\n  private def verifyNoFreeVariables() = {\n    val vars = freeVariables(expr)\n    if (vars.length != 0)\n      throw new ExprException(\"Lambda contains free variables: \" + vars.mkString(\",\"))\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/Parser.scala",
    "content": "package expr\n\nimport scala.util.parsing.combinator.JavaTokenParsers\n\nobject Parser {\n  def parse(input: String): Expr = {\n    val parser = new Parser()\n    val result = parser.parseAll(parser.expr, input)\n    result.getOrElse { throw new BadInputException(input) }\n  }\n}\n\nclass Parser extends JavaTokenParsers {\n  def expr = addition\n  def addition = binaryOp(BinOp.+, subtraction)\n  def subtraction = binaryOp(BinOp.-, multiplication)\n  def multiplication = binaryOp(BinOp.*, division)\n  def division = binaryOp(BinOp./, exp)\n  def exp = binaryOp(BinOp.^, factor)\n  def factor: Parser[Expr] = \"(\" ~> expr <~ \")\" | number | call | name;\n  def call: Parser[Expr] = ident ~ \"(\" ~ repsep(expr, \",\") ~ \")\" ^^ {\n    case name ~ \"(\" ~ args ~ \")\" => Call(name, args)\n  }\n  def number: Parser[Num] = floatingPointNumber ^^ (x => Num(x.toDouble))\n  def name: Parser[Name] = ident ^^ Name\n\n  private def binaryOp(operator: BinOp.Operator, operand: Parser[Expr]): Parser[Expr] = {\n    val symbol = operator.toString;\n    operand ~ rep(symbol ~> operand) ^^ {\n      case first ~ operands => (first /: operands) { (binOp, operand) => BinOp(operator, binOp, operand) }\n    }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/Printer.scala",
    "content": "package expr\n\nobject Printer {\n  private def parenthesize(expr: Expr, enclosingPrecendence: Int): String = {\n    val str = asString(expr)\n    expr match {\n      case BinOp(operator, _, _) if operator.precendance > enclosingPrecendence =>\n        \"(\" + str + \")\"\n      case _ => str\n    }\n  }\n\n  def asString(expr: Expr): String = {\n    expr match {\n      case Num(number) => number.toString.replaceAll(\".0$\", \"\")\n      case Name(name) => name\n      case Call(name, args) => \"%s(%s)\".format(name, args.map(asString).mkString(\", \"))\n      case BinOp(operator, left, right) =>\n        val enclosing = operator.precendance\n        parenthesize(left, enclosing) + \" \" + operator + \" \" + parenthesize(right, enclosing)\n    }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/ScalaCode.scala",
    "content": "package expr\n\nobject ScalaCode {\n  def define0(doc: String)(code: => Double): ScalaCode = define(doc) { case Nil => code }\n  def define1(doc: String)(code: (Double) => Double): ScalaCode = define(doc) { case List(a) => code(a) }\n  def define2(doc: String)(code: (Double, Double) => Double): ScalaCode = define(doc) { case List(a, b) => code(a, b) }\n  def define3(doc: String)(code: (Double, Double, Double) => Double): ScalaCode = define(doc) { case List(a, b, c) => code(a, b, c) }\n\n  private def define(doc: String)(code: PartialFunction[List[Double], Double]): ScalaCode = {\n    def codeWithVerification(params: List[Double]): Double = {\n      if (!code.isDefinedAt(params))\n        throw new ExprException(\"Function called with an unexpected number of arguments\")\n      code(params)\n    }\n    new ScalaCode(doc, codeWithVerification)\n  }\n}\n\nclass ScalaCode(doc: String, code: List[Double] => Double) extends Callable {\n  override def eval(env: Env, params: Seq[Double]): Double = code(params.toList)\n  override def toString = \"<ScalaCode:%s>\".format(doc)\n}\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/repl/Command.scala",
    "content": "package expr.repl\n\nabstract sealed class Command\n\nobject Command {\n  case class Exit() extends Command\n  case class ShowEnv() extends Command\n  case class Help() extends Command\n  case class Eval(expr: Expr) extends Command\n  case class Assign(variable: String, expr: Expr) extends Command\n  case class Define(name: String, lambda: Lambda) extends Command\n\n  def parse(input: String): Command = {\n    val parser = new CommandParser\n    val result = parser.parseAll(parser.command, input)\n\n    result.getOrElse { throw new BadInputException(\"Cannot be parsed\") }\n  }\n\n  class CommandParser extends expr.Parser {\n    def command = exit | help | showEnv | define | assign | eval\n    def define = ident ~ \"=\" ~ \"lambda\" ~ \"(\" ~ repsep(ident, \",\") ~ \")\" ~ \"{\" ~ expr ~ \"}\" ^^ {\n      case name ~ \"=\" ~ \"lambda\" ~ \"(\" ~ args ~ \")\" ~ \"{\" ~ expr ~ \"}\" => Define(name, Lambda(args, expr))\n    }\n    def assign = ident ~ \"=\" ~ expr ^^ { case variable ~ \"=\" ~ expr => Assign(variable, expr) }\n    def help = \"help\" ^^ { case _ => Help() }\n    def exit = \"exit\" ^^ { case _ => Exit() }\n    def showEnv = \"names\" ^^ { case _ => ShowEnv() }\n    def eval = expr ^^ { case expr => Eval(expr) }\n  }\n}\n\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/repl/ConsoleShell.scala",
    "content": "package expr.repl\n\nobject ConsoleShell extends Shell {\n  override def read(): String = {\n    print(\"> \")\n    Console.readLine\n  }\n\n  override def write(output: String) = print(output)\n}\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/repl/InteractiveInterpreter.scala",
    "content": "package expr.repl\n\nimport Expr.parse\n\nobject InteractiveInterpreter extends Application {\n  val env = Env.empty\n    .extend(\"PI\", Math.Pi)\n    .extend(\"E\", Math.E)\n    .extend(\"sin\", ScalaCode.define1(\"sin(x) in radians\") { x => Math.sin(x) })\n    .extend(\"cos\", ScalaCode.define1(\"cos(x) in radians\") { x => Math.cos(x) })\n    .extend(\"ln\", ScalaCode.define1(\"ln(x) -- log with base e\") { x => Math.log(x) })\n    .extend(\"one\", Lambda(List(\"x\"), parse(\"sin(x) ^ 2 + cos(x) ^ 2\")))\n    .extend(\"log\", Lambda(List(\"base\", \"number\"), parse(\"ln(number) / ln(base)\")))\n\n  println(\"Type 'help' for help.\")\n  new REPL(JLineShell, env).start()\n}\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/repl/JLineShell.scala",
    "content": "package expr.repl\n\nobject JLineShell extends Shell {\n  val reader = new jline.ConsoleReader()\n  override def read(): String = reader.readLine(\"> \")\n  override def write(output: String) = print(output)\n}\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/repl/REPL.scala",
    "content": "package expr.repl\n\nimport expr.BadInputException\nimport Command._\n\nclass REPL(shell: Shell, private var env: Env) {\n  def this(shell: Shell) { this(shell, Env.empty) }\n\n  def start() = processNextLine()\n\n  private def processNextLine() {\n    try {\n      parse(shell.read) match {\n        case Eval(expr) => shell.writeln(\"= \" + expr.eval(env))\n        case Assign(name, expr) => env = env.extend(name, expr.eval(env))\n        case Define(name, lambda) => env = env.extend(name, lambda)\n        case ShowEnv() => listNames()\n        case Help() => showHelp()\n        case Exit() => return\n      }\n    } catch {\n      case ex: BadInputException => shell.writeln(\"ERROR: Unparsable input\")\n      case ex: ExprException => shell.writeln(\"ERROR: \" + ex.message)\n    }\n    processNextLine()\n  }\n\n  private def listNames() {\n    if (env.names.isEmpty) return\n\n    val width = env.names.toList.map(_.length).sort(_ > _).first\n    def pad(name: String) = name + \" \" * (width - name.length)\n\n    for (name <- env.names) {\n      shell.writeln(\"%s = %s\".format(pad(name), env(name).repr))\n    }\n  }\n\n  private def showHelp() {\n    shell.writeln(\"\"\"|Usage instructions:\n                     |  * write any expression in order to evaluate it:\n                     |\n                     |     1 + 2 + 3 + 5 + 7 + 11 + 13\n                     |     X + add(2, 4)\n                     |     1 + 2 - 3 * 4 / 5 ^ 6\n                     |\n                     |  * assign variables or define functions with =\n                     |\n                     |     ANSWER = 42\n                     |     add = lambda(X, Y) { X + Y }\n                     |\n                     |  * other available commands\n                     |\n                     |     names -- show all defined names\n                     |     exit  -- quit the interpreter\n                     |     help  -- you are looking at it\"\"\".stripMargin)\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/main/scala/expr/repl/Shell.scala",
    "content": "package expr.repl\n\ntrait Shell {\n  def read(): String\n  def write(output: String)\n  def writeln(output: String) = write(output + \"\\n\")\n}\n"
  },
  {
    "path": "scala/expr/src/test/scala/expr/EnvSpec.scala",
    "content": "package expr\n\nimport org.scalatest.Spec\nimport org.scalatest.matchers.ShouldMatchers\n\nclass EnvSpec extends Spec with ShouldMatchers {\n  it(\"can be extended with a variable\") {\n    val env = Env.empty.extend(\"X\", 1.0)\n    expect(1.0) { env.variable(\"X\") }\n  }\n\n  it(\"can be extended with multiple variables\") {\n    val env = Env.empty.extend(Array(\"X\" -> 1.0, \"Y\" -> 2.0))\n    expect(1.0) { env.variable(\"X\") }\n    expect(2.0) { env.variable(\"Y\") }\n  }\n\n  it(\"overrides existing variables\") {\n    val env = Env.empty.extend(\"X\", 1)\n    expect(2) { env.extend(\"X\", 2).variable(\"X\") }\n    expect(2) { env.extend(Array(\"X\" -> 2)).variable(\"X\") }\n  }\n\n  it(\"can be extended with a functions\") {\n    val add = Lambda(List(\"X\", \"Y\"), Name(\"X\") + Name(\"Y\"))\n    val env = Env.empty.extend(\"add\", add)\n    expect(add) { env.function(\"add\") }\n  }\n\n  it(\"raises an error when queried for an unexisting name\") {\n    intercept[ExprException] { Env.empty.variable(\"X\") }\n    intercept[ExprException] { Env.empty.function(\"X\") }\n  }\n\n  it(\"can tell its own bound names\") {\n    val env = Env.empty.extend(\"X\", 1).extend(\"foo\", Lambda(List(), Num(1)))\n    expect(Set(\"X\", \"foo\")) { env.names }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/test/scala/expr/EvaluationSpec.scala",
    "content": "package expr\n\nimport org.scalatest.Spec\nimport org.scalatest.matchers.ShouldMatchers\n\nimport Expr.parse\n\nclass EvaluationSpec extends Spec with ShouldMatchers {\n  val add = Lambda(List(\"X\", \"Y\"), Name(\"X\") + Name(\"Y\"))\n  val twice = Lambda(List(\"X\"), Call(\"add\", List(Name(\"X\"), Name(\"X\"))))\n  val negate = ScalaCode.define1(\"negate\") { x => -x }\n\n  val env = Env.empty\n    .extend(\"X\", 1)\n    .extend(\"Y\", 2)\n    .extend(\"add\", add)\n    .extend(\"twice\", twice)\n    .extend(\"negate\", negate)\n\n  val examples = Array(\n    \"1\" -> 1\n    , \"2 + 3\" -> 5\n    , \"X + Y\" -> 3\n    , \"Y ^ (X * 4)\" -> 16\n    , \"4 - Y\" -> 2\n    , \"9 / 3\" -> 3\n    , \"add(1, 2)\" -> 3\n    , \"twice(2)\" -> 4\n    , \"negate(42)\" -> -42\n  )\n\n  for((input, expectation) <- examples) {\n    it(\"evaluates \" + input + \" to \" + expectation) {\n      expect(expectation) { parse(input).eval(env) }\n    }\n\n    it(\"can evaluate with actors \" + input + \" to \" + expectation) {\n      expect(expectation) { parse(input).aeval(env) }\n    }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/test/scala/expr/ExprGen.scala",
    "content": "package expr\n\nimport org.scalacheck._\nimport org.scalacheck.Prop._\nimport org.scalacheck.Gen._\nimport org.scalacheck.Arbitrary.arbitrary\n\nimport expr.BinOp._\n\nobject ExprGen {\n  def eval(e: Expr) = e.eval(env)\n\n  val env = Env.empty\n    .extend(\"x\", 1.44)\n    .extend(\"e\", 2.71)\n    .extend(\"add\", Lambda(List(\"x\", \"y\"), Name(\"x\") + Name(\"y\")))\n    .extend(\"twice\", Lambda(List(\"x\"), Name(\"x\") + Name(\"x\")))\n    .extend(\"pi\", ScalaCode.define0(\"pi()\") { Math.Pi })\n\n  val number = arbitrary[Double].map(Num(_))\n  val name = oneOf(\"x\", \"e\").map(Name(_))\n\n  def binOp: Gen[Expr] = (for {\n    op <- oneOf(BinOp.+, BinOp.-, BinOp.*, BinOp./, BinOp.^)\n    left <- oneOf(binOp, call, number, name)\n    right <- oneOf(binOp, call, number, name)\n  } yield BinOp(op, left, right)) suchThat {\n    case BinOp(op1, _, BinOp(op2, _, _)) if op1 == op2 => false\n    case _ => true\n  }\n\n  def call: Gen[Expr] = for {\n    a <- oneOf(binOp, number, name)\n    b <- oneOf(binOp, number, name)\n    fun <- oneOf(\"pi\", \"twice\", \"add\")\n  } yield (fun match {\n    case \"pi\" => Call(\"pi\", List())\n    case \"twice\" => Call(\"twice\", List(a))\n    case \"add\" => Call(\"add\", List(a, b))\n  })\n\n  def expr: Gen[Expr] = binOp\n}\n"
  },
  {
    "path": "scala/expr/src/test/scala/expr/ExpressionSpec.scala",
    "content": "package expr\n\nimport org.scalatest.Spec\nimport org.scalatest.matchers.ShouldMatchers\n\nclass ExpressionSpec extends Spec with ShouldMatchers {\n  it(\"allows creating a binary operation with +\") {\n    expect(BinOp(BinOp.+, Num(1), Num(2))) {\n      Num(1) + Num(2)\n    }\n  }\n\n  it(\"allows creating a binary operation with *\") {\n    expect(BinOp(BinOp.*, Num(1), Num(2))) {\n      Num(1) * Num(2)\n    }\n  }\n\n  it(\"allows creating a BinOp with ^\") {\n    expect(BinOp(BinOp.^, Num(1), Num(2))) {\n      Num(1) ^ Num(2)\n    }\n  }\n\n  it(\"allows creating a BinOp with -\") {\n    expect(BinOp(BinOp.-, Num(1), Num(2))) {\n      Num(1) - Num(2)\n    }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/test/scala/expr/LambdaSpec.scala",
    "content": "package expr\n\nimport org.scalatest.Spec\nimport org.scalatest.matchers.ShouldMatchers\n\nimport BinOp.{Operator => O}\n\nclass LambdaSpec extends Spec with ShouldMatchers {\n  val env = Env.empty\n  val add = Lambda(List(\"X\", \"Y\"), Name(\"X\") + Name(\"Y\"))\n\n  it(\"can be evaluated with given parameters\") {\n    expect(3) { add.eval(env, List(1, 2)) }\n  }\n\n  it(\"can be printed as a string\") {\n    expect(\"lambda(X, Y) { X + Y }\") { add.toString }\n  }\n\n  it(\"raises an error when invoked with the wrong number of arguments\") {\n    intercept[ExprException] { add.eval(env, List(1, 2, 3)) }\n  }\n\n  it(\"cannot be constructed with free variables\") {\n    intercept[ExprException] { Lambda(List(\"X\"), Name(\"X\") + Name(\"Y\")) }\n    intercept[ExprException] { Lambda(List(\"X\"), Call(\"foo\", List(Name(\"X\"), Name(\"Y\")))) }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/test/scala/expr/ParsingSpec.scala",
    "content": "package expr\n\nimport org.scalatest.Spec\nimport org.scalatest.matchers.ShouldMatchers\n\nimport Expr.parse\nimport BinOp._\nimport expr.{BinOp => O}\n\nclass ParsingSpec extends Spec with ShouldMatchers {\n  val examples = Array(\n    \"1\" -> Num(1)\n    , \"X\" -> Name(\"X\")\n    , \"1 + X\" -> BinOp(O.+, Num(1), Name(\"X\"))\n    , \"1 - 2\" -> BinOp(O.-, Num(1), Num(2))\n    , \"X * 2\" -> BinOp(*, Name(\"X\"), Num(2))\n    , \"X / Y\" -> BinOp(/, Name(\"X\"), Name(\"Y\"))\n    , \"2 ^ X\" -> BinOp(^, Num(2), Name(\"X\"))\n    , \"1 + 2 + 3\" -> BinOp(O.+, BinOp(O.+, Num(1), Num(2)), Num(3))\n    , \"1 + 2 + 3 + 4\" -> BinOp(O.+, BinOp(O.+, BinOp(O.+, Num(1), Num(2)), Num(3)), Num(4))\n    , \"1 - 2 + 3\" -> BinOp(O.+, BinOp(O.-, Num(1), Num(2)), Num(3))\n    , \"1 + 2 - 3\" -> BinOp(O.+, Num(1), BinOp(O.-, Num(2), Num(3)))\n    , \"1 ^ 2 + 3 * 4\" -> BinOp(O.+, BinOp(^, Num(1), Num(2)), BinOp(*, Num(3), Num(4)))\n    , \"2 / 3 ^ 4\" -> BinOp(O./, Num(2), BinOp(O.^, Num(3), Num(4)))\n    , \"2 ^ 3 / 4\" -> BinOp(O./, BinOp(O.^, Num(2), Num(3)), Num(4))\n    , \"foo(1, 2)\" -> Call(\"foo\", List(Num(1), Num(2)))\n    , \"foo(X + Y)\" -> Call(\"foo\", List(BinOp(O.+, Name(\"X\"), Name(\"Y\"))))\n    , \"a(b(), 3 + c())\" -> Call(\"a\", List(Call(\"b\", List()), BinOp(O.+, Num(3), Call(\"c\", List()))))\n  )\n\n  for ((input, ast) <- examples) {\n    it(\"parses \" + input) {\n      expect(ast) { parse(input) }\n    }\n  }\n\n  it(\"throws an exception on invalid input\") {\n    val invalidInput = \"+ + +\"\n    intercept[BadInputException] { parse(invalidInput) }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/test/scala/expr/PrintingExpressionsSpec.scala",
    "content": "package expr\n\nimport org.scalatest.Spec\nimport org.scalatest.matchers.ShouldMatchers\n\nclass PrintingExpressionsSpec extends Spec with ShouldMatchers {\n  val examples = Array(\n    Num(1) + Num(2) -> \"1 + 2\"\n    , (Name(\"x\") ^ Num(2)) + Num(2) * Name(\"x\") + Num(1) -> \"x ^ 2 + 2 * x + 1\"\n    , (Name(\"x\") + Num(2)) * Num(3) -> \"(x + 2) * 3\"\n    , (Num(1) - Num(2)) + (Num(3) - Num(4)) -> \"1 - 2 + 3 - 4\"\n    , (Call(\"add\", Array(Num(1), Num(2)))) -> \"add(1, 2)\"\n    , (Num(1) - (Num(2) + Num(3))) -> \"1 - (2 + 3)\"\n  )\n\n  for ((expr, string) <- examples) {\n    it(\"prints \" + string) {\n      expect(string) { expr.toString }\n    }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/test/scala/expr/PropertiesSpec.scala",
    "content": "package expr\n\nimport org.scalatest.Spec\nimport org.scalatest.prop.Checkers\nimport org.scalatest.matchers.ShouldMatchers\n\nimport org.scalacheck.Prop._\n\nimport Expr.parse\n\nclass PropertiesSpec extends Spec with Checkers {\n  def sameResult(left: Double, right: Double): Boolean = (left == right) || (left.isNaN && right.isNaN)\n\n  describe(\"An expression\") {\n    it(\"is equal to its parsed toString\") {\n      check(forAll(ExprGen.expr) { expr => expr == parse(expr.toString) })\n    }\n\n    it(\"is evaluated to the same value as its parse . toString\") {\n      check(forAll(ExprGen.expr) { expr =>\n        sameResult(expr.eval(ExprGen.env), parse(expr.toString).eval(ExprGen.env))\n      })\n    }\n\n    it(\"evaluates to the same value with eval() and aeval()\") {\n      check(forAll(ExprGen.expr) { expr => sameResult(expr.eval(ExprGen.env), expr.aeval(ExprGen.env)) })\n    }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/test/scala/expr/ScalaCodeSpec.scala",
    "content": "package expr\n\nimport org.scalatest.Spec\nimport org.scalatest.matchers.ShouldMatchers\n\nclass ScalaCodeSpec extends Spec with ShouldMatchers {\n  it(\"allows easy construction of functions of no arguments\") {\n    val code = ScalaCode.define0(\"\") { 42 }\n    expect(42) { code.eval(Env.empty, List()) }\n  }\n\n  it(\"allows easy construction of functions of one argument\") {\n    val code = ScalaCode.define1(\"\") { a => a * 2 }\n    expect(4) { code.eval(Env.empty, List(2)) }\n  }\n\n  it(\"allows easy construction of functions of two arguments\") {\n    val code = ScalaCode.define2(\"\") { (a, b) => a + b }\n    expect(3) { code.eval(Env.empty, List(1, 2)) }\n  }\n\n  it(\"allows easy construction of functions of three arguments\") {\n    val code = ScalaCode.define3(\"\") { (a, b, c) => a + b * c }\n    expect(7) { code.eval(Env.empty, List(1, 2, 3)) }\n  }\n\n  it(\"can be converted to a string that contains its docstring\") {\n    val code = ScalaCode.define0(\"fun()\") { 42 }\n    expect(\"<ScalaCode:fun()>\") { code.toString }\n  }\n\n  it(\"raises an error when not invoked with the right number of arguments\") {\n    val code = ScalaCode.define2(\"\") { (a, b) => a + b }\n    intercept[ExprException] { code.eval(Env.empty, List(1, 2, 3)) }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/test/scala/expr/repl/CommandSpec.scala",
    "content": "package expr.repl\n\nimport org.scalatest.Spec\nimport org.scalatest.matchers.ShouldMatchers\n\nimport Command._\n\nclass CommandSpec extends Spec with ShouldMatchers {\n  it(\"parses 'exit' as the Exit() command\") {\n    expect(Exit()) { Command.parse(\"exit\") }\n  }\n\n  it(\"parses 'names' as the ShowEnv() command\") {\n    expect(ShowEnv()) { Command.parse(\"names\") }\n  }\n\n  it(\"parses '1 + 2' as an Eval(1 + 2)\") {\n    expect(Eval(Num(1) + Num(2))) { Command.parse(\"1 + 2\") }\n  }\n\n  it(\"parses 'X = 1 + 2' as an Assign(X, 1 + 2)\") {\n    expect(Assign(\"X\", Num(1) + Num(2))) { Command.parse(\"X = 1 + 2\") }\n  }\n\n  it(\"parses 'add = lambda(X, Y) { X + Y }' add Define(add, Lambda(..))\") {\n    val lambda = Lambda(List(\"X\", \"Y\"), Name(\"X\") + Name(\"Y\"))\n    expect(Define(\"add\", lambda)) { Command.parse(\"add = lambda(X, Y) { X + Y }\") }\n  }\n\n  it(\"throws an exception when command cannot be parsed\") {\n    intercept[BadInputException] { Command.parse(\"+++\") }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/test/scala/expr/repl/REPLSpec.scala",
    "content": "package expr.repl\n\nimport org.scalatest.Spec\nimport org.scalatest.matchers.ShouldMatchers\n\nclass REPLSpec extends Spec with ShouldMatchers {\n  def lastMessageInSession(inputs: String*): String = {\n    val shell = new RecordedShell(inputs ++ List(\"exit\"): _*)\n    new REPL(shell).start()\n    shell.lastMessage\n  }\n\n  it(\"evaluates an expression if given\") {\n    expect(\"= 3.0\") { lastMessageInSession(\"1 + 2\") }\n  }\n\n  it(\"evaluates expressions in the defined context\") {\n    expect(\"= 3.0\") { lastMessageInSession(\"X = 1\", \"Y = 2\", \"X + Y\") }\n  }\n\n  it(\"evaluates function definitions\") {\n    expect(\"= 3.0\") { lastMessageInSession(\"add = lambda(X, Y) { X + Y }\", \"add(1, 2)\") }\n  }\n\n  it(\"lists the environment when requested\") {\n    expect(\"X = 1.0\") { lastMessageInSession(\"X = 1\", \"names\") }\n  }\n\n  it(\"displays an error when given an unparsable expression\") {\n    expect(\"ERROR: Unparsable input\") { lastMessageInSession(\"+++\") }\n  }\n\n  it(\"displays an error when refering to an unknown variable\") {\n    expect(\"ERROR: Undefined variable: X\") { lastMessageInSession(\"X + 1\") }\n  }\n\n  it(\"displays an error when calling an unknown function\") {\n    expect(\"ERROR: Undefined function: foo\") { lastMessageInSession(\"foo()\") }\n  }\n\n  it(\"displays an error when trying to define a function with free variables\") {\n    expect(\"ERROR: Lambda contains free variables: Y\") { lastMessageInSession(\"foo = lambda(X) { X + Y }\") }\n  }\n\n  it(\"displays an error when a function is called with the wrong number of arguments\") {\n    expect(\"ERROR: Lambda expects 1 argument(s), but was called with 0\") {\n      lastMessageInSession(\"x = lambda(X) { X }\", \"x()\")\n    }\n  }\n}\n"
  },
  {
    "path": "scala/expr/src/test/scala/expr/repl/RecordingShell.scala",
    "content": "package expr.repl\n\nclass RecordedShell(playback: String*) extends Shell {\n  var inputs = playback.toArray\n  var outputBuffer = \"\"\n\n  def read(): String = {\n    if (inputs.isEmpty)\n      throw new IllegalStateException(\"Inputs already consumed\")\n\n    val result = inputs(0)\n    inputs = inputs.drop(1)\n    return result\n  }\n\n  def write(output: String) = outputBuffer += output\n\n  def messages = outputBuffer.split(\"\\n\")\n  def lastMessage = messages.last\n}\n"
  },
  {
    "path": "scala/programming_in_scala/.gitignore",
    "content": "*.class\n*.log\n\n# sbt specific\ndist/*\ntarget/\nlib_managed/\nsrc_managed/\nproject/boot/\nproject/plugins/project/\n\n"
  },
  {
    "path": "scala/programming_in_scala/README",
    "content": "A playground for the code in \"Programming in Scala\"\n\nRuns on scala 2.7.7 with sbt\n"
  },
  {
    "path": "scala/programming_in_scala/project/build/ProgrammingInScala.scala",
    "content": "import sbt._\nclass ProgrammingInScalaProject(info: ProjectInfo) extends DefaultProject(info) {\n  val scalatest = \"org.scalatest\" % \"scalatest\" % \"1.1\"\n}\n"
  },
  {
    "path": "scala/programming_in_scala/project/build.properties",
    "content": "#Project properties\n#Tue Nov 30 21:57:58 CET 2010\nproject.organization=skanev.com\nproject.name=Programming in Scala playground\nsbt.version=0.7.4\nproject.version=1.0\nbuild.scala.versions=2.7.7\nproject.initialize=false\n"
  },
  {
    "path": "scala/programming_in_scala/src/main/scala/actorsimulation/Adders.scala",
    "content": "package actorsimulation\n\ntrait Adders extends Circuit {\n  def halfAdder(a: Wire, b: Wire, s: Wire, c: Wire) {\n    val d, e = new Wire\n    orGate(a, b, d)\n    andGate(a, b, c)\n    inverter(c, e)\n    andGate(d, e, s)\n  }\n\n  def fullAdder(a: Wire, b: Wire, cin: Wire, sum: Wire, cout: Wire) {\n    val s, c1, c2 = new Wire\n    halfAdder(a, cin, s, c1)\n    halfAdder(b, s, sum, c2)\n    orGate(c1, c2, cout)\n  }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/main/scala/actorsimulation/Circuit.scala",
    "content": "package actorsimulation\n\nimport scala.actors.Actor\n\nclass Circuit {\n  val clock = new Clock\n\n  val WireDelay = 1\n  val InvertedDelay = 2\n  val OrGateDelay = 3\n  val AndGateDelay = 3\n\n  case class SetSignal(sig: Boolean)\n  case class SignalChanged(wire: Wire, sig: Boolean)\n\n  class Wire(name: String, init: Boolean) extends Simulant {\n    def this(name: String) { this(name, false) }\n    def this() { this(\"unnamed\") }\n\n    val clock = Circuit.this.clock\n    clock.add(this)\n\n    private var sigVal = init\n    private var observers: List[Actor] = List()\n\n    def handleSimMessage(msg: Any) {\n      msg match {\n        case SetSignal(s) =>\n          if (s != sigVal) {\n            sigVal = s\n            signalObservers()\n          }\n      }\n    }\n\n    def signalObservers() {\n      for (observer <- observers)\n        clock ! AfterDelay(WireDelay, SignalChanged(this, sigVal), observer)\n    }\n\n    override def simStarting() { signalObservers() }\n\n    def addObserver(observer: Actor) {\n      observers = observer :: observers\n    }\n\n    override def toString = \"Wire(\" + name + \")\"\n  }\n\n  private object DummyWire extends Wire(\"dummy\")\n\n  abstract class Gate(in1: Wire, in2: Wire, out: Wire) extends Simulant {\n    def computeOutput(s1: Boolean, s2: Boolean): Boolean\n    val delay: Int\n\n    val clock = Circuit.this.clock\n    clock.add(this)\n\n    in1.addObserver(this)\n    in2.addObserver(this)\n\n    var s1, s2 = false\n\n    def handleSimMessage(msg: Any) {\n      msg match {\n        case SignalChanged(w, sig) => \n          if (w == in1) s1 = sig\n          if (w == in2) s2 = sig\n          clock ! AfterDelay(delay, SetSignal(computeOutput(s1, s2)), out)\n      }\n    }\n  }\n\n  def orGate(in1: Wire, in2: Wire, output: Wire) =\n    new Gate(in1, in2, output) {\n      val delay = OrGateDelay\n      def computeOutput(s1: Boolean, s2: Boolean) = s1 || s2\n    }\n\n  def andGate(in1: Wire, in2: Wire, output: Wire) =\n    new Gate(in1, in2, output) {\n      val delay = AndGateDelay\n      def computeOutput(s1: Boolean, s2: Boolean) = s1 && s2\n    }\n\n  def inverter(input: Wire, output: Wire) =\n    new Gate(input, DummyWire, output) {\n      val delay = InvertedDelay\n      def computeOutput(s1: Boolean, s2: Boolean) = !s1\n    }\n\n  def probe(wire: Wire) = new Simulant {\n    val clock = Circuit.this.clock\n    clock.add(this)\n    wire.addObserver(this)\n    def handleSimMessage(msg: Any) {\n      msg match {\n        case SignalChanged(wire, signalValue) =>\n          println(\"singal \" + wire + \" changed to \" + signalValue)\n      }\n    }\n  }\n\n  def start() { clock ! Start }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/main/scala/actorsimulation/Clock.scala",
    "content": "package actorsimulation\n\nimport scala.actors.Actor\nimport scala.actors.Actor._\n\ncase class Ping(time: Int)\ncase class Pong(time: Int, from: Actor)\n\ncase class WorkItem(time: Int, msg: Any, target: Actor)\ncase class AfterDelay(delay: Int, msg: Any, targe: Actor)\n\ncase object Start\ncase object Stop\n\nclass Clock extends Actor {\n  private var running = false\n  private var currentTime = 0\n  private var agenda: List[WorkItem] = List()\n  private var allSimulants: List[Actor] = List()\n  private var busySimulants: Set[Actor] = Set.empty\n\n  start()\n\n  def add(simulant: Actor) {\n    allSimulants = simulant :: allSimulants\n  }\n\n  def act() {\n    loop {\n      if (running && busySimulants.isEmpty)\n        advance()\n\n      reactToOneMessage()\n    }\n  }\n\n  private def advance() {\n    if (agenda.isEmpty && currentTime > 0) {\n      println(\"** Agenda empty. Clock time exiting at time \" + currentTime + \".\")\n      self ! Stop\n      return\n    }\n\n    currentTime += 1\n    println(\"Advancing to time \" + currentTime)\n\n    processCurrentEvents()\n    for (sim <- allSimulants)\n      sim ! Ping(currentTime)\n\n    busySimulants = Set.empty ++ allSimulants\n  }\n\n  private def processCurrentEvents() {\n    val todoNow = agenda.takeWhile(_.time <= currentTime)\n\n    agenda = agenda.drop(todoNow.length)\n\n    for(WorkItem(time, msg, target) <- todoNow) {\n      assert(time == currentTime)\n      target ! msg\n    }\n  }\n\n  private def reactToOneMessage() {\n    react {\n      case AfterDelay(delay, msg, target) =>\n        val item = WorkItem(currentTime + delay, msg, target)\n        agenda = insert(agenda, item)\n\n      case Pong(time, sim) =>\n        assert(time == currentTime)\n        assert(busySimulants contains sim)\n        busySimulants -= sim\n\n      case Start => running = true\n\n      case Stop =>\n        for (sim <- allSimulants)\n          sim ! Stop\n        exit()\n    }\n  }\n\n  private def insert(agenda: List[WorkItem], item: WorkItem): List[WorkItem] = {\n    if (agenda.isEmpty || item.time < agenda.head.time) item :: agenda\n    else agenda.head :: insert(agenda.tail, item)\n  }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/main/scala/actorsimulation/Demo.scala",
    "content": "package actorsimulation\n\nobject Demo {\n  def main(args: Array[String]) {\n    val circuit = new Circuit with Adders\n    import circuit._\n\n    val ain = new Wire(\"ain\", true)\n    val bin = new Wire(\"bin\", false)\n    val cin = new Wire(\"cin\", true)\n    val sout = new Wire(\"sout\")\n    val cout = new Wire(\"cout\")\n\n    probe(ain)\n    probe(bin)\n    probe(cin)\n    probe(sout)\n    probe(cout)\n\n    fullAdder(ain, bin, cin, sout, cout)\n\n    circuit.start()\n  }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/main/scala/actorsimulation/Simulant.scala",
    "content": "package actorsimulation\n\nimport scala.actors.Actor\nimport scala.actors.Actor._\n\ntrait Simulant extends Actor {\n  val clock: Clock\n\n  start()\n\n  def handleSimMessage(msg: Any)\n  def simStarting() { }\n\n  def act() {\n    loop {\n      react {\n        case Stop => exit()\n        case Ping(time) =>\n          if (time == 1) simStarting()\n          clock ! Pong(time, self)\n        case msg => handleSimMessage(msg)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/main/scala/arithmetic/Expr.scala",
    "content": "package arithmetic\n\nimport layout.Element\nimport layout.Element.elem\n\nsealed abstract class Expr\ncase class Var(name: String) extends Expr\ncase class Number(num: Double) extends Expr\ncase class UnOp(operator: String, arg: Expr) extends Expr\ncase class BinOp(operator: String, left: Expr, right: Expr) extends Expr\n\nobject Expr {\n  def simplify: (Expr => Expr) = {\n    case UnOp(\"-\", UnOp(\"-\", e)) => e\n    case BinOp(\"+\", e, Number(0)) => e\n    case BinOp(\"*\", e, Number(1)) => e\n    case BinOp(\"*\", e, Number(0)) => Number(0)\n    case BinOp(\"+\", x, y) if x == y => BinOp(\"*\", x, Number(2))\n    case UnOp(o, e) => UnOp(o, simplify(e))\n    case BinOp(o, l, r) => BinOp(o, simplify(l), simplify(r))\n    case e => e\n  }\n}\n\nclass ExprFormatter {\n  private val opGroups =\n    Array(\n      Set(\"|\", \"||\"),\n      Set(\"&\", \"&&\"),\n      Set(\"^\"),\n      Set(\"==\", \"!=\"),\n      Set(\"<\", \"<=\", \">\", \">=\"),\n      Set(\"+\", \"-\"),\n      Set(\"*\", \"%\")\n    )\n\n  private val precendence = {\n    val assocs =\n      for {\n        i <- 0 until opGroups.length\n        op <- opGroups(i)\n      } yield op -> i\n    Map() ++ assocs\n  }\n\n  private val unaryPrecendence = opGroups.length\n  private val fractionPrecendence = -1\n\n  private def format(e: Expr, enclPrec: Int): Element =\n    e match {\n      case Var(name) => elem(name)\n      case Number(num) => elem(num.toString.replaceAll(\".0$\", \"\"))\n      case UnOp(op, arg) => elem(op) beside format(arg, unaryPrecendence)\n      case BinOp(\"/\", left, right) => \n        val top = format(left, fractionPrecendence)\n        val bottom = format(right, fractionPrecendence)\n        val line = elem('-', top.width max bottom.width, 1)\n        val frac = top above line above bottom\n        if (enclPrec != fractionPrecendence) frac\n        else elem(\" \") beside frac beside elem(\" \")\n      case BinOp(op, left, right) => \n        val opPrec = precendence(op)\n        val l = format(left, opPrec)\n        val r = format(right, opPrec)\n        val oper = l beside elem(\" \" + op + \" \") beside r\n        if (enclPrec <= opPrec) oper\n        else elem(\"(\") beside oper beside elem(\")\")\n    }\n\n  def format(e: Expr): Element = format(e, 0)\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/main/scala/layout/Element.scala",
    "content": "package layout\n\nobject Element {\n  private class ArrayElement(\n    val contents: Array[String]\n  ) extends Element\n\n  private class LineElement(line: String) extends Element {\n    def contents = Array(line)\n  }\n\n  private class UniformElement(\n    val fill: Char,\n    override val width: Int,\n    override val height: Int\n  ) extends Element {\n    def contents = Array.make(height, fill.toString * width)\n  }\n\n  def elem(lines: Array[String]): Element =\n    new ArrayElement(lines)\n  def elem(line: String): Element =\n    new LineElement(line)\n  def elem(fill: Char, width: Int, height: Int): Element =\n    new UniformElement(fill, width, height)\n}\n\nimport Element.elem\n\nabstract class Element {\n  def contents: Array[String]\n  def width = if (contents.isEmpty) 0 else contents(0).length\n  def height = contents.size\n  override def toString = contents.mkString(\"\\n\")\n\n  def above(that: Element): Element = {\n    val adjustedThis = this widen that.width\n    val adjustedThat = that widen this.width\n    elem(adjustedThis.contents ++ adjustedThat.contents)\n  }\n\n  def beside(that: Element): Element = {\n    val adjustedThis = this heighten that.height\n    val adjustedThat = that heighten this.height\n    elem(\n      for (\n        (line1, line2) <- adjustedThis.contents zip adjustedThat.contents\n      ) yield line1 + line2\n    )\n  }\n\n  def widen(w: Int): Element = {\n    if (w <= width) this\n    else {\n      val left = elem(' ', (w - width) / 2, height)\n      val right = elem(' ', w - width - left.width, height)\n      left beside this beside right\n    }\n  }\n\n  def heighten(h: Int): Element = {\n    if (h <= height) this\n    else {\n      val top = elem(' ', width, (h - height) / 2)\n      val bottom = elem(' ', width, h - height - top.height)\n      top above this above bottom\n    }\n  }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/main/scala/layout/Spiral.scala",
    "content": "package layout\n\nimport Element.elem\n\nobject Spiral {\n  val space = elem(\" \")\n  val corner = elem(\"+\")\n\n  def spiral(edges: Int): Element = spiral(edges, 0)\n  def spiral(edges: Int, direction: Int): Element = {\n    if (edges == 1)\n      elem(\"+\")\n    else {\n      val innerSpiral = spiral(edges - 1, (direction + 3) % 4)\n      def verticalBar = elem('|', 1, innerSpiral.height)\n      def horizontalBar = elem('-', innerSpiral.width, 1)\n      direction match {\n        case 0 => (corner beside horizontalBar) above (innerSpiral beside space)\n        case 1 => (innerSpiral above space) beside (corner above verticalBar)\n        case 2 => (space beside innerSpiral) above (horizontalBar beside corner)\n        case _ => (verticalBar above corner) beside (space above innerSpiral)\n      }\n    }\n  }\n\n  def main(args: Array[String]) {\n    val sides = args(0).toInt\n    println(spiral(sides))\n  }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/main/scala/simulation/BasicCircuitSimulation.scala",
    "content": "package simulation\n\nabstract class BasicCircuitSimulation extends Simulation {\n  def InverterDelay: Int\n  def AndGateDelay: Int\n  def OrGateDelay: Int\n\n  class Wire {\n    private var sigVal = false\n    private var actions: List[Action] = List()\n\n    def getSignal = sigVal\n\n    def setSignal(s: Boolean) =\n      if (s != sigVal) {\n        sigVal = s\n        actions foreach (_ ())\n      }\n\n    def addAction(a: Action) = {\n      actions = a ::actions\n      a()\n    }\n  }\n\n  def inverter(input: Wire, output: Wire) = {\n    def inverterAction() {\n      val inputSig = input.getSignal\n      afterDelay(InverterDelay) {\n        output setSignal !inputSig\n      }\n    }\n    input addAction inverterAction\n  }\n\n  def andGate(a1: Wire, a2: Wire, output: Wire) = {\n    def andGateAction() {\n      val a1Sig = a1.getSignal\n      val a2Sig = a2.getSignal\n      afterDelay(AndGateDelay) {\n        output setSignal (a1Sig & a2Sig)\n      }\n    }\n    a1 addAction andGateAction\n    a2 addAction andGateAction\n  }\n\n  def orGate(o1: Wire, o2: Wire, output: Wire) = {\n    def orGateAction() {\n      val o1Sig = o1.getSignal\n      val o2Sig = o2.getSignal\n      afterDelay(OrGateDelay) {\n        output setSignal (o1Sig | o2Sig)\n      }\n    }\n    o1 addAction orGateAction\n    o2 addAction orGateAction\n  }\n\n  def probe(name: String, wire: Wire) {\n    def probeAction() {\n      println(name + \" \" + currentTime + \" new-value = \" + wire.getSignal)\n    }\n    wire addAction probeAction\n  }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/main/scala/simulation/CircuitSimulation.scala",
    "content": "package simulation\n\nabstract class CircuitSimulation extends BasicCircuitSimulation {\n  def halfAdder(a: Wire, b: Wire, s: Wire, c: Wire) {\n    val d, e = new Wire\n    orGate(a, b, d)\n    andGate(a, b, c)\n    inverter(c, e)\n    andGate(d, e, s)\n  }\n\n  def fullAdder(a: Wire, b: Wire, cin: Wire, sum: Wire, cout: Wire) {\n    val s, c1, c2 = new Wire\n    halfAdder(a, cin, s, c1)\n    halfAdder(b, s, sum, c2)\n    orGate(c1, c2, cout)\n  }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/main/scala/simulation/Simulation.scala",
    "content": "package simulation\n\nabstract class Simulation {\n  type Action = () => Unit\n\n  case class WorkItem(time: Int, action: Action)\n\n  private var curtime = 0\n  def currentTime: Int = curtime\n\n  private var agenda: List[WorkItem] = List()\n\n  private def insert(agenda: List[WorkItem], item:WorkItem): List[WorkItem] = {\n    if (agenda.isEmpty || item.time < agenda.head.time) item :: agenda\n    else agenda.head :: insert(agenda.tail, item)\n  }\n\n  def afterDelay(delay: Int)(block: => Unit) {\n    var item = WorkItem(currentTime + delay, () => block)\n    agenda = insert(agenda, item)\n  }\n\n  private def next() {\n    (agenda: @unchecked) match {\n      case item :: rest =>\n        agenda = rest\n        curtime = item.time\n        item.action()\n    }\n  }\n\n  def run() {\n    afterDelay(0) {\n      println(\"*** simulation started, time = \" + currentTime + \"***\")\n    }\n    while (!agenda.isEmpty) next()\n  }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/main/scala/simulation/StairwayBookSimulation.scala",
    "content": "package simulation\n\nobject StairwayBookSimulation extends CircuitSimulation {\n  def InverterDelay = 1\n  def AndGateDelay = 3\n  def OrGateDelay = 5\n\n  def main(args: Array[String]) = {\n    var input1, input2, sum, carry = new Wire\n    probe(\"sum\", sum)\n    probe(\"carry\", carry)\n    halfAdder(input1, input2, sum, carry)\n    input1 setSignal true\n    run()\n    input2 setSignal true\n    run()\n  }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/test/scala/arithmetic/ExprFormatterSpec.scala",
    "content": "package arithmetic\n\nimport org.scalatest.Spec\nimport org.scalatest.matchers.ShouldMatchers\n\nclass ExprFormatterSpec extends Spec with ShouldMatchers {\n  describe(\"ExprFormatter.format\") {\n    def draw(e: Expr): String = new ExprFormatter().format(e).toString\n\n    it(\"can draw a + (b + c)\") {\n      draw(BinOp(\"+\", Var(\"a\"), BinOp(\"+\", Var(\"b\"), Var(\"c\")))) should equal (\"a + b + c\")\n    }\n\n    it(\"can draw (a / b) / c\") {\n      draw(BinOp(\"/\", BinOp(\"/\", Var(\"a\"), Var(\"b\")), Var(\"c\"))) should equal (\n        \"\"\"| a \n           | - \n           | b \n           |---\n           | c \"\"\".stripMargin\n      )\n    }\n\n    it(\"can draw x / x + 1\") {\n      draw(BinOp(\"/\", Var(\"x\"), BinOp(\"+\", Var(\"x\"), Number(1)))) should equal (\n        \"\"\"|  x  \n           |-----\n           |x + 1\"\"\".stripMargin\n      )\n    }\n\n    it(\"can draw ((a / (b * c) + 1 / n) / 3)\") {\n      draw(BinOp(\"/\", BinOp(\"+\", BinOp(\"/\", Var(\"a\"), BinOp(\"*\", Var(\"b\"), Var(\"c\"))),\n                                 BinOp(\"/\", Number(1), Var(\"n\"))),\n                      Number(3))\n      ) should equal (\n        \"\"\"|  a     1\n           |----- + -\n           |b * c   n\n           |---------\n           |    3    \"\"\".stripMargin\n      )\n    }\n\n    it(\"can draw ((1 / 2) * (x + 1)) / ((x / 2) + (1.5 / x))\") {\n      draw(BinOp(\"/\", BinOp(\"*\", BinOp(\"/\", Number(1), Number(2)),\n                                 BinOp(\"+\", Var(\"x\"), Number(1))),\n                      BinOp(\"+\", BinOp(\"/\", Var(\"x\"), Number(2)),\n                                 BinOp(\"/\", Number(1.5), Var(\"x\"))))\n      ) should equal (\n        \"\"\"|1          \n           |- * (x + 1)\n           |2          \n           |-----------\n           |  x   1.5  \n           |  - + ---  \n           |  2    x   \"\"\".stripMargin\n      )\n    }\n  }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/test/scala/arithmetic/SimplificationSpec.scala",
    "content": "package arithmetic\n\nimport org.scalatest.Spec\nimport org.scalatest.matchers.ShouldMatchers\n\nimport Expr.simplify\n\nclass SimplificationSpec extends Spec with ShouldMatchers {\n  describe(\"Expr.simplify(expr)\") {\n    it(\"simplifies -(-1)) to 1\") {\n      simplify(UnOp(\"-\", UnOp(\"-\", Number(1)))) should equal (Number(1))\n    }\n\n    it(\"simplifies e+0 to e\") {\n      simplify(BinOp(\"+\", Var(\"e\"), Number(0))) should equal (Var(\"e\"))\n    }\n\n    it(\"simplifies e*1 to e\") {\n      simplify(BinOp(\"*\", Var(\"e\"), Number(1))) should equal (Var(\"e\"))\n    }\n\n    it(\"simplifies e*0 to 0\") {\n      simplify(BinOp(\"*\", Var(\"e\"), Number(0))) should equal (Number(0))\n    }\n\n    it(\"'simplifies' (a+b)+(a+b) to (a+b)*2\") {\n      simplify(BinOp(\"+\",\n        BinOp(\"+\", Var(\"a\"), Var(\"b\")),\n        BinOp(\"+\", Var(\"a\"), Var(\"b\"))\n      )) should equal (BinOp(\"*\",\n        BinOp(\"+\", Var(\"a\"), Var(\"b\")),\n        Number(2)))\n    }\n\n    it(\"simplifies log((-(-1)) + (x+0)) to log(1)\") {\n      simplify(UnOp(\"log\",\n        BinOp(\"+\",\n          UnOp(\"-\", UnOp(\"-\", Number(1))),\n          BinOp(\"+\", Var(\"x\"), Number(0))))\n      ) should equal (UnOp(\"log\", BinOp(\"+\", Number(1), Var(\"x\"))))\n    }\n  }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/test/scala/layout/CompositionSpec.scala",
    "content": "package layout\n\nimport org.scalatest.Spec\nimport org.scalatest.matchers.ShouldMatchers\nimport Element.elem\n\nclass CompositionSpec extends Spec with ShouldMatchers {\n  it(\".widen(w: Int) pads the element with spaces until it reaches width w\") {\n    elem(\"x\").widen(3).toString should equal (\" x \")\n    elem(\"x\").widen(4).toString should equal (\" x  \")\n    elem(Array(\"1\", \"2\")).widen(3).toString should equal(\" 1 \\n 2 \")\n  }\n\n  it(\".heighten(h: Int) pads the element with spaces until it reaches height h\") {\n    elem(\"x\").heighten(3).toString should equal (\" \\nx\\n \")\n    elem(\"x\").heighten(2).toString should equal (\"x\\n \")\n    elem(\"12345\").heighten(2).toString should equal (\"\"\"|12345\n                                                        |     \"\"\".stripMargin)\n  }\n\n  describe(\".above\") {\n    it(\"put one element above the other\") {\n      (elem(\"12\") above elem(\"34\")).toString should equal (\"12\\n34\")\n    }\n\n    it(\"allows for elements of different size\") {\n      val composition = elem(\"1234\").above(elem(\"12\")).toString\n      composition should equal (\"\"\"|1234\n                                   | 12 \"\"\".stripMargin)\n    }\n  }\n\n  describe(\".beside\") {\n    it(\"puts two elements next to each other\") {\n      (elem(Array(\"1\", \"2\")) beside elem(Array(\"3\", \"4\"))).toString should equal (\"13\\n24\")\n    }\n\n    it(\"allows for elements of different sizes\") {\n      val composition = elem(\"one \").beside(elem(Array(\"one\", \"two\"))).toString\n      composition should equal (\"\"\"|one one\n                                   |    two\"\"\".stripMargin)\n    }\n  }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/test/scala/layout/FactoryMethodsSpec.scala",
    "content": "package layout\n\nimport org.scalatest.Spec\nimport org.scalatest.matchers.ShouldMatchers\nimport Element.elem\n\nclass FactoryMethodsSpec extends Spec with ShouldMatchers {\n  describe(\"Element.elem(lines: Array[String]\") {\n    it(\"constructs an element from multiple lines of text\") {\n      elem(Array(\"aaa\", \"bbb\", \"ccc\")).toString should equal (\"aaa\\nbbb\\nccc\")\n    }\n\n    it(\"constructs an element as wide as the first string in lines\") {\n      elem(Array(\"12345\", \"54321\")).width should equal (5)\n    }\n\n    it(\"constructs an element with width equal to 0 if lines is empty\") {\n      elem(Array[String]()).width should equal (0)\n    }\n\n    it(\"constructs an element with height equal to the length of lines\") {\n      elem(Array(\"1\", \"2\", \"3\")).height should equal (3)\n    }\n  }\n\n  describe(\"Element.elem(line: String\") {\n    it(\"constructs a one-row element from line\") {\n      elem(\"12345\").toString should equal (\"12345\")\n    }\n\n    it(\"constructs an element as wide as line\") {\n      elem(\"12345\").width should equal (5)\n    }\n\n    it(\"constructs an element with height 1\") {\n      elem(\"something\").height should equal (1)\n    }\n  }\n\n  describe(\"Element.elem(fill: Char, width: Int, height: Int)\") {\n    it(\"constructs a width x height block, filled uniformly with fill\") {\n      elem('o', 3, 2).toString should equal (\"ooo\\nooo\")\n    }\n\n    it(\"constructs an element with the given width\") {\n      elem('o', 3, 2).width should equal (3)\n    }\n\n    it(\"constructs an element with the given height\") {\n      elem('o', 3, 2).height should equal (2)\n    }\n  }\n}\n"
  },
  {
    "path": "scala/programming_in_scala/src/test/scala/layout/SpiralSpec.scala",
    "content": "package layout\n\nimport org.scalatest.Spec\nimport org.scalatest.matchers.ShouldMatchers\n\nclass SpiralSpec extends Spec with ShouldMatchers {\n  def spiral(edges: Int) = Spiral.spiral(edges).toString\n\n  it(\"renders spirals with 6 edges\") {\n    spiral(6) should equal (\"\"\":+-----\n                               :|     \n                               :| +-+ \n                               :| + | \n                               :|   | \n                               :+---+ \"\"\".stripMargin(':'))\n  }\n\n  it(\"renders a spiral with 11 edges\") {\n    spiral(11) should equal (\"\"\":+----------\n                                :|          \n                                :| +------+ \n                                :| |      | \n                                :| | +--+ | \n                                :| | |  | | \n                                :| | ++ | | \n                                :| |    | | \n                                :| +----+ | \n                                :|        | \n                                :+--------+ \"\"\".stripMargin(':'))\n  }\n\n  it(\"renders a spiral with 17 edges\") {\n    spiral(17) should equal (\"\"\":+----------------\n                                :|                \n                                :| +------------+ \n                                :| |            | \n                                :| | +--------+ | \n                                :| | |        | | \n                                :| | | +----+ | | \n                                :| | | |    | | | \n                                :| | | | ++ | | | \n                                :| | | |  | | | | \n                                :| | | +--+ | | | \n                                :| | |      | | | \n                                :| | +------+ | | \n                                :| |          | | \n                                :| +----------+ | \n                                :|              | \n                                :+--------------+ \"\"\".stripMargin(':'))\n  }\n}\n"
  },
  {
    "path": "scheme/eopl/.gitignore",
    "content": "Gemfile.lock\n"
  },
  {
    "path": "scheme/eopl/.ruby-version",
    "content": "2.3.3\n"
  },
  {
    "path": "scheme/eopl/.rvmrc",
    "content": "rvm --create 1.9.3@eopl\n"
  },
  {
    "path": "scheme/eopl/01/01.scm",
    "content": "; EOPL exercise 1.01\n;\n; Write inductive definitions of the following sets. Write each definition in\n; all tree styles (top-down, bottom-up, and rules of inference). Using your\n; rules, show the derivation of some sample elements of each set.\n;\n; 1. {3n + 2 | n ∈ N}\n; 2. {2n + 3m + 1 | m, n ∈ N}\n; 3. {(n, 2n + 1) | n ∈ N}\n; 4. {(n, n²) | n ∈ N} Do not mention squaring in your rules. As a hint,\n;    remember the equation (n + 1)² = n² + 2n + 1\n\n; 1. {3n + 2 | m ∈ N}\n;\n;    top-down:\n;\n;      A natural number k is in S if and only if\n;      1. k = 2, or\n;      2. k - 3 ∈ S.\n;\n;    bottom-up:\n;\n;      Define the set S to be the smallest set contained in N and satisfying\n;      the following two properties:\n;      1. 2 ∈ S, and\n;      3. if k ∈ S, then k + 3 ∈ S.\n;\n;    rules of inference:\n;\n;         ─────\n;         2 ∈ S\n;\n;         k ∈ S\n;      ───────────\n;      (k + 3) ∈ S\n;\n;    sample derivation:\n;\n;      2 ∈ S\n;      ─────\n;      5 ∈ S\n;      ─────\n;      8 ∈ S\n;\n; 2. {2n + 3m + 1 | m, n ∈ N}\n;\n;    top-down:\n;\n;      A natural number k is in S if and only if\n;      1. k = 1, or\n;      2. k - 2 ∈ S, or\n;      3. k - 3 ∈ S.\n;\n;    bottom-up:\n;\n;      Define the set S to be the smallest set contained in N and satisfying\n;      the following three properties:\n;      1. 1 ∈ S, or\n;      2. if k ∈ S, then k + 2 ∈ S, or\n;      3. if k ∈ S, then k + 3 ∈ S.\n;\n;    rules of inference:\n;\n;         ─────\n;         1 ∈ S\n;\n;         k ∈ S\n;      ───────────\n;      (k + 2) ∈ S\n;\n;         k ∈ S\n;      ───────────\n;      (k + 3) ∈ S\n;\n;    sample derivation:\n;\n;       1 ∈ S\n;       ─────\n;       3 ∈ S\n;       ─────\n;       6 ∈ S\n;       ─────\n;       8 ∈ S\n;      ──────\n;      11 ∈ S\n;\n; 3. {(n, 2n + 1) | n ∈ N}\n;\n;    top-down:\n;\n;      A two-element list (a, b) is in S if and only if\n;      1. a = 0, b = 1, or\n;      2. (a - 1, b - 2) ∈ S.\n;\n;    bottom-up:\n;\n;      The set S is the smallest set of Scheme lists with two elements\n;      satisfying the following two properties:\n;      1. (0, 1) ∈ S\n;      2. if (a, b) ∈ S, then (a + 1, b + 2) ∈ S\n;\n;    rules of inference:\n;\n;          ──────────\n;          (0, 1) ∈ S\n;\n;          (a, b) ∈ S\n;      ──────────────────\n;      (a + 1, b + 2) ∈ S\n;\n;    sample derivation:\n;\n;      (0, 1) ∈ S\n;      ──────────\n;      (1, 3) ∈ S\n;      ──────────\n;      (2, 5) ∈ S\n;      ──────────\n;      (3, 8) ∈ S\n;\n; 4. {(n, n²) | n ∈ N}\n;\n;    top-down:\n;\n;      A two-element list (a, b) is in S if and only if\n;      1. a = 0, b = 0, or\n;      2. (a - 1, b - 2a - 1) ∈ S.\n;\n;    bottom-up:\n;\n;      The set S is the smallest set of Scheme lists with two elements\n;      satisfying the following two properties:\n;      1. (0, 1) ∈ S\n;      2. if (a, b) ∈ S, then (a + 1, b + 2a + 1) ∈ S\n;\n;    rules of inference:\n;\n;             ──────────\n;             (0, 0) ∈ S\n;\n;             (a, b) ∈ S\n;      ───────────────────────\n;      (a + 1, b + 2a + 1) ∈ S\n;\n;    sample derivation:\n;\n;      (0, 0) ∈ S\n;      ──────────\n;      (1, 1) ∈ S\n;      ──────────\n;      (2, 4) ∈ S\n;      ──────────\n;      (3, 9) ∈ S\n"
  },
  {
    "path": "scheme/eopl/01/02.scm",
    "content": "; EOPL exercise 1.02\n;\n; What sets are defined by the following pairs of rules? Explain why.\n;\n;                     (n, k) ∈ S\n; 1. (0, 1) ∈ S   ──────────────────\n;                 (n + 1, k + 7) ∈ S\n;\n;                    (n, k) ∈ S\n; 2. (0, 1) ∈ S   ───────────────\n;                 (n + 1, 2k) ∈ S\n;\n;                        (n, i, j) ∈ S\n; 3. (0, 0, 1) ∈ S   ─────────────────────\n;                    (n + 1, j, i + j) ∈ S\n;\n;                          (n, i, j) ∈ S\n; 4. (0, 1, 0) ∈ S   ─────────────────────────\n;                    (n + 1, i + 2, i + j) ∈ S\n\n; 1. This is the set of (n, 7n + 1) for n ∈ N. It is rather obvious why.\n;\n; 2. This is the set (n, 2ⁿ). You can tell that the first element grows in\n;    increments of (like f(n) = n) and the second gets multiplied by two on\n;    every iteration (like f(n) = 2ⁿ).\n;\n; 3. This set represents the Fibonacci numbers. If they are zero-indexed and\n;    the first fibonaci number is 0, then this is (n, fib(n), fib(n + 1)).\n;    This is easy to see, because the first element grows linearly,\n;    independent from the other two. The second becomes the third from the\n;    previous iteration and the third is the sum of the second and third from\n;    the previous iteration, which is essentially the definition of Fibonacci.\n;\n; 4. This is an interesting one. It results to (n, 2n + 1, n²). It's easy to\n;    see that the first one grows linearly, independent of the other two. The\n;    second starts with 1 and grows by 2 on every iteration, thus 2n + 1. The\n;    third one grows by 2n + 1 on every iteration, where n is the iteration\n;    count. Thus, if the third element is calculated by g(n):\n;\n;    g(0) = 0         = n⁰\n;    g(1) = 1 + 0 = 1 = n¹\n;    g(2) = 3 + 1 = 4 = n²\n;    ...\n;    g(n + 1) = i + j = 2n + 1 + n² = n² + 2n + 1 = (n + 1)²\n"
  },
  {
    "path": "scheme/eopl/01/03.scm",
    "content": "; EOPL exercise 1.03\n;\n; Find a set T of natural numbers such that 0 ∈ T, and whenever n ∈ T, then\n; n + 3 ∈ T, but T ≠ S, where S is the set defined in definition 1.1.2.\n\n; I really don't get the point of this exercise, since it looks simple enough,\n; but if we add that 1 ∈ T, then T would be a subset of S and therefore\n; different than it. Note that it will be the union of S and {n + 1 | n ∈ N}.\n"
  },
  {
    "path": "scheme/eopl/01/04.scm",
    "content": "; EOPL exercise 1.04\n;\n; Write a derivation from List-of-Int to (-7 . (3 . (14 . ())))\n\n;   List-of-Int\n; ⇒ (-7 . List-of-Int)\n; ⇒ (-7 . (3 . List-of-Int))\n; ⇒ (-7 . (3 . (14 . List-of-Int)))\n; ⇒ (-7 . (3 . (14 . ())))\n"
  },
  {
    "path": "scheme/eopl/01/05.scm",
    "content": "; EOPL exercise 1.05\n;\n; Prove that if e ∈ LcExp, then there are the same number of left and right\n; parenthesis in e.\n\n; The lambda expression grammar is:\n;\n; LcExp ::= Identifier\n;       ::= (lambda (Identifier) LcExp)\n;       ::= (LcExp LcExp)\n;\n; I don't think I need induction here, but let's try to put it in.\n;\n; Proof: The proof is by induction on the size of e, where we take the size of\n; e to be the number of productions in the grammar. The induction hypothesis\n; IH(k), is that any expression with number of productions ≤ k has the same\n; number of left and right parenthesis.\n;\n; 1. There is only one expression with 1 production and this is Identifier.\n;    All other have a LcExp non-terminal, thus requiring more productions. By\n;    definition, identifiers don't include parenthesis, so IH(1) holds.\n; 2. Let k be an integer such that IH(k) holds. We will show that IH(k + 1)\n;    holds as well. If e requires ≤ k + 1 productions, there are three\n;    possibilities in the grammar:\n;\n;      (a) e can be of the form Identifer. There are no parenthesis, so this\n;          holds trivially.\n;      (b) e can be of the form (lambda (Identifier) e₁). The number of left\n;          parenthesis is 2 + left-parens(e₁). The number of right parenthesis\n;          is 2 + right-parens(e₁). Since e requires ≤ k + 1 productions, we\n;          can infer that e₁ requires ≤ k productions. From the hypothesis, we\n;          know that e₁ has the same number of left and right parenthesis,\n;          thus IH(k + 1) holds.\n;      (c) e can be of the form (e₁ e₂), where e₁ and e₂ are of the form\n;          LcExp. Since e requires ≤ k + 1 productions, both require ≤ k\n;          productions and we know that each has the same number of\n;          parenthesis. Thus if p₁ = left-parens(e₁) = right-parens(e₁) and\n;          p₂ = left-parens(e₂) = right-parens(e₂), then we see that:\n;\n;          left-parens(e)  = 1 + left-parens(e₁) + left-parens(e₂ )  = 1 + p₁ + p₂\n;          right-parens(e) = 1 + right-parens(e₁) + right-parens(e₂) = 1 + p₁ + p₂\n;\n;          and thus\n;\n;          left-parens(e) = right-parens(2)\n;\n;          which proves that IH(k + 1) holds.\n;\n; This completes the proof of the claim that IH(k + 1) holds and therefore\n; completes the induction.∎\n"
  },
  {
    "path": "scheme/eopl/01/06.scm",
    "content": "; EOPL exercise 1.06\n;\n; If we reversed the order of the tests in nth-element, what would go wrong?\n\n; The code will look like this:\n\n(define nth-element\n  (lambda (lst n)\n    (if (zero? n)\n      (car lst)\n      (if (null? lst)\n        (report-list-too-short n)\n        (nth-element (cdr lst) (- n 1))))))\n\n; We will loose the error message in one specific case - that is, when we call\n; (nth-elemen lst n) when n is (length lst), that is, when we try to access\n; one more elements than the list has. In that case, the computation will\n; eventually be reduced to a call (nth-element '() 0). Since n is zero, the\n; computation will attempt to return the car of '(), which will result to an\n; error. This is not the error we had in mind, though.\n"
  },
  {
    "path": "scheme/eopl/01/07.scm",
    "content": "; EOPL exercise 1.07\n;\n; The error message form nth-element is uninformative. Rewrite nth-element so\n; that it produces a more informative error message such as \"(a b c) does not\n; have 8 elements\"\n\n; I don't know how much Scheme can I use in this exercise, so I will just go\n; with an internal definition.\n\n(define (nth-element lst n)\n  (define (iter items counter)\n    (if (null? items)\n      (eopl:error 'nth-element \"~s does not have ~s elements.\" lst n)\n      (if (zero? counter)\n        (car items)\n        (iter (cdr items) (- counter 1)))))\n  (iter lst n))\n"
  },
  {
    "path": "scheme/eopl/01/08.scm",
    "content": "; EOPL exercise 1.08\n;\n; In the definition of remove-first, if the last line were replaced by\n; (remove-first s (cdr los)), what function would the resulting procedure\n; compute? Give the contract, including the usage statement, for the revised\n; procedure.\n\n; drop-until: Sym ╳ Listof(Sym) → Listof(Sym)\n; usage: (drop-until s los) returns the suffix of the list los that starts\n;        after the first occurence of the symbol s.\n(define drop-until\n  (lambda (s los)\n    (if (null? los)\n      '()\n      (if (eqv? (car los) s)\n        (cdr los)\n        (drop-until s (cdr los))))))\n"
  },
  {
    "path": "scheme/eopl/01/09.scm",
    "content": "; EOPL exercise 1.09\n;\n; Define remove, which is like remove-first, except that it removes all\n; occurences of a given symbol form a list of symbols, not just the first.\n\n; Of course, remove is already defined in Scheme, so I'm going to define\n; another function, remove-all, to allow the function body to see itself in\n; the enclosing environment.\n\n(define remove-all\n  (lambda (s los)\n    (cond ((null? los) '())\n          ((eq? (car los) s) (remove-all s (cdr los)))\n          (#t (cons (car los) (remove-all s (cdr los)))))))\n\n(define remove remove-all)\n"
  },
  {
    "path": "scheme/eopl/01/10.scm",
    "content": "; EOPL exercise 1.10\n;\n; We typically use \"or\" to mean \"inclusive or\". What other meanings can \"or\"\n; have?\n\n; Of course, it can be \"exclusive or\", as in the expression \"Coffee or tea?\".\n; It implies that you have to chose either coffee or tea, but not both. This\n; is known as the XOR operation.\n"
  },
  {
    "path": "scheme/eopl/01/11.scm",
    "content": "; EOPL exercise 1.11\n;\n; In the last line of subts-in-s-exp, the recursion is on sexp and not a\n; smaller substructure. Why is the recursion guaranteed to halt?\n\n; The recursion might be on sexp, but it calls subst instead. The substs\n; procedure will reduce the problem to a smaller problem, which would\n; guarantee that it will halt.\n"
  },
  {
    "path": "scheme/eopl/01/12.scm",
    "content": "; EOPL exercise 1.12\n;\n; Eliminate the one call to subst-in-s-exp in subst, by replacing it by its\n; definition and simplifying the resulting procedure. The result will be a\n; version of substs that does not need subst-in-s-exp. This technique is\n; called inlining, and is used by optimizing compilers.\n\n(define subst\n  (lambda (new old slist)\n    (if (null? slist)\n      '()\n      (cons\n        (if (symbol? (car slist))\n          (if (eqv? (car slist) old) new (car slist))\n          (subst new old (car slist)))\n        (subst new old (cdr slist))))))\n"
  },
  {
    "path": "scheme/eopl/01/13.scm",
    "content": "; EOPL exercise 1.13\n;\n; In our example, we began by eliminating the Kleene star in the grammar of\n; S-list. Write subst following the original grammar by using map.\n\n(define subst\n  (lambda (new old slist)\n    (map (lambda (sexp) (subst-in-s-exp new old sexp))\n         slist)))\n\n(define subst-in-s-exp\n  (lambda (new old sexp)\n    (if (symbol? sexp)\n      (if (eqv? sexp old) new sexp)\n      (subst new old sexp))))\n"
  },
  {
    "path": "scheme/eopl/01/14.scm",
    "content": "; EOPL exercise 1.14\n;\n; Given the assumption 0 ≤ n < length(v), prove that partial-vector-sum is\n; correct.\n\n; I don't grok this. It's extremely straightforward. Let's try using induction.\n;\n; 1. (partial-vector-sum v 0) returns the sum of indices in [0, 0]. This is\n;    trivially obvious.\n; 2. Let's assume that it is correct for k. For k + 1, partial-vector-sum\n;    returns (vector-ref v k+1) + (partial-vector-sum v k). This is the sum of\n;    this is the value of the partial sum from 0 to k + 1.\n"
  },
  {
    "path": "scheme/eopl/01/15.scm",
    "content": "; EOPL exercise 1.15\n;\n; (duple n x) returns a list containing n copies of x.\n;\n; > (duple 2 3)\n; (3 3)\n; > (duple 4 '(ha ha))\n; ((ha ha) (ha ha) (ha ha) (ha ha))\n; > (duple 0 '(blah))\n; '()\n\n; duple: Int × Any → Listof(Any)\n; usage: takes an argument item and returns a list of containing n copies of\n;        item.\n(define duple\n  (lambda (count item)\n    (if (zero? count)\n      '()\n      (cons item (duple (- count 1) item)))))\n"
  },
  {
    "path": "scheme/eopl/01/16.scm",
    "content": "; EOPL exercise 1.16\n;\n; (invert lst), where lst is a list of 2-lists (lists of length two), returns\n; a list with each 2-list reversed.\n;\n; > (invert '((a 1) (a 2) (1 b) (2 b)))\n; ((1 a) (2 a) (b 1) (b 2))\n\n(define invert\n  (lambda (pairs)\n    (if (null? pairs)\n      '()\n      (cons (list (cadar pairs) (caar pairs))\n            (invert (cdr pairs))))))\n"
  },
  {
    "path": "scheme/eopl/01/17.scm",
    "content": "; EOPL exercise 1.17\n;\n; (down lst) wraps parenthesis aroudn each top-level elements of lst.\n;\n; > (down '(1 2 3))\n; ((1) (2) (3))\n; > (down '((a) (fine) (idea)))\n; (((a)) ((fine)) ((idea)))\n; > (down '(a (more (complicated)) object))\n; ((a) ((more (complicated))) (object))\n\n(define down\n  (lambda (lst)\n    (map list lst)))\n"
  },
  {
    "path": "scheme/eopl/01/18.scm",
    "content": "; EOPL exercise 1.18\n;\n; (swapper s1 s2 slist) returns a list the same as slist, but with all\n; occurences of s1 replaced by s2 and all occurences of s2 replaced by s1.\n;\n; > (swapper 'a 'd '(a b c d))\n; (d b c a)\n; > (swapper 'a 'd '(a d () c d))\n; (d a () c a)\n; > (swapper 'x 'y '((x) y (z (x))))\n; ((y) x (z (y)))\n\n(define (swapper s1 s2 slist)\n  (cond ((null? slist) '())\n        ((eqv? s1 slist) s2)\n        ((eqv? s2 slist) s1)\n        ((symbol? slist) slist)\n        (#t (map (curry swapper s1 s2) slist))))\n"
  },
  {
    "path": "scheme/eopl/01/19.scm",
    "content": "; EOPL exercise 1.19\n;\n; (list-set lst n x) returns a list like lst, except that the n-th element,\n; using zero-based indexing, is x.\n;\n; > (list-set '(a b c d) 2 '(1 2))\n; (a b (1 2) d)\n; > (list-ref (list-set '(a b c d) 3 '(1 5 10)) 3)\n; (1 5 10)\n\n(define (list-set lst n x)\n  (if (zero? n)\n    (cons x (cdr lst))\n    (cons (car lst) (list-set (cdr lst) (- n 1) x))))\n\n"
  },
  {
    "path": "scheme/eopl/01/20.scm",
    "content": "; EOPL exercise 1.20\n;\n; (count-occurences s slist) returns the number of occurences of s in slist.\n;\n; > (count-occurences 'x '((f x) y (((x z) x))))\n; 3\n; > (count-occurences 'x '((f x) y (((x z) () x))))\n; 3\n; > (count-occurences 'w '((f x) y (((x z) x))))\n; 0\n\n(define (count-occurences s slist)\n  (cond ((null? slist) 0)\n        ((symbol? slist) (if (eqv? s slist) 1 0))\n        (#t (+ (count-occurences s (car slist))\n               (count-occurences s (cdr slist))))))\n"
  },
  {
    "path": "scheme/eopl/01/21.scm",
    "content": "; EOPL exercise 1.21\n;\n; (product sos1 sos2), where sos1 and sos2 are each a list of symbols without\n; repetitions, returns a list of 2-lists that represents a Cartesian product\n; of sos1 and sos2. The 2-lists can appear in any order.\n;\n; > (product '(a b c) '(x y))\n; ((a x) (a y) (b x) (b y) (c x) (c y))\n\n(define (product sos1 sos2)\n  (if (null? sos1)\n    '()\n    (append (map (lambda (s) (list (car sos1) s)) sos2)\n            (product (cdr sos1) sos2))))\n\n"
  },
  {
    "path": "scheme/eopl/01/22.scm",
    "content": "; EOPL exercise 1.22\n;\n; (filter-in pred lst) returns the list of those elements in lst that satisfy\n; the predicate pred.\n;\n; > (filter-in number? '(a 2 (1 3) b 7))\n; (2 7)\n; > (filter-in symbol? '(a (b c) 17 foo))\n; (a foo)\n\n(define (filter-in pred lst)\n  (if (null? lst)\n    '()\n    (if (pred (car lst))\n      (cons (car lst) (filter-in pred (cdr lst)))\n      (filter-in pred (cdr lst)))))\n"
  },
  {
    "path": "scheme/eopl/01/23.scm",
    "content": "; EOPL exercise 1.23\n;\n; (list-index pred lst) returns the 0-based position of the first element of\n; lst that satisfies the predicate pred. If no element of lst satisfies the\n; predicate, then list-index returns #f.\n;\n; > (list-index number? '(a 2 (1 3) b 7))\n; 1\n; > (list-index symbol? '(a (b c) 17 foo))\n; 0\n; > (list-index symbol? '(1 2 (a b) 3))\n; #f\n\n(define (list-index pred lst)\n  (define (iter counter items)\n    (cond ((null? items) #f)\n          ((pred (car items)) counter)\n          (#t (iter (+ counter 1) (cdr items)))))\n  (iter 0 lst))\n\n"
  },
  {
    "path": "scheme/eopl/01/24.scm",
    "content": "; EOPL exercise 1.24\n;\n; (every? pred lst) returns #f if any element of lst fails to satisfy pred,\n; and returns #t otherwise.\n;\n; > (every? number? '(a b c 3 e))\n; #f\n; > (every? number? '(1 2 3 5 4))\n; #t\n\n(define (every? pred lst)\n  (cond ((null? lst) #t)\n        ((pred (car lst)) (every? pred (cdr lst)))\n        (#t #f)))\n"
  },
  {
    "path": "scheme/eopl/01/25.scm",
    "content": "; EOPL exercise 1.25\n;\n; (exists? number? '(a b c 3 e)) returns #t if any element of lst satisfies\n; pred, and returns #f otherwise.\n;\n; > (exists? number? '(a b c 3 e))\n; #t\n; > (exists? number? '(a b c d e))\n; #f\n\n(define (exists? pred lst)\n  (cond ((null? lst) #f)\n        ((pred (car lst)) #t)\n        (#t (exists? pred (cdr lst)))))\n"
  },
  {
    "path": "scheme/eopl/01/26.scm",
    "content": "; EOPL exercise 1.26\n;\n; (up lst) removes a pair of parentheses from each top-level element of lst.\n; If a top-level element is not a list, it is included in result, as is. The\n; value of (up (down lst)) is equivalent to lst, but (down (up lst)) is not\n; necessarily lst. (See exercise 1.17).\n;\n; > (up '((1 2) (3 4)))\n; (1 2 3 4)\n; > (up '((x (y)) z))\n; (x (y) z)\n\n(define (up lst)\n  (if (null? lst)\n    '()\n    (append (if (pair? (car lst))\n              (car lst)\n              (list (car lst)))\n            (up (cdr lst)))))\n\n"
  },
  {
    "path": "scheme/eopl/01/27.scm",
    "content": "; EOPL exercise 1.27\n;\n; (flatten slist) returns a list of the symbols contained in slist in the\n; order in which they occur when slist is printed. Intuitively, flatten\n; removes all the inner parentheses from its arguments.\n;\n; > (flatten '(a b c))\n; (a b c)\n; > (flatten '((a) () (b ()) () (c)))\n; (a b c)\n; > (flatten '((a b) c (((d)) e)))\n; (a b c d e)\n; > (flatten '(a b (() (c))))\n; (a b c)\n\n(define (flatten slist)\n  (cond ((null? slist) '())\n        ((pair? slist) (append (flatten (car slist))\n                               (flatten (cdr slist))))\n        (#t (list slist))))\n"
  },
  {
    "path": "scheme/eopl/01/28.scm",
    "content": "; EOPL exercise 1.28\n;\n; (merge loi1 loi2), where loi1 and loi2 are lists of integers that are sorted\n; in ascending order, returns a sorted list of all integers in loi1 and loi2.\n;\n; > (merge '(1 4) '(1 2 8))\n; (1 1 2 4 8)\n; > (merge '(35 62 81 90 91) '(3 83 85 90))\n; (3 35 62 81 83 85 90 90 91)\n\n(define (merge loi1 loi2)\n  (cond ((null? loi1) loi2)\n        ((null? loi2) loi1)\n        ((< (car loi1) (car loi2)) (cons (car loi1) (merge (cdr loi1) loi2)))\n        (#t (cons (car loi2) (merge loi1 (cdr loi2))))))\n"
  },
  {
    "path": "scheme/eopl/01/29.scm",
    "content": "; EOPL exercise 1.29\n;\n; (sort loi) returns a list of the elements of loi in ascending order.\n;\n; > (sort '(8 2 5 2 3))\n; (2 2 3 5 8)\n\n(define (merge loi1 loi2)\n  (cond ((null? loi1) loi2)\n        ((null? loi2) loi1)\n        ((< (car loi1) (car loi2)) (cons (car loi1) (merge (cdr loi1) loi2)))\n        (#t (cons (car loi2) (merge loi1 (cdr loi2))))))\n\n(define (split loi)\n  (define (iter first second n)\n    (if (zero? n)\n      (list first second)\n      (iter (cdr first) (cons (car first) second) (- n 1))))\n  (iter loi '() (quotient (length loi) 2)))\n\n(define (merge-sort loi)\n  (if (<= (length loi) 1)\n    loi\n    (let* ((lists (split loi))\n           (first (car lists))\n           (second (cadr lists)))\n      (merge (merge-sort first)\n             (merge-sort second)))))\n\n(define (sort loi)\n  (merge-sort loi))\n"
  },
  {
    "path": "scheme/eopl/01/30.scm",
    "content": "; EOPL exercise 1.30\n;\n; (sort/predicate pred loi) returns a list of elements sorted by the\n; predicate.\n;\n; > (sort/predicate < '(8 2 5 2 3))\n; (2 2 3 5 8)\n; > (sort/predicate > '(8 2 5 2 3))\n; (8 5 3 2 2)\n\n(define (sort/predicate pred loi)\n  (define (split loi)\n    (define (iter first second n)\n      (if (zero? n)\n        (list first second)\n        (iter (cdr first) (cons (car first) second) (- n 1))))\n    (iter loi '() (quotient (length loi) 2)))\n\n  (define (merge loi1 loi2)\n    (cond ((null? loi1) loi2)\n          ((null? loi2) loi1)\n          ((pred (car loi1) (car loi2)) (cons (car loi1) (merge (cdr loi1) loi2)))\n          (#t (cons (car loi2) (merge loi1 (cdr loi2))))))\n\n  (define (merge-sort loi)\n    (if (<= (length loi) 1)\n      loi\n      (let* ((lists (split loi))\n             (first (car lists))\n             (second (cadr lists)))\n        (merge (merge-sort first)\n               (merge-sort second)))))\n  (merge-sort loi))\n"
  },
  {
    "path": "scheme/eopl/01/31.scm",
    "content": "; EOPL exercise 1.31\n;\n; Write the following procedures for calculating on a bintree (definition\n; 1.1.7): leaf and interior-node, which builds bintrees, leaf?, which tests\n; whether a bintree is a leaf, and lson, rson and contents-of, which extract\n; components of a node. contents-of should work on both leaves end interior\n; nodes.\n\n(define (leaf? tree)\n  (number? tree))\n\n(define (leaf number)\n  (if (number? number)\n    number\n    (eopl:error 'leaf \"Leaf argument must be a number. Got ~s instead.\" number)))\n\n(define (interior-node data left-son right-son)\n  (if (symbol? data)\n    (list data left-son right-son)\n    (eopl:error 'interior-node \"Data must be a symbol. Got ~s instead.\" data)))\n\n(define (lson tree) (cadr tree))\n(define (rson tree) (caddr tree))\n\n(define (contents-of tree)\n  (if (leaf? tree)\n    tree\n    (car tree)))\n"
  },
  {
    "path": "scheme/eopl/01/32.scm",
    "content": "; EOPL exercise 1.32\n;\n; Write a procedure double-tree that takes a bintree, as represented in\n; definition 1.1.7, and produces another bintree like the original, but with\n; all the integers in the leaves doubled.\n\n; We base this on the previous exercise\n(load-relative \"31.scm\")\n\n(define (double-tree tree)\n  (if (leaf? tree)\n    (* (contents-of tree) 2)\n    (interior-node (contents-of tree)\n                   (double-tree (lson tree))\n                   (double-tree (rson tree)))))\n"
  },
  {
    "path": "scheme/eopl/01/33.scm",
    "content": "; EOPL exercise 1.33\n;\n; Write a procedure mark-leaves-with-red-depth that takes a bintree\n; (definition 1.1.7), and produces a bintree of the same shape as the\n; original, except that in the new tree, each leaf contains the integer of\n; nodes between it and the root that contain the symbol red. For example, the\n; expression\n;\n; (mark-leaves-with-red-depth\n;   (interior-node 'bar\n;     (interior-node 'bar\n;       (leaf 26)\n;       (leaf 12))\n;     (interior-node 'red\n;       (leaf 11)\n;       (interior-node 'quux\n;         (leaf 117)\n;         (leaf 14)))))\n;\n; which is written using the procedures defined in exercise 1.31, should\n; return the bintree\n;\n; (red\n;   (bar 1 1)\n;   (red 2 (quux 2 2)))\n\n(load-relative \"31.scm\")\n\n(define (mark-leaves-with-red-depth tree)\n  (define (traverse tree count)\n    (if (leaf? tree)\n      (leaf count)\n      (let ((new-count (if (eqv? (contents-of tree) 'red)\n                           (+ count 1)\n                           count)))\n        (interior-node (contents-of tree)\n                       (traverse (lson tree) new-count)\n                       (traverse (rson tree) new-count)))))\n  (traverse tree 0))\n"
  },
  {
    "path": "scheme/eopl/01/34.scm",
    "content": "; EOPL exercise 1.34\n;\n; Write a procedure path that takes an integer n and a binary search tree bst\n; (page 10) that contains the integer n, and returns a list of lefts and\n; rights showing how to find the node containing n. If n is found at the root,\n; it returns the empty list.\n;\n; > (path 17 '(14 (7 () (12 () ()))\n;                 (26 (20 (17 () ())\n;                         ())\n;                     (31 () ()))))\n; (right left left)\n\n(define (path n bst)\n  (if (eqv? n (car bst))\n      '()\n      (if (< n (car bst))\n          (cons 'left (path n (cadr bst)))\n          (cons 'right (path n (caddr bst))))))\n"
  },
  {
    "path": "scheme/eopl/01/35.scm",
    "content": "; EOPL exercise 1.35\n;\n; Write a procedure number-leaves that takes a bintree, and produces a bintree\n; like the original, except the contents of the leaves are numbered starting\n; from 0. For example,\n;\n; (number-leaves\n;   (interior-node 'foo\n;     (interior-node 'bar\n;       (leaf 26)\n;       (leaf 12))\n;     (interior-node 'baz\n;       (leaf 11)\n;       (interior-node 'quux\n;         (leaf 117)\n;         (leaf 14)))))\n;\n; should return\n;\n; (foo\n;   (bar 0 1)\n;   (baz\n;     2\n;     (quux 3 4)))\n\n(load-relative \"31.scm\")\n\n(define (number-leaves tree)\n  (define (traverse tree counter)\n    (if (leaf? tree)\n      (cons (+ counter 1) (leaf counter))\n      (let* ((node-data (contents-of tree))\n             (lson-result (traverse (lson tree) counter))\n             (counter-after-lson (car lson-result))\n             (result-lson (cdr lson-result))\n             (rson-result (traverse (rson tree) counter-after-lson))\n             (result-counter (car rson-result))\n             (result-rson (cdr rson-result))\n             (result-tree (interior-node node-data result-lson result-rson)))\n        (cons result-counter result-tree))))\n  (cdr (traverse tree 0)))\n"
  },
  {
    "path": "scheme/eopl/01/36.scm",
    "content": "; EOPL exercise 1.36\n;\n; Write a procedure g such that number-elements from page 23 could be defined\n; as\n;\n; (define number-elements\n;   (lambda (lst)\n;     (if (null? lst) '()\n;       (g (list 0 (car lst)) (number-elements (cdr lst))))))\n\n(define g\n  (lambda (head tail)\n    (cons head\n          (map (lambda (elem) (list (+ 1 (car elem))\n                                    (cadr elem)))\n               tail))))\n\n(define number-elements\n  (lambda (lst)\n    (if (null? lst) '()\n      (g (list 0 (car lst)) (number-elements (cdr lst))))))\n"
  },
  {
    "path": "scheme/eopl/01/tests/07-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../07.scm\")\n\n(define eopl-1.07-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.07\"\n\n    (check-equal? (nth-element '(a b c) 0) 'a)\n    (check-equal? (nth-element '(a b c) 1) 'b)\n    (check-equal? (nth-element '(a b c) 2) 'c)\n\n    (check-exn (regexp \"\\\\(a b c\\\\) does not have 8 elements.\")\n               (lambda () (nth-element '(a b c) 8)))\n))\n\n(exit (run-tests eopl-1.07-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/08-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../08.scm\")\n\n(define eopl-1.08-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.08\"\n\n    (check-equal? (drop-until 'c '(a b c d e f))\n                  '(d e f))\n))\n\n(exit (run-tests eopl-1.08-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/09-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../09.scm\")\n\n(define eopl-1.09-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.09\"\n\n    (check-equal? (remove 'a '(a b a c a d a))\n                  '(b c d))\n))\n\n(exit (run-tests eopl-1.09-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/12-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../12.scm\")\n\n(define eopl-1.12-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.12\"\n\n    (check-equal? (subst 'z 'a '(a b a ((c a) d a (f a)) g a))\n                  '(z b z ((c z) d z (f z)) g z))\n))\n\n(exit (run-tests eopl-1.12-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/13-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../13.scm\")\n\n(define eopl-1.13-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.13\"\n\n    (check-equal? (subst 'z 'a '(a b a ((c a) d a (f a)) g a))\n                  '(z b z ((c z) d z (f z)) g z))\n))\n\n(exit (run-tests eopl-1.13-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/15-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../15.scm\")\n\n(define eopl-1.15-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.15\"\n\n    (check-equal? (duple 2 3)\n                  '(3 3))\n    (check-equal? (duple 4 '(ha ha))\n                  '((ha ha) (ha ha) (ha ha) (ha ha)))\n    (check-equal? (duple 0 '(blah))\n                  '())\n))\n\n(exit (run-tests eopl-1.15-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/16-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../16.scm\")\n\n(define eopl-1.16-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.16\"\n\n    (check-equal? (invert '((a 1) (a 2) (1 b) (2 b)))\n                  '((1 a) (2 a) (b 1) (b 2)))\n))\n\n(exit (run-tests eopl-1.16-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/17-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../17.scm\")\n\n(define eopl-1.17-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.17\"\n\n    (check-equal? (down '(1 2 3))\n                  '((1) (2) (3)))\n    (check-equal? (down '((a) (fine) (idea)))\n                  '(((a)) ((fine)) ((idea))))\n    (check-equal? (down '(a (more (complicated)) object))\n                  '((a) ((more (complicated))) (object)))\n))\n\n(exit (run-tests eopl-1.17-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/18-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../18.scm\")\n\n(define eopl-1.18-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.18\"\n\n    (check-equal? (swapper 'a 'd '(a b c d))\n                  '(d b c a))\n    (check-equal? (swapper 'a 'd '(a d () c d))\n                  '(d a () c a))\n    (check-equal? (swapper 'x 'y '((x) y (z (x))))\n                  '((y) x (z (y))))\n))\n\n(exit (run-tests eopl-1.18-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/19-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../19.scm\")\n\n(define eopl-1.19-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.19\"\n\n    (check-equal? (list-set '(a b c d) 2 '(1 2))\n                  '(a b (1 2) d))\n    (check-equal? (list-ref (list-set '(a b c d) 3 '(1 5 10)) 3)\n                  '(1 5 10))\n))\n\n(exit (run-tests eopl-1.19-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/20-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../20.scm\")\n\n(define eopl-1.20-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.20\"\n\n    (check-equal? (count-occurences 'x '((f x) y (((x z) x))))\n                  3)\n    (check-equal? (count-occurences 'x '((f x) y (((x z) () x))))\n                  3)\n    (check-equal? (count-occurences 'w '((f x) y (((x z) x))))\n                  0)\n))\n\n(exit (run-tests eopl-1.20-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/21-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../21.scm\")\n\n(define eopl-1.21-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.21\"\n\n    (check-equal? (product '(a b c) '(x y))\n                  '((a x) (a y) (b x) (b y) (c x) (c y)))\n))\n\n(exit (run-tests eopl-1.21-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/22-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../22.scm\")\n\n(define eopl-1.22-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.22\"\n\n    (check-equal? (filter-in number? '(a 2 (1 3) b 7))\n                  '(2 7))\n    (check-equal? (filter-in symbol? '(a (b c) 17 foo))\n                  '(a foo))\n))\n\n(exit (run-tests eopl-1.22-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/23-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../23.scm\")\n\n(define eopl-1.23-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.23\"\n\n    (check-equal? (list-index number? '(a 2 (1 3) b 7))\n                  1)\n    (check-equal? (list-index symbol? '(a (b c) 17 foo))\n                  0)\n    (check-equal? (list-index symbol? '(1 2 (a b) 3))\n                  #f)\n))\n\n(exit (run-tests eopl-1.23-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/24-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../24.scm\")\n\n(define eopl-1.24-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.24\"\n\n    (check-equal? (every? number? '(a b c 3 e))\n                  #f)\n    (check-equal? (every? number? '(1 2 3 5 4))\n                  #t)\n    (check-equal? (every? number? '())\n                  #t)\n))\n\n(exit (run-tests eopl-1.24-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/25-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../25.scm\")\n\n(define eopl-1.25-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.25\"\n\n    (check-equal? (exists? number? '(a b c 3 e))\n                  #t)\n    (check-equal? (exists? number? '(a b c d e))\n                  #f)\n    (check-equal? (exists? number? '())\n                  #f)\n))\n\n(exit (run-tests eopl-1.25-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/26-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../26.scm\")\n\n(define eopl-1.26-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.26\"\n\n    (check-equal? (up '((1 2) (3 4)))\n                  '(1 2 3 4))\n    (check-equal? (up '((x (y)) z))\n                  '(x (y) z))\n))\n\n(exit (run-tests eopl-1.26-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/27-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../27.scm\")\n\n(define eopl-1.27-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.27\"\n\n    (check-equal? (flatten '(a b c))\n                  '(a b c))\n    (check-equal? (flatten '((a) () (b ()) () (c)))\n                  '(a b c))\n    (check-equal? (flatten '((a b) c (((d)) e)))\n                  '(a b c d e))\n    (check-equal? (flatten '(a b (() (c))))\n                  '(a b c))\n))\n\n(exit (run-tests eopl-1.27-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/28-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../28.scm\")\n\n(define eopl-1.28-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.28\"\n\n    (check-equal? (merge '(1 4) '(1 2 8))\n                  '(1 1 2 4 8))\n    (check-equal? (merge '(35 62 81 90 91) '(3 83 85 90))\n                  '(3 35 62 81 83 85 90 90 91))\n))\n\n(exit (run-tests eopl-1.28-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/29-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../29.scm\")\n\n(define eopl-1.29-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.29\"\n\n    (check-equal? (sort '(8 2 5 2 3))\n                  '(2 2 3 5 8))\n))\n\n(exit (run-tests eopl-1.29-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/30-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../30.scm\")\n\n(define eopl-1.30-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.30\"\n\n    (check-equal? (sort/predicate < '(8 2 5 2 3))\n                  '(2 2 3 5 8))\n    (check-equal? (sort/predicate > '(8 2 5 2 3))\n                  '(8 5 3 2 2))\n))\n\n(exit (run-tests eopl-1.30-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/31-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../31.scm\")\n\n(define eopl-1.31-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.31\"\n\n    (check-equal? (leaf 10) 10)\n    (check-exn exn? (lambda () (leaf 'symbol)))\n\n    (check-true (leaf? 10))\n    (check-false (leaf? '(a 1 2)))\n\n    (check-equal? (interior-node 'a (leaf 1) (leaf 2)) '(a 1 2))\n    (check-exn exn? (lambda () (interior-node 1 (leaf 1) (leaf 2))))\n\n    (check-equal? (lson (interior-node 'node (leaf 1) (leaf 2)))\n                  (leaf 1))\n    (check-equal? (rson (interior-node 'node (leaf 1) (leaf 2)))\n                  (leaf 2))\n\n    (check-equal? (contents-of (interior-node 'node (leaf 1) (leaf 2)))\n                  'node)\n    (check-equal? (contents-of (leaf 1))\n                  1)\n))\n\n(exit (run-tests eopl-1.31-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/32-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../32.scm\")\n\n(define eopl-1.32-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.32\"\n\n    (check-equal?\n      (double-tree\n        (interior-node 'root\n                       (interior-node 'left (leaf 1) (leaf 2))\n                       (interior-node 'right\n                                      (leaf 3)\n                                      (interior-node 'right2 (leaf 4) (leaf 5)))))\n      (interior-node 'root\n                     (interior-node 'left (leaf 2) (leaf 4))\n                     (interior-node 'right\n                                    (leaf 6)\n                                    (interior-node 'right2 (leaf 8) (leaf 10)))))\n))\n\n(exit (run-tests eopl-1.32-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/33-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../33.scm\")\n\n(define eopl-1.33-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.33\"\n\n    (check-equal?\n      (mark-leaves-with-red-depth\n        (interior-node 'red\n          (interior-node 'bar\n            (leaf 26)\n            (leaf 12))\n          (interior-node 'red\n            (leaf 11)\n            (interior-node 'quux\n              (leaf 117)\n              (leaf 14)))))\n      '(red\n         (bar 1 1)\n         (red 2 (quux 2 2))))\n))\n\n(exit (run-tests eopl-1.33-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/34-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../34.scm\")\n\n(define eopl-1.34-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.34\"\n\n    (check-equal? (path 17 '(14 (7 () (12 () ()))\n                                (26 (20 (17 () ())\n                                        ())\n                                    (31 () ()))))\n                  '(right left left))\n))\n\n(exit (run-tests eopl-1.34-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/35-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../35.scm\")\n\n(define eopl-1.35-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.35\"\n\n    (check-equal?\n      (number-leaves\n        (interior-node 'foo\n          (interior-node 'bar\n            (leaf 26)\n            (leaf 12))\n          (interior-node 'baz\n            (leaf 11)\n            (interior-node 'quux\n              (leaf 117)\n              (leaf 14)))))\n      '(foo\n         (bar 0 1)\n         (baz\n           2\n           (quux 3 4))))\n))\n\n(exit (run-tests eopl-1.35-tests))\n"
  },
  {
    "path": "scheme/eopl/01/tests/36-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require eopl)\n(load-relative \"../36.scm\")\n\n(define eopl-1.36-tests\n  (test-suite\n    \"Tests for EOPL exercise 1.36\"\n\n    (check-equal? (number-elements '(a b c d))\n                  '((0 a) (1 b) (2 c) (3 d)))\n))\n\n(exit (run-tests eopl-1.36-tests))\n"
  },
  {
    "path": "scheme/eopl/02/01.scm",
    "content": "; EOPL exercise 2.01\n;\n; Implement the four required operations for bigits. Then use your\n; implementation to calculate the factorial of 10. How does the execution time\n; vary as this argument changes? How does the execution time vary as the base\n; changes? Explain why.\n\n; And this has only one star? Anyway. The results of execution time is in the\n; end of the file.\n\n; Let's use Racket parameters to simplify testing and benchmarking:\n\n(define base (make-parameter 10))\n\n; Some observers that will be used:\n\n(define (first-bigit bignum) (car bignum))\n(define (rest-bigits bignum) (cdr bignum))\n\n; The four required operations:\n\n(define (zero)\n  '())\n\n(define (is-zero? bignum)\n  (null? bignum))\n\n(define (successor bignum)\n  (cond ((null? bignum) '(1))\n        ((eqv? (first-bigit bignum) (- (base) 1))\n         (cons 0 (successor (rest-bigits bignum))))\n        (else\n         (cons (+ (first-bigit bignum) 1)\n               (rest-bigits bignum)))))\n\n(define (predecessor bignum)\n  (cond ((null? bignum)\n         (eopl:error 'predecessor \"We don't support negative numbers\"))\n        ((equal? bignum '(1)) '())\n        ((zero? (first-bigit bignum))\n         (cons (- (base) 1)\n               (predecessor (rest-bigits bignum))))\n        (else\n         (cons (- (first-bigit bignum) 1)\n               (rest-bigits bignum)))))\n\n; Converting a bignum to int:\n\n(define (bignum->int bignum)\n  (if (is-zero? bignum)\n      0\n      (+ (first-bigit bignum)\n         (* (base) (bignum->int (rest-bigits bignum))))))\n\n(define (int->bignum n)\n  (define (iter n result)\n    (if (zero? n)\n        result\n        (iter (- n 1) (successor result))))\n  (iter n (zero)))\n\n; Some additional operations in order to have a nicer factorial:\n\n(define (add bignum1 bignum2)\n  (if (is-zero? bignum1)\n      bignum2\n      (add (predecessor bignum1) (successor bignum2))))\n\n(define (multiply bignum1 bignum2)\n  (define (iter n result)\n    (if (is-zero? n)\n        result\n        (iter (predecessor n) (add bignum1 result))))\n  (iter bignum2 (zero)))\n\n; Factorial with bignums\n\n(define (factorial bignum)\n  (if (is-zero? bignum)\n      (successor (zero))\n      (multiply bignum (factorial (predecessor bignum)))))\n\n; Benchmarking\n\n(define (benchmark-in-base base-to-use)\n  (parameterize ((base base-to-use))\n    (printf \"Running factorial in base ~s:\\n\" (base))\n    (for ([n (in-range 6 11)])\n         (benchmark-factorial n))))\n\n(define (benchmark-factorial n)\n  (printf \"  ~s! (base ~s): \" n (base))\n  (time (factorial (int->bignum n))))\n\n(define (run-benchmarks)\n  (benchmark-in-base 2)\n  (benchmark-in-base 4)\n  (benchmark-in-base 10)\n  (benchmark-in-base 1000)\n  (benchmark-in-base 100000))\n\n; Finally, the results:\n;\n; Running factorial in base 2:\n;   6! (base 2): cpu time: 0 real time: 1 gc time: 0\n;   7! (base 2): cpu time: 4 real time: 3 gc time: 0\n;   8! (base 2): cpu time: 30 real time: 30 gc time: 0\n;   9! (base 2): cpu time: 267 real time: 268 gc time: 11\n;   10! (base 2): cpu time: 2530 real time: 2532 gc time: 24\n; Running factorial in base 4:\n;   6! (base 4): cpu time: 0 real time: 0 gc time: 0\n;   7! (base 4): cpu time: 3 real time: 3 gc time: 0\n;   8! (base 4): cpu time: 19 real time: 18 gc time: 0\n;   9! (base 4): cpu time: 161 real time: 161 gc time: 3\n;   10! (base 4): cpu time: 1561 real time: 1563 gc time: 14\n; Running factorial in base 10:\n;   6! (base 10): cpu time: 0 real time: 1 gc time: 0\n;   7! (base 10): cpu time: 2 real time: 1 gc time: 0\n;   8! (base 10): cpu time: 14 real time: 15 gc time: 1\n;   9! (base 10): cpu time: 133 real time: 133 gc time: 0\n;   10! (base 10): cpu time: 1268 real time: 1269 gc time: 13\n; Running factorial in base 1000:\n;   6! (base 1000): cpu time: 0 real time: 1 gc time: 0\n;   7! (base 1000): cpu time: 2 real time: 1 gc time: 0\n;   8! (base 1000): cpu time: 12 real time: 13 gc time: 0\n;   9! (base 1000): cpu time: 114 real time: 113 gc time: 2\n;   10! (base 1000): cpu time: 1114 real time: 1115 gc time: 15\n; Running factorial in base 100000:\n;   6! (base 100000): cpu time: 0 real time: 0 gc time: 0\n;   7! (base 100000): cpu time: 3 real time: 2 gc time: 0\n;   8! (base 100000): cpu time: 13 real time: 14 gc time: 0\n;   9! (base 100000): cpu time: 113 real time: 113 gc time: 2\n;   10! (base 100000): cpu time: 1116 real time: 1119 gc time: 14\n;\n; There is just too much recursion happening in order for me to be willing to\n; analyze why those are the results. successor and predecessor don't work in\n; constant time, which makes me unwilling to analyze how multiple and add\n; interact with them.\n;\n; If you want to reproduce the results, just uncomment the following line:\n;\n; (run-benchmarks)\n"
  },
  {
    "path": "scheme/eopl/02/02.scm",
    "content": "; EOPL exercise 2.02\n;\n; Analyze each of these proposed representations critically. To what extent do\n; they succeed or fail in satisfying the specification of the datatype?\n\n; All of the representations satisfy the specification fully.\n;\n; 1. Unary representation\n;\n; This is extremely memory hungry. It is also equivalent to using bignums with\n; base 1. It does not allow us to create very large numbers, but all the\n; operations are performed in constant time. If the memory is limitless, this\n; representation will allow us to create arbitrary large numbers.\n;\n; 2. Scheme number representation:\n;\n; Depending on whether the Scheme numbers are seamlessly converted to bignums\n; (which they usually are), this representation might not allow us to\n;\n; 3. Bignum representation:\n;\n; This representation is more memory-efficient than the first, but operations\n; are not in constant time. That is, calling successor on a n-sized list of\n; base - 1 will take O(n) time. It is, of course, the most sensible way to\n; implement numbers, provided that we implement the arithmetic operations by\n; depending on the representation, instead of the four observers.\n"
  },
  {
    "path": "scheme/eopl/02/03.scm",
    "content": "; EOPL exercise 2.03\n;\n; Define a representation of all the integers (negative and nonnegative) as\n; diff-trees, where a diff-tree is a list defined by the grammar\n;\n;   Diff-tree ::= (one) | (diff Diff-tree Diff-tree)\n;\n; The list (one) represents 1. If t₁ represents n₁ and t₂ represents n₂, then\n; (diff t₁ t₂) is a representation of n₁ - n₂.\n;\n; So both (one) and (diff (one) (diff (one) (one))) are representations of 1;\n; (diff (diff (one) (one)) (one)) is a representation of -1.\n;\n; 1. Show that every number has infinitely many representations in this\n;    system.\n; 2. Turn this representation of the integers into an implementation by\n;    writing zero, is-zero?, successor and predecessor, as specified on\n;    page 32, except that now the negative integers are also represented. Your\n;    procedures should take as input any of the multiple legal representations\n;    of an integer in this scheme. For example, if your successor procedure is\n;    given any of the infinitely many legal representations of 1, it should\n;    produce one of the legal representations of 2. It is permissible for\n;    different legal representations of 1 to yield different representations\n;    of 2.\n; 3. Write a proedure diff-tree-plus that does addition in this\n;    representation. Your procedure should be optimized for the diff-tree\n;    representation, and should do its work in a constant amount of time\n;    (independent of the size of its inputs). In particular, it should not be\n;    recursive.\n\n; 1. It's rather obvious that a number has infinitelly many representations.\n;\n; Anyway, if n is represented as (diff M S), then we can also represent it as\n; (diff (diff M (one)) (diff S (one))). It will be the same number. We can\n; apply this infinitely many times. This is not the only way to modify the\n; representation of the number, but it is the simplest.\n;\n; 2. Let's take a nice layered approach.\n;\n; First, here are constructors for the representation:\n\n(define (one) '(one))\n(define (diff left right) `(diff ,left ,right))\n\n; Here are some observers:\n\n(define (one? diff-tree) (eqv? (car diff-tree) 'one))\n(define (diff? diff-tree) (eqv? (car diff-tree) 'diff))\n(define (diff-first diff-tree) (cadr diff-tree))\n(define (diff-second diff-tree) (caddr diff-tree))\n\n; Here are a few higher-level observers minuend and subtrahend tread (one)\n; as (diff (one) (diff (one) (one))).\n\n(define (minuend diff-tree)\n  (if (one? diff-tree)\n      (one)\n      (diff-first diff-tree)))\n(define (subtrahend diff-tree)\n  (if (one? diff-tree)\n      (diff (one) (one))\n      (diff-second diff-tree)))\n\n; Here are the four operations we have to implement. Note that is-zero?\n; explicitly converts the diff-tree to an integer and compares it with 0.\n; Since we know how successor and predecessor work, there is probably a more\n; interesting way to check (without conversion), but I don't care enough to\n; figure it out.\n\n(define (zero)\n  (diff (one) (one)))\n\n(define (is-zero? n)\n  (define (to-int n)\n    (if (one? n)\n        1\n        (- (to-int (minuend n))\n           (to-int (subtrahend n)))))\n  (zero? (to-int n)))\n\n(define (successor n)\n  (diff (minuend n)\n        (diff (subtrahend n) (one))))\n\n(define (predecessor n)\n  (diff n (one)))\n\n; 3. diff-tree-plus\n\n(define (diff-tree-plus diff-tree-1 diff-tree-2)\n  (diff diff-tree-1\n        (diff (subtrahend diff-tree-2)\n              (minuend diff-tree-2))))\n"
  },
  {
    "path": "scheme/eopl/02/04.scm",
    "content": "; EOPL exercise 2.04\n;\n; Consider the data type of stacks of values, with an interface consisting of\n; the procedures empty-stack, push, pop, and empty-stack?. Write a\n; specification for these operations in the style of the example above. Which\n; operations are constructors and which are observers?\n\n; (empty-stack)          = [∅]\n; (push [stack] val)     = [val|stack]\n; (pop [stack])          = { error if stack is ∅\n;                          { [tail], if stack is [head|tail]\n; (empty-stack? [stack]) = { #t if stack is ∅\n;                          { #f otherwise\n;\n; empty-stack? is a obsever, all others are constructors.\n;\n; Note that this is really missing an observer top in order to be useful.\n"
  },
  {
    "path": "scheme/eopl/02/05.scm",
    "content": "; EOPL exercise 2.05\n;\n; We can use any data structure for representing environments, if we can\n; distinguish empty environments from non-empty ones, and in which one can\n; extract the pieces of a non-empty environment. Implement environments using\n; a representation in which the empty environment is represented as the empty\n; list, and in which extend-env builds an environment that looks like\n;\n;     +---+---+\n;     | o | o ---> saved-env\n;     +-|-+---+\n;       |\n;       V\n;     +---+---+\n;     | o | o ---> saved-val\n;     +-|-+---+\n;       |\n;       V\n;   saved-var\n;\n; This is called an a-list or association-list representation.\n\n(define (empty-env)\n  '())\n\n(define (extend-env var val env)\n  (cons (cons var val)\n        env))\n\n(define (apply-env env var)\n  (cond ((null? env) (eopl:error 'apply-env \"Variable not found\"))\n        ((eqv? (caar env) var) (cdar env))\n        (else (apply-env (cdr env) var))))\n"
  },
  {
    "path": "scheme/eopl/02/06.scm",
    "content": "; EOPL exercise 2.06\n;\n; Invent at least three different representations of the environment interface\n; and implement them.\n\n; 1. 2-list representation\n;    ((a 1) (b 2) (c 3) ...)\n\n(define empty-env '())\n(define extend-env '())\n(define apply-env '())\n\n(define (use-2-list)\n  (set! empty-env\n    (lambda () '()))\n\n  (set! extend-env\n    (lambda (var val env)\n      (cons (list var val)\n            env)))\n\n  (set! apply-env\n    (lambda (env var)\n      (cond ((null? env) (eopl:error 'apply-env \"Variable not found\"))\n            ((eqv? (caar env) var) (cadar env))\n            (else (apply-env (cdr env) var))))))\n\n; 2. two lists representation\n;    ((a b c ...) (1 2 3 ...))\n\n(define (use-two-lists)\n  (set! empty-env\n    (lambda () '(() ())))\n\n  (set! extend-env\n    (lambda (var val env)\n      (list (cons var (car env))\n            (cons val (cadr env)))))\n\n  (set! apply-env\n    (lambda (env var)\n      (cond ((null? (car env)) (eopl:error 'apply-env \"Variable not found\"))\n            ((eqv? (caar env) var) (caadr env))\n            (else (apply-env (list (cdar env) (cdadr env)) var))))))\n\n; 2. var-val list\n;    (a 1 b 2 c 3 ...)\n\n(define (use-var-val-list)\n  (set! empty-env\n    (lambda () '()))\n\n  (set! extend-env\n    (lambda (var val env)\n      (cons var\n            (cons val env))))\n\n  (set! apply-env\n    (lambda (env var)\n      (cond ((null? env) (eopl:error 'apply-env \"Variable not found\"))\n            ((eqv? (car env) var) (cadr env))\n            (else (apply-env (cddr env) var))))))\n"
  },
  {
    "path": "scheme/eopl/02/07.scm",
    "content": "; EOPL exercise 2.07\n;\n; Rewrite apply-env in figure 2.1 to give a more informative error message.\n\n; This is the original code:\n\n(define empty-env\n  (lambda () (list 'empty-env)))\n\n(define extend-env\n  (lambda (var val env)\n    (list 'extend-env var val env)))\n\n(define apply-env\n  (lambda (env search-var)\n    (cond\n      ((eqv? (car env) 'empty-env)\n       (report-no-binding-found search-var))\n      ((eqv? (car env) 'extend-env)\n       (let ((saved-var (cadr env))\n             (saved-val (caddr env))\n             (saved-env (cadddr env)))\n         (if (eqv? search-var saved-var)\n           saved-val\n           (apply-env saved-env search-var))))\n      (else\n        (report-invalid-env env)))))\n\n(define report-no-binding-found\n  (lambda (search-var)\n    (eopl:error 'apply-env \"No binding for ~s\" search-var)))\n\n(define report-invalid-env\n  (lambda (env)\n    (eopl:error 'apply-env \"Bad environment: ~s\" env)))\n\n; Here's the rewritten apply-env\n\n(define (apply-env search-env search-var)\n  (define (search env)\n    (cond ((eqv? (car env) 'empty-env)\n           (eopl:error 'apply-env \"Variable ~s not found in environment: ~s\" search-var search-env))\n          ((eqv? (car env) 'extend-env)\n           (let ((saved-var (cadr env))\n                 (saved-val (caddr env))\n                 (saved-env (cadddr env)))\n             (if (eqv? search-var saved-var)\n                 saved-val\n                 (search saved-env))))\n          (else\n           (report-invalid-env env))))\n  (search search-env))\n"
  },
  {
    "path": "scheme/eopl/02/08.scm",
    "content": "; EOPL exercise 2.08\n;\n; Add to the environment interface an observer called empty-env? and implement\n; it using the a-list representation.\n\n(load-relative \"05.scm\")\n\n(define (empty-env? env)\n  (null? env))\n"
  },
  {
    "path": "scheme/eopl/02/09.scm",
    "content": "; EOPL exercise 2.09\n;\n; Add to the environment interface an observer called has-binding? that takes\n; an environment env and a variable s and tests to see if s has an associated\n; value in env. Implement using the a-list representation.\n\n(load-relative \"05.scm\")\n\n(define (has-binding? env var)\n  (cond ((null? env) #f)\n        ((eqv? (caar env) var) #t)\n        (else (has-binding? (cdr env) var))))\n"
  },
  {
    "path": "scheme/eopl/02/10.scm",
    "content": "; EOPL exercise 2.10\n;\n; Add to the environment interface a constructor extend-env*, and implement it\n; using the a-list representation. This constructor takes a list of variables,\n; a list of values of the same length, and an environment, and is specified by\n;\n;   (extend-env* (varᵤ ... varᵤ) (valᵤ ... valᵤ) [f]) = [g],\n;     where g(var) = { valᵢ     if var = varᵢ for some i such that 1 ≤ i ≤ u\n;                    { f(val)   otherwise\n\n(load-relative \"05.scm\")\n\n(define (extend-env* vars vals env)\n  (if (null? vars)\n      env\n      (extend-env (car vars) (car vals)\n                  (extend-env* (cdr vars) (cdr vals) env))))\n"
  },
  {
    "path": "scheme/eopl/02/11.scm",
    "content": "; EOPL exercise 2.11\n;\n; A naive implementation of extend-env* from the preceding exercise requires\n; time proportional to k to run. It is possible to represent environments so\n; that extend-env* requires only constant time: represent the empty\n; environment by the empty list, and represent a non-empty environment by the\n; data structure\n;\n;      +---+---+\n;      | o | o ---> saved-env\n;      +-|-+---+\n;        |\n;        V\n;      +---+---+\n;      | o | o ---> saved-vals\n;      +-|-+---+\n;        |\n;        V\n;    saved-vars\n;\n; Such an environment might look like\n;\n;                 backbone\n;    +---+---+       V        +---+---+             +---+---+\n;    | o | o ---------------->| o | o ------------->| o | o ------> rest of environment\n;    +-|-+---+                +-|-+---+             +-|-+---+\n;      |                        |                     |\n;      V                        V                     V\n;    +---+---+                +---+---+             +---+---+\n;    | o | o ---> (11 12 13)  | o | o ---> (66 77)  | o | o ---> (88 99)\n;    +-|-+---+                +-|-+---+             +-|-+---+\n;      |                        |                     |\n;      V                        V                     V\n;   (a b c)                   (x z)                 (x y)\n;\n; This is called the ribcage representation. The environment is represented as\n; a list of pairs called ribs; each left rib is a list of variables and each\n; right rib is the corresponding list of values.\n;\n; Implement the environment interface, including extend-env*, in this\n; representation.\n\n(define (empty-env)\n  '())\n\n(define (extend-env var val env)\n  (extend-env* (list var) (list val) env))\n\n(define (extend-env* vars vals env)\n  (cons (cons vars vals) env))\n\n(define (apply-env env var)\n  (define (scan vars vals)\n    (cond ((null? vars) (apply-env (cdr env) var))\n          ((eq? (car vars) var) (car vals))\n          (else (scan (cdr vars) (cdr vals)))))\n  (if (null? env)\n      (eopl:error 'apply-env \"Variable not found: ~s\" var)\n      (scan (caar env) (cdar env))))\n"
  },
  {
    "path": "scheme/eopl/02/12.scm",
    "content": "; EOPL exercise 2.12\n;\n; Implement the stack data type of exercise 2.4 using a procedural\n; representation.\n\n; I just don't get this. Anyway.\n\n(define (empty-stack? stack)\n  (stack (lambda (top rest) (null? rest))))\n\n(define (empty-stack)\n  (lambda (proc)\n    (proc #f '())))\n\n(define (push val stack)\n  (lambda (proc)\n    (proc val stack)))\n\n(define (pop stack)\n  (stack (lambda (top rest) rest)))\n"
  },
  {
    "path": "scheme/eopl/02/13.scm",
    "content": "; EOPL exercise 2.13\n;\n; Extend the procedural representation to implement empty-env? by representing\n; the environment by a list of two procedures: one that returns the value\n; associated with a variable, as before, and one that returns whether or not\n; the environment is empty.\n\n(define empty-env\n  (lambda ()\n    (list (lambda (search-var)\n            (report-no-binding-found search-var))\n          (lambda () #t))))\n\n(define extend-env\n  (lambda (saved-var saved-val saved-env)\n    (list (lambda (search-var)\n            (if (eqv? search-var saved-var)\n              saved-val\n              (apply-env saved-env search-var)))\n          (lambda () #f))))\n\n(define apply-env\n  (lambda (env search-var)\n    ((car env) search-var)))\n\n(define empty-env?\n  (lambda (env)\n    ((cadr env))))\n"
  },
  {
    "path": "scheme/eopl/02/14.scm",
    "content": "; EOPL exercise 2.14\n;\n; Extend the representation of the preceding exercise to include a third\n; procedure that implements has-binding? (see exercise 2.9).\n\n(define empty-env\n  (lambda ()\n    (list (lambda (search-var)\n            (report-no-binding-found search-var))\n          (lambda () #t)\n          (lambda (search-var) #f))))\n\n(define extend-env\n  (lambda (saved-var saved-val saved-env)\n    (list (lambda (search-var)\n            (if (eqv? search-var saved-var)\n              saved-val\n              (apply-env saved-env search-var)))\n          (lambda () #f)\n          (lambda (search-var)\n            (if (eqv? search-var saved-var)\n              #t\n              (has-binding? saved-env search-var))))))\n\n(define apply-env\n  (lambda (env search-var)\n    ((car env) search-var)))\n\n(define empty-env?\n  (lambda (env)\n    ((cadr env))))\n\n(define has-binding?\n  (lambda (env search-var)\n    ((caddr env) search-var)))\n"
  },
  {
    "path": "scheme/eopl/02/15.scm",
    "content": "; EOPL exercise 2.15\n;\n; Implement the lambda-calculus interface for the representations specified by\n; the grammar above.\n\n(define (var-exp var) var)\n(define (var-exp? exp) (symbol? exp))\n(define (var-exp->var exp) exp)\n\n(define (lambda-exp var body) `(lambda (,var) ,body))\n(define (lambda-exp? exp) (and (pair? exp) (eqv? (car exp) 'lambda)))\n(define (lambda-exp->bound-var exp) (caadr exp))\n(define (lambda-exp->body exp) (caddr exp))\n\n(define (app-exp rator rand) (list rator rand))\n(define (app-exp? exp) (and (pair? exp) (not (eqv? (car exp) 'lambda))))\n(define (app-exp->rator exp) (car exp))\n(define (app-exp->rand exp) (cadr exp))\n"
  },
  {
    "path": "scheme/eopl/02/16.scm",
    "content": "; EOPL exercise 2.16\n;\n; Modify the implementation to use a representation in which there are no\n; parentheses around the bound variable in a lambda expression.\n\n(define (var-exp var) var)\n(define (var-exp? exp) (symbol? exp))\n(define (var-exp->var exp) exp)\n\n(define (lambda-exp var body) (list 'lambda var body))\n(define (lambda-exp? exp) (and (pair? exp) (eqv? (car exp) 'lambda)))\n(define (lambda-exp->bound-var exp) (cadr exp))\n(define (lambda-exp->body exp) (caddr exp))\n\n(define (app-exp rator rand) (list rator rand))\n(define (app-exp? exp) (and (pair? exp) (not (eqv? (car exp) 'lambda))))\n(define (app-exp->rator exp) (car exp))\n(define (app-exp->rand exp) (cadr exp))\n"
  },
  {
    "path": "scheme/eopl/02/17.scm",
    "content": "; EOPL exercise 2.17\n;\n; Invent at least two other representations of the data type of\n; lambda-calculus expressions and implement them.\n\n(define var-exp (void))\n(define var-exp? (void))\n(define var-exp->var (void))\n\n(define lambda-exp (void))\n(define lambda-exp? (void))\n(define lambda-exp->bound-var (void))\n(define lambda-exp->body (void))\n\n(define app-exp (void))\n(define app-exp? (void))\n(define app-exp->rator (void))\n(define app-exp->rand (void))\n\n; 1. Lc-exp ::= Identifier\n;           ::= (Identifier -> Lc-exp)\n;           ::= (Lc-exp (Lc-exp))\n\n(define (use-representation-1)\n  (set! var-exp (lambda (var) var))\n  (set! var-exp? symbol?)\n  (set! var-exp->var (lambda (var-exp) var-exp))\n\n  (set! lambda-exp (lambda (var body) (list var '-> body)))\n  (set! lambda-exp? (lambda (exp) (and (pair? exp)\n                                       (pair? (cdr exp))\n                                       (eqv? (cadr exp) '->))))\n  (set! lambda-exp->bound-var car)\n  (set! lambda-exp->body caddr)\n\n  (set! app-exp (lambda (rator rand) `(,rator (,rand))))\n  (set! app-exp? (lambda (exp) (and (pair? exp)\n                                    (pair? (cdr exp))\n                                    (pair? (cadr exp)))))\n  (set! app-exp->rator car)\n  (set! app-exp->rand caadr))\n\n; 2. Lc-exp ::= (var-exp Identifier)\n;           ::= (lambda-exp Identifier Lc-exp)\n;           ::= (app-exp Lc-exp Lc-exp)\n\n(define (use-representation-2)\n  (define (tagged-list? exp tag) (and (pair? exp)\n                                      (eqv? (car exp) tag)))\n\n  (set! var-exp (curry list 'var-exp))\n  (set! var-exp? (curryr tagged-list? 'var-exp))\n  (set! var-exp->var cadr)\n\n  (set! lambda-exp (curry list 'lambda-exp))\n  (set! lambda-exp? (curryr tagged-list? 'lambda-exp))\n  (set! lambda-exp->bound-var cadr)\n  (set! lambda-exp->body caddr)\n\n  (set! app-exp (curry list 'app-exp))\n  (set! app-exp? (curryr tagged-list? 'app-exp))\n  (set! app-exp->rator cadr)\n  (set! app-exp->rand caddr))\n"
  },
  {
    "path": "scheme/eopl/02/18.scm",
    "content": "; EOPL exercise 2.18\n;\n; We usually represent a sequence of values as a list. In this representation,\n; it is easy to move from one element in a sequence to the next, but it is\n; hard to move form one element to the preceding one without the help of\n; context arguments. Implement non-empty bidirectional sequences of integers,\n; as suggested by the grammar\n;\n;   NodeInSequence ::= (Int Listof(Int) Listof(Int))\n;\n; The first list of numbers is the elements of the sequence preceding the\n; current one, in reverse order, and the second list is the elements of the\n; sequence after the current one. For example, (6 (5 4 3 2 1) (7 8 9))\n; represents the list (1 2 3 4 5 6 7 8 9), with the focus on the element 6.\n;\n; In this representation, implement the procedure number->sequence, which\n; takes a number and produces a sequence consisting of exactly that number.\n; Also implement current-element, move-to-left, move-to-right, insert-to-left,\n; insert-to-right, at-left-end?, and at-right-end?\n;\n; For example:\n;\n; > (number->sequence 7)\n; (7 () ())\n; > (current-element '(6 (5 4 3 2 1) (7 8 9)))\n; 6\n; > (move-to-left '(6 (5 4 3 2 1) (7 8 9)))\n; (5 (4 3 2 1) (6 7 8 9))\n; > (move-to-right '(6 (5 4 3 2 1) (7 8 9)))\n; (7 (6 5 4 3 2 1) (8 9))\n; > (insert-to-left 13 '(6 (5 4 3 2 1) (7 8 9)))\n; (6 (13 5 4 3 2 1) (7 8 9))\n; > (insert-to-right 13 '(6 (5 4 3 2 1) (7 8 9)))\n; (6 (5 4 3 2 1) (13 7 8 9))\n;\n; The procedure move-to-right should fail if its arguments is at the right end\n; of the sequence, and the procedure move-to-left should fail if its argument\n; is at the left end of the sequence.\n\n(define (number->sequence num)\n  `(,num () ()))\n\n(define (current-element seq)\n  (car seq))\n\n(define (move-to-left seq)\n  (if (null? (cadr seq))\n      (eopl:error 'move-to-left \"Left sequence is empty: ~s\" seq)\n      (list (caadr seq) (cdadr seq) (cons (car seq) (caddr seq)))))\n\n(define (move-to-right seq)\n  (if (null? (caddr seq))\n      (eopl:error 'move-to-left \"Right sequence is empty: ~s\" seq)\n      (list (caaddr seq) (cons (car seq) (cadr seq)) (cdaddr seq))))\n\n(define (insert-to-left num seq)\n  (list (car seq) (cons num (cadr seq)) (caddr seq)))\n\n(define (insert-to-right num seq)\n  (list (car seq) (cadr seq) (cons num (caddr seq))))\n\n(define (at-left-end? seq)\n  (null? (cadr seq)))\n\n(define (at-right-end? seq)\n  (null? (caddr seq)))\n"
  },
  {
    "path": "scheme/eopl/02/19.scm",
    "content": "; EOPL exercise 2.19\n;\n; A binary tree with empty leaves and with interior nodes labeled with\n; integers could be represented using the grammar\n;\n;   Bintree ::= () | (Int Bintree Bintree)\n;\n; In this representation, implement the procedure number->bintree, which takes\n; a number and produces a binary tree consisting of a single node, containing\n; that number. Also implement current-element, move-to-left-son,\n; move-to-right-son, at-leaf?, insert-to-left, and insert-to-right. For\n; example,\n;\n; > (number->bintree 13)\n; (13 () ())\n; > (define t1 (insert-to-right 14\n;                (insert-to-left 12)\n;                  (number->bintree 13)))\n; > t1\n; (13\n;   (12 () ())\n;   (14 () ()))\n; > (move-to-left t1)\n; (12 () ())\n; > (current-element (move-to-left-son t1))\n; 12\n; > (at-leaf? (move-to-right-son (move-to-left-son t1)))\n; #t\n; > (insert-to-left 15 t1)\n; (13\n;   (15\n;     (12 () ())\n;     ())\n;   (14 () ()))\n\n(define (number->bintree n)\n  `(,n () ()))\n\n(define (current-element tree)\n  (car tree))\n\n(define (move-to-left-son tree)\n  (cadr tree))\n\n(define (move-to-right-son tree)\n  (caddr tree))\n\n(define (at-leaf? tree)\n  (null? tree))\n\n(define (insert-to-left n tree)\n  (list (car tree)\n        (list n (cadr tree) '())\n        (caddr tree)))\n\n(define (insert-to-right n tree)\n  (list (car tree)\n        (cadr tree)\n        (list n '() (caddr tree))))\n"
  },
  {
    "path": "scheme/eopl/02/20.scm",
    "content": "; EOPL exercise 2.20\n;\n; In the representation of binary trees in exercise 2.19 it is easy to move\n; from a parent node to one of its sons, but it is impossible to move form a\n; son to its parent without the help of context arguments. Extend the\n; representation of lists in exercise 2.18 to represent nodes in a binary\n; tree. As a hint, consider representing the portion of the tree above the\n; current node by a reversed list, as in exercise 2.18.\n;\n; In this representation, implement the procedures from exercise 2.19. Also\n; implement move-up, at-root? and at-leaf?.\n;\n(define (number->bintree n)\n  `(,n () () ()))\n\n(define (current-element tree)\n  (car tree))\n\n(define (move-to-left-son tree)\n  (let ((son (cadr tree)))\n    (if (null? son)\n        (list '() '() '() tree)\n        (list (car son) (cadr son) (caddr son) tree))))\n\n(define (move-to-right-son tree)\n  (let ((son (caddr tree)))\n    (if (null? son)\n        (list '() '() '() tree)\n        (list (car son) (cadr son) (caddr son) tree))))\n\n(define (move-up tree)\n  (cadddr tree))\n\n(define (at-leaf? tree)\n  (null? (car tree)))\n\n(define (at-root? tree)\n  (null? (cadddr tree)))\n\n(define (insert-to-left n tree)\n  (list (car tree)\n        (list n (cadr tree) '() '())\n        (caddr tree)\n        (cadddr tree)))\n\n(define (insert-to-right n tree)\n  (list (car tree)\n        (cadr tree)\n        (list n '() (caddr tree) '())\n        (cadddr tree)))\n"
  },
  {
    "path": "scheme/eopl/02/21.scm",
    "content": "; EOPL exercise 2.21\n;\n; Implement the data type of environments, as in section 2.2.2, using\n; define-datatype. Then include has-binding? of exercise 2.9.\n\n(define (any? obj) #t)\n\n(define-datatype env env?\n  (empty-env)\n  (extend-env (var symbol?)\n              (val any?)\n              (enclosing env?)))\n\n(define (has-binding? search-env search-var)\n  (cases env search-env\n    (empty-env () #f)\n    (extend-env (var val enclosing)\n                (or (eqv? var search-var)\n                    (has-binding? enclosing search-var)))))\n"
  },
  {
    "path": "scheme/eopl/02/22.scm",
    "content": "; EOPL exercise 2.22\n;\n; Using define-datatype, implement the stack data type of exercise 2.4.\n\n(define-datatype stack stack?\n  (empty-stack)\n  (push (var (lambda (x) #t))\n        (frame stack?)))\n\n(define (empty-stack? st)\n  (cases stack st\n    (empty-stack () #t)\n    (push (var frame) #f)))\n\n(define (pop st)\n  (cases stack st\n    (empty-stack () (eopl:error 'pop \"Empty stack.\"))\n    (push (var frame) frame)))\n"
  },
  {
    "path": "scheme/eopl/02/23.scm",
    "content": "; EOPL exercise 2.23\n;\n; The define of lc-exp ignores the condition in definition 1.1.8 that says\n; \"Identifier is any symbol other than lambda.\" Modify the definition of\n; identifier? to capture this condition. As a hint, remember that any\n; predicate can be used in define datatype, even ones you define.\n\n(define (id? sym)\n  (and (symbol? sym)\n       (not (eqv? sym 'lambda))))\n\n(define-datatype lc-exp lc-exp?\n  (var-exp\n    (var id?))\n  (lambda-exp\n    (bound-var id?)\n    (body lc-exp?))\n  (app-exp\n    (rator lc-exp?)\n    (rand lc-exp?)))\n"
  },
  {
    "path": "scheme/eopl/02/24.scm",
    "content": "; EOPL exercise 2.24\n;\n; Here is a definition of binary trees using define-datatype.\n;\n; (define-datatype bintree bintree?\n;   (leaf-node\n;     (num integer?))\n;   (interior-node\n;     (key symbol?)\n;     (left bintree?)\n;     (right bintree?)))\n;\n; Implement a bintree-to-list procedure for binary trees, so that\n; (bintree-to-list (interior-node 'a (leaf-node 3) (leaf-node 4))) returns the\n; list\n;\n; (interior-node\n;   a\n;   (leaf-node 3)\n;   (leaf-node 4))\n\n(define-datatype bintree bintree?\n  (leaf-node\n    (num integer?))\n  (interior-node\n    (key symbol?)\n    (left bintree?)\n    (right bintree?)))\n\n(define (bintree-to-list tree)\n  (cases bintree tree\n    (leaf-node (n)\n      (list 'leaf-node n))\n    (interior-node (key left right)\n      (list 'interior-node\n            key\n            (bintree-to-list left)\n            (bintree-to-list right)))))\n"
  },
  {
    "path": "scheme/eopl/02/25.scm",
    "content": "; EOPL exercise 2.25\n;\n; Use cases to write max-interior, which takes a binary tree of integers (as\n; in the preceding exercise) with at least one interior node and returns the\n; symbol associated with an interior node with a maximal leaf sum.\n;\n; > (define tree-1\n;     (interior-node 'foo (leaf-node 2) (leaf-node 3)))\n; > (define tree-2\n;     (interior-node 'bar (leaf-node -1) tree-1))\n; > (define tree-3\n;     (interior-node 'baz tree-2 (leaf-node 1)))\n; > (max-interior tree-2)\n; foo\n; > (max-interior tree-3)\n; baz\n;\n; The last invocation of max-interior might also have returned foo, since both\n; the foo and baz nodes have a leaf sum of 5.\n\n(define-datatype bintree bintree?\n  (leaf-node\n    (num integer?))\n  (interior-node\n    (key symbol?)\n    (left bintree?)\n    (right bintree?)))\n\n(define (key-of tree)\n  (cases bintree tree\n    (leaf-node (num) (eopl:error 'key-of \"Leaf node ~s\" num))\n    (interior-node (key left right) key)))\n\n(define (tree-sum tree)\n  (cases bintree tree\n    (leaf-node (num) num)\n    (interior-node (key left right)\n      (+ (tree-sum left) (tree-sum right)))))\n\n(define (interior? tree)\n  (cases bintree tree\n    (leaf-node (num) #f)\n    (interior-node (key left right) #t)))\n\n(define (max-node tree)\n  (cases bintree tree\n    (leaf-node (num) #f)\n    (interior-node (key left right)\n      (let ((max-child (cond ((and (interior? left) (interior? right))\n                              (if (< (tree-sum left) (tree-sum right))\n                                  right\n                                  left))\n                             ((and (interior? left)) left)\n                             ((and (interior? right)) right)\n                             (else #f))))\n        (cond ((not max-child) tree)\n              ((< (tree-sum max-child) (tree-sum tree)) tree)\n              (else max-child))))))\n\n(define (max-interior tree)\n  (key-of (max-node tree)))\n"
  },
  {
    "path": "scheme/eopl/02/26.scm",
    "content": "; EOPL exercise 2.26\n;\n; Here is another version of exercise 1.33. Consider a set of trees given by\n; the following grammar:\n;\n;   Red-blue-tree    ::= Red-blue-subtree\n;   Red-blue-subtree ::= (red-node Red-blue-subtree Red-blue-subtree)\n;                        (blue-node {Red-blue-subtree}*)\n;                        (leaf-node Int)\n;\n; Write an equivalent definition using define-datatype, and use the resulting\n; interface to write a procedure that takes a tree and builds a tree of the\n; same shape, except that each leaf node is replaced by a leaf node that\n; contains the number of red nodes on the path between it and the root.\n\n(define-datatype red-blue-tree red-blue-tree?\n  (red-node\n    (left red-blue-tree?)\n    (right red-blue-tree?))\n  (blue-node\n    (trees (list-of red-blue-tree?)))\n  (leaf-node\n    (num integer?)))\n\n(define (list-of predicate)\n  (lambda (object)\n    (or (null? object)\n        (and (pair? object)\n             (predicate (car object))\n             ((list-of predicate) (cdr object))))))\n\n(define (mark-with-red-depth tree)\n  (define (iter tree counter)\n    (cases red-blue-tree tree\n      (red-node (left right)\n        (red-node (iter left (+ counter 1))\n                  (iter right (+ counter 1))))\n      (blue-node (nodes)\n        (blue-node (map (curryr iter counter) nodes)))\n      (leaf-node (num)\n        (leaf-node counter))))\n  (iter tree 0))\n"
  },
  {
    "path": "scheme/eopl/02/27.scm",
    "content": "; EOPL exercise 2.27\n;\n; Draw the abstract syntax tree for the lambda calculus expressions\n;\n; ((lambda (a) (a b)) c)\n;\n; (lambda (x)\n;   (lambda (y)\n;     ((lambda (x)\n;        (x y))\n;      x)))\n\n; Expression: ((lambda (a) (a b)) c)\n;\n;                      +---------+\n;                      | app-exp |\n;                      +---------+\n;                      /         \\\n;                  rator         rand\n;                   /               \\\n;        +------------+             +---------+\n;        | lambda-exp |             | var-exp |\n;        +------------+             +---------+\n;          /        \\                    |\n;     bound-var     body                var\n;        /             \\                 |\n;     +---+          +---------+       +---+\n;     | a |          | app-exp |       | c |\n;     +---+          +---------+       +---+\n;                     /       \\\n;                 rator       rand\n;                  /             \\\n;           +---------+       +---------+\n;           | var-exp |       | var-exp |\n;           +---------+       +---------+\n;                |                 |\n;               var               var\n;                |                 |\n;              +---+             +---+\n;              | a |             | b |\n;              +---+             +---+\n;\n;\n;\n; Expression: (lambda (x)\n;               (lambda (y)\n;                 ((lambda (x)\n;                    (x y))\n;                  x)))\n;\n;         +------------+\n;         | lambda-exp |\n;         +------------+\n;           /        \\\n;      bound-var     body\n;        /              \\\n;     +---+        +------------+\n;     | x |        | lambda-exp |\n;     +---+        +------------+\n;                    /        \\\n;               bound-var     body\n;                 /              \\\n;              +---+         +---------+\n;              | y |         | app-exp |\n;              +---+         +---------+\n;                             /       \\\n;                         rator       rand\n;                          /             \\\n;              +------------+           +---------+\n;              | lambda-exp |           | var-exp |\n;              +------------+           +---------+\n;                /        \\                  |\n;           bound-var     body              var\n;             /              \\               |\n;          +---+         +---------+       +---+\n;          | x |         | app-exp |       | x |\n;          +---+         +---------+       +---+\n;                         /       \\\n;                     rator       rand\n;                      /             \\\n;              +---------+         +---------+\n;              | var-exp |         | var-exp |\n;              +---------+         +---------+\n;                   |                   |\n;                  var                 var\n;                   |                   |\n;                 +---+               +---+\n;                 | x |               | y |\n;                 +---+               +---+\n"
  },
  {
    "path": "scheme/eopl/02/28.scm",
    "content": "; EOPL exercise 2.28\n;\n; Write an unparser that converts the abstract syntax of an lc-exp into a\n; string that matches the second grammar in this section (page 52).\n\n(define (id? sym)\n  (and (symbol? sym)\n       (not (eqv? sym 'lambda))))\n\n(define-datatype lc-exp lc-exp?\n  (var-exp\n    (var id?))\n  (lambda-exp\n    (bound-var id?)\n    (body lc-exp?))\n  (app-exp\n    (rator lc-exp?)\n    (rand lc-exp?)))\n\n(define (unparse exp)\n  (cases lc-exp exp\n    (var-exp (name)\n      (symbol->string name))\n    (lambda-exp (bound-var body)\n      (format \"(lambda (~a) ~a)\" bound-var (unparse body)))\n    (app-exp (rator rand)\n      (format \"(~a ~a)\" (unparse rator) (unparse rand)))))\n\n"
  },
  {
    "path": "scheme/eopl/02/29.scm",
    "content": "; EOPL exercise 2.29\n;\n; Where a Kleene star or plus (page 7) is used in concrete syntax, it is most\n; convenient to use a list of associated subtrees when constructing an\n; abstract syntax tree. For example, if the grammar for lambda-calculus\n; expressions had been\n;\n;   Lc-exp ::= Identifier\n;              +---------------+\n;              | var-exp (var) |\n;              +---------------+\n;\n;          ::= (lambda ({Identifier}*) Lc-exp)\n;              +------------------------------+\n;              | lambda-exp (bound-vars body) |\n;              +------------------------------+\n;\n;          ::= (Lc-exp {Lc-exp}*)\n;              +-----------------------+\n;              | app-exp (rator rands) |\n;              +-----------------------+\n;\n; then the predicate for the bound-vars field could be (list-of identifier?),\n; and the predicate for the rands fields could be (list-of lc-exp?). Write a\n; define-datatype and a parser for this grammar that works in this way.\n\n(define (id? sym)\n  (and (symbol? sym)\n       (not (eqv? sym 'lambda))))\n\n(define-datatype lc-exp lc-exp?\n  (var-exp\n    (var id?))\n  (lambda-exp\n    (args (list-of id?))\n    (body lc-exp?))\n  (app-exp\n    (rator lc-exp?)\n    (rands (list-of lc-exp?))))\n\n(define (parse sexp)\n  (cond ((eqv? sexp 'lambda)\n         (eopl:error 'parse \"lambda is not a valid identifier\"))\n        ((symbol? sexp)\n         (var-exp sexp))\n        ((and (pair? sexp)\n              (eqv? (car sexp) 'lambda))\n         (lambda-exp (cadr sexp) (parse (caddr sexp))))\n        ((and (pair? sexp))\n         (app-exp (parse (car sexp))\n                  (map parse (cdr sexp))))\n        (else\n         (eopl:error 'parse \"Don't know how to parse ~s\" sexp))))\n"
  },
  {
    "path": "scheme/eopl/02/30.scm",
    "content": "; EOPL exercise 2.30\n;\n; The procedure parse-expression as defined above is fragile: it does not\n; detect several possible syntactic errors, such as (a b c), and aborts with\n; inappropriate error messages for other expressions, such as (lambda). Modify\n; it so that it is robust, accepting any s-exp and issuing an appropriate\n; error message if the s-exp does not represent a lambda-calculus expression.\n\n(load-relative \"23.scm\")\n\n(define (parse datum)\n  (cond ((symbol? datum)\n         (when (eqv? datum 'lambda)\n           (eopl:error 'parse \"lambda is not a valid identifier\"))\n         (var-exp datum))\n        ((and (pair? datum)\n              (eqv? (car datum) 'lambda))\n         (unless (= (length datum) 3)\n           (eopl:error 'parse \"lambda requires two components. given: ~s\" datum))\n         (when (symbol? (cadr datum))\n           (eopl:error 'parse \"lambda requires an arglist. given: ~s\" (cadr datum)))\n         (unless (= (length (cadr datum)) 1)\n           (eopl:error 'parse \"lambda requires exactly one argument. given: ~s\" (cadr datum)))\n         (lambda-exp (car (cadr datum))\n                     (parse (caddr datum))))\n        ((pair? datum)\n         (unless (= (length datum) 2)\n           (eopl:error 'parse \"application requires two components. given: ~s\" datum))\n         (app-exp (parse (car datum))\n                  (parse (cadr datum))))\n        (else (eopl:error 'parse \"Invalid syntax: ~s\" datum))))\n\n\n"
  },
  {
    "path": "scheme/eopl/02/31.scm",
    "content": "; EOPL exercise 2.31\n;\n; Sometimes it is useful to specify a concrete syntax as a sequence of symbols\n; and integers, surrounded by parentheses. For example, one might define the\n; set of prefix lists by\n;\n;   Prefix-list ::= (Prefix-exp)\n;   Prefix-exp  ::= Int\n;               ::= - Prefix-exp Prefix-exp\n;\n; so that (- - 3 2 - 4 - 12 7) is a legal prefix list. This is sometimes\n; called Polish prefix notation, after its inventor, Jan Łukasiewicz. Write a\n; parser to convert a prefix-list of the abstract syntax\n;\n; (define-datatype prefix-exp prefix-exp?\n;   (const-exp\n;     (num integer?))\n;   (diff-exp\n;     (operand1 prefix-exp?)\n;     (operand2 prefix-exp?)))\n;\n; so that the example above produces the same abstract syntax tree as the\n; sequence of constructors\n;\n; (diff-exp\n;   (diff-exp\n;     (const-exp 3)\n;     (const-exp 2))\n;   (diff-exp\n;     (const-exp 4)\n;     (diff-exp\n;       (const-exp 12)\n;       (const-exp 7))))\n;\n; As a hit, consider writing a procedure that takes a list and produces a\n; prefix-exp and the list of leftover list elements.\n\n(define-datatype prefix-exp prefix-exp?\n  (const-exp\n    (num integer?))\n  (diff-exp\n    (operand1 prefix-exp?)\n    (operand2 prefix-exp?)))\n\n(define (read-prefix-exp datum)\n  (cond ((null? datum)\n         (eopl:error 'parse \"Unexpected end of input\"))\n        ((number? (car datum))\n         (cons (const-exp (car datum))\n               (cdr datum)))\n        ((eqv? (car datum) '-)\n         (let* ((result-1 (read-prefix-exp (cdr datum)))\n                (operand-1 (car result-1))\n                (suffix-1 (cdr result-1))\n                (result-2 (read-prefix-exp suffix-1))\n                (operand-2 (car result-2))\n                (suffix-2 (cdr result-2)))\n           (cons (diff-exp operand-1 operand-2)\n                 suffix-2)))\n        (else\n         (eopl:error 'read-prefix-exp \"Unrecognized input: ~s\" (car datum)))))\n\n(define (parse datum)\n  (let* ((result (read-prefix-exp datum))\n         (prefix-exp (car result))\n         (remaining (cdr result)))\n    (if (null? remaining)\n        prefix-exp\n        (eopl:error 'parse \"Trailing output: ~s\" remaining))))\n"
  },
  {
    "path": "scheme/eopl/02/tests/01-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../01.scm\")\n\n(define eopl-2.01-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.01\"\n\n    (check-equal? (zero) '())\n\n    (test-suite \"successor\"\n      (parameterize ((base 4))\n        (check-equal? (successor (zero)) '(1))\n        (check-equal? (successor '(2 1)) '(3 1))\n        (check-equal? (successor '(3 1 1)) '(0 2 1))\n        (check-equal? (successor '(3 3 3)) '(0 0 0 1))\n        (check-equal? (successor '(3 3 3 1)) '(0 0 0 2))))\n\n    (test-suite \"predecessor\"\n      (parameterize ((base 4))\n        (check-equal? (predecessor '(1)) '())\n        (check-equal? (predecessor '(3 1)) '(2 1))\n        (check-equal? (predecessor '(0 2 1)) '(3 1 1))\n        (check-equal? (predecessor '(0 0 0 1)) '(3 3 3))\n        (check-equal? (predecessor '(0 0 0 2)) '(3 3 3 1))))\n\n    (test-suite \"bignum->int\"\n      (parameterize ((base 10))\n        (check-equal? (bignum->int '()) 0)\n        (check-equal? (bignum->int '(0 0 1)) 100)\n        (check-equal? (bignum->int '(3 2 1)) 123)))\n\n    (test-suite \"int->bignum\"\n      (parameterize ((base 10))\n        (check-equal? (int->bignum 0) '())\n        (check-equal? (int->bignum 100) '(0 0 1))\n        (check-equal? (int->bignum 321) '(1 2 3))))\n\n    (test-suite \"multiply\"\n      (parameterize ((base 10))\n        (check-equal? (multiply (zero) '(6 2 3)) (zero))\n        (check-equal? (bignum->int (multiply '(8 5 7) '(6 2 3)))\n                      (* 758 326))))\n\n    (test-suite \"factorial\"\n      (check-equal? (factorial (int->bignum 5))\n                    (int->bignum 120)))\n))\n\n(exit (run-tests eopl-2.01-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/03-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../03.scm\")\n\n(define eopl-2.03-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.03\"\n\n    (check-equal? (zero) '(diff (one) (one)))\n\n    (check-equal? (successor '(one))\n                  '(diff (one) (diff (diff (one) (one))\n                                     (one))))\n\n    (check-equal? (predecessor '(one))\n                  '(diff (one) (one)))\n    (check-equal? (predecessor '(diff (one) (one)))\n                  '(diff (diff (one) (one)) (one)))\n\n    (check-equal? (diff-tree-plus '(diff (one) (one))\n                                  '(one))\n                  '(diff (diff (one) (one))\n                         (diff (diff (one) (one)) (one))))\n\n    (check-equal? (diff-tree-plus '(diff (one) (one))\n                                  '(diff (diff (one) (one)) (one)))\n                  '(diff (diff (one) (one))\n                         (diff (one) (diff (one) (one)))))\n\n    (check-true (is-zero? (zero)))\n    (check-true (is-zero? '(diff (diff (one) (diff (one) (one)))\n                                 (diff (one) (diff (one) (one))))))\n    (check-true (is-zero? '(diff (diff (one) (diff (one) (one)))\n                                 (one))))\n    (check-false (is-zero? '(diff (one) (diff (one) (one)))))\n\n    (check-true (is-zero? ((compose successor predecessor) (zero))))\n    (check-true (is-zero? ((compose predecessor successor) (zero))))\n\n    (check-true (is-zero? ((compose successor successor predecessor predecessor) (zero))))\n    (check-true (is-zero? ((compose successor predecessor successor predecessor) (zero))))\n    (check-true (is-zero? ((compose successor predecessor predecessor successor) (zero))))\n\n    (check-true (is-zero? ((compose predecessor predecessor successor successor) (zero))))\n    (check-true (is-zero? ((compose predecessor successor predecessor successor) (zero))))\n    (check-true (is-zero? ((compose predecessor successor successor predecessor) (zero))))\n\n    (check-false (is-zero? (predecessor (zero))))\n    (check-false (is-zero? (successor (zero))))\n\n    (check-false (is-zero? ((compose predecessor predecessor) (zero))))\n    (check-false (is-zero? ((compose predecessor predecessor predecessor) (zero))))\n    (check-false (is-zero? ((compose predecessor predecessor successor) (zero))))\n    (check-false (is-zero? ((compose predecessor successor predecessor) (zero))))\n    (check-false (is-zero? ((compose predecessor successor successor) (zero))))\n\n    (check-false (is-zero? ((compose successor successor) (zero))))\n    (check-false (is-zero? ((compose successor successor successor) (zero))))\n    (check-false (is-zero? ((compose successor successor predecessor) (zero))))\n    (check-false (is-zero? ((compose successor predecessor successor) (zero))))\n    (check-false (is-zero? ((compose successor predecessor predecessor) (zero))))\n))\n\n(exit (run-tests eopl-2.03-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/05-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../05.scm\")\n\n(define eopl-2.05-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.05\"\n\n    (check-exn exn? (lambda () (apply-env (empty-env) 'a)))\n    (check-exn exn? (lambda () (apply-env (extend-env 'a 1 (empty-env)) 'b)))\n    (check-equal? (apply-env (extend-env 'a 1 (empty-env)) 'a)\n                  1)\n    (check-equal? (apply-env (extend-env 'a 1 (extend-env 'b 2 (empty-env))) 'b)\n                  2)\n    (check-equal? (apply-env (extend-env 'a 3\n                               (extend-env 'b 2\n                                 (extend-env 'a 1\n                                   (empty-env))))\n                             'a)\n                  3)\n\n))\n\n(exit (run-tests eopl-2.05-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/06-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../06.scm\")\n\n(define eopl-2.06-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.06\"\n\n    (test-suite \"1. 2-list\"\n      (use-2-list)\n      (check-exn exn? (lambda () (apply-env (empty-env) 'a)))\n      (check-exn exn? (lambda () (apply-env (extend-env 'a 1 (empty-env)) 'b)))\n      (check-equal? (apply-env (extend-env 'a 1 (empty-env)) 'a)\n                    1)\n      (check-equal? (apply-env (extend-env 'a 1 (extend-env 'b 2 (empty-env))) 'b)\n                    2)\n      (check-equal? (apply-env (extend-env 'a 3\n                                 (extend-env 'b 2\n                                   (extend-env 'a 1\n                                     (empty-env))))\n                               'a)\n                    3))\n\n    (test-suite \"2. two lists\"\n      (use-two-lists)\n      (check-exn exn? (lambda () (apply-env (empty-env) 'a)))\n      (check-exn exn? (lambda () (apply-env (extend-env 'a 1 (empty-env)) 'b)))\n      (check-equal? (apply-env (extend-env 'a 1 (empty-env)) 'a)\n                    1)\n      (check-equal? (apply-env (extend-env 'a 1 (extend-env 'b 2 (empty-env))) 'b)\n                    2)\n      (check-equal? (apply-env (extend-env 'a 3\n                                 (extend-env 'b 2\n                                   (extend-env 'a 1\n                                     (empty-env))))\n                               'a)\n                    3))\n\n    (test-suite \"3. var-val list\"\n      (use-var-val-list)\n      (check-exn exn? (lambda () (apply-env (empty-env) 'a)))\n      (check-exn exn? (lambda () (apply-env (extend-env 'a 1 (empty-env)) 'b)))\n      (check-equal? (apply-env (extend-env 'a 1 (empty-env)) 'a)\n                    1)\n      (check-equal? (apply-env (extend-env 'a 1 (extend-env 'b 2 (empty-env))) 'b)\n                    2)\n      (check-equal? (apply-env (extend-env 'a 3\n                                 (extend-env 'b 2\n                                   (extend-env 'a 1\n                                     (empty-env))))\n                               'a)\n                    3))\n))\n\n(exit (run-tests eopl-2.06-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/07-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../07.scm\")\n\n(define eopl-2.07-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.07\"\n\n    (check-exn (regexp \"Variable b not found in environment: \\\\(extend-env a 1 \\\\(empty-env\\\\)\\\\)\")\n               (lambda () (apply-env (extend-env 'a 1 (empty-env)) 'b)))\n))\n\n(exit (run-tests eopl-2.07-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/08-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../08.scm\")\n\n(define eopl-2.08-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.08\"\n\n    (check-true (empty-env? (empty-env)))\n    (check-false (empty-env? (extend-env 'a 1 (empty-env))))\n))\n\n(exit (run-tests eopl-2.08-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/09-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../09.scm\")\n\n(define eopl-2.09-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.09\"\n\n    (check-true (has-binding? (extend-env 'a 1 (empty-env)) 'a))\n    (check-true (has-binding? (extend-env 'a 1 (extend-env 'b 2 (empty-env))) 'b))\n\n    (check-false (has-binding? (empty-env) 'a))\n    (check-false (has-binding? (extend-env 'a 1 (extend-env 'b 2 (empty-env))) 'c))\n))\n\n(exit (run-tests eopl-2.09-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/10-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../10.scm\")\n\n(define eopl-2.10-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.10\"\n\n    (check-equal? (apply-env (extend-env* '(a b c) '(1 2 3) (empty-env)) 'a)\n                  1)\n    (check-equal? (apply-env (extend-env* '(a b c) '(1 2 3) (empty-env)) 'b)\n                  2)\n    (check-equal? (apply-env (extend-env* '(a b c) '(1 2 3) (empty-env)) 'c)\n                  3)\n))\n\n(exit (run-tests eopl-2.10-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/11-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../11.scm\")\n\n(define eopl-2.11-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.11\"\n\n    (check-exn exn? (lambda () (apply-env (empty-env) 'a)))\n    (check-exn exn? (lambda () (apply-env (extend-env 'a 1 (empty-env)) 'b)))\n    (check-equal? (apply-env (extend-env 'a 1 (empty-env)) 'a)\n                  1)\n    (check-equal? (apply-env (extend-env 'a 1 (extend-env 'b 2 (empty-env))) 'b)\n                  2)\n    (check-equal? (apply-env (extend-env 'a 3\n                               (extend-env 'b 2\n                                 (extend-env 'a 1\n                                   (empty-env))))\n                             'a)\n                  3)\n\n    (check-equal? (apply-env (extend-env* '(a b c) '(1 2 3) (empty-env)) 'a)\n                  1)\n    (check-equal? (apply-env (extend-env* '(a b c) '(1 2 3) (empty-env)) 'b)\n                  2)\n    (check-equal? (apply-env (extend-env* '(a b c) '(1 2 3) (empty-env)) 'c)\n                  3)\n))\n\n(exit (run-tests eopl-2.11-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/12-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../12.scm\")\n\n(define eopl-2.12-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.12\"\n\n    (check-true (empty-stack? (empty-stack)))\n    (check-true (empty-stack? (pop (push 1 (empty-stack)))))\n    (check-false (empty-stack? (push 1 (empty-stack))))\n    (check-false (empty-stack? (pop (push 2 (push 1 (empty-stack))))))\n))\n\n(exit (run-tests eopl-2.12-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/13-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../13.scm\")\n\n(define eopl-2.13-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.13\"\n\n    (check-exn exn? (lambda () (apply-env (empty-env) 'a)))\n    (check-exn exn? (lambda () (apply-env (extend-env 'a 1 (empty-env)) 'b)))\n    (check-equal? (apply-env (extend-env 'a 1 (empty-env)) 'a)\n                  1)\n    (check-equal? (apply-env (extend-env 'a 1 (extend-env 'b 2 (empty-env))) 'b)\n                  2)\n    (check-equal? (apply-env (extend-env 'a 3\n                               (extend-env 'b 2\n                                 (extend-env 'a 1\n                                   (empty-env))))\n                             'a)\n                  3)\n\n    (check-false (empty-env? (extend-env 'a 1 (empty-env))))\n    (check-true (empty-env? (empty-env)))\n))\n\n(exit (run-tests eopl-2.13-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/14-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../14.scm\")\n\n(define eopl-2.14-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.14\"\n\n    (check-exn exn? (lambda () (apply-env (empty-env) 'a)))\n    (check-exn exn? (lambda () (apply-env (extend-env 'a 1 (empty-env)) 'b)))\n    (check-equal? (apply-env (extend-env 'a 1 (empty-env)) 'a)\n                  1)\n    (check-equal? (apply-env (extend-env 'a 1 (extend-env 'b 2 (empty-env))) 'b)\n                  2)\n    (check-equal? (apply-env (extend-env 'a 3\n                               (extend-env 'b 2\n                                 (extend-env 'a 1\n                                   (empty-env))))\n                             'a)\n                  3)\n\n    (check-false (empty-env? (extend-env 'a 1 (empty-env))))\n    (check-true (empty-env? (empty-env)))\n\n    (check-false (has-binding? (empty-env) 'a))\n    (check-false (has-binding? (extend-env 'a 1 (empty-env)) 'b))\n    (check-true (has-binding? (extend-env 'a 1 (empty-env)) 'a))\n    (check-true (has-binding? (extend-env 'a 1 (extend-env 'b 2 (empty-env))) 'b))\n))\n\n(exit (run-tests eopl-2.14-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/15-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../15.scm\")\n\n(define eopl-2.15-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.15\"\n\n    (check-true (var-exp? (var-exp 'a)))\n    (check-equal? (var-exp->var (var-exp 'a)) 'a)\n\n    (check-true (lambda-exp? (lambda-exp 'a (var-exp 'b))))\n    (check-equal? (lambda-exp->bound-var (lambda-exp 'a (var-exp 'b))) 'a)\n    (check-equal? (lambda-exp->body (lambda-exp 'a (var-exp 'b))) (var-exp 'b))\n\n    (check-true (app-exp? (app-exp (var-exp 'a) (var-exp 'b))))\n    (check-equal? (app-exp->rator (app-exp (var-exp 'a) (var-exp 'b))) (var-exp 'a))\n    (check-equal? (app-exp->rand (app-exp (var-exp 'a) (var-exp 'b))) (var-exp 'b))\n\n    (check-false (app-exp? (lambda-exp 'a (var-exp 'b))))\n    (check-false (lambda-exp? (app-exp (var-exp 'a) (var-exp 'b))))\n))\n\n(exit (run-tests eopl-2.15-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/16-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../16.scm\")\n\n(define eopl-2.16-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.16\"\n\n    (check-equal? (lambda-exp 'a (var-exp 'b))\n                  '(lambda a b))\n\n    (check-true (var-exp? (var-exp 'a)))\n    (check-equal? (var-exp->var (var-exp 'a)) 'a)\n\n    (check-true (lambda-exp? (lambda-exp 'a (var-exp 'b))))\n    (check-equal? (lambda-exp->bound-var (lambda-exp 'a (var-exp 'b))) 'a)\n    (check-equal? (lambda-exp->body (lambda-exp 'a (var-exp 'b))) (var-exp 'b))\n\n    (check-true (app-exp? (app-exp (var-exp 'a) (var-exp 'b))))\n    (check-equal? (app-exp->rator (app-exp (var-exp 'a) (var-exp 'b))) (var-exp 'a))\n    (check-equal? (app-exp->rand (app-exp (var-exp 'a) (var-exp 'b))) (var-exp 'b))\n\n    (check-false (app-exp? (lambda-exp 'a (var-exp 'b))))\n    (check-false (lambda-exp? (app-exp (var-exp 'a) (var-exp 'b))))\n))\n\n(exit (run-tests eopl-2.16-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/17-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../17.scm\")\n\n(define eopl-2.17-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.17\"\n\n    (test-suite \"Representation 1\"\n      (use-representation-1)\n\n      (check-true (var-exp? (var-exp 'a)))\n      (check-equal? (var-exp->var (var-exp 'a)) 'a)\n\n      (check-true (lambda-exp? (lambda-exp 'a (var-exp 'b))))\n      (check-equal? (lambda-exp->bound-var (lambda-exp 'a (var-exp 'b))) 'a)\n      (check-equal? (lambda-exp->body (lambda-exp 'a (var-exp 'b))) (var-exp 'b))\n\n      (check-true (app-exp? (app-exp (var-exp 'a) (var-exp 'b))))\n      (check-equal? (app-exp->rator (app-exp (var-exp 'a) (var-exp 'b))) (var-exp 'a))\n      (check-equal? (app-exp->rand (app-exp (var-exp 'a) (var-exp 'b))) (var-exp 'b))\n\n      (check-false (app-exp? (lambda-exp 'a (var-exp 'b))))\n      (check-false (lambda-exp? (app-exp (var-exp 'a) (var-exp 'b)))))\n\n    (test-suite \"Representation 2\"\n      (use-representation-2)\n\n      (check-true (var-exp? (var-exp 'a)))\n      (check-equal? (var-exp->var (var-exp 'a)) 'a)\n\n      (check-true (lambda-exp? (lambda-exp 'a (var-exp 'b))))\n      (check-equal? (lambda-exp->bound-var (lambda-exp 'a (var-exp 'b))) 'a)\n      (check-equal? (lambda-exp->body (lambda-exp 'a (var-exp 'b))) (var-exp 'b))\n\n      (check-true (app-exp? (app-exp (var-exp 'a) (var-exp 'b))))\n      (check-equal? (app-exp->rator (app-exp (var-exp 'a) (var-exp 'b))) (var-exp 'a))\n      (check-equal? (app-exp->rand (app-exp (var-exp 'a) (var-exp 'b))) (var-exp 'b))\n\n      (check-false (app-exp? (lambda-exp 'a (var-exp 'b))))\n      (check-false (lambda-exp? (app-exp (var-exp 'a) (var-exp 'b)))))\n))\n\n(exit (run-tests eopl-2.17-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/18-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../18.scm\")\n\n(define eopl-2.18-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.18\"\n\n    (check-equal? (number->sequence 7)\n                  '(7 () ()))\n    (check-equal? (current-element '(6 (5 4 3 2 1) (7 8 9)))\n                  '6)\n    (check-equal? (move-to-left '(6 (5 4 3 2 1) (7 8 9)))\n                  '(5 (4 3 2 1) (6 7 8 9)))\n    (check-equal? (move-to-right '(6 (5 4 3 2 1) (7 8 9)))\n                  '(7 (6 5 4 3 2 1) (8 9)))\n    (check-equal? (insert-to-left 13 '(6 (5 4 3 2 1) (7 8 9)))\n                  '(6 (13 5 4 3 2 1) (7 8 9)))\n    (check-equal? (insert-to-right 13 '(6 (5 4 3 2 1) (7 8 9)))\n                  '(6 (5 4 3 2 1) (13 7 8 9)))\n\n    (check-exn exn? (lambda () (move-to-right '(2 (1) ()))))\n    (check-exn exn? (lambda () (move-to-left '(2 () (3)))))\n    (check-true (at-left-end? '(2 () (3))))\n    (check-false (at-left-end? '(2 (1) (3))))\n    (check-true (at-right-end? '(2 (1) ())))\n    (check-false (at-right-end? '(2 (1) (3))))\n))\n\n(exit (run-tests eopl-2.18-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/19-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../19.scm\")\n\n(define eopl-2.19-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.19\"\n\n    (check-equal? (number->bintree 13)\n                  '(13 () ()))\n\n    (check-equal? (insert-to-left 4 '(1 (2 () ()) (3 () ())))\n                  '(1 (4 (2 () ()) ()) (3 () ())))\n\n    (check-equal? (insert-to-right 4 '(1 (2 () ()) (3 () ())))\n                  '(1 (2 () ()) (4 () (3 () ()))))\n\n    (let ((t1 (insert-to-right 14 (insert-to-left 12 (number->bintree 13)))))\n      (check-equal? t1 '(13 (12 () ()) (14 () ())))\n      (check-equal? (move-to-left-son t1)\n                    '(12 () ()))\n      (check-equal? (current-element (move-to-left-son t1))\n                    12)\n      (check-equal? (at-leaf? (move-to-right-son (move-to-left-son t1)))\n                    #t)\n      (check-equal? (insert-to-left 15 t1)\n                    '(13 (15 (12 () ()) ()) (14 () ()))))\n))\n\n(exit (run-tests eopl-2.19-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/20-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../20.scm\")\n\n(define eopl-2.20-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.20\"\n\n    (check-equal? (move-to-left-son (insert-to-left 2 (number->bintree 1)))\n                  '(2 () () (1 (2 () () ()) () ())))\n    (check-equal? (move-to-right-son (insert-to-right 2 (number->bintree 1)))\n                  '(2 () () (1 () (2 () () ()) ())))\n\n    (check-equal? (move-up (move-to-left-son (insert-to-left 2 (number->bintree 1))))\n                  (insert-to-left 2 (number->bintree 1)))\n    (check-equal? (move-up (move-to-right-son (insert-to-right 2 (number->bintree 1))))\n                  (insert-to-right 2 (number->bintree 1)))\n    (check-true (at-leaf?\n                  (move-to-left-son\n                    (move-to-left-son\n                      (insert-to-left 2 (number->bintree 1))))))\n    (check-true (at-leaf?\n                  (move-to-right-son\n                    (move-to-right-son\n                      (insert-to-right 2 (number->bintree 1))))))\n    (check-equal?\n      (move-up\n        (move-up\n          (move-to-left-son\n            (move-to-left-son\n              (insert-to-left 2 (number->bintree 1))))))\n      (insert-to-left 2 (number->bintree 1)))\n\n    (check-equal?\n      (move-up\n        (move-up\n          (move-to-right-son\n            (move-to-right-son\n              (insert-to-right 2 (number->bintree 1))))))\n      (insert-to-right 2 (number->bintree 1)))\n\n    (check-true (at-root? (number->bintree 1)))\n    (check-false (at-root? (move-to-right-son (insert-to-right 2 (number->bintree 1)))))\n))\n\n(exit (run-tests eopl-2.20-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/21-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../21.scm\")\n\n(define eopl-2.21-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.21\"\n\n    (check-true (has-binding? (extend-env 'a 1 (empty-env)) 'a))\n    (check-true (has-binding? (extend-env 'a 1 (extend-env 'b 2 (empty-env))) 'b))\n\n    (check-false (has-binding? (empty-env) 'a))\n    (check-false (has-binding? (extend-env 'a 1 (extend-env 'b 2 (empty-env))) 'c))\n))\n\n(exit (run-tests eopl-2.21-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/22-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../22.scm\")\n\n(define eopl-2.22-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.22\"\n\n    (check-true (empty-stack? (empty-stack)))\n    (check-true (empty-stack? (pop (push 1 (empty-stack)))))\n    (check-false (empty-stack? (push 1 (empty-stack))))\n    (check-false (empty-stack? (pop (push 2 (push 1 (empty-stack))))))\n))\n\n(exit (run-tests eopl-2.22-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/23-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../23.scm\")\n\n(define eopl-2.23-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.23\"\n\n    (check-exn exn? (lambda () (app-exp (var-exp 'lambda) (var-exp 'lambda))))\n    (check-exn exn? (lambda () (app-exp (var-exp 'a) (var-exp 'lambda))))\n    (check-exn exn? (lambda () (app-exp (var-exp 'lambda) (var-exp 'a))))\n    (check-exn exn? (lambda () (lambda-exp 'lambda (var-exp 'lambda))))\n    (check-exn exn? (lambda () (lambda-exp 'a (var-exp 'lambda))))\n    (check-exn exn? (lambda () (lambda-exp 'lambda (var-exp 'a))))\n))\n\n(exit (run-tests eopl-2.23-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/24-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../24.scm\")\n\n(define eopl-2.24-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.24\"\n\n    (check-equal? (bintree-to-list (interior-node 'a (leaf-node 3) (leaf-node 4)))\n                  '(interior-node a (leaf-node 3) (leaf-node 4)))\n))\n\n(exit (run-tests eopl-2.24-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/25-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../25.scm\")\n\n(define eopl-2.25-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.25\"\n\n    (let* ((tree-1 (interior-node 'foo (leaf-node 2) (leaf-node 3)))\n           (tree-2 (interior-node 'bar (leaf-node -1) tree-1))\n           (tree-3 (interior-node 'baz tree-2 (leaf-node 1))))\n      (check-equal? 'foo (max-interior tree-2))\n      (check-equal? 'baz (max-interior tree-3)))\n))\n\n(exit (run-tests eopl-2.25-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/26-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../26.scm\")\n\n(define eopl-2.26-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.26\"\n\n    (check-equal?\n      (mark-with-red-depth\n        (red-node\n          (blue-node (list (red-node (leaf-node 0)\n                                     (leaf-node 0))\n                           (leaf-node 0)\n                           (blue-node (list (leaf-node 0)\n                                            (red-node (leaf-node 0)\n                                                      (leaf-node 0))))))\n          (leaf-node 0)))\n      (red-node\n        (blue-node (list (red-node (leaf-node 2)\n                                   (leaf-node 2))\n                         (leaf-node 1)\n                         (blue-node (list (leaf-node 1)\n                                          (red-node (leaf-node 2)\n                                                    (leaf-node 2))))))\n        (leaf-node 1)))\n))\n\n(exit (run-tests eopl-2.26-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/28-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../28.scm\")\n\n(define eopl-2.28-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.28\"\n\n    (check-equal? (unparse (var-exp 'a))\n                  \"a\")\n    (check-equal? (unparse (lambda-exp 'x (app-exp (var-exp 'x) (var-exp 'y))))\n                  \"(lambda (x) (x y))\")\n    (check-equal? (unparse (app-exp (lambda-exp 'x (var-exp 'x))\n                                    (app-exp (var-exp 'a) (var-exp 'b))))\n                  \"((lambda (x) x) (a b))\")\n))\n\n(exit (run-tests eopl-2.28-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/29-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../29.scm\")\n\n(define eopl-2.29-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.29\"\n\n    (check-equal? (parse 'x)\n                  (var-exp 'x))\n    (check-equal? (parse '(lambda (a b c) a))\n                  (lambda-exp '(a b c) (var-exp 'a)))\n    (check-equal? (parse '((lambda (a b) a) x y))\n                  (app-exp (lambda-exp '(a b) (var-exp 'a))\n                           (list (var-exp 'x)\n                                 (var-exp 'y))))\n))\n\n(exit (run-tests eopl-2.29-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/30-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../30.scm\")\n\n(define eopl-2.30-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.30\"\n\n    (check-equal? (parse 'a)\n                  (var-exp 'a))\n    (check-equal? (parse '(lambda (a) a))\n                  (lambda-exp 'a (var-exp 'a)))\n    (check-equal? (parse '(a b))\n                  (app-exp (var-exp 'a)\n                           (var-exp 'b)))\n\n    (check-exn (regexp \"lambda is not a valid identifier\")\n               (lambda () (parse 'lambda)))\n    (check-exn (regexp \"lambda requires two components. given: \\\\(lambda\\\\)\")\n               (lambda () (parse '(lambda))))\n    (check-exn (regexp \"lambda requires two components. given: \\\\(lambda a\\\\)\")\n               (lambda () (parse '(lambda a))))\n    (check-exn (regexp \"lambda requires two components. given: \\\\(lambda a b c\\\\)\")\n               (lambda () (parse '(lambda a b c))))\n    (check-exn (regexp \"lambda requires an arglist. given: a\")\n               (lambda () (parse '(lambda a b))))\n    (check-exn (regexp \"lambda requires exactly one argument. given: \\\\(\\\\)\")\n               (lambda () (parse '(lambda () a))))\n    (check-exn (regexp \"lambda requires exactly one argument. given: \\\\(a b\\\\)\")\n               (lambda () (parse '(lambda (a b) a))))\n\n    (check-exn (regexp \"application requires two components. given: \\\\(a\\\\)\")\n               (lambda () (parse '(a))))\n    (check-exn (regexp \"application requires two components. given: \\\\(a b c\\\\)\")\n               (lambda () (parse '(a b c))))\n))\n\n(exit (run-tests eopl-2.30-tests))\n"
  },
  {
    "path": "scheme/eopl/02/tests/31-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../31.scm\")\n\n(define eopl-2.31-tests\n  (test-suite\n    \"Tests for EOPL exercise 2.31\"\n\n    (check-equal? (parse '(- - 3 2 - 4 - 12 7))\n                  (diff-exp (diff-exp (const-exp 3) (const-exp 2))\n                            (diff-exp (const-exp 4)\n                                      (diff-exp (const-exp 12) (const-exp 7)))))\n))\n\n(exit (run-tests eopl-2.31-tests))\n"
  },
  {
    "path": "scheme/eopl/03/01.scm",
    "content": "; EOPL exercise 3.01\n;\n; In figure 3.3, list all the places where we used the fact that\n; ⎣ ⎡ n⎤ ⎦ = n.\n\n; I will use {} for ⎣  and ⎦ and [] for ⎡  and ⎤. I will annotate the code below:\n;\n; Let p = [i = 1, v = 5, x = 10].\n;\n; (value-of\n;   <<-(-(x, 3), -(v, i))>>\n;   p)\n;\n; = [(-\n;     {(value-of <<-(x, 3)>> p)}\n;     {(value-of <<-(v, i)>> p)})]\n;\n; = [(-\n;     (-\n;       {(value-of <<x>> p)}\n;       {(value-of <<3>> p)})\n;     {(value-of <<-(v, i)>>)})]\n;\n; = [(-\n;     (-\n;       10                               ; HERE\n;       {(value-of <<3>> p)})\n;     {(value-of <<-(v, i)>>)})]\n;\n; = [(-\n;     (-\n;       10\n;       3)                               ; HERE\n;     {(value-of <<-(v, i)>>)})]\n;\n; = [(-\n;     7\n;     {(value-of <<-(v, i)>>)})]\n;\n; = [(-\n;     7\n;     (-\n;       {(value-of <<x>> p)}\n;       {(value-of <<i>> p)}))]\n;\n; = [(-\n;     7\n;     (-\n;       5                                ; HERE\n;       {(value-of <<i>> p)}))]\n;\n; = [(-\n;     7\n;     (-\n;       5\n;       1))]                             ; HERE\n; = [(-\n;     7\n;     4)]\n;\n; = [4]\n"
  },
  {
    "path": "scheme/eopl/03/02.scm",
    "content": "; EOPL exercise 3.02\n;\n; Give an expressed value val ∈ ExpVal for which ⎡ ⎣ val⎦ ⎤ ≠ val.\n\n; This is tricky. We don't have it in the LET language. let's explore a\n; language has rational numbers in ExpVal, but the implementation language\n; does not have that notion. Instad, expval->num converts the rational number\n; to a float. In that language\n;\n; (num-val (expval->num ⎡ 1/3⎤))\n;\n; would not return one third, but a rational number that is close to it.\n"
  },
  {
    "path": "scheme/eopl/03/03.scm",
    "content": "; EOPL exercise 3.03\n;\n; Why is subtraction a better choice than addition for our single arithmetic\n; operation?\n\n; Because we don't have negative numbers in our syntax. Thus, we cannot parse\n; -x, but we can still represent it as -(0, x). This would not have been true\n; if we used addition instead.\n;\n; Furthermore, we can represent x + y as -(x, -(0, y)) if we have subtraction.\n; If we only have addition, there is on way to represent subtraction - (unless\n; we had negation, but that is a second arithmetic operation).\n"
  },
  {
    "path": "scheme/eopl/03/04.scm",
    "content": "; EOPL exercise 3.04\n;\n; Write out the derivation of figure 3.4 as a derivation tree in the style of\n; one on page 5.\n\n; I cannot figure this exercise out. Figure 3.4 is:\n;\n; (value-of (if-exp exp₁ exp₂ exp₃) p)\n;\n; = (if (expval->bool (value-of exp₁ p))\n;     (value-of exp₂ p)\n;     (value-of exp₃ p))\n;\n; I have no clue how to represent this as a derivation tree. Next!\n"
  },
  {
    "path": "scheme/eopl/03/05.scm",
    "content": "; EOPL exercise 3.05\n;\n; Write out the derivation of figure 3.5 as a derivation tree in the style of\n; the one on page 5.\n\n; This is the same of the previous and I still can't figure out what I'm\n; supposed to do. I can write a derivation tree, if I had a concrete\n; expression, but it uses exp₁ and exp₂ instead. I can come up with a concrete\n; expression and write the tree, but I just don't think it is worth it.\n"
  },
  {
    "path": "scheme/eopl/03/06.scm",
    "content": "; EOPL exercise 3.06\n;\n; Extend the language by adding a new operator minus that takes one argument,\n; n, and returns -n. For example, the value of minus(-(minus(5), 9)) should be\n; 14.\n\n(load-relative \"cases/let/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (minus-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"minus\" \"(\" expression \")\") minus-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; Eval\n\n(define-datatype expval expval?\n  (num-val (num number?))\n  (bool-val (bool boolean?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (minus-exp (arg)\n      (num-val (- (expval->num (value-of arg env)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))))\n"
  },
  {
    "path": "scheme/eopl/03/07.scm",
    "content": "; EOPL exercise 3.07\n;\n; Extend the language by adding operators for addition, multiplication, and\n; integer quotient.\n\n(load-relative \"cases/let/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (minus-exp\n    (expr expression?))\n  (add-exp\n    (left expression?)\n    (right expression?))\n  (diff-exp\n    (left expression?)\n    (right expression?))\n  (mult-exp\n    (left expression?)\n    (right expression?))\n  (div-exp\n    (left expression?)\n    (right expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"+\" \"(\" expression \",\" expression \")\") add-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"*\" \"(\" expression \",\" expression \")\") mult-exp)\n    (expression (\"/\" \"(\" expression \",\" expression \")\") div-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"minus\" \"(\" expression \")\") minus-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; Eval\n\n(define-datatype expval expval?\n  (num-val (num number?))\n  (bool-val (bool boolean?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (add-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (+ left-num right-num)))))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val (- minuend-num subtrahend-num)))))\n    (mult-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (* left-num right-num)))))\n    (div-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (quotient left-num right-num)))))\n    (minus-exp (arg)\n      (num-val (- (expval->num (value-of arg env)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))))\n"
  },
  {
    "path": "scheme/eopl/03/08.scm",
    "content": "; EOPL exercise 3.08\n;\n; Add a numeric equality predicate equal? and numeric order predicates\n; greater? and less? to the set of operations in the defined language.\n\n(load-relative \"cases/let/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (minus-exp\n    (expr expression?))\n  (add-exp\n    (left expression?)\n    (right expression?))\n  (diff-exp\n    (left expression?)\n    (right expression?))\n  (mult-exp\n    (left expression?)\n    (right expression?))\n  (div-exp\n    (left expression?)\n    (right expression?))\n  (zero?-exp\n    (expr expression?))\n  (equal?-exp\n    (left expression?)\n    (right expression?))\n  (less?-exp\n    (left expression?)\n    (right expression?))\n  (greater?-exp\n    (left expression?)\n    (right expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"+\" \"(\" expression \",\" expression \")\") add-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"*\" \"(\" expression \",\" expression \")\") mult-exp)\n    (expression (\"/\" \"(\" expression \",\" expression \")\") div-exp)\n    (expression (\"equal?\" \"(\" expression \",\" expression \")\") equal?-exp)\n    (expression (\"less?\" \"(\" expression \",\" expression \")\") less?-exp)\n    (expression (\"greater?\" \"(\" expression \",\" expression \")\") greater?-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"minus\" \"(\" expression \")\") minus-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; Eval\n\n(define-datatype expval expval?\n  (num-val (num number?))\n  (bool-val (bool boolean?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (add-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (+ left-num right-num)))))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val (- minuend-num subtrahend-num)))))\n    (mult-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (* left-num right-num)))))\n    (div-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (quotient left-num right-num)))))\n    (minus-exp (arg)\n      (num-val (- (expval->num (value-of arg env)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (equal?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (= (expval->num left-val)\n                     (expval->num right-val)))))\n    (less?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (< (expval->num left-val)\n                     (expval->num right-val)))))\n    (greater?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (> (expval->num left-val)\n                     (expval->num right-val)))))\n    ))\n"
  },
  {
    "path": "scheme/eopl/03/09.scm",
    "content": "; EOPL exercise 3.09\n;\n; Add a list processing operations to the language, including cons, car, cdr,\n; null? and emptylist. A list should be able to contain any expressed value,\n; including another list. Give the definitions of the expressed and denoted\n; values of the languages, as in section 3.2.2. For example,\n;\n; let x = 4\n; in cons(x,\n;         cons(cons(-(x, 1),\n;                   emptylist),\n;              emptylist))\n\n(load-relative \"cases/let/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (minus-exp\n    (expr expression?))\n  (add-exp\n    (left expression?)\n    (right expression?))\n  (diff-exp\n    (left expression?)\n    (right expression?))\n  (mult-exp\n    (left expression?)\n    (right expression?))\n  (div-exp\n    (left expression?)\n    (right expression?))\n  (zero?-exp\n    (expr expression?))\n  (equal?-exp\n    (left expression?)\n    (right expression?))\n  (less?-exp\n    (left expression?)\n    (right expression?))\n  (greater?-exp\n    (left expression?)\n    (right expression?))\n  (cons-exp\n    (car expression?)\n    (cdr expression?))\n  (car-exp\n    (expr expression?))\n  (cdr-exp\n    (expr expression?))\n  (null?-exp\n    (expr expression?))\n  (emptylist-exp)\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"+\" \"(\" expression \",\" expression \")\") add-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"*\" \"(\" expression \",\" expression \")\") mult-exp)\n    (expression (\"/\" \"(\" expression \",\" expression \")\") div-exp)\n    (expression (\"cons\" \"(\" expression \",\" expression \")\") cons-exp)\n    (expression (\"car\" \"(\" expression \")\") car-exp)\n    (expression (\"cdr\" \"(\" expression \")\") cdr-exp)\n    (expression (\"null?\" \"(\" expression \")\") null?-exp)\n    (expression (\"emptylist\") emptylist-exp)\n    (expression (\"equal?\" \"(\" expression \",\" expression \")\") equal?-exp)\n    (expression (\"less?\" \"(\" expression \",\" expression \")\") less?-exp)\n    (expression (\"greater?\" \"(\" expression \",\" expression \")\") greater?-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"minus\" \"(\" expression \")\") minus-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; Eval\n\n(define-datatype expval expval?\n  (num-val (num number?))\n  (bool-val (bool boolean?))\n  (pair-val (car expval?) (cdr expval?))\n  (emptylist-val))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->pair val)\n  (cases expval val\n    (pair-val (car cdr) (cons car cdr))\n    (else (eopl:error 'expval->pair \"Invalid pair: ~s\" val))))\n\n(define (pair-car val)\n  (cases expval val\n    (pair-val (car cdr) car)\n    (else (eopl:error 'pair-car \"Expected a pair: ~s\" val))))\n\n(define (pair-cdr val)\n  (cases expval val\n    (pair-val (car cdr) cdr)\n    (else (eopl:error 'pair-cdr \"Expected a pair: ~s\" val))))\n\n(define (pair-null? val)\n  (cases expval val\n    (emptylist-val () (bool-val #t))\n    (else (bool-val #f))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (add-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (+ left-num right-num)))))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val (- minuend-num subtrahend-num)))))\n    (mult-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (* left-num right-num)))))\n    (div-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (quotient left-num right-num)))))\n    (minus-exp (arg)\n      (num-val (- (expval->num (value-of arg env)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (equal?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (= (expval->num left-val)\n                     (expval->num right-val)))))\n    (less?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (< (expval->num left-val)\n                     (expval->num right-val)))))\n    (greater?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (> (expval->num left-val)\n                     (expval->num right-val)))))\n    (emptylist-exp ()\n      (emptylist-val))\n    (cons-exp (car cdr)\n      (let ((car-val (value-of car env))\n            (cdr-val (value-of cdr env)))\n        (pair-val car-val cdr-val)))\n    (car-exp (expr)\n      (pair-car (value-of expr env)))\n    (cdr-exp (expr)\n      (pair-cdr (value-of expr env)))\n    (null?-exp (expr)\n      (pair-null? (value-of expr env)))))\n"
  },
  {
    "path": "scheme/eopl/03/10.scm",
    "content": "; EOPL exercise 3.10\n;\n; Add an operation list to the language. This operation should take any number\n; of arguments, and return an expressed value containing the list of their\n; values. For example,\n;\n;   let x = 4\n;   in list(x, -(x, 1), -(x, 3))\n\n(load-relative \"cases/let/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (minus-exp\n    (expr expression?))\n  (add-exp\n    (left expression?)\n    (right expression?))\n  (diff-exp\n    (left expression?)\n    (right expression?))\n  (mult-exp\n    (left expression?)\n    (right expression?))\n  (div-exp\n    (left expression?)\n    (right expression?))\n  (zero?-exp\n    (expr expression?))\n  (equal?-exp\n    (left expression?)\n    (right expression?))\n  (less?-exp\n    (left expression?)\n    (right expression?))\n  (greater?-exp\n    (left expression?)\n    (right expression?))\n  (cons-exp\n    (car expression?)\n    (cdr expression?))\n  (car-exp\n    (expr expression?))\n  (cdr-exp\n    (expr expression?))\n  (null?-exp\n    (expr expression?))\n  (emptylist-exp)\n  (list-exp\n    (exprs (list-of expression?)))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"+\" \"(\" expression \",\" expression \")\") add-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"*\" \"(\" expression \",\" expression \")\") mult-exp)\n    (expression (\"/\" \"(\" expression \",\" expression \")\") div-exp)\n    (expression (\"cons\" \"(\" expression \",\" expression \")\") cons-exp)\n    (expression (\"car\" \"(\" expression \")\") car-exp)\n    (expression (\"cdr\" \"(\" expression \")\") cdr-exp)\n    (expression (\"null?\" \"(\" expression \")\") null?-exp)\n    (expression (\"emptylist\") emptylist-exp)\n    (expression (\"list\" \"(\" (separated-list expression \",\") \")\") list-exp)\n    (expression (\"equal?\" \"(\" expression \",\" expression \")\") equal?-exp)\n    (expression (\"less?\" \"(\" expression \",\" expression \")\") less?-exp)\n    (expression (\"greater?\" \"(\" expression \",\" expression \")\") greater?-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"minus\" \"(\" expression \")\") minus-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; Eval\n\n(define-datatype expval expval?\n  (num-val (num number?))\n  (bool-val (bool boolean?))\n  (pair-val (car expval?) (cdr expval?))\n  (emptylist-val))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->pair val)\n  (cases expval val\n    (pair-val (car cdr) (cons car cdr))\n    (else (eopl:error 'expval->pair \"Invalid pair: ~s\" val))))\n\n(define (pair-car val)\n  (cases expval val\n    (pair-val (car cdr) car)\n    (else (eopl:error 'pair-car \"Expected a pair: ~s\" val))))\n\n(define (pair-cdr val)\n  (cases expval val\n    (pair-val (car cdr) cdr)\n    (else (eopl:error 'pair-cdr \"Expected a pair: ~s\" val))))\n\n(define (pair-null? val)\n  (cases expval val\n    (emptylist-val () (bool-val #t))\n    (else (bool-val #f))))\n\n(define (list-val pair)\n  (if (null? pair)\n      (emptylist-val)\n      (pair-val (car pair)\n                (list-val (cdr pair)))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (add-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (+ left-num right-num)))))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val (- minuend-num subtrahend-num)))))\n    (mult-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (* left-num right-num)))))\n    (div-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (quotient left-num right-num)))))\n    (minus-exp (arg)\n      (num-val (- (expval->num (value-of arg env)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (equal?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (= (expval->num left-val)\n                     (expval->num right-val)))))\n    (less?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (< (expval->num left-val)\n                     (expval->num right-val)))))\n    (greater?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (> (expval->num left-val)\n                     (expval->num right-val)))))\n    (emptylist-exp ()\n      (emptylist-val))\n    (cons-exp (car cdr)\n      (let ((car-val (value-of car env))\n            (cdr-val (value-of cdr env)))\n        (pair-val car-val cdr-val)))\n    (car-exp (expr)\n      (pair-car (value-of expr env)))\n    (cdr-exp (expr)\n      (pair-cdr (value-of expr env)))\n    (null?-exp (expr)\n      (pair-null? (value-of expr env)))\n    (list-exp (exprs)\n      (list-val (map (curryr value-of env) exprs)))\n    ))\n"
  },
  {
    "path": "scheme/eopl/03/11.scm",
    "content": "; EOPL exercise 3.11\n;\n; In a real language, one might have many operators such as those in the\n; preceding exercises. Rearrange the code in the interpreter so that it is easy\n; to add new operators.\n\n; This is annoyingly tricky because of SLLGEN. I can't figure out why, but I\n; can't get it to either dynamically define the grammar with a predefined list\n; of operators (when the list is not specified as a literal) and I can't get\n; the scanner to treat some words as operators. Instead, I'm going to simplify\n; everything. I'm just going to implement the four arithmetic operators. If\n; more operators are added, the grammar needs to be modifying accordingly.\n\n(load-relative \"cases/let/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (op-exp\n    (operator symbol?)\n    (operands (list-of expression?)))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (operator ((or \"+\" \"-\" \"*\" \"/\")) symbol)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (operator \"(\" (separated-list expression \",\" ) \")\") op-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; Eval\n\n(define-datatype expval expval?\n  (num-val (num number?))\n  (bool-val (bool boolean?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n; The new stuff. Operators are defined in a table and value-of dispatches\n; accordingly.\n\n(define operators-table (make-hash))\n\n(define (apply-op rator rands)\n  (apply (hash-ref operators-table rator)\n         rands))\n\n(define (lift op)\n  (lambda args\n    (num-val (apply op (map expval->num args)))))\n\n(define operators\n  (list (list '+ (lift +))\n        (list '- (lift -))\n        (list '* (lift *))\n        (list '/ (lift quotient))))\n\n(for ([olist operators])\n     (hash-set! operators-table (car olist) (cadr olist)))\n\n; The new value-of\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body (extend-env var value env))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (op-exp (rator rands)\n      (apply-op rator (map (lambda (e) (value-of e env)) rands)))))\n"
  },
  {
    "path": "scheme/eopl/03/12.scm",
    "content": "; EOPL exercise 3.12\n;\n; Add to the defined language a facility that adds a cond expression. Use the\n; grammar\n;\n;   Expression ::= cond {Expression ==> Expression}* end\n;\n; In this expression, the expressions on the left-hand sides of the ==>'s are\n; evaluated in order until one of them returns a true value. The the value of\n; the entire expression is the value of the corresponding right-hand\n; expression. If none of the tests succeeds, the expression should report an\n; error.\n\n(load-relative \"cases/let/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (minus-exp\n    (expr expression?))\n  (add-exp\n    (left expression?)\n    (right expression?))\n  (diff-exp\n    (left expression?)\n    (right expression?))\n  (mult-exp\n    (left expression?)\n    (right expression?))\n  (div-exp\n    (left expression?)\n    (right expression?))\n  (zero?-exp\n    (expr expression?))\n  (equal?-exp\n    (left expression?)\n    (right expression?))\n  (less?-exp\n    (left expression?)\n    (right expression?))\n  (greater?-exp\n    (left expression?)\n    (right expression?))\n  (cons-exp\n    (car expression?)\n    (cdr expression?))\n  (cond-exp\n    (conditions (list-of expression?))\n    (actions (list-of expression?)))\n  (car-exp\n    (expr expression?))\n  (cdr-exp\n    (expr expression?))\n  (null?-exp\n    (expr expression?))\n  (emptylist-exp)\n  (list-exp\n    (exprs (list-of expression?)))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"cond\" (arbno expression \"==>\" expression) \"end\") cond-exp)\n    (expression (\"+\" \"(\" expression \",\" expression \")\") add-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"*\" \"(\" expression \",\" expression \")\") mult-exp)\n    (expression (\"/\" \"(\" expression \",\" expression \")\") div-exp)\n    (expression (\"cons\" \"(\" expression \",\" expression \")\") cons-exp)\n    (expression (\"car\" \"(\" expression \")\") car-exp)\n    (expression (\"cdr\" \"(\" expression \")\") cdr-exp)\n    (expression (\"null?\" \"(\" expression \")\") null?-exp)\n    (expression (\"emptylist\") emptylist-exp)\n    (expression (\"list\" \"(\" (separated-list expression \",\") \")\") list-exp)\n    (expression (\"equal?\" \"(\" expression \",\" expression \")\") equal?-exp)\n    (expression (\"less?\" \"(\" expression \",\" expression \")\") less?-exp)\n    (expression (\"greater?\" \"(\" expression \",\" expression \")\") greater?-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"minus\" \"(\" expression \")\") minus-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; Eval\n\n(define-datatype expval expval?\n  (num-val (num number?))\n  (bool-val (bool boolean?))\n  (pair-val (car expval?) (cdr expval?))\n  (emptylist-val))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->pair val)\n  (cases expval val\n    (pair-val (car cdr) (cons car cdr))\n    (else (eopl:error 'expval->pair \"Invalid pair: ~s\" val))))\n\n(define (pair-car val)\n  (cases expval val\n    (pair-val (car cdr) car)\n    (else (eopl:error 'pair-car \"Expected a pair: ~s\" val))))\n\n(define (pair-cdr val)\n  (cases expval val\n    (pair-val (car cdr) cdr)\n    (else (eopl:error 'pair-cdr \"Expected a pair: ~s\" val))))\n\n(define (pair-null? val)\n  (cases expval val\n    (emptylist-val () (bool-val #t))\n    (else (bool-val #f))))\n\n(define (list-val pair)\n  (if (null? pair)\n      (emptylist-val)\n      (pair-val (car pair)\n                (list-val (cdr pair)))))\n\n(define (eval-cond conditions actions env)\n  (cond ((null? conditions)\n         (bool-val #f))\n        ((expval->bool (value-of (car conditions) env))\n         (value-of (car actions) env))\n        (else\n         (eval-cond (cdr conditions) (cdr actions) env))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (add-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (+ left-num right-num)))))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val (- minuend-num subtrahend-num)))))\n    (mult-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (* left-num right-num)))))\n    (div-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (quotient left-num right-num)))))\n    (minus-exp (arg)\n      (num-val (- (expval->num (value-of arg env)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (equal?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (= (expval->num left-val)\n                     (expval->num right-val)))))\n    (less?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (< (expval->num left-val)\n                     (expval->num right-val)))))\n    (greater?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (> (expval->num left-val)\n                     (expval->num right-val)))))\n    (emptylist-exp ()\n      (emptylist-val))\n    (cons-exp (car cdr)\n      (let ((car-val (value-of car env))\n            (cdr-val (value-of cdr env)))\n        (pair-val car-val cdr-val)))\n    (car-exp (expr)\n      (pair-car (value-of expr env)))\n    (cdr-exp (expr)\n      (pair-cdr (value-of expr env)))\n    (null?-exp (expr)\n      (pair-null? (value-of expr env)))\n    (list-exp (exprs)\n      (list-val (map (curryr value-of env) exprs)))\n    (cond-exp (conditions actions)\n      (eval-cond conditions actions env))\n    ))\n"
  },
  {
    "path": "scheme/eopl/03/13.scm",
    "content": "; EOPL exercise 3.13\n;\n; Change the values of the language so that integers are the only expressed\n; values. Modify if so that the value 0 is treated as false and all other\n; values are treated as true. Modify the predicates accordingly.\n\n(load-relative \"cases/let/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (minus-exp\n    (expr expression?))\n  (add-exp\n    (left expression?)\n    (right expression?))\n  (diff-exp\n    (left expression?)\n    (right expression?))\n  (mult-exp\n    (left expression?)\n    (right expression?))\n  (div-exp\n    (left expression?)\n    (right expression?))\n  (zero?-exp\n    (expr expression?))\n  (equal?-exp\n    (left expression?)\n    (right expression?))\n  (less?-exp\n    (left expression?)\n    (right expression?))\n  (greater?-exp\n    (left expression?)\n    (right expression?))\n  (cond-exp\n    (conditions (list-of expression?))\n    (actions (list-of expression?)))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"cond\" (arbno expression \"==>\" expression) \"end\") cond-exp)\n    (expression (\"+\" \"(\" expression \",\" expression \")\") add-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"*\" \"(\" expression \",\" expression \")\") mult-exp)\n    (expression (\"/\" \"(\" expression \",\" expression \")\") div-exp)\n    (expression (\"equal?\" \"(\" expression \",\" expression \")\") equal?-exp)\n    (expression (\"less?\" \"(\" expression \",\" expression \")\") less?-exp)\n    (expression (\"greater?\" \"(\" expression \",\" expression \")\") greater?-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"minus\" \"(\" expression \")\") minus-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; Eval\n\n(define (eval-cond conditions actions env)\n  (cond ((null? conditions)\n         0)\n        ((zero? (value-of (car conditions) env))\n         (eval-cond (cdr conditions) (cdr actions) env))\n        (else\n         (value-of (car actions) env))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) num)\n    (var-exp (var) (apply-env env var))\n    (add-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (+ left-val right-val)))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (- minuend-val subtrahend-val)))\n    (mult-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (* left-val right-val)))\n    (div-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (quotient left-val right-val)))\n    (minus-exp (arg)\n      (- (value-of arg env)))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (if (zero? value)\n            1\n            0)))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (not (zero? value))\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (equal?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (if (= left-val right-val)\n            1\n            0)))\n    (less?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (if (< left-val right-val)\n            1\n            0)))\n    (greater?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (if (> left-val right-val)\n            1\n            0)))\n    (cond-exp (conditions actions)\n      (eval-cond conditions actions env))))\n"
  },
  {
    "path": "scheme/eopl/03/14.scm",
    "content": "; EOPL exercise 3.14\n;\n; As an alternative to the previous exercise, add a new nonterminal Bool-exp\n; of boolean expressions to the language. Change the production for\n; conditional expressions to say\n;\n;   Expression ::= if Bool-exp then Expression else Expression\n;\n; Write suitable productions for Bool-exp and implement value-of-bool-exp.\n; Where do the predicates of exercise 3.8 wind up in this organization?\n\n(load-relative \"cases/let/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (minus-exp\n    (expr expression?))\n  (add-exp\n    (left expression?)\n    (right expression?))\n  (diff-exp\n    (left expression?)\n    (right expression?))\n  (mult-exp\n    (left expression?)\n    (right expression?))\n  (div-exp\n    (left expression?)\n    (right expression?))\n  (zero?-exp\n    (expr expression?))\n  (equal?-exp\n    (left expression?)\n    (right expression?))\n  (less?-exp\n    (left expression?)\n    (right expression?))\n  (greater?-exp\n    (left expression?)\n    (right expression?))\n  (cons-exp\n    (car expression?)\n    (cdr expression?))\n  (cond-exp\n    (conditions (list-of expression?))\n    (actions (list-of expression?)))\n  (car-exp\n    (expr expression?))\n  (cdr-exp\n    (expr expression?))\n  (null?-exp\n    (expr expression?))\n  (emptylist-exp)\n  (list-exp\n    (exprs (list-of expression?)))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"cond\" (arbno boolean \"==>\" expression) \"end\") cond-exp)\n    (expression (\"+\" \"(\" expression \",\" expression \")\") add-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"*\" \"(\" expression \",\" expression \")\") mult-exp)\n    (expression (\"/\" \"(\" expression \",\" expression \")\") div-exp)\n    (expression (\"cons\" \"(\" expression \",\" expression \")\") cons-exp)\n    (expression (\"car\" \"(\" expression \")\") car-exp)\n    (expression (\"cdr\" \"(\" expression \")\") cdr-exp)\n    (expression (\"emptylist\") emptylist-exp)\n    (expression (\"list\" \"(\" (separated-list expression \",\") \")\") list-exp)\n    (expression (\"minus\" \"(\" expression \")\") minus-exp)\n    (expression (\"if\" boolean \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (boolean (\"null?\" \"(\" expression \")\") null?-exp)\n    (boolean (\"equal?\" \"(\" expression \",\" expression \")\") equal?-exp)\n    (boolean (\"less?\" \"(\" expression \",\" expression \")\") less?-exp)\n    (boolean (\"greater?\" \"(\" expression \",\" expression \")\") greater?-exp)\n    (boolean (\"zero?\" \"(\" expression \")\") zero?-exp)\n    ))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; Eval\n\n(define-datatype expval expval?\n  (num-val (num number?))\n  (bool-val (bool boolean?))\n  (pair-val (car expval?) (cdr expval?))\n  (emptylist-val))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->pair val)\n  (cases expval val\n    (pair-val (car cdr) (cons car cdr))\n    (else (eopl:error 'expval->pair \"Invalid pair: ~s\" val))))\n\n(define (pair-car val)\n  (cases expval val\n    (pair-val (car cdr) car)\n    (else (eopl:error 'pair-car \"Expected a pair: ~s\" val))))\n\n(define (pair-cdr val)\n  (cases expval val\n    (pair-val (car cdr) cdr)\n    (else (eopl:error 'pair-cdr \"Expected a pair: ~s\" val))))\n\n(define (pair-null? val)\n  (cases expval val\n    (emptylist-val () (bool-val #t))\n    (else (bool-val #f))))\n\n(define (list-val pair)\n  (if (null? pair)\n      (emptylist-val)\n      (pair-val (car pair)\n                (list-val (cdr pair)))))\n\n(define (eval-cond conditions actions env)\n  (cond ((null? conditions)\n         (bool-val #f))\n        ((expval->bool (value-of (car conditions) env))\n         (value-of (car actions) env))\n        (else\n         (eval-cond (cdr conditions) (cdr actions) env))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (add-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (+ left-num right-num)))))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val (- minuend-num subtrahend-num)))))\n    (mult-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (* left-num right-num)))))\n    (div-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (quotient left-num right-num)))))\n    (minus-exp (arg)\n      (num-val (- (expval->num (value-of arg env)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (equal?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (= (expval->num left-val)\n                     (expval->num right-val)))))\n    (less?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (< (expval->num left-val)\n                     (expval->num right-val)))))\n    (greater?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (> (expval->num left-val)\n                     (expval->num right-val)))))\n    (emptylist-exp ()\n      (emptylist-val))\n    (cons-exp (car cdr)\n      (let ((car-val (value-of car env))\n            (cdr-val (value-of cdr env)))\n        (pair-val car-val cdr-val)))\n    (car-exp (expr)\n      (pair-car (value-of expr env)))\n    (cdr-exp (expr)\n      (pair-cdr (value-of expr env)))\n    (null?-exp (expr)\n      (pair-null? (value-of expr env)))\n    (list-exp (exprs)\n      (list-val (map (curryr value-of env) exprs)))\n    (cond-exp (conditions actions)\n      (eval-cond conditions actions env))\n    ))\n"
  },
  {
    "path": "scheme/eopl/03/15.scm",
    "content": "; EOPL exercise 3.15\n;\n; Extend the language by adding a new operation print that takes one argument,\n; print its, and returns the integer 1. Why is this operation not expressible\n; in our specification framework?\n\n; The implementation is below.\n;\n; We cannot express it in our specification framework, because it has\n; side-effect (printing out STDOUT) and we don't have a way to express\n; side-effects.\n\n(load-relative \"cases/let/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (minus-exp\n    (expr expression?))\n  (add-exp\n    (left expression?)\n    (right expression?))\n  (diff-exp\n    (left expression?)\n    (right expression?))\n  (mult-exp\n    (left expression?)\n    (right expression?))\n  (div-exp\n    (left expression?)\n    (right expression?))\n  (zero?-exp\n    (expr expression?))\n  (equal?-exp\n    (left expression?)\n    (right expression?))\n  (less?-exp\n    (left expression?)\n    (right expression?))\n  (greater?-exp\n    (left expression?)\n    (right expression?))\n  (cons-exp\n    (car expression?)\n    (cdr expression?))\n  (cond-exp\n    (conditions (list-of expression?))\n    (actions (list-of expression?)))\n  (car-exp\n    (expr expression?))\n  (cdr-exp\n    (expr expression?))\n  (null?-exp\n    (expr expression?))\n  (emptylist-exp)\n  (list-exp\n    (exprs (list-of expression?)))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (print-exp\n    (expr expression?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"print\" expression) print-exp)\n    (expression (\"cond\" (arbno expression \"==>\" expression) \"end\") cond-exp)\n    (expression (\"+\" \"(\" expression \",\" expression \")\") add-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"*\" \"(\" expression \",\" expression \")\") mult-exp)\n    (expression (\"/\" \"(\" expression \",\" expression \")\") div-exp)\n    (expression (\"cons\" \"(\" expression \",\" expression \")\") cons-exp)\n    (expression (\"car\" \"(\" expression \")\") car-exp)\n    (expression (\"cdr\" \"(\" expression \")\") cdr-exp)\n    (expression (\"null?\" \"(\" expression \")\") null?-exp)\n    (expression (\"emptylist\") emptylist-exp)\n    (expression (\"list\" \"(\" (separated-list expression \",\") \")\") list-exp)\n    (expression (\"equal?\" \"(\" expression \",\" expression \")\") equal?-exp)\n    (expression (\"less?\" \"(\" expression \",\" expression \")\") less?-exp)\n    (expression (\"greater?\" \"(\" expression \",\" expression \")\") greater?-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"minus\" \"(\" expression \")\") minus-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; Eval\n\n(define-datatype expval expval?\n  (num-val (num number?))\n  (bool-val (bool boolean?))\n  (pair-val (car expval?) (cdr expval?))\n  (emptylist-val))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->pair val)\n  (cases expval val\n    (pair-val (car cdr) (cons car cdr))\n    (else (eopl:error 'expval->pair \"Invalid pair: ~s\" val))))\n\n(define (pair-car val)\n  (cases expval val\n    (pair-val (car cdr) car)\n    (else (eopl:error 'pair-car \"Expected a pair: ~s\" val))))\n\n(define (pair-cdr val)\n  (cases expval val\n    (pair-val (car cdr) cdr)\n    (else (eopl:error 'pair-cdr \"Expected a pair: ~s\" val))))\n\n(define (pair-null? val)\n  (cases expval val\n    (emptylist-val () (bool-val #t))\n    (else (bool-val #f))))\n\n(define (list-val pair)\n  (if (null? pair)\n      (emptylist-val)\n      (pair-val (car pair)\n                (list-val (cdr pair)))))\n\n(define (eval-cond conditions actions env)\n  (cond ((null? conditions)\n         (bool-val #f))\n        ((expval->bool (value-of (car conditions) env))\n         (value-of (car actions) env))\n        (else\n         (eval-cond (cdr conditions) (cdr actions) env))))\n\n(define (print-out value)\n  (cases expval value\n    (num-val (n) (display n))\n    (bool-val (b) (display b))\n    (emptylist-val () (display \"emptylist\"))\n    (pair-val (head tail)\n      (display \"cons(\")\n      (print-out head)\n      (display \", \")\n      (print-out tail)\n      (display \")\"))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (add-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (+ left-num right-num)))))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val (- minuend-num subtrahend-num)))))\n    (mult-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (* left-num right-num)))))\n    (div-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (quotient left-num right-num)))))\n    (minus-exp (arg)\n      (num-val (- (expval->num (value-of arg env)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (equal?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (= (expval->num left-val)\n                     (expval->num right-val)))))\n    (less?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (< (expval->num left-val)\n                     (expval->num right-val)))))\n    (greater?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (> (expval->num left-val)\n                     (expval->num right-val)))))\n    (emptylist-exp ()\n      (emptylist-val))\n    (cons-exp (car cdr)\n      (let ((car-val (value-of car env))\n            (cdr-val (value-of cdr env)))\n        (pair-val car-val cdr-val)))\n    (car-exp (expr)\n      (pair-car (value-of expr env)))\n    (cdr-exp (expr)\n      (pair-cdr (value-of expr env)))\n    (null?-exp (expr)\n      (pair-null? (value-of expr env)))\n    (list-exp (exprs)\n      (list-val (map (curryr value-of env) exprs)))\n    (print-exp (expr)\n      (print-out (value-of expr env))\n      (num-val 1))\n    (cond-exp (conditions actions)\n      (eval-cond conditions actions env))\n    ))\n"
  },
  {
    "path": "scheme/eopl/03/16.scm",
    "content": "; EOPL exercise 3.16\n;\n; Extend the language so that a let declaration can declare an arbitrary\n; number of variables, using the grammar\n;\n;   Expression ::= let {Identifier = Expression}* in Expression\n;\n; As in Scheme's let, each of the right-hand sides is evaluated in the current\n; environment, and the body is evaluated with each new variable bound to the\n; value of its associated right-hand side. For example,\n;\n;   let x = 30\n;   in let x = -(x, 1)\n;          y = -(x, 2)\n;      in -(x, y)\n;\n; should evaluate to 1.\n\n(load-relative \"cases/let/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (minus-exp\n    (expr expression?))\n  (add-exp\n    (left expression?)\n    (right expression?))\n  (diff-exp\n    (left expression?)\n    (right expression?))\n  (mult-exp\n    (left expression?)\n    (right expression?))\n  (div-exp\n    (left expression?)\n    (right expression?))\n  (zero?-exp\n    (expr expression?))\n  (equal?-exp\n    (left expression?)\n    (right expression?))\n  (less?-exp\n    (left expression?)\n    (right expression?))\n  (greater?-exp\n    (left expression?)\n    (right expression?))\n  (cons-exp\n    (car expression?)\n    (cdr expression?))\n  (cond-exp\n    (conditions (list-of expression?))\n    (actions (list-of expression?)))\n  (car-exp\n    (expr expression?))\n  (cdr-exp\n    (expr expression?))\n  (null?-exp\n    (expr expression?))\n  (emptylist-exp)\n  (list-exp\n    (exprs (list-of expression?)))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (print-exp\n    (expr expression?))\n  (let-exp\n    (vars (list-of symbol?))\n    (vals (list-of expression?))\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"print\" expression) print-exp)\n    (expression (\"cond\" (arbno expression \"==>\" expression) \"end\") cond-exp)\n    (expression (\"+\" \"(\" expression \",\" expression \")\") add-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"*\" \"(\" expression \",\" expression \")\") mult-exp)\n    (expression (\"/\" \"(\" expression \",\" expression \")\") div-exp)\n    (expression (\"cons\" \"(\" expression \",\" expression \")\") cons-exp)\n    (expression (\"car\" \"(\" expression \")\") car-exp)\n    (expression (\"cdr\" \"(\" expression \")\") cdr-exp)\n    (expression (\"null?\" \"(\" expression \")\") null?-exp)\n    (expression (\"emptylist\") emptylist-exp)\n    (expression (\"list\" \"(\" (separated-list expression \",\") \")\") list-exp)\n    (expression (\"equal?\" \"(\" expression \",\" expression \")\") equal?-exp)\n    (expression (\"less?\" \"(\" expression \",\" expression \")\") less?-exp)\n    (expression (\"greater?\" \"(\" expression \",\" expression \")\") greater?-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"minus\" \"(\" expression \")\") minus-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"let\" (arbno identifier \"=\" expression) \"in\" expression) let-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; Eval\n\n(define-datatype expval expval?\n  (num-val (num number?))\n  (bool-val (bool boolean?))\n  (pair-val (car expval?) (cdr expval?))\n  (emptylist-val))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->pair val)\n  (cases expval val\n    (pair-val (car cdr) (cons car cdr))\n    (else (eopl:error 'expval->pair \"Invalid pair: ~s\" val))))\n\n(define (pair-car val)\n  (cases expval val\n    (pair-val (car cdr) car)\n    (else (eopl:error 'pair-car \"Expected a pair: ~s\" val))))\n\n(define (pair-cdr val)\n  (cases expval val\n    (pair-val (car cdr) cdr)\n    (else (eopl:error 'pair-cdr \"Expected a pair: ~s\" val))))\n\n(define (pair-null? val)\n  (cases expval val\n    (emptylist-val () (bool-val #t))\n    (else (bool-val #f))))\n\n(define (list-val pair)\n  (if (null? pair)\n      (emptylist-val)\n      (pair-val (car pair)\n                (list-val (cdr pair)))))\n\n(define (eval-cond conditions actions env)\n  (cond ((null? conditions)\n         (bool-val #f))\n        ((expval->bool (value-of (car conditions) env))\n         (value-of (car actions) env))\n        (else\n         (eval-cond (cdr conditions) (cdr actions) env))))\n\n(define (print-out value)\n  (cases expval value\n    (num-val (n) (display n))\n    (bool-val (b) (display b))\n    (emptylist-val () (display \"emptylist\"))\n    (pair-val (head tail)\n      (display \"cons(\")\n      (print-out head)\n      (display \", \")\n      (print-out tail)\n      (display \")\"))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (add-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (+ left-num right-num)))))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val (- minuend-num subtrahend-num)))))\n    (mult-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (* left-num right-num)))))\n    (div-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (quotient left-num right-num)))))\n    (minus-exp (arg)\n      (num-val (- (expval->num (value-of arg env)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (vars vals body)\n      (value-of body (extend-env* vars\n                                  (map (curryr value-of env) vals)\n                                  env)))\n    (equal?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (= (expval->num left-val)\n                     (expval->num right-val)))))\n    (less?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (< (expval->num left-val)\n                     (expval->num right-val)))))\n    (greater?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (> (expval->num left-val)\n                     (expval->num right-val)))))\n    (emptylist-exp ()\n      (emptylist-val))\n    (cons-exp (car cdr)\n      (let ((car-val (value-of car env))\n            (cdr-val (value-of cdr env)))\n        (pair-val car-val cdr-val)))\n    (car-exp (expr)\n      (pair-car (value-of expr env)))\n    (cdr-exp (expr)\n      (pair-cdr (value-of expr env)))\n    (null?-exp (expr)\n      (pair-null? (value-of expr env)))\n    (list-exp (exprs)\n      (list-val (map (curryr value-of env) exprs)))\n    (print-exp (expr)\n      (print-out (value-of expr env))\n      (num-val 1))\n    (cond-exp (conditions actions)\n      (eval-cond conditions actions env))))\n"
  },
  {
    "path": "scheme/eopl/03/17.scm",
    "content": "; EOPL exercise 3.17\n;\n; Extend the language with a let* expression that works like Scheme's let*, so\n; that\n;\n;   let x = 30\n;   in let* x = -(x, 1) y = -(x, 2)\n;      in -(x, y)\n;\n; should evaluate to 2.\n\n(load-relative \"cases/let/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (minus-exp\n    (expr expression?))\n  (add-exp\n    (left expression?)\n    (right expression?))\n  (diff-exp\n    (left expression?)\n    (right expression?))\n  (mult-exp\n    (left expression?)\n    (right expression?))\n  (div-exp\n    (left expression?)\n    (right expression?))\n  (zero?-exp\n    (expr expression?))\n  (equal?-exp\n    (left expression?)\n    (right expression?))\n  (less?-exp\n    (left expression?)\n    (right expression?))\n  (greater?-exp\n    (left expression?)\n    (right expression?))\n  (cons-exp\n    (car expression?)\n    (cdr expression?))\n  (cond-exp\n    (conditions (list-of expression?))\n    (actions (list-of expression?)))\n  (car-exp\n    (expr expression?))\n  (cdr-exp\n    (expr expression?))\n  (null?-exp\n    (expr expression?))\n  (emptylist-exp)\n  (list-exp\n    (exprs (list-of expression?)))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (print-exp\n    (expr expression?))\n  (let-exp\n    (vars (list-of symbol?))\n    (vals (list-of expression?))\n    (body expression?))\n  (let*-exp\n    (vars (list-of symbol?))\n    (vals (list-of expression?))\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"print\" expression) print-exp)\n    (expression (\"cond\" (arbno expression \"==>\" expression) \"end\") cond-exp)\n    (expression (\"+\" \"(\" expression \",\" expression \")\") add-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"*\" \"(\" expression \",\" expression \")\") mult-exp)\n    (expression (\"/\" \"(\" expression \",\" expression \")\") div-exp)\n    (expression (\"cons\" \"(\" expression \",\" expression \")\") cons-exp)\n    (expression (\"car\" \"(\" expression \")\") car-exp)\n    (expression (\"cdr\" \"(\" expression \")\") cdr-exp)\n    (expression (\"null?\" \"(\" expression \")\") null?-exp)\n    (expression (\"emptylist\") emptylist-exp)\n    (expression (\"list\" \"(\" (separated-list expression \",\") \")\") list-exp)\n    (expression (\"equal?\" \"(\" expression \",\" expression \")\") equal?-exp)\n    (expression (\"less?\" \"(\" expression \",\" expression \")\") less?-exp)\n    (expression (\"greater?\" \"(\" expression \",\" expression \")\") greater?-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"minus\" \"(\" expression \")\") minus-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"let\" (arbno identifier \"=\" expression) \"in\" expression) let-exp)\n    (expression (\"let*\" (arbno identifier \"=\" expression) \"in\" expression) let*-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; Eval\n\n(define-datatype expval expval?\n  (num-val (num number?))\n  (bool-val (bool boolean?))\n  (pair-val (car expval?) (cdr expval?))\n  (emptylist-val))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->pair val)\n  (cases expval val\n    (pair-val (car cdr) (cons car cdr))\n    (else (eopl:error 'expval->pair \"Invalid pair: ~s\" val))))\n\n(define (pair-car val)\n  (cases expval val\n    (pair-val (car cdr) car)\n    (else (eopl:error 'pair-car \"Expected a pair: ~s\" val))))\n\n(define (pair-cdr val)\n  (cases expval val\n    (pair-val (car cdr) cdr)\n    (else (eopl:error 'pair-cdr \"Expected a pair: ~s\" val))))\n\n(define (pair-null? val)\n  (cases expval val\n    (emptylist-val () (bool-val #t))\n    (else (bool-val #f))))\n\n(define (list-val pair)\n  (if (null? pair)\n      (emptylist-val)\n      (pair-val (car pair)\n                (list-val (cdr pair)))))\n\n(define (eval-cond conditions actions env)\n  (cond ((null? conditions)\n         (bool-val #f))\n        ((expval->bool (value-of (car conditions) env))\n         (value-of (car actions) env))\n        (else\n         (eval-cond (cdr conditions) (cdr actions) env))))\n\n(define (print-out value)\n  (cases expval value\n    (num-val (n) (display n))\n    (bool-val (b) (display b))\n    (emptylist-val () (display \"emptylist\"))\n    (pair-val (head tail)\n      (display \"cons(\")\n      (print-out head)\n      (display \", \")\n      (print-out tail)\n      (display \")\"))))\n\n(define (eval-let* vars vals body env)\n  (if (null? vars)\n      (value-of body env)\n      (eval-let* (cdr vars)\n                 (cdr vals)\n                 body\n                 (extend-env (car vars)\n                             (value-of (car vals) env)\n                             env))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (add-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (+ left-num right-num)))))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val (- minuend-num subtrahend-num)))))\n    (mult-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (* left-num right-num)))))\n    (div-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (quotient left-num right-num)))))\n    (minus-exp (arg)\n      (num-val (- (expval->num (value-of arg env)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (vars vals body)\n      (value-of body (extend-env* vars\n                                  (map (curryr value-of env) vals)\n                                  env)))\n    (let*-exp (vars vals body)\n      (eval-let* vars vals body env))\n    (equal?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (= (expval->num left-val)\n                     (expval->num right-val)))))\n    (less?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (< (expval->num left-val)\n                     (expval->num right-val)))))\n    (greater?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (> (expval->num left-val)\n                     (expval->num right-val)))))\n    (emptylist-exp ()\n      (emptylist-val))\n    (cons-exp (car cdr)\n      (let ((car-val (value-of car env))\n            (cdr-val (value-of cdr env)))\n        (pair-val car-val cdr-val)))\n    (car-exp (expr)\n      (pair-car (value-of expr env)))\n    (cdr-exp (expr)\n      (pair-cdr (value-of expr env)))\n    (null?-exp (expr)\n      (pair-null? (value-of expr env)))\n    (list-exp (exprs)\n      (list-val (map (curryr value-of env) exprs)))\n    (print-exp (expr)\n      (print-out (value-of expr env))\n      (num-val 1))\n    (cond-exp (conditions actions)\n      (eval-cond conditions actions env))))\n"
  },
  {
    "path": "scheme/eopl/03/18.scm",
    "content": "; EOPL exercise 3.18\n;\n; Add an expression to the defined language\n;\n;   Expression ::= unpack {Identifier}* = Expression in Expression\n;\n; so that unpack x y z = lst in ... binds x, y, and z to the elements of lst\n; if lst is a list of exactly three elements, and reports an error otherwise.\n; For example, the value of\n;\n;   let u = 7\n;   in unpack x y = cons(u, cons(3, emptylist))\n;      in -(x, y)\n;\n; should be 4.\n\n(load-relative \"cases/let/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (minus-exp\n    (expr expression?))\n  (add-exp\n    (left expression?)\n    (right expression?))\n  (diff-exp\n    (left expression?)\n    (right expression?))\n  (mult-exp\n    (left expression?)\n    (right expression?))\n  (div-exp\n    (left expression?)\n    (right expression?))\n  (zero?-exp\n    (expr expression?))\n  (equal?-exp\n    (left expression?)\n    (right expression?))\n  (less?-exp\n    (left expression?)\n    (right expression?))\n  (greater?-exp\n    (left expression?)\n    (right expression?))\n  (cons-exp\n    (car expression?)\n    (cdr expression?))\n  (cond-exp\n    (conditions (list-of expression?))\n    (actions (list-of expression?)))\n  (car-exp\n    (expr expression?))\n  (cdr-exp\n    (expr expression?))\n  (null?-exp\n    (expr expression?))\n  (emptylist-exp)\n  (list-exp\n    (exprs (list-of expression?)))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (print-exp\n    (expr expression?))\n  (let-exp\n    (vars (list-of symbol?))\n    (vals (list-of expression?))\n    (body expression?))\n  (let*-exp\n    (vars (list-of symbol?))\n    (vals (list-of expression?))\n    (body expression?))\n  (unpack-exp\n    (names (list-of symbol?))\n    (lst expression?)\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"print\" expression) print-exp)\n    (expression (\"cond\" (arbno expression \"==>\" expression) \"end\") cond-exp)\n    (expression (\"+\" \"(\" expression \",\" expression \")\") add-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"*\" \"(\" expression \",\" expression \")\") mult-exp)\n    (expression (\"/\" \"(\" expression \",\" expression \")\") div-exp)\n    (expression (\"cons\" \"(\" expression \",\" expression \")\") cons-exp)\n    (expression (\"car\" \"(\" expression \")\") car-exp)\n    (expression (\"cdr\" \"(\" expression \")\") cdr-exp)\n    (expression (\"null?\" \"(\" expression \")\") null?-exp)\n    (expression (\"emptylist\") emptylist-exp)\n    (expression (\"list\" \"(\" (separated-list expression \",\") \")\") list-exp)\n    (expression (\"equal?\" \"(\" expression \",\" expression \")\") equal?-exp)\n    (expression (\"less?\" \"(\" expression \",\" expression \")\") less?-exp)\n    (expression (\"greater?\" \"(\" expression \",\" expression \")\") greater?-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"minus\" \"(\" expression \")\") minus-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"let\" (arbno identifier \"=\" expression) \"in\" expression) let-exp)\n    (expression (\"let*\" (arbno identifier \"=\" expression) \"in\" expression) let*-exp)\n    (expression (\"unpack\" (arbno identifier) \"=\" expression \"in\" expression) unpack-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; Eval\n\n(define-datatype expval expval?\n  (num-val (num number?))\n  (bool-val (bool boolean?))\n  (pair-val (car expval?) (cdr expval?))\n  (emptylist-val))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->pair val)\n  (cases expval val\n    (pair-val (car cdr) (cons car cdr))\n    (else (eopl:error 'expval->pair \"Invalid pair: ~s\" val))))\n\n(define (pair-car val)\n  (cases expval val\n    (pair-val (car cdr) car)\n    (else (eopl:error 'pair-car \"Expected a pair: ~s\" val))))\n\n(define (pair-cdr val)\n  (cases expval val\n    (pair-val (car cdr) cdr)\n    (else (eopl:error 'pair-cdr \"Expected a pair: ~s\" val))))\n\n(define (emptylist? val)\n  (cases expval val\n    (emptylist-val () #t)\n    (else #f)))\n\n(define (pair-null? val)\n  (cases expval val\n    (emptylist-val () (bool-val #t))\n    (else (bool-val #f))))\n\n(define (list-val pair)\n  (if (null? pair)\n      (emptylist-val)\n      (pair-val (car pair)\n                (list-val (cdr pair)))))\n\n(define (eval-cond conditions actions env)\n  (cond ((null? conditions)\n         (bool-val #f))\n        ((expval->bool (value-of (car conditions) env))\n         (value-of (car actions) env))\n        (else\n         (eval-cond (cdr conditions) (cdr actions) env))))\n\n(define (print-out value)\n  (cases expval value\n    (num-val (n) (display n))\n    (bool-val (b) (display b))\n    (emptylist-val () (display \"emptylist\"))\n    (pair-val (head tail)\n      (display \"cons(\")\n      (print-out head)\n      (display \", \")\n      (print-out tail)\n      (display \")\"))))\n\n(define (eval-let* vars vals body env)\n  (if (null? vars)\n      (value-of body env)\n      (eval-let* (cdr vars)\n                 (cdr vals)\n                 body\n                 (extend-env (car vars)\n                             (value-of (car vals) env)\n                             env))))\n\n(define (eval-unpack names lst-exp body env)\n  (define lst (value-of lst-exp env))\n  (define (bind-names vars vals new-env)\n    (cond ((and (null? vars) (pair-null? vals))\n           new-env)\n          ((or (null? vars) (emptylist? vals))\n           (eopl:error 'eval-unpack \"List size mismatch ~a, ~a\" names lst))\n          (else\n           (bind-names (cdr vars) (pair-cdr vals)\n                       (extend-env (car vars) (pair-car vals) new-env)))))\n  (value-of body (bind-names names lst env)))\n\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (add-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (+ left-num right-num)))))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val (- minuend-num subtrahend-num)))))\n    (mult-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (* left-num right-num)))))\n    (div-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (let ((left-num (expval->num left-val))\n              (right-num (expval->num right-val)))\n          (num-val (quotient left-num right-num)))))\n    (minus-exp (arg)\n      (num-val (- (expval->num (value-of arg env)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (vars vals body)\n      (value-of body (extend-env* vars\n                                  (map (curryr value-of env) vals)\n                                  env)))\n    (let*-exp (vars vals body)\n      (eval-let* vars vals body env))\n    (equal?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (= (expval->num left-val)\n                     (expval->num right-val)))))\n    (less?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (< (expval->num left-val)\n                     (expval->num right-val)))))\n    (greater?-exp (left right)\n      (let ((left-val (value-of left env))\n            (right-val (value-of right env)))\n        (bool-val (> (expval->num left-val)\n                     (expval->num right-val)))))\n    (emptylist-exp ()\n      (emptylist-val))\n    (cons-exp (car cdr)\n      (let ((car-val (value-of car env))\n            (cdr-val (value-of cdr env)))\n        (pair-val car-val cdr-val)))\n    (car-exp (expr)\n      (pair-car (value-of expr env)))\n    (cdr-exp (expr)\n      (pair-cdr (value-of expr env)))\n    (null?-exp (expr)\n      (pair-null? (value-of expr env)))\n    (list-exp (exprs)\n      (list-val (map (curryr value-of env) exprs)))\n    (print-exp (expr)\n      (print-out (value-of expr env))\n      (num-val 1))\n    (unpack-exp (names lst body)\n      (eval-unpack names lst body env))\n    (cond-exp (conditions actions)\n      (eval-cond conditions actions env))))\n"
  },
  {
    "path": "scheme/eopl/03/19.scm",
    "content": "; EOPL exercise 3.19\n;\n; In many languages, procedures must be created and named at the same time.\n; Modify the language of this section to have this property by replacing the\n; proc expression with a letproc expression.\n\n(load-relative \"cases/proc/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (letproc-exp\n    (name symbol?)\n    (var symbol?)\n    (body expression?)\n    (expr expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"letproc\" identifier \"(\" identifier \")\" \"=\" expression \"in\" expression) letproc-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; Eval\n\n(define-datatype proc proc?\n  (procedure\n    (var symbol?)\n    (body expression?)\n    (saved-env environment?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (var body saved-env)\n      (value-of body (extend-env var val saved-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (letproc-exp (name var body expr)\n      (value-of expr\n                (extend-env name\n                            (proc-val (procedure var body env))\n                            env)))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator env)))\n            (arg (value-of rand env)))\n        (apply-procedure proc arg)))))\n"
  },
  {
    "path": "scheme/eopl/03/20.scm",
    "content": "; EOPL exercise 3.20\n;\n; In PROC, procedures have only one argument, but one can get the effect of\n; multiple argument procedures by using procedures that return other\n; procedures. For example, one might write code like\n;\n;     let f = proc (x) proc (y) ...\n;     in ((f 3) 4)\n;\n; The trick is called currying, and the procedure is said to be curried. Write\n; a curried procedure that takes two arguments and returns their sum. You can\n; write x + y in our language by writing -(x, -(0, y)).\n\n(load-relative \"cases/proc/all.scm\")\n\n(define two-plus-three\n  \"let add = proc (x) proc (y) -(x, -(0, y))\n       in ((add 2) 3)\")\n"
  },
  {
    "path": "scheme/eopl/03/21.scm",
    "content": "; EOPL exercise 3.21\n;\n; Extend the language of this section to include procedures with multiple\n; arguments and class with multiple operands, as suggested by the grammar\n;\n;   Expression ::= proc ({Identifier}*(,)) Expression\n;   Expression ::= (Expression {Expression}*)\n\n(load-relative \"cases/proc/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var (list-of symbol?))\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand (list-of expression?))))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" (separated-list identifier \",\") \")\" expression) proc-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression (arbno expression) \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The evaluator\n\n(define-datatype proc proc?\n  (procedure\n    (var (list-of symbol?))\n    (body expression?)\n    (saved-env environment?)))\n\n(define (apply-procedure proc1 vals)\n  (cases proc proc1\n    (procedure (vars body saved-env)\n      (value-of body (extend-env* vars vals saved-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (proc-exp (vars body)\n      (proc-val (procedure vars body env)))\n    (call-exp (rator rands)\n      (let ((proc (expval->proc (value-of rator env)))\n            (args (map (lambda (rand) (value-of rand env))\n                       rands)))\n        (apply-procedure proc args)))))\n\n"
  },
  {
    "path": "scheme/eopl/03/22.scm",
    "content": "; EOPL exercise 3.22\n;\n; The concrete syntax of this section uses different syntax for a built-in\n; operation, such as difference, from a procedure call. Modify the concrete\n; syntax so that the user of this language need not know which operations are\n; built-in and which are defined procedures. The exercise may range from very\n; easy to hard, depending on the parsing technology being used.\n\n; This is quite annoying using SLLGEN. I'm doing it with a particularly nasty\n; function var-or-call that takes an ugly parse result and classifies it as a\n; var-exp or a call-exp.\n;\n; If I was less lazy, I could get foo(1)(2) to work. I'm not.\n\n(load-relative \"cases/proc/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var (list-of symbol?))\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand (list-of expression?))))\n\n(define (var-or-call id args)\n  (cond ((null? args) (var-exp id))\n        ((= (length args) 1) (call-exp (var-exp id) (car args)))\n        (else (eopl:error 'parse \"Can't parse this\"))))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (identifier (arbno \"(\" (separated-list expression \",\") \")\")) var-or-call)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (\"proc\" \"(\" (separated-list identifier \",\") \")\" expression) proc-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The evaluator\n\n(define-datatype proc proc?\n  (procedure\n    (var (list-of symbol?))\n    (body expression?)\n    (saved-env environment?)))\n\n(define (apply-procedure proc1 vals)\n  (cases proc proc1\n    (procedure (vars body saved-env)\n      (value-of body (extend-env* vars vals saved-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (proc-exp (vars body)\n      (proc-val (procedure vars body env)))\n    (call-exp (rator rands)\n      (let ((proc (expval->proc (value-of rator env)))\n            (args (map (lambda (rand) (value-of rand env))\n                       rands)))\n        (apply-procedure proc args)))))\n\n"
  },
  {
    "path": "scheme/eopl/03/23.scm",
    "content": "; EOPL exercise 3.23\n;\n; What is the value of the following PROC program?\n;\n;   let makemult = proc (maker)\n;                   proc (x)\n;                    if zero?(x)\n;                    then 0\n;                    else -(((maker maker) -(x, 1)), -4)\n;   in let times4 = proc (x) ((makemult makemult) x)\n;      in (times4 3)\n;\n; Use tricks of this program to write a procedure for factorial in PROC. As a\n; hint, remember that you can use currying (exercise 3.20) to define a\n; two-argument procedure times.\n\n; This smells of the Y combinator. Cool. The program returns 12, as the names\n; of its procedures suggest.\n\n(load-relative \"cases/proc/all.scm\")\n\n(define the-given-program\n  \"let makemult = proc (maker)\n                   proc (x)\n                    if zero?(x)\n                    then 0\n                    else -(((maker maker) -(x, 1)), -(0, 4))\n   in let times4 = proc (x) ((makemult makemult) x)\n      in (times4 3)\")\n\n(define factorial-5-program\n  \"let makemult = proc (maker)\n                   proc (x)\n                    proc (y)\n                     if zero?(y)\n                     then 0\n                     else -((((maker maker) x) -(y, 1)), -(0, x))\n   in let times = proc (x)\n                   proc (y)\n                    (((makemult makemult) x) y)\n      in let makefact = proc (fact)\n                         proc (n)\n                          if zero?(n)\n                          then 1\n                          else ((times n) ((fact fact) -(n, 1)))\n         in let factorial = proc (n)\n                             ((makefact makefact) n)\n            in (factorial 5)\")\n"
  },
  {
    "path": "scheme/eopl/03/24.scm",
    "content": "; EOPL exercise 3.24\n;\n; Use the tricks of the program above to write the pair of mutually recursive\n; procedures, odd and even, as in exercise 3.32.\n\n(load-relative \"cases/proc/all.scm\")\n\n(define the-program\n  \"let of = proc (o) proc (e) proc (n)\n             if zero?(n)\n             then 0\n             else (((e o) e) -(n, 1))\n   in let ef = proc (o) proc (e) proc (n)\n                if zero? (n)\n                then 1\n                else (((o o) e) -(n, 1))\n      in let odd = proc(n) (((of of) ef) n)\n         in let even = proc(n) (((ef of) ef) n)\n            in -(-((even 10), (odd 10)),\n                 -((odd 11), (even 11)))\")\n"
  },
  {
    "path": "scheme/eopl/03/25.scm",
    "content": "; EOPL exercise 3.25\n;\n; The tricks of the previous exercises can be generalized to show that we can\n; define any recursive procedure in PROC. Consider the following bit of code:\n;\n; let makerec = proc (f)\n;                let d = proc (x)\n;                         proc (z) ((f (x x)) z)\n;                in proc (n) ((f (d d)) n)\n; in let maketimes4 = proc (f)\n;                      proc (x)\n;                       if zero?(x)\n;                       then 0\n;                       else -((f -(x, 1)), -(0, 4))\n;    in let times4 = (makerec maketimes4)\n;       in (times4 3)\n;\n; Show that it returns 12.\n\n; This is the Y-combinator. I'm showing that it returns 12 by running it in\n; the tests.\n\n(load-relative \"cases/proc/all.scm\")\n\n(define the-example-program\n  \"let makerec = proc (f)\n                  let d = proc (x)\n                           proc (z) ((f (x x)) z)\n                  in proc (n) ((f (d d)) n)\n   in let maketimes4 = proc (f)\n                        proc (x)\n                         if zero?(x)\n                         then 0\n                         else -((f -(x, 1)), -(0, 4))\n      in let times4 = (makerec maketimes4)\n         in (times4 3)\")\n"
  },
  {
    "path": "scheme/eopl/03/26.scm",
    "content": "; EOPL exercise 3.26\n;\n; In our data-structure representation of procedures, we have kept the entire\n; environment in the closure. But of course all we need are the bindings of\n; the free variables. Modify the representation of procedures to retain only\n; the free variables.\n\n(load-relative \"cases/proc/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The evaluator\n\n(define-datatype proc proc?\n  (procedure\n    (var symbol?)\n    (body expression?)\n    (saved-env environment?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (var body saved-env)\n      (value-of body (extend-env var val saved-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (proc-exp (var body)\n      (proc-val (procedure var body env)))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator env)))\n            (arg (value-of rand env)))\n        (apply-procedure proc arg)))))\n\n; The required optimization\n\n(define (free-variables expr bound)\n  (remove-duplicates\n    (let recur ((expr expr) (bound bound))\n      (cases expression expr\n             (const-exp (num) '())\n             (var-exp (var)\n               (if (memq var bound)\n                   '()\n                   (list var)))\n             (diff-exp (minuend subtrahend)\n               (append (recur minuend bound)\n                       (recur subtrahend bound)))\n             (zero?-exp (arg)\n               (recur arg bound))\n             (if-exp (predicate consequent alternative)\n               (append (recur predicate bound)\n                       (recur consequent bound)\n                       (recur alternative bound)))\n             (let-exp (var value-exp body)\n               (append (recur value-exp bound)\n                       (recur body (cons var bound))))\n             (proc-exp (var body)\n               (recur body (cons var bound)))\n             (call-exp (rator rand)\n                (append (recur rator bound)\n                        (recur rand bound)))))))\n\n(define (slice-env vars env)\n  (filter (lambda (binding) (memq (car binding) vars))\n          env))\n\n(define (make-procedure var body saved-env)\n  (let* ((free-vars (free-variables body (list var)))\n         (simpler-env (slice-env free-vars saved-env)))\n    (procedure var body simpler-env)))\n"
  },
  {
    "path": "scheme/eopl/03/27.scm",
    "content": "; EOPL exercise 3.27\n;\n; Add a new kind of procedure called a traceproc to the language. A traceproc\n; works exactly like a proc, except that it prints a trace message on entry\n; and exit.\n\n(load-relative \"cases/proc/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (traceproc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"traceproc\" \"(\" identifier \")\" expression) traceproc-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The evaluator\n\n(define-datatype proc proc?\n  (procedure\n    (var symbol?)\n    (body expression?)\n    (saved-env environment?)\n    (trace? boolean?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (var body saved-env trace?)\n      (when trace? (printf \"enter: ~a = ~v\\n\" var val))\n      (let ((result (value-of body (extend-env var val saved-env))))\n        (when trace? (printf \"exit: ~a\\n\" var))\n        result))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (proc-exp (var body)\n      (proc-val (procedure var body env #f)))\n    (traceproc-exp (var body)\n      (proc-val (procedure var body env #t)))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator env)))\n            (arg (value-of rand env)))\n        (apply-procedure proc arg)))))\n"
  },
  {
    "path": "scheme/eopl/03/28.scm",
    "content": "; EOPL exercise 3.28\n;\n; Dynamic binding (or dynamic scoping) is an alternative design for\n; procedures, in which the procedure body is evaluated in an environment\n; obtained by extending the environment at the point of call. For example, in\n;\n;   let a = 3\n;   in let p = proc (x) -(x, a)\n;          a = 5\n;      in -(a, (p 2))\n;\n; the a in the procedure body would be bound to 5, not 3. Modify the language\n; to use dynamic binding. Do this twice, one using procedural representation\n; for procedures, and once using a data-structure representation.\n\n; I'll do it just once, with the existing (data-structure) representation. It\n; is simple enough with the other one.\n\n(load-relative \"cases/proc/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The evaluator\n\n(define-datatype proc proc?\n  (procedure\n    (var symbol?)\n    (body expression?)))\n\n(define (apply-procedure proc1 val env)\n  (cases proc proc1\n    (procedure (var body)\n      (value-of body (extend-env var val env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (proc-exp (var body)\n      (proc-val (procedure var body)))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator env)))\n            (arg (value-of rand env)))\n        (apply-procedure proc arg env)))))\n"
  },
  {
    "path": "scheme/eopl/03/29.scm",
    "content": "; EOPL exercise 3.29\n;\n; Unfortunatelly, programs that use dynamic binding may be exceptionally\n; difficult to understand. For example, undex lexical binding, consistently\n; renaming the bound variables of a procedure can never change the behavior of\n; a program: we can even remove all variables and replace them by their\n; lexical addresses, as in section 3.6. But under dynamic binding, this\n; transformation is unsafe.\n;\n; For example, under dynamic binding, the procedure proc (z) a returns the\n; value of the variable a in the caller's environment. Thus, the program\n;\n;   let a = 3\n;   in let p = proc (z) a\n;      in let f = proc (x) (p 0)\n;         in let a = 5\n;            in (f 2)\n;\n; returns 5, since a's value at the call site is 5. What if f's formal\n; parameter were a?\n\n; It would return 2. The test demonstrates it.\n\n(load-relative \"28.scm\")\n\n(define the-hypothetical-program\n  \"let a = 3\n   in let p = proc (z) a\n      in let f = proc (a) (p 0)\n         in let a = 5\n            in (f 2)\")\n"
  },
  {
    "path": "scheme/eopl/03/30.scm",
    "content": "; EOPL exercise 3.30\n;\n; What is the purpose of the call to proc-val on the next-to-last line of\n; apply-env?\n\n; It's a really simple question. Applying environments return expvals, not\n; procedures. If there is no call to proc-val, then the procedure gets passed\n; to expval->proc, which yields an error.\n"
  },
  {
    "path": "scheme/eopl/03/31.scm",
    "content": "; EOPL exercise 3.31\n;\n; Extend the language above to allow the declaration of a recursive procedure\n; of possibly many arguments, as in exercise 3.21.\n\n; The environment\n\n(define-datatype environment environment?\n  (empty-env)\n  (extend-env\n    (var symbol?)\n    (val expval?)\n    (env environment?))\n  (extend-env-rec\n    (p-name symbol?)\n    (b-vars (list-of symbol?))\n    (body expression?)\n    (env environment?)))\n\n(define (extend-env* vars vals env)\n  (if (null? vars)\n      env\n      (extend-env* (cdr vars)\n                   (cdr vals)\n                   (extend-env (car vars) (car vals) env))))\n\n(define (apply-env env search-var)\n  (cases environment env\n    (empty-env ()\n      (eopl:error 'apply-env \"Variable not found: ~s\" search-var))\n    (extend-env (saved-var saved-val saved-env)\n      (if (eqv? search-var saved-var)\n          saved-val\n          (apply-env saved-env search-var)))\n    (extend-env-rec (p-name b-vars p-body saved-env)\n      (if (eqv? search-var p-name)\n          (proc-val (procedure b-vars p-body env))\n          (apply-env saved-env search-var)))))\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var (list-of symbol?))\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand (list-of expression?)))\n  (letrec-exp\n    (p-name symbol?)\n    (b-vars (list-of symbol?))\n    (p-body expression?)\n    (letrec-body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" (separated-list identifier \",\") \")\" expression) proc-exp)\n    (expression (\"letrec\" identifier \"(\" (separated-list identifier \",\") \")\" \"=\" expression \"in\" expression) letrec-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression (arbno expression) \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The evaluator\n\n(define-datatype proc proc?\n  (procedure\n    (vars (list-of symbol?))\n    (body expression?)\n    (saved-env environment?)))\n\n(define (apply-procedure proc1 vals)\n  (cases proc proc1\n    (procedure (vars body saved-env)\n      (value-of body (extend-env* vars vals saved-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (proc-exp (vars body)\n      (proc-val (procedure vars body env)))\n    (call-exp (rator rands)\n      (let ((proc (expval->proc (value-of rator env)))\n            (args (map (lambda (rand) (value-of rand env))\n                       rands)))\n        (apply-procedure proc args)))\n    (letrec-exp (p-name b-vars p-body letrec-body)\n      (value-of letrec-body\n        (extend-env-rec p-name b-vars p-body env)))))\n\n"
  },
  {
    "path": "scheme/eopl/03/32.scm",
    "content": "; EOPL exercise 3.32\n;\n; Extend the language above to allow the declaration of any number of mutually\n; recursive unary procedures, for example:\n;\n;   letrec\n;     even(x) = if zero?(x) then 1 else (odd -(x, 1))\n;     odd(x)  = if zero?(x) then 0 else (even -(x, 1))\n;   in (odd 13)\n\n; The environment\n\n(define-datatype environment environment?\n  (empty-env)\n  (extend-env\n    (var symbol?)\n    (val expval?)\n    (env environment?))\n  (extend-env-rec\n    (p-name (list-of symbol?))\n    (b-var (list-of symbol?))\n    (body (list-of expression?))\n    (env environment?)))\n\n(define (extend-env* vars vals env)\n  (if (null? vars)\n      env\n      (extend-env* (cdr vars)\n                   (cdr vals)\n                   (extend-env (car vars) (car vals) env))))\n\n(define (apply-env env search-var)\n  (cases environment env\n    (empty-env ()\n      (eopl:error 'apply-env \"Variable not found: ~s\" search-var))\n    (extend-env (saved-var saved-val saved-env)\n      (if (eqv? search-var saved-var)\n          saved-val\n          (apply-env saved-env search-var)))\n    (extend-env-rec (p-names b-vars p-bodies saved-env)\n      (let recur ((p-names p-names)\n                  (b-vars b-vars)\n                  (p-bodies p-bodies))\n        (cond ((null? p-names)\n               (apply-env saved-env search-var))\n              ((eqv? search-var (car p-names))\n               (proc-val (procedure (car b-vars) (car p-bodies) env)))\n              (else\n               (recur (cdr p-names) (cdr b-vars) (cdr p-bodies))))))))\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?))\n  (letrec-exp\n    (p-names (list-of symbol?))\n    (b-vars (list-of symbol?))\n    (p-bodies (list-of expression?))\n    (letrec-body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"letrec\" (arbno identifier \"(\" identifier \")\" \"=\" expression) \"in\" expression) letrec-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The Evaluator\n\n(define-datatype proc proc?\n  (procedure\n    (var symbol?)\n    (body expression?)\n    (saved-env environment?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (var body saved-env)\n      (value-of body (extend-env var val saved-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (proc-exp (var body)\n      (proc-val (procedure var body env)))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator env)))\n            (arg (value-of rand env)))\n        (apply-procedure proc arg)))\n    (letrec-exp (p-names b-vars p-bodies letrec-body)\n      (value-of letrec-body\n        (extend-env-rec p-names b-vars p-bodies env)))))\n"
  },
  {
    "path": "scheme/eopl/03/33.scm",
    "content": "; EOPL exercise 3.33\n;\n; Extend the language above to allow the declaration of any number of mutually\n; recursive procedures, each of possibly many arguments, as in exercise 3.21.\n\n; The environment\n\n(define-datatype environment environment?\n  (empty-env)\n  (extend-env\n    (var symbol?)\n    (val expval?)\n    (env environment?))\n  (extend-env-rec\n    (p-names (list-of symbol?))\n    (b-vars (list-of (list-of symbol?)))\n    (body (list-of expression?))\n    (env environment?)))\n\n(define (extend-env* vars vals env)\n  (if (null? vars)\n      env\n      (extend-env* (cdr vars)\n                   (cdr vals)\n                   (extend-env (car vars) (car vals) env))))\n\n(define (apply-env env search-var)\n  (cases environment env\n    (empty-env ()\n      (eopl:error 'apply-env \"Variable not found: ~s\" search-var))\n    (extend-env (saved-var saved-val saved-env)\n      (if (eqv? search-var saved-var)\n          saved-val\n          (apply-env saved-env search-var)))\n    (extend-env-rec (p-names b-sigs p-bodies saved-env)\n      (let recur ((p-names p-names)\n                  (b-sigs b-sigs)\n                  (p-bodies p-bodies))\n        (cond ((null? p-names)\n               (apply-env saved-env search-var))\n              ((eqv? search-var (car p-names))\n               (proc-val (procedure (car b-sigs) (car p-bodies) env)))\n              (else\n               (recur (cdr p-names) (cdr b-sigs) (cdr p-bodies))))))))\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (vars (list-of symbol?))\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rands (list-of expression?)))\n  (letrec-exp\n    (p-names (list-of symbol?))\n    (b-vars (list-of (list-of symbol?)))\n    (p-bodies (list-of expression?))\n    (letrec-body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" (separated-list identifier \",\") \")\" expression) proc-exp)\n    (expression (\"letrec\" (arbno identifier \"(\" (separated-list identifier \",\") \")\" \"=\" expression) \"in\" expression) letrec-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression (arbno expression) \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The Evaluator\n\n(define-datatype proc proc?\n  (procedure\n    (vars (list-of symbol?))\n    (body expression?)\n    (saved-env environment?)))\n\n(define (apply-procedure proc1 vals)\n  (cases proc proc1\n    (procedure (vars body saved-env)\n      (value-of body (extend-env* vars vals saved-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (proc-exp (vars body)\n      (proc-val (procedure vars body env)))\n    (call-exp (rator rands)\n      (let ((proc (expval->proc (value-of rator env)))\n            (arg (map (lambda (rand) (value-of rand env))\n                      rands)))\n        (apply-procedure proc arg)))\n    (letrec-exp (p-names b-vars p-bodies letrec-body)\n      (value-of letrec-body\n        (extend-env-rec p-names b-vars p-bodies env)))))\n"
  },
  {
    "path": "scheme/eopl/03/34.scm",
    "content": "; EOPL exercise 3.34\n;\n; Implement extend-env-rec in the procedural representation of environment\n; from section 2.2.3.\n\n(load-relative \"cases/letrec/parser.scm\")\n(load-relative \"cases/letrec/eval.scm\")\n\n(define (environment? env)\n  (procedure? env))\n\n(define (empty-env)\n  (lambda (search-var)\n    (eopl:error 'apply-env \"Variable not found: ~s\" var)))\n\n(define (extend-env var val env)\n  (lambda (search-var)\n    (if (eqv? search-var var)\n        val\n        (env search-var))))\n\n(define (extend-env-rec name var body env)\n  (lambda (search-var)\n    (if (eqv? search-var name)\n        (proc-val (procedure var body (extend-env-rec name var body env)))\n        (env search-var))))\n\n(define (extend-env* vars vals env)\n  (if (null? vars)\n      env\n      (extend-env* (cdr vars)\n                   (cdr vals)\n                   (extend-env (car vars) (car vals) env))))\n\n(define (apply-env env search-var)\n  (env search-var))\n"
  },
  {
    "path": "scheme/eopl/03/35.scm",
    "content": "; EOPL exercise 3.35\n;\n; Thre representation we have seen so far are inefficient, becuase they build\n; a new closure every time the procedure is retrieved. But the closure is the\n; same every time. We can build the closures only once, by putting the value\n; in a vector of length 1 and building an explicit circular structure, like:\n;\n;   +------------+---+---+---+\n;   | extend-env | . | . | o----> saved-env\n;   +------------+-|-+-|-+---+\n;          ^       |   |\n;          |       V   V\n;          |       x  +------------------------------------------------------------------------------------------+\n;          |          |             +-----------+---+-----------------------------------------------------+---+  |\n;          |          |   proc-val  | procedure | x | <<if zero?(x) then 0 else -((double -(x, 1)), -2)>> | . |  |\n;          |          |             +-----------+---+-----------------------------------------------------+-|-+  |\n;          |          +-------------------------------------------------------------------------------------|----+\n;          |                                                                                                |\n;          +------------------------------------------------------------------------------------------------+\n;\n; Here's the code to build the data structure.\n;\n;   (define extend-env-rec\n;     (lambda (p-name b-var body saved-env)\n;       (let ((vec (make-vector 1)))\n;         (let ((new-env (extend-env p-name vec saved-env)))\n;           (vector-set! vec 0 (proc-val (procedure b-var body new-env)))\n;           new-env))))\n;\n; Complete the implementation of this representation by modifying the\n; definitions of the environment data type and apply-env accordingly. Be sure\n; that apply-env alwasy returns an expressed value.\n\n(load-relative \"cases/letrec/parser.scm\")\n(load-relative \"cases/letrec/eval.scm\")\n\n(define environment? (or/c pair? null?))\n\n(define (empty-env)\n  '())\n\n(define (extend-env var val env)\n  (cons (list var val)\n        env))\n\n(define (extend-env* vars vals env)\n  (if (null? vars)\n      env\n      (extend-env* (cdr vars)\n                   (cdr vals)\n                   (extend-env (car vars) (car vals) env))))\n\n(define (extend-env-rec p-name b-var body saved-env)\n  (let* ((vec (make-vector 1))\n         (new-env (extend-env p-name vec saved-env)))\n    (vector-set! vec 0 (proc-val (procedure b-var body new-env)))\n    new-env))\n\n(define (apply-env env var)\n  (cond ((null? env) (eopl:error 'apply-env \"Variable not found\"))\n        ((eqv? (caar env) var)\n         (let ((val (cadar env)))\n           (if (vector? val)\n               (vector-ref val 0)\n               val)))\n        (#t (apply-env (cdr env) var))))\n"
  },
  {
    "path": "scheme/eopl/03/36.scm",
    "content": "; EOPL exercise 3.36\n;\n; Extend this implementation to handle the language from exercise 3.32.\n\n(define environment? (or/c pair? null?))\n\n(define (empty-env)\n  '())\n\n(define (extend-env var val env)\n  (cons (list var val)\n        env))\n\n(define (extend-env* vars vals env)\n  (if (null? vars)\n      env\n      (extend-env* (cdr vars)\n                   (cdr vals)\n                   (extend-env (car vars) (car vals) env))))\n\n(define (extend-env-rec p-names b-vars bodies saved-env)\n  (let* ((vecs (map (lambda (_) (make-vector 1)) p-names))\n         (new-env (foldl (lambda (p-name vec env)\n                           (extend-env p-name vec env))\n                         saved-env p-names vecs)))\n    (for-each (lambda (vec b-var body)\n                (vector-set! vec 0 (proc-val (procedure b-var body new-env))))\n              vecs b-vars bodies)\n    new-env))\n\n(define (apply-env env var)\n  (cond ((null? env) (eopl:error 'apply-env \"Variable not found\"))\n        ((eqv? (caar env) var)\n         (let ((val (cadar env)))\n           (if (vector? val)\n               (vector-ref val 0)\n               val)))\n        (#t (apply-env (cdr env) var))))\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?))\n  (letrec-exp\n    (p-names (list-of symbol?))\n    (b-vars (list-of symbol?))\n    (p-bodies (list-of expression?))\n    (letrec-body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"letrec\" (arbno identifier \"(\" identifier \")\" \"=\" expression) \"in\" expression) letrec-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The Evaluator\n\n(define-datatype proc proc?\n  (procedure\n    (var symbol?)\n    (body expression?)\n    (saved-env environment?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (var body saved-env)\n      (value-of body (extend-env var val saved-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (proc-exp (var body)\n      (proc-val (procedure var body env)))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator env)))\n            (arg (value-of rand env)))\n        (apply-procedure proc arg)))\n    (letrec-exp (p-names b-vars p-bodies letrec-body)\n      (value-of letrec-body\n        (extend-env-rec p-names b-vars p-bodies env)))))\n"
  },
  {
    "path": "scheme/eopl/03/37.scm",
    "content": "; EOPL exercise 3.37\n;\n; With dynamic binding (exercise 3.28), recursive procedures may be bound by\n; let; no special mechanism is necessary for recursion. This is of historical\n; interest; in the early years of programming language design other approaches\n; to recursion, such as those discussed in section 3.4, were not widely\n; understood. To demonstrate recursion via dynamic binding, test the program\n;\n;   let fact = proc (n) add(1)\n;   in let fact = proc (n)\n;                  if zero?(n)\n;                  then 1\n;                  else *(n, (fact -(n, 1)))\n;      in (fact 5)\n;\n; using both lexical and dynamic binding. Write the mutually recursive\n; procedures even and odd as in section 3.4 in the defined language with\n; dynamic binding.\n\n(load-relative \"28.scm\")\n\n(define the-program\n  \"let odd  = proc (n) if zero?(n) then 0 else (even -(n, 1))\n   in let even = proc (n) if zero?(n) then 1 else (odd -(n, 1))\n      in (odd 11)\")\n"
  },
  {
    "path": "scheme/eopl/03/38.scm",
    "content": "; EOPL exercise 3.38\n;\n; Extend the lexical address translator and interpreter to handle cond from\n; exercise 3.12.\n\n(load-relative \"cases/nameless/env.scm\")\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?))\n  (nameless-var-exp\n    (num integer?))\n  (nameless-let-exp\n    (exp1 expression?)\n    (body expression?))\n  (nameless-proc-exp\n    (body expression?))\n  (cond-exp\n    (conditions (list-of expression?))\n    (actions (list-of expression?))))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"cond\" (arbno expression \"==>\" expression) \"end\") cond-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The evaluator\n(define-datatype proc proc?\n  (procedure\n    (body expression?)\n    (saved-nameless-env nameless-environment?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (body saved-nameless-env)\n      (value-of body (extend-nameless-env val saved-nameless-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (translation-of expr senv)\n  (cases expression expr\n    (const-exp (num) (const-exp num))\n    (diff-exp (minuend subtrahend)\n      (diff-exp\n        (translation-of minuend senv)\n        (translation-of subtrahend senv)))\n    (zero?-exp (arg)\n      (zero?-exp (translation-of arg senv)))\n    (if-exp (predicate consequent alternative)\n      (if-exp\n        (translation-of predicate senv)\n        (translation-of consequent senv)\n        (translation-of alternative senv)))\n    (var-exp (var)\n      (nameless-var-exp (apply-senv senv var)))\n    (let-exp (var value-exp body)\n      (nameless-let-exp\n        (translation-of value-exp senv)\n        (translation-of body (extend-senv var senv))))\n    (proc-exp (var body)\n      (nameless-proc-exp\n        (translation-of body (extend-senv var senv))))\n    (call-exp (rator rand)\n      (call-exp\n        (translation-of rator senv)\n        (translation-of rand senv)))\n    (cond-exp (conditions actions)\n      (cond-exp\n        (map (lambda (e) (translation-of e senv)) conditions)\n        (map (lambda (e) (translation-of e senv)) actions)))\n    (else\n      (eopl:error 'translation-of \"Cannot translate ~a\" expr))))\n\n(define (eval-cond conditions actions nenv)\n  (cond ((null? conditions)\n         (bool-val #f))\n        ((expval->bool (value-of (car conditions) nenv))\n         (value-of (car actions) nenv))\n        (else\n         (eval-cond (cdr conditions) (cdr actions) nenv))))\n\n(define (value-of expr nenv)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend nenv))\n            (subtrahend-val (value-of subtrahend nenv)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg nenv)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate nenv)))\n        (if (expval->bool value)\n            (value-of consequent nenv)\n            (value-of alternative nenv))))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator nenv)))\n            (arg (value-of rand nenv)))\n        (apply-procedure proc arg)))\n    (nameless-var-exp (n)\n      (apply-nameless-env nenv n))\n    (nameless-let-exp (value-exp body)\n      (let ((val (value-of value-exp nenv)))\n        (value-of body\n                  (extend-nameless-env val nenv))))\n    (nameless-proc-exp (body)\n      (proc-val\n        (procedure body nenv)))\n    (cond-exp (conditions actions)\n      (eval-cond conditions actions nenv))\n    (else\n      (eopl:error 'value-of \"Cannot evaluate ~a\" expr))))\n"
  },
  {
    "path": "scheme/eopl/03/39.scm",
    "content": "; EOPL exercise 3.39\n;\n; Extend the lexical address translator and interpreter to handle pack and\n; unpack from exercise 3.18.\n\n; The environments\n\n(load-relative \"cases/nameless/env.scm\")\n\n(define (extend-senv* vars senv)\n  (append vars senv))\n\n(define (extend-nenv* vals nenv)\n  (append vals nenv))\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?))\n  (nameless-var-exp\n    (num integer?))\n  (nameless-let-exp\n    (exp1 expression?)\n    (body expression?))\n  (nameless-proc-exp\n    (body expression?))\n  (cond-exp\n    (conditions (list-of expression?))\n    (actions (list-of expression?)))\n  (cons-exp\n    (car expression?)\n    (cdr expression?))\n  (car-exp\n    (expr expression?))\n  (cdr-exp\n    (expr expression?))\n  (null?-exp\n    (expr expression?))\n  (emptylist-exp)\n  (list-exp\n    (exprs (list-of expression?)))\n  (unpack-exp\n    (names (list-of symbol?))\n    (lst expression?)\n    (body expression?))\n  (nameless-unpack-exp\n    (size integer?)\n    (lst expression?)\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"cond\" (arbno expression \"==>\" expression) \"end\") cond-exp)\n    (expression (\"cons\" \"(\" expression \",\" expression \")\") cons-exp)\n    (expression (\"car\" \"(\" expression \")\") car-exp)\n    (expression (\"cdr\" \"(\" expression \")\") cdr-exp)\n    (expression (\"null?\" \"(\" expression \")\") null?-exp)\n    (expression (\"emptylist\") emptylist-exp)\n    (expression (\"list\" \"(\" (separated-list expression \",\") \")\") list-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"unpack\" (arbno identifier) \"=\" expression \"in\" expression) unpack-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The evaluator\n\n(define-datatype proc proc?\n  (procedure\n    (body expression?)\n    (saved-nameless-env nameless-environment?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (body saved-nameless-env)\n      (value-of body (extend-nameless-env val saved-nameless-env)))))\n\n(define-datatype expval expval?\n  (num-val (num number?))\n  (bool-val (bool boolean?))\n  (pair-val (car expval?) (cdr expval?))\n  (emptylist-val)\n  (proc-val (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (expval->pair val)\n  (cases expval val\n    (emptylist-val () '())\n    (pair-val (car cdr) (cons car (expval->pair cdr)))\n    (else (eopl:error 'expval->pair \"Invalid pair: ~s\" val))))\n\n(define (pair-car val)\n  (cases expval val\n    (pair-val (car cdr) car)\n    (else (eopl:error 'pair-car \"Expected a pair: ~s\" val))))\n\n(define (pair-cdr val)\n  (cases expval val\n    (pair-val (car cdr) cdr)\n    (else (eopl:error 'pair-cdr \"Expected a pair: ~s\" val))))\n\n(define (emptylist? val)\n  (cases expval val\n    (emptylist-val () #t)\n    (else #f)))\n\n(define (list-val pair)\n  (if (null? pair)\n      (emptylist-val)\n      (pair-val (car pair)\n                (list-val (cdr pair)))))\n\n(define (translation-of expr senv)\n  (cases expression expr\n    (const-exp (num) (const-exp num))\n    (diff-exp (minuend subtrahend)\n      (diff-exp\n        (translation-of minuend senv)\n        (translation-of subtrahend senv)))\n    (zero?-exp (arg)\n      (zero?-exp (translation-of arg senv)))\n    (if-exp (predicate consequent alternative)\n      (if-exp\n        (translation-of predicate senv)\n        (translation-of consequent senv)\n        (translation-of alternative senv)))\n    (var-exp (var)\n      (nameless-var-exp (apply-senv senv var)))\n    (let-exp (var value-exp body)\n      (nameless-let-exp\n        (translation-of value-exp senv)\n        (translation-of body (extend-senv var senv))))\n    (proc-exp (var body)\n      (nameless-proc-exp\n        (translation-of body (extend-senv var senv))))\n    (call-exp (rator rand)\n      (call-exp\n        (translation-of rator senv)\n        (translation-of rand senv)))\n    (cond-exp (conditions actions)\n      (cond-exp\n        (map (lambda (e) (translation-of e senv)) conditions)\n        (map (lambda (e) (translation-of e senv)) actions)))\n    (emptylist-exp ()\n      (emptylist-exp))\n    (null?-exp (arg)\n      (null?-exp (translation-of arg senv)))\n    (cons-exp (car cdr)\n      (cons-exp\n        (translation-of car senv)\n        (translation-of cdr senv)))\n    (car-exp (lst)\n      (car-exp (translation-of lst senv)))\n    (cdr-exp (lst)\n      (cdr-exp (translation-of lst senv)))\n    (list-exp (exprs)\n      (list-exp (map (lambda (e) (translation-of e senv)) exprs)))\n    (unpack-exp (vars lst body)\n      (nameless-unpack-exp\n        (length vars)\n        (translation-of lst senv)\n        (translation-of body (extend-senv* vars senv))))\n    (else\n      (eopl:error 'translation-of \"Cannot translate ~a\" expr))))\n\n(define (eval-cond conditions actions nenv)\n  (cond ((null? conditions)\n         (bool-val #f))\n        ((expval->bool (value-of (car conditions) nenv))\n         (value-of (car actions) nenv))\n        (else\n         (eval-cond (cdr conditions) (cdr actions) nenv))))\n\n(define (eval-unpack size list-exp body nenv)\n  (let ((vals (expval->pair (value-of list-exp nenv))))\n    (if (eqv? (length vals) size)\n        (value-of body (extend-nenv* vals nenv))\n        (eopl:error 'eval-unpack \"Size mismatch: ~a ~a\" size vals))))\n\n(define (value-of expr nenv)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend nenv))\n            (subtrahend-val (value-of subtrahend nenv)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg nenv)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate nenv)))\n        (if (expval->bool value)\n            (value-of consequent nenv)\n            (value-of alternative nenv))))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator nenv)))\n            (arg (value-of rand nenv)))\n        (apply-procedure proc arg)))\n    (nameless-var-exp (n)\n      (apply-nameless-env nenv n))\n    (nameless-let-exp (value-exp body)\n      (let ((val (value-of value-exp nenv)))\n        (value-of body\n                  (extend-nameless-env val nenv))))\n    (nameless-proc-exp (body)\n      (proc-val\n        (procedure body nenv)))\n    (cond-exp (conditions actions)\n      (eval-cond conditions actions nenv))\n    (emptylist-exp ()\n      (emptylist-val))\n    (null?-exp (arg)\n      (bool-val (emptylist? (value-of arg nenv))))\n    (cons-exp (car cdr)\n      (pair-val\n        (value-of car nenv)\n        (value-of cdr nenv)))\n    (car-exp (lst-exp)\n      (pair-car (value-of lst-exp nenv)))\n    (cdr-exp (lst-exp)\n      (pair-cdr (value-of lst-exp nenv)))\n    (list-exp (exprs)\n      (list-val (map (curryr value-of nenv) exprs)))\n    (nameless-unpack-exp (size lst body)\n      (eval-unpack size lst body nenv))\n    (else\n      (eopl:error 'value-of \"Cannot evaluate ~a\" expr))))\n"
  },
  {
    "path": "scheme/eopl/03/40.scm",
    "content": "; EOPL exercise 3.40\n;\n; Extend the lexical address translator and interpreter to handle letrec. Do\n; this by modifying the context argument of to translation-of so that it keeps\n; track of not only the name of each bound variable, but also whether it was\n; bound by letrec or not. For a reference to a variable that was bound by a\n; letrec, generate a new kind of reference, called a nameless-letrec-var-exp.\n; You can then continue to use the nameless environment representation above,\n; and the interpreter can do the right thing with a nameless-letrec-var-exp.\n\n; This is slightly awkward. I'm certain that I would have produced better\n; results if I could tweak the nameless environment a little bit.\n;\n; The most annoying thing is that I need to box the procedure body into a\n; proc, nested in a proc-val, so I can maintain the constraint on\n; nameless-environment.\n\n; The environment\n\n(define environment? (or/c pair? null?))\n\n(define (empty-senv)\n  '())\n\n(define (extend-senv type var senv)\n  (cons (list type var) senv))\n\n(define (extend-senv-lambda var senv)\n  (extend-senv 'lambda var senv))\n\n(define (extend-senv-letrec var senv)\n  (extend-senv 'letrec var senv))\n\n(define (apply-senv senv var)\n  (let recur ((index 0)\n              (senv senv))\n    (cond ((null? senv) (eopl:error 'apply-senv \"Unbound variable: ~a\" var))\n          ((eqv? var (cadar senv)) (values (caar senv) index))\n          (else (recur (+ index 1) (cdr senv))))))\n\n(define (nameless-environment? x)\n  ((list-of expval?) x))\n\n(define (empty-nameless-env)\n  '())\n\n(define (extend-nameless-env val nameless-env)\n  (cons val nameless-env))\n\n(define (apply-nameless-env nameless-env n)\n  (list-ref nameless-env n))\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (letrec-exp\n    (p-name symbol?)\n    (b-var symbol?)\n    (p-body expression?)\n    (letrec-body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?))\n  (nameless-var-exp\n    (num integer?))\n  (nameless-letrec-var-exp\n    (num integer?))\n  (nameless-let-exp\n    (exp1 expression?)\n    (body expression?))\n  (nameless-letrec-exp\n    (p-body expression?)\n    (letrec-body expression?))\n  (nameless-proc-exp\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"letrec\" identifier \"(\" identifier \")\" \"=\" expression \"in\" expression) letrec-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The evaluator\n\n(define-datatype proc proc?\n  (procedure\n    (body expression?)\n    (saved-nameless-env nameless-environment?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (body saved-nameless-env)\n      (value-of body (extend-nameless-env val saved-nameless-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (translation-of expr senv)\n  (cases expression expr\n    (const-exp (num) (const-exp num))\n    (diff-exp (minuend subtrahend)\n      (diff-exp\n        (translation-of minuend senv)\n        (translation-of subtrahend senv)))\n    (zero?-exp (arg)\n      (zero?-exp (translation-of arg senv)))\n    (if-exp (predicate consequent alternative)\n      (if-exp\n        (translation-of predicate senv)\n        (translation-of consequent senv)\n        (translation-of alternative senv)))\n    (var-exp (var)\n      (let-values (((type index) (apply-senv senv var)))\n        (case type\n          ((lambda) (nameless-var-exp index))\n          ((letrec) (nameless-letrec-var-exp index))\n          (else (eopl:error 'value-of \"Unknown variable type: ~a\" type)))))\n    (let-exp (var value-exp body)\n      (nameless-let-exp\n        (translation-of value-exp senv)\n        (translation-of body (extend-senv-lambda var senv))))\n    (letrec-exp (p-name b-var p-body letrec-body)\n      (nameless-letrec-exp\n        (translation-of p-body (extend-senv-lambda b-var (extend-senv-letrec p-name senv)))\n        (translation-of letrec-body (extend-senv-letrec p-name senv))))\n    (proc-exp (var body)\n      (nameless-proc-exp\n        (translation-of body (extend-senv-lambda var senv))))\n    (call-exp (rator rand)\n      (call-exp\n        (translation-of rator senv)\n        (translation-of rand senv)))\n    (else\n      (eopl:error 'translation-of \"Cannot translate ~a\" expr))))\n\n(define (value-of expr nenv)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend nenv))\n            (subtrahend-val (value-of subtrahend nenv)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg nenv)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate nenv)))\n        (if (expval->bool value)\n            (value-of consequent nenv)\n            (value-of alternative nenv))))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator nenv)))\n            (arg (value-of rand nenv)))\n        (apply-procedure proc arg)))\n    (nameless-var-exp (n)\n      (apply-nameless-env nenv n))\n    (nameless-letrec-var-exp (n)\n      (let* ((new-nenv (drop nenv n))\n             (proc-obj (expval->proc (car new-nenv))))\n        (cases proc proc-obj\n          (procedure (body saved-env)\n            (proc-val (procedure body new-nenv)))\n          (else (eopl:error 'value-of \"Expected a procedure\")))))\n    (nameless-let-exp (value-exp body)\n      (let ((val (value-of value-exp nenv)))\n        (value-of body\n                  (extend-nameless-env val nenv))))\n    (nameless-letrec-exp (proc-body letrec-body)\n      (let ((the-proc (proc-val (procedure proc-body nenv))))\n        (value-of letrec-body\n                  (extend-nameless-env the-proc nenv))))\n    (nameless-proc-exp (body)\n      (proc-val\n        (procedure body nenv)))\n    (else\n      (eopl:error 'value-of \"Cannot evaluate ~a\" expr))))\n"
  },
  {
    "path": "scheme/eopl/03/41.scm",
    "content": "; EOPL exercise 3.41\n;\n; Modify the lexical address translator and interpreter to handle let\n; expressions, procedures and procedure calls with multiple arguments, as in\n; exercise 3.21. Do this using a nameless version of the ribcage\n; representation of environments (exercise 2.11). For this representation, the\n; lexical address will consist of two nonnegative integers: the lexical depth,\n; to indicate the number of contours crossed, as before; and a position, to\n; indicate the position of the variable in the declaration.\n\n; The environments\n\n(define environment? (or/c pair? null?))\n\n(define (empty-senv)\n  '())\n\n(define (extend-senv vars senv)\n  (cons vars senv))\n\n(define (apply-senv senv var)\n  (let recur ((depth 0)\n              (position 0)\n              (frames (cdr senv))\n              (vars (car senv)))\n    (cond ((and (null? vars) (null? frames)) (eopl:error 'apply-senv \"Unbound variable: ~a\" var))\n          ((null? vars) (recur (+ depth 1) 0 (cdr frames) (car frames)))\n          ((eq? var (car vars)) (list depth position))\n          (else (recur depth (+ position 1) frames (cdr vars))))))\n\n(define (nameless-environment? x)\n  ((list-of (list-of expval?)) x))\n\n(define (empty-nameless-env)\n  '())\n\n(define (extend-nameless-env vals nameless-env)\n  (cons vals nameless-env))\n\n(define (apply-nameless-env nameless-env depth position)\n  (list-ref (list-ref nameless-env depth) position))\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (vars (list-of symbol?))\n    (vals (list-of expression?))\n    (body expression?))\n  (proc-exp\n    (vars (list-of symbol?))\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rands (list-of expression?)))\n  (nameless-var-exp\n    (depth integer?)\n    (position integer?))\n  (nameless-let-exp\n    (exps (list-of expression?))\n    (body expression?))\n  (nameless-proc-exp\n    (arity integer?)\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" (arbno identifier) \")\" expression) proc-exp)\n    (expression (\"let\" (arbno identifier \"=\" expression) \"in\" expression) let-exp)\n    (expression (\"(\" expression (arbno expression) \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The evaluator\n\n(define-datatype proc proc?\n  (procedure\n    (arity integer?)\n    (body expression?)\n    (saved-nameless-env nameless-environment?)))\n\n(define (apply-procedure proc1 vals)\n  (cases proc proc1\n    (procedure (arity body saved-nameless-env)\n      (if (= (length vals) arity)\n          (value-of body (extend-nameless-env vals saved-nameless-env))\n          (eopl:error 'apply-procedure \"Wrong arity\")))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (translation-of expr senv)\n  (cases expression expr\n    (const-exp (num) (const-exp num))\n    (diff-exp (minuend subtrahend)\n      (diff-exp\n        (translation-of minuend senv)\n        (translation-of subtrahend senv)))\n    (zero?-exp (arg)\n      (zero?-exp (translation-of arg senv)))\n    (if-exp (predicate consequent alternative)\n      (if-exp\n        (translation-of predicate senv)\n        (translation-of consequent senv)\n        (translation-of alternative senv)))\n    (var-exp (var)\n      (apply nameless-var-exp (apply-senv senv var)))\n    (let-exp (vars vals-exps body)\n      (nameless-let-exp\n        (map (curryr translation-of senv) vals-exps)\n        (translation-of body (extend-senv vars senv))))\n    (proc-exp (vars body)\n      (nameless-proc-exp\n        (length vars)\n        (translation-of body (extend-senv vars senv))))\n    (call-exp (rator rands)\n      (call-exp\n        (translation-of rator senv)\n        (map (curryr translation-of senv) rands)))\n    (else\n      (eopl:error 'translation-of \"Cannot translate ~a\" expr))))\n\n(define (value-of expr nenv)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend nenv))\n            (subtrahend-val (value-of subtrahend nenv)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg nenv)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate nenv)))\n        (if (expval->bool value)\n            (value-of consequent nenv)\n            (value-of alternative nenv))))\n    (call-exp (rator rands)\n      (let ((proc (expval->proc (value-of rator nenv)))\n            (args (map (curryr value-of nenv) rands)))\n        (apply-procedure proc args)))\n    (nameless-var-exp (depth position)\n      (apply-nameless-env nenv depth position))\n    (nameless-let-exp (val-exps body)\n      (let ((vals (map (curryr value-of nenv) val-exps)))\n        (value-of body\n                  (extend-nameless-env vals nenv))))\n    (nameless-proc-exp (arity body)\n      (proc-val\n        (procedure arity body nenv)))\n    (else\n      (eopl:error 'value-of \"Cannot evaluate ~a\" expr))))\n"
  },
  {
    "path": "scheme/eopl/03/42.scm",
    "content": "; EOPL exercise 3.42\n;\n; Modify the lexical address translator and intrepreter to used the trimmed\n; representation of procedures from exercise 3.26. For this, you will need to\n; translate the body of the procedure not (extend-senv var senv), but in a new\n; static environment that tells exactly where each variable will be kept in\n; the trimmed representation.\n\n; The environment\n\n(define environment? (or/c pair? null?))\n\n(define (empty-senv)\n  '())\n\n(define (extend-senv var senv)\n  (cons var senv))\n\n(define (apply-senv senv var)\n  (cond ((null? senv) (eopl:error 'apply-senv \"Unbound variable: ~a\" var))\n        ((eqv? var (car senv)) 0)\n        (else (+ 1 (apply-senv (cdr senv) var)))))\n\n(define (nameless-environment? x)\n  ((list-of expval?) x))\n\n(define (empty-nameless-env)\n  '())\n\n(define (extend-nameless-env val nameless-env)\n  (cons val nameless-env))\n\n(define (apply-nameless-env nameless-env n)\n  (list-ref nameless-env n))\n\n; The parser\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?))\n  (nameless-var-exp\n    (num integer?))\n  (nameless-let-exp\n    (exp1 expression?)\n    (body expression?))\n  (nameless-proc-exp\n    (body expression?)\n    (indices (list-of integer?))))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The interpreter\n\n(define-datatype proc proc?\n  (procedure\n    (body expression?)\n    (saved-nameless-env nameless-environment?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (body saved-nameless-env)\n      (value-of body (extend-nameless-env val saved-nameless-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (translation-of expr senv)\n  (cases expression expr\n    (const-exp (num) (const-exp num))\n    (diff-exp (minuend subtrahend)\n      (diff-exp\n        (translation-of minuend senv)\n        (translation-of subtrahend senv)))\n    (zero?-exp (arg)\n      (zero?-exp (translation-of arg senv)))\n    (if-exp (predicate consequent alternative)\n      (if-exp\n        (translation-of predicate senv)\n        (translation-of consequent senv)\n        (translation-of alternative senv)))\n    (var-exp (var)\n      (nameless-var-exp (apply-senv senv var)))\n    (let-exp (var value-exp body)\n      (nameless-let-exp\n        (translation-of value-exp senv)\n        (translation-of body (extend-senv var senv))))\n    (proc-exp (var body)\n      (let* ((vars (free-variables body (list var)))\n             (indices (map (curry position senv) vars)))\n        (nameless-proc-exp\n          (translation-of body (extend-senv var vars))\n          indices)))\n    (call-exp (rator rand)\n      (call-exp\n        (translation-of rator senv)\n        (translation-of rand senv)))\n    (else\n      (eopl:error 'translation-of \"Cannot translate ~a\" expr))))\n\n(define (value-of expr nenv)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend nenv))\n            (subtrahend-val (value-of subtrahend nenv)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg nenv)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate nenv)))\n        (if (expval->bool value)\n            (value-of consequent nenv)\n            (value-of alternative nenv))))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator nenv)))\n            (arg (value-of rand nenv)))\n        (apply-procedure proc arg)))\n    (nameless-var-exp (n)\n      (apply-nameless-env nenv n))\n    (nameless-let-exp (value-exp body)\n      (let ((val (value-of value-exp nenv)))\n        (value-of body\n                  (extend-nameless-env val nenv))))\n    (nameless-proc-exp (body indices)\n      (proc-val\n        (procedure body (slice-nenv nenv indices))))\n    (else\n      (eopl:error 'value-of \"Cannot evaluate ~a\" expr))))\n\n; The new code\n\n(define (slice-nenv nenv indices)\n  (map (curry apply-nameless-env nenv) indices))\n\n(define (position lst elem)\n  (cond ((null? lst) (eopl:error 'position \"Empty list\"))\n        ((eqv? (car lst) elem) 0)\n        (else (+ 1 (position (cdr lst) elem)))))\n\n(define (free-variables expr bound)\n  (remove-duplicates\n    (let recur ((expr expr) (bound bound))\n      (cases expression expr\n             (const-exp (num) '())\n             (var-exp (var)\n               (if (memq var bound)\n                   '()\n                   (list var)))\n             (diff-exp (minuend subtrahend)\n               (append (recur minuend bound)\n                       (recur subtrahend bound)))\n             (zero?-exp (arg)\n               (recur arg bound))\n             (if-exp (predicate consequent alternative)\n               (append (recur predicate bound)\n                       (recur consequent bound)\n                       (recur alternative bound)))\n             (let-exp (var value-exp body)\n               (append (recur value-exp bound)\n                       (recur body (cons var bound))))\n             (proc-exp (var body)\n               (recur body (cons var bound)))\n             (call-exp (rator rand)\n                (append (recur rator bound)\n                        (recur rand bound)))\n             (else\n               (eopl:error 'free-variables \"Can't find variables in: ~a\" expr))))))\n"
  },
  {
    "path": "scheme/eopl/03/43.scm",
    "content": "; EOPL exercise 3.43\n;\n; The translator can do more than keep track of the names of variables. For\n; example, consider the program:\n;\n;   let x = 3\n;   in let f = proc (y) -(y, x)\n;      in (f 13)\n;\n; Here we can tell statically that at the procedure call, f will be bound to a\n; procedure whose body is -(y, x), where x has the same value that it had at\n; the procedure-creation site. Therefore we could avoid looking up f in the\n; environment entirely. Extend the translator to keep track of \"known\n; procedures\" and generate code that avoids an environment lookup at the call\n; of such a procedure.\n\n; Let's start with a \"known environment\". It will store all values that can be\n; statically determined. Whenever we have a call with an operator that can be\n; determined via the known environment, we will translate it to a\n; known-proc-call (which is a new variant in the expression datatype).\n\n(define (empty-kenv)\n  '())\n\n(define (apply-kenv kenv var)\n  (let ((pair (assoc var kenv)))\n    (if pair\n        (cadr pair)\n        (eopl:error 'apply-kenv \"Unknown variable: ~a\" var))))\n\n(define (extend-kenv kenv var value)\n  (cons (list var value)\n        kenv))\n\n(define (kenv-names kenv)\n  (map car kenv))\n\n; The data type needs to be pulled up, because of, marcos\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?))\n  (nameless-var-exp\n    (num integer?))\n  (nameless-let-exp\n    (exp1 expression?)\n    (body expression?))\n  (nameless-proc-exp\n    (body expression?))\n  (known-proc-call\n    (procedure expval?)\n    (argument expression?)))\n\n; Some functions to work with known environments\n\n(define (construct-nenv senv kenv)\n  (map (curry apply-kenv kenv) senv))\n\n(define (constant? expr kenv)\n  (null? (free-variables expr (kenv-names kenv))))\n\n(define (eval-const expr senv kenv)\n  (value-of (translation-of expr senv (empty-kenv))\n            (construct-nenv senv kenv)))\n\n(define (known-procedure-ref kenv expr)\n  (cases expression expr\n    (var-exp (name)\n      (let ((pair (assoc name kenv)))\n        (if pair\n            (cadr pair)\n            #f)))\n    (else #f)))\n\n; The environment\n\n(define environment? (or/c pair? null?))\n\n(define (empty-senv)\n  '())\n\n(define (extend-senv var senv)\n  (cons var senv))\n\n(define (apply-senv senv var)\n  (cond ((null? senv) (eopl:error 'apply-senv \"Unbound variable: ~a\" var))\n        ((eqv? var (car senv)) 0)\n        (else (+ 1 (apply-senv (cdr senv) var)))))\n\n(define (nameless-environment? x)\n  ((list-of expval?) x))\n\n(define (empty-nameless-env)\n  '())\n\n(define (extend-nameless-env val nameless-env)\n  (cons val nameless-env))\n\n(define (apply-nameless-env nameless-env n)\n  (list-ref nameless-env n))\n\n; The parser\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The evaluator\n\n(define-datatype proc proc?\n  (procedure\n    (body expression?)\n    (saved-nameless-env nameless-environment?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (body saved-nameless-env)\n      (value-of body (extend-nameless-env val saved-nameless-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (translation-of expr senv kenv)\n  (cases expression expr\n    (const-exp (num) (const-exp num))\n    (diff-exp (minuend subtrahend)\n      (diff-exp\n        (translation-of minuend senv kenv)\n        (translation-of subtrahend senv kenv)))\n    (zero?-exp (arg)\n      (zero?-exp (translation-of arg senv kenv)))\n    (if-exp (predicate consequent alternative)\n      (if-exp\n        (translation-of predicate senv kenv)\n        (translation-of consequent senv kenv)\n        (translation-of alternative senv kenv)))\n    (var-exp (var)\n      (nameless-var-exp (apply-senv senv var)))\n    (let-exp (var value-exp body)\n      (nameless-let-exp\n        (translation-of value-exp senv kenv)\n        (translation-of body\n                        (extend-senv var senv)\n                        (if (constant? value-exp kenv)\n                            (extend-kenv kenv var (eval-const value-exp senv kenv))\n                            kenv))))\n    (proc-exp (var body)\n      (nameless-proc-exp\n        (translation-of body (extend-senv var senv) kenv)))\n    (call-exp (rator rand)\n      (let ((proc (known-procedure-ref kenv rator)))\n        (if proc\n            (known-proc-call\n              proc\n              (translation-of rand senv kenv))\n            (call-exp\n              (translation-of rator senv kenv)\n              (translation-of rand senv kenv)))))\n    (else\n      (eopl:error 'translation-of \"Cannot translate ~a\" expr))))\n\n(define (value-of expr nenv)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend nenv))\n            (subtrahend-val (value-of subtrahend nenv)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg nenv)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate nenv)))\n        (if (expval->bool value)\n            (value-of consequent nenv)\n            (value-of alternative nenv))))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator nenv)))\n            (arg (value-of rand nenv)))\n        (apply-procedure proc arg)))\n    (nameless-var-exp (n)\n      (apply-nameless-env nenv n))\n    (nameless-let-exp (value-exp body)\n      (let ((val (value-of value-exp nenv)))\n        (value-of body\n                  (extend-nameless-env val nenv))))\n    (nameless-proc-exp (body)\n      (proc-val\n        (procedure body nenv)))\n    (known-proc-call (proc rand)\n      (apply-procedure (expval->proc proc)\n                       (value-of rand nenv)))\n    (else\n      (eopl:error 'value-of \"Cannot evaluate ~a\" expr))))\n\n; Free-variables\n\n(define (free-variables expr bound)\n  (remove-duplicates\n    (let recur ((expr expr) (bound bound))\n      (cases expression expr\n             (const-exp (num) '())\n             (var-exp (var)\n               (if (memq var bound)\n                   '()\n                   (list var)))\n             (diff-exp (minuend subtrahend)\n               (append (recur minuend bound)\n                       (recur subtrahend bound)))\n             (zero?-exp (arg)\n               (recur arg bound))\n             (if-exp (predicate consequent alternative)\n               (append (recur predicate bound)\n                       (recur consequent bound)\n                       (recur alternative bound)))\n             (let-exp (var value-exp body)\n               (append (recur value-exp bound)\n                       (recur body (cons var bound))))\n             (proc-exp (var body)\n               (recur body (cons var bound)))\n             (call-exp (rator rand)\n                (append (recur rator bound)\n                        (recur rand bound)))\n             (else\n               (eopl:error 'free-variables \"Can't find variables in: ~a\" expr))))))\n"
  },
  {
    "path": "scheme/eopl/03/44.scm",
    "content": "; EOPL exercise 3.44\n;\n; In the preceding example, the only use of f is as a known procedure.\n; Therefore the procedure built by the expression proc (y) -(y, x) is never\n; used. Modify the translator so that such a procedure is never constructred.\n\n; We base this on the previous exercise. We just need to modify how let treats\n; its value-exp. If value-exp is a procedure and the var is used only in\n; operator position within the let body, then instead of translating the right\n; side of the let, we put a sentinel value (unused-proc-exp) in there.\n\n; We can, of course, interpret the exercise as having to inline the procedure,\n; but I don't want to go as far.\n\n; The known environment\n\n(define (empty-kenv)\n  '())\n\n(define (apply-kenv kenv var)\n  (let ((pair (assoc var kenv)))\n    (if pair\n        (cadr pair)\n        (eopl:error 'apply-kenv \"Unknown variable: ~a\" var))))\n\n(define (kenv-defines? kenv var)\n  (if (assoc var kenv)\n      #t\n      #f))\n\n(define (extend-kenv kenv var value)\n  (cons (list var value)\n        kenv))\n\n(define (kenv-names kenv)\n  (map car kenv))\n\n; The data type needs to be pulled up, because of, marcos\n\n(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?))\n  (nameless-var-exp\n    (num integer?))\n  (nameless-let-exp\n    (exp1 expression?)\n    (body expression?))\n  (nameless-proc-exp\n    (body expression?))\n  (known-proc-exp\n    (procedure expval?))\n  (known-proc-call-exp\n    (procedure expval?)\n    (argument expression?))\n  (unused-proc-exp))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n; Some functions to work with known environments\n\n(define (construct-nenv senv kenv)\n  (map (curry apply-kenv kenv) senv))\n\n(define (constant? expr kenv)\n  (null? (free-variables expr (kenv-names kenv))))\n\n(define (eval-const expr senv kenv)\n  (value-of (translation-of expr senv (empty-kenv))\n            (construct-nenv senv kenv)))\n\n(define (known-procedure-ref kenv expr)\n  (cases expression expr\n    (var-exp (name)\n      (let ((pair (assoc name kenv)))\n        (if pair\n            (cadr pair)\n            #f)))\n    (else #f)))\n\n; The new code\n\n(define (var-exp? expr)\n  (cases expression expr\n    (var-exp (name) #t)\n    (else #f)))\n\n(define (proc-val? val)\n  (cases expval val\n    (proc-val (proc) #t)\n    (else #f)))\n\n(define (procedure-safe-to-remove? body var kenv)\n  (and (kenv-defines? kenv var)\n       (proc-val? (apply-kenv kenv var))\n       (used-only-as-operator? body var)))\n\n(define (used-only-as-operator? expr var)\n  (cases expression expr\n    (const-exp (num) #t)\n    (var-exp (name)\n      (not (eqv? var name)))\n    (diff-exp (minuend subtrahend)\n      (and (used-only-as-operator? minuend var)\n           (used-only-as-operator? subtrahend var)))\n    (zero?-exp (arg)\n      (used-only-as-operator? arg var))\n    (if-exp (predicate consequent alternative)\n      (and (used-only-as-operator? predicate var)\n           (used-only-as-operator? consequent var)\n           (used-only-as-operator? alternative var)))\n    (let-exp (let-name value-exp body)\n      (and (used-only-as-operator? value-exp var)\n           (or (eqv? let-name var)\n               (used-only-as-operator? value-exp var))))\n    (proc-exp (param body)\n      (or (eqv? param var)\n          (used-only-as-operator? body var)))\n    (call-exp (rator rand)\n      (and (or (var-exp? rator)\n               (used-only-as-operator? rator var))\n           (used-only-as-operator? rand var)))\n    (else (eopl:error 'used-only-as-operator? \"Unexpected expression: ~a\" expr))))\n\n; The environment\n\n(define environment? (or/c pair? null?))\n\n(define (empty-senv)\n  '())\n\n(define (extend-senv var senv)\n  (cons var senv))\n\n(define (apply-senv senv var)\n  (cond ((null? senv) (eopl:error 'apply-senv \"Unbound variable: ~a\" var))\n        ((eqv? var (car senv)) 0)\n        (else (+ 1 (apply-senv (cdr senv) var)))))\n\n(define (nameless-environment? x)\n  ((list-of expval?) x))\n\n(define (empty-nameless-env)\n  '())\n\n(define (extend-nameless-env val nameless-env)\n  (cons val nameless-env))\n\n(define (apply-nameless-env nameless-env n)\n  (list-ref nameless-env n))\n\n; The parser\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n; The evaluator\n\n(define-datatype proc proc?\n  (procedure\n    (body expression?)\n    (saved-nameless-env nameless-environment?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (body saved-nameless-env)\n      (value-of body (extend-nameless-env val saved-nameless-env)))))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (translation-of expr senv kenv)\n  (cases expression expr\n    (const-exp (num) (const-exp num))\n    (diff-exp (minuend subtrahend)\n      (diff-exp\n        (translation-of minuend senv kenv)\n        (translation-of subtrahend senv kenv)))\n    (zero?-exp (arg)\n      (zero?-exp (translation-of arg senv kenv)))\n    (if-exp (predicate consequent alternative)\n      (if-exp\n        (translation-of predicate senv kenv)\n        (translation-of consequent senv kenv)\n        (translation-of alternative senv kenv)))\n    (var-exp (var)\n      (nameless-var-exp (apply-senv senv var)))\n    (let-exp (var value-exp body)\n      (if (constant? value-exp kenv)\n          (let* ((value (eval-const value-exp senv kenv))\n                 (body-kenv (extend-kenv kenv var value))\n                 (body-senv (extend-senv var senv)))\n            (nameless-let-exp\n              (if (procedure-safe-to-remove? body var body-kenv)\n                  (unused-proc-exp)\n                  (known-proc-exp value))\n              (translation-of body body-senv body-kenv)))\n          (nameless-let-exp\n            (translation-of value-exp senv kenv)\n            (translation-of body (extend-senv var senv) kenv))))\n    (proc-exp (var body)\n      (nameless-proc-exp\n        (translation-of body (extend-senv var senv) kenv)))\n    (call-exp (rator rand)\n      (let ((proc (known-procedure-ref kenv rator)))\n        (if proc\n            (known-proc-call-exp\n              proc\n              (translation-of rand senv kenv))\n            (call-exp\n              (translation-of rator senv kenv)\n              (translation-of rand senv kenv)))))\n    (else\n      (eopl:error 'translation-of \"Cannot translate ~a\" expr))))\n\n(define (value-of expr nenv)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend nenv))\n            (subtrahend-val (value-of subtrahend nenv)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg nenv)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate nenv)))\n        (if (expval->bool value)\n            (value-of consequent nenv)\n            (value-of alternative nenv))))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator nenv)))\n            (arg (value-of rand nenv)))\n        (apply-procedure proc arg)))\n    (nameless-var-exp (n)\n      (apply-nameless-env nenv n))\n    (nameless-let-exp (value-exp body)\n      (let ((val (value-of value-exp nenv)))\n        (value-of body\n                  (extend-nameless-env val nenv))))\n    (nameless-proc-exp (body)\n      (proc-val\n        (procedure body nenv)))\n    (known-proc-exp (proc)\n      proc)\n    (known-proc-call-exp (proc rand)\n      (apply-procedure (expval->proc proc)\n                       (value-of rand nenv)))\n    (unused-proc-exp () 'unused-procedure)\n    (else\n      (eopl:error 'value-of \"Cannot evaluate ~a\" expr))))\n\n; Free-variables\n\n(define (free-variables expr bound)\n  (remove-duplicates\n    (let recur ((expr expr) (bound bound))\n      (cases expression expr\n             (const-exp (num) '())\n             (var-exp (var)\n               (if (memq var bound)\n                   '()\n                   (list var)))\n             (diff-exp (minuend subtrahend)\n               (append (recur minuend bound)\n                       (recur subtrahend bound)))\n             (zero?-exp (arg)\n               (recur arg bound))\n             (if-exp (predicate consequent alternative)\n               (append (recur predicate bound)\n                       (recur consequent bound)\n                       (recur alternative bound)))\n             (let-exp (var value-exp body)\n               (append (recur value-exp bound)\n                       (recur body (cons var bound))))\n             (proc-exp (var body)\n               (recur body (cons var bound)))\n             (call-exp (rator rand)\n                (append (recur rator bound)\n                        (recur rand bound)))\n             (else\n               (eopl:error 'free-variables \"Can't find variables in: ~a\" expr))))))\n"
  },
  {
    "path": "scheme/eopl/03/cases/let/all.scm",
    "content": "(require eopl)\n(load-relative \"parser.scm\")\n(load-relative \"env.scm\")\n(load-relative \"eval.scm\")\n"
  },
  {
    "path": "scheme/eopl/03/cases/let/env.scm",
    "content": "(define (empty-env)\n  '())\n\n(define (extend-env var val env)\n  (cons (list var val)\n        env))\n\n(define (extend-env* vars vals env)\n  (if (null? vars)\n      env\n      (extend-env* (cdr vars)\n                   (cdr vals)\n                   (extend-env (car vars) (car vals) env))))\n\n(define (apply-env env var)\n  (cond ((null? env) (eopl:error 'apply-env \"Variable not found\"))\n        ((eqv? (caar env) var) (cadar env))\n        (#t (apply-env (cdr env) var))))\n"
  },
  {
    "path": "scheme/eopl/03/cases/let/eval.scm",
    "content": "(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))))\n"
  },
  {
    "path": "scheme/eopl/03/cases/let/parser.scm",
    "content": "(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n"
  },
  {
    "path": "scheme/eopl/03/cases/let/test-helpers.scm",
    "content": "(define (run code)\n  (eval* code (empty-env)))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (cases expval result\n      (num-val (num) num)\n      (bool-val (bool) bool))))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map (lambda (val)\n                      (if (boolean? val)\n                          (bool-val val)\n                          (num-val val)))\n                    vals)\n               (empty-env)))\n"
  },
  {
    "path": "scheme/eopl/03/cases/let/tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"all.scm\")\n(load-relative \"test-helpers.scm\")\n\n(define let-language-tests\n  (test-suite\n    \"Tests for the LET language\"\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n))\n\n(exit (run-tests let-language-tests))\n"
  },
  {
    "path": "scheme/eopl/03/cases/letrec/all.scm",
    "content": "(require eopl)\n(load-relative \"parser.scm\")\n(load-relative \"env.scm\")\n(load-relative \"eval.scm\")\n"
  },
  {
    "path": "scheme/eopl/03/cases/letrec/env.scm",
    "content": "(define-datatype environment environment?\n  (empty-env)\n  (extend-env\n    (var symbol?)\n    (val expval?)\n    (env environment?))\n  (extend-env-rec\n    (p-name symbol?)\n    (b-var symbol?)\n    (body expression?)\n    (env environment?)))\n\n(define (extend-env* vars vals env)\n  (if (null? vars)\n      env\n      (extend-env* (cdr vars)\n                   (cdr vals)\n                   (extend-env (car vars) (car vals) env))))\n\n(define (apply-env env search-var)\n  (cases environment env\n    (empty-env ()\n      (eopl:error 'apply-env \"Variable not found: ~s\" search-var))\n    (extend-env (saved-var saved-val saved-env)\n      (if (eqv? search-var saved-var)\n          saved-val\n          (apply-env saved-env search-var)))\n    (extend-env-rec (p-name b-var p-body saved-env)\n      (if (eqv? search-var p-name)\n          (proc-val (procedure b-var p-body env))\n          (apply-env saved-env search-var)))))\n"
  },
  {
    "path": "scheme/eopl/03/cases/letrec/eval.scm",
    "content": "(define-datatype proc proc?\n  (procedure\n    (var symbol?)\n    (body expression?)\n    (saved-env environment?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (var body saved-env)\n      (value-of body (extend-env var val saved-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (proc-exp (var body)\n      (proc-val (procedure var body env)))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator env)))\n            (arg (value-of rand env)))\n        (apply-procedure proc arg)))\n    (letrec-exp (p-name b-var p-body letrec-body)\n      (value-of letrec-body\n        (extend-env-rec p-name b-var p-body env)))))\n"
  },
  {
    "path": "scheme/eopl/03/cases/letrec/parser.scm",
    "content": "(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?))\n  (letrec-exp\n    (p-name symbol?)\n    (b-var symbol?)\n    (p-body expression?)\n    (letrec-body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"letrec\" identifier \"(\" identifier \")\" \"=\" expression \"in\" expression) letrec-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n"
  },
  {
    "path": "scheme/eopl/03/cases/letrec/test-helpers.scm",
    "content": "(define (run code)\n  (eval* code (empty-env)))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (cases expval result\n      (num-val (num) num)\n      (bool-val (bool) bool)\n      (proc-val (proc) proc))))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map (lambda (val)\n                      (if (boolean? val)\n                          (bool-val val)\n                          (num-val val)))\n                    vals)\n               (empty-env)))\n"
  },
  {
    "path": "scheme/eopl/03/cases/letrec/tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"all.scm\")\n(load-relative \"test-helpers.scm\")\n\n(define letrec-language-tests\n  (test-suite\n    \"Tests for the LETREC language\"\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n\n    (check-equal? (run \"let f = proc (x) -(x, 11)\n                        in (f (f 77))\")\n                  55)\n\n    (check-equal? (run \"(proc (f) (f (f 77))\n                         proc (x) -(x, 11))\")\n                  55)\n\n    (check-equal? (run \"let x = 200\n                        in let f = proc (z) -(z, x)\n                           in let x = 100\n                              in let g = proc (z) -(z, x)\n                                 in -((f 1), (g 1))\")\n                  -100)\n\n    (check-equal? (run \"letrec double(x)\n                                = if zero?(x) then 0 else -((double -(x, 1)), -(0, 2))\n                        in (double 6)\")\n                  12)\n))\n\n(exit (run-tests letrec-language-tests))\n"
  },
  {
    "path": "scheme/eopl/03/cases/nameless/all.scm",
    "content": "(require eopl)\n(load-relative \"../../../support/eopl.scm\")\n(load-relative \"parser.scm\")\n(load-relative \"env.scm\")\n(load-relative \"eval.scm\")\n"
  },
  {
    "path": "scheme/eopl/03/cases/nameless/env.scm",
    "content": "(define environment? (or/c pair? null?))\n\n(define (empty-senv)\n  '())\n\n(define (extend-senv var senv)\n  (cons var senv))\n\n(define (apply-senv senv var)\n  (cond ((null? senv) (eopl:error 'apply-senv \"Unbound variable: ~a\" var))\n        ((eqv? var (car senv)) 0)\n        (else (+ 1 (apply-senv (cdr senv) var)))))\n\n(define (nameless-environment? x)\n  ((list-of expval?) x))\n\n(define (empty-nameless-env)\n  '())\n\n(define (extend-nameless-env val nameless-env)\n  (cons val nameless-env))\n\n(define (apply-nameless-env nameless-env n)\n  (list-ref nameless-env n))\n\n"
  },
  {
    "path": "scheme/eopl/03/cases/nameless/eval.scm",
    "content": "(define-datatype proc proc?\n  (procedure\n    (body expression?)\n    (saved-nameless-env nameless-environment?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (body saved-nameless-env)\n      (value-of body (extend-nameless-env val saved-nameless-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (translation-of expr senv)\n  (cases expression expr\n    (const-exp (num) (const-exp num))\n    (diff-exp (minuend subtrahend)\n      (diff-exp\n        (translation-of minuend senv)\n        (translation-of subtrahend senv)))\n    (zero?-exp (arg)\n      (zero?-exp (translation-of arg senv)))\n    (if-exp (predicate consequent alternative)\n      (if-exp\n        (translation-of predicate senv)\n        (translation-of consequent senv)\n        (translation-of alternative senv)))\n    (var-exp (var)\n      (nameless-var-exp (apply-senv senv var)))\n    (let-exp (var value-exp body)\n      (nameless-let-exp\n        (translation-of value-exp senv)\n        (translation-of body (extend-senv var senv))))\n    (proc-exp (var body)\n      (nameless-proc-exp\n        (translation-of body (extend-senv var senv))))\n    (call-exp (rator rand)\n      (call-exp\n        (translation-of rator senv)\n        (translation-of rand senv)))\n    (else\n      (eopl:error 'translation-of \"Cannot translate ~a\" expr))))\n\n(define (value-of expr nenv)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend nenv))\n            (subtrahend-val (value-of subtrahend nenv)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg nenv)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate nenv)))\n        (if (expval->bool value)\n            (value-of consequent nenv)\n            (value-of alternative nenv))))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator nenv)))\n            (arg (value-of rand nenv)))\n        (apply-procedure proc arg)))\n    (nameless-var-exp (n)\n      (apply-nameless-env nenv n))\n    (nameless-let-exp (value-exp body)\n      (let ((val (value-of value-exp nenv)))\n        (value-of body\n                  (extend-nameless-env val nenv))))\n    (nameless-proc-exp (body)\n      (proc-val\n        (procedure body nenv)))\n    (else\n      (eopl:error 'value-of \"Cannot evaluate ~a\" expr))))\n"
  },
  {
    "path": "scheme/eopl/03/cases/nameless/parser.scm",
    "content": "(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?))\n  (nameless-var-exp\n    (num integer?))\n  (nameless-let-exp\n    (exp1 expression?)\n    (body expression?))\n  (nameless-proc-exp\n    (body expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n"
  },
  {
    "path": "scheme/eopl/03/cases/nameless/test-helpers.scm",
    "content": "(define (run code)\n  (eval* code (empty-nameless-env)))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (expr (translation-of expr (empty-senv)))\n         (result (value-of expr env)))\n    (cases expval result\n      (num-val (num) num)\n      (bool-val (bool) bool)\n      (proc-val (proc) proc))))\n"
  },
  {
    "path": "scheme/eopl/03/cases/nameless/tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"all.scm\")\n(load-relative \"test-helpers.scm\")\n\n(define nameless-interpreter-tests\n  (test-suite\n    \"Tests for the nameless interpreter\"\n\n    (check-equal? (run \"42\") 42)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n\n    (check-equal? (run \"let f = proc (x) -(x, 11)\n                        in (f (f 77))\")\n                  55)\n\n    (check-equal? (run \"(proc (f) (f (f 77))\n                         proc (x) -(x, 11))\")\n                  55)\n\n    (check-equal? (run \"let x = 200\n                        in let f = proc (z) -(z, x)\n                           in let x = 100\n                              in let g = proc (z) -(z, x)\n                                 in -((f 1), (g 1))\")\n                  -100)\n))\n\n(exit (run-tests nameless-interpreter-tests))\n"
  },
  {
    "path": "scheme/eopl/03/cases/proc/all.scm",
    "content": "(require eopl)\n(load-relative \"parser.scm\")\n(load-relative \"env.scm\")\n(load-relative \"eval.scm\")\n"
  },
  {
    "path": "scheme/eopl/03/cases/proc/env.scm",
    "content": "(define environment? (or/c pair? null?))\n\n(define (empty-env)\n  '())\n\n(define (extend-env var val env)\n  (cons (list var val)\n        env))\n\n(define (extend-env* vars vals env)\n  (if (null? vars)\n      env\n      (extend-env* (cdr vars)\n                   (cdr vals)\n                   (extend-env (car vars) (car vals) env))))\n\n(define (apply-env env var)\n  (cond ((null? env) (eopl:error 'apply-env \"Variable not found\"))\n        ((eqv? (caar env) var) (cadar env))\n        (#t (apply-env (cdr env) var))))\n"
  },
  {
    "path": "scheme/eopl/03/cases/proc/eval.scm",
    "content": "(define-datatype proc proc?\n  (procedure\n    (var symbol?)\n    (body expression?)\n    (saved-env environment?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (var body saved-env)\n      (value-of body (extend-env var val saved-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (proc-exp (var body)\n      (proc-val (procedure var body env)))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator env)))\n            (arg (value-of rand env)))\n        (apply-procedure proc arg)))))\n"
  },
  {
    "path": "scheme/eopl/03/cases/proc/parser.scm",
    "content": "(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n"
  },
  {
    "path": "scheme/eopl/03/cases/proc/test-helpers.scm",
    "content": "(define (run code)\n  (eval* code (empty-env)))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (cases expval result\n      (num-val (num) num)\n      (bool-val (bool) bool)\n      (proc-val (proc) proc))))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map (lambda (val)\n                      (if (boolean? val)\n                          (bool-val val)\n                          (num-val val)))\n                    vals)\n               (empty-env)))\n"
  },
  {
    "path": "scheme/eopl/03/cases/proc/tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"all.scm\")\n(load-relative \"test-helpers.scm\")\n\n(define proc-language-tests\n  (test-suite\n    \"Tests for the PROC language\"\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n\n    (check-equal? (run \"let f = proc (x) -(x, 11)\n                        in (f (f 77))\")\n                  55)\n\n    (check-equal? (run \"(proc (f) (f (f 77))\n                         proc (x) -(x, 11))\")\n                  55)\n\n    (check-equal? (run \"let x = 200\n                        in let f = proc (z) -(z, x)\n                           in let x = 100\n                              in let g = proc (z) -(z, x)\n                                 in -((f 1), (g 1))\")\n                  -100)\n))\n\n(exit (run-tests proc-language-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/06-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../06.scm\")\n(load-relative \"helpers/let.scm\")\n\n(define eopl-3.06-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.06\"\n\n    (check-equal? (run \"minus(-(minus(5), 9))\") 14)\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n))\n\n(exit (run-tests eopl-3.06-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/07-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../07.scm\")\n(load-relative \"helpers/let.scm\")\n\n(define eopl-3.07-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.07\"\n\n    (check-equal? (run \"+(4, 5)\") 9)\n    (check-equal? (run \"*(7, 4)\") 28)\n    (check-equal? (run \"/(10, 3)\") 3)\n\n    (check-equal? (run \"minus(-(minus(5), 9))\") 14)\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n))\n\n(exit (run-tests eopl-3.07-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/08-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../08.scm\")\n(load-relative \"helpers/let.scm\")\n\n(define eopl-3.08-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.08\"\n\n    (check-true (run \"equal?(1, 1)\"))\n    (check-false (run \"equal?(1, 2)\"))\n\n    (check-true (run \"less?(1, 2)\"))\n    (check-false (run \"less?(1, 1)\"))\n    (check-false (run \"less?(1, 0)\"))\n\n    (check-true (run \"greater?(1, 0)\"))\n    (check-false (run \"greater?(1, 1)\"))\n    (check-false (run \"greater?(1, 2)\"))\n\n    (check-equal? (run \"+(4, 5)\") 9)\n    (check-equal? (run \"*(7, 4)\") 28)\n    (check-equal? (run \"/(10, 3)\") 3)\n\n    (check-equal? (run \"minus(-(minus(5), 9))\") 14)\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n))\n\n(exit (run-tests eopl-3.08-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/09-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../09.scm\")\n\n(define (run code)\n  (eval* code (empty-env)))\n\n(define (expval->schemeval val)\n  (cases expval val\n    (num-val (num) num)\n    (bool-val (bool) bool)\n    (emptylist-val () '())\n    (pair-val (car cdr)\n      (cons (expval->schemeval car)\n            (expval->schemeval cdr)))))\n\n(define (schemeval->expval val)\n  (cond ((null? val) (emptylist-val))\n        ((pair? val) (pair-val (schemeval->expval (car val)) (schemeval->expval (cdr val))))\n        ((number? val) (num-val val))\n        ((boolean? val) (bool-val val))\n        (else (error 'schemeval->expval \"Don't know how to convert ~s\" val))))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (expval->schemeval result)))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map schemeval->expval vals)\n               (empty-env)))\n\n(define eopl-3.09-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.09\"\n\n    (check-equal? (run \"emptylist\") '())\n    (check-equal? (run \"cons(1, 2)\") '(1 . 2))\n    (check-equal? (run \"car(cons(1, 2))\") 1)\n    (check-equal? (run \"cdr(cons(1, 2))\") 2)\n\n    (check-true  (run \"null?(emptylist)\"))\n    (check-false (run \"null?(cons(1, 2))\"))\n\n    (check-equal? (run \"let x = 4\n                        in cons(x,\n                                cons(cons(-(x, 1),\n                                          emptylist),\n                                     emptylist))\")\n                  '(4 (3)))\n\n    (check-true (run \"equal?(1, 1)\"))\n    (check-false (run \"equal?(1, 2)\"))\n\n    (check-true (run \"less?(1, 2)\"))\n    (check-false (run \"less?(1, 1)\"))\n    (check-false (run \"less?(1, 0)\"))\n\n    (check-true (run \"greater?(1, 0)\"))\n    (check-false (run \"greater?(1, 1)\"))\n    (check-false (run \"greater?(1, 2)\"))\n\n    (check-equal? (run \"+(4, 5)\") 9)\n    (check-equal? (run \"*(7, 4)\") 28)\n    (check-equal? (run \"/(10, 3)\") 3)\n\n    (check-equal? (run \"minus(-(minus(5), 9))\") 14)\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n))\n\n(exit (run-tests eopl-3.09-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/10-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../10.scm\")\n\n(define (run code)\n  (eval* code (empty-env)))\n\n(define (expval->schemeval val)\n  (cases expval val\n    (num-val (num) num)\n    (bool-val (bool) bool)\n    (emptylist-val () '())\n    (pair-val (car cdr)\n      (cons (expval->schemeval car)\n            (expval->schemeval cdr)))))\n\n(define (schemeval->expval val)\n  (cond ((null? val) (emptylist-val))\n        ((pair? val) (pair-val (schemeval->expval (car val)) (schemeval->expval (cdr val))))\n        ((number? val) (num-val val))\n        ((boolean? val) (bool-val val))\n        (else (error 'schemeval->expval \"Don't know how to convert ~s\" val))))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (expval->schemeval result)))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map schemeval->expval vals)\n               (empty-env)))\n\n(define eopl-3.10-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.10\"\n\n    (check-equal? (run \"list(1)\") '(1))\n    (check-equal? (run \"list(1, 2, 3)\") '(1 2 3))\n    (check-equal? (run \"let x = 4\n                        in list(x, -(x, 1), -(x, 3))\")\n                  '(4 3 1))\n\n    (check-equal? (run \"emptylist\") '())\n    (check-equal? (run \"cons(1, 2)\") '(1 . 2))\n    (check-equal? (run \"car(cons(1, 2))\") 1)\n    (check-equal? (run \"cdr(cons(1, 2))\") 2)\n\n    (check-true  (run \"null?(emptylist)\"))\n    (check-false (run \"null?(cons(1, 2))\"))\n\n    (check-equal? (run \"let x = 4\n                        in cons(x,\n                                cons(cons(-(x, 1),\n                                          emptylist),\n                                     emptylist))\")\n                  '(4 (3)))\n\n    (check-true (run \"equal?(1, 1)\"))\n    (check-false (run \"equal?(1, 2)\"))\n\n    (check-true (run \"less?(1, 2)\"))\n    (check-false (run \"less?(1, 1)\"))\n    (check-false (run \"less?(1, 0)\"))\n\n    (check-true (run \"greater?(1, 0)\"))\n    (check-false (run \"greater?(1, 1)\"))\n    (check-false (run \"greater?(1, 2)\"))\n\n    (check-equal? (run \"+(4, 5)\") 9)\n    (check-equal? (run \"*(7, 4)\") 28)\n    (check-equal? (run \"/(10, 3)\") 3)\n\n    (check-equal? (run \"minus(-(minus(5), 9))\") 14)\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n))\n\n(exit (run-tests eopl-3.10-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/11-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../11.scm\")\n\n(define (run code)\n  (eval* code (empty-env)))\n\n(define (expval->schemeval val)\n  (cases expval val\n    (num-val (num) num)\n    (bool-val (bool) bool)))\n\n(define (schemeval->expval val)\n  (cond ((number? val) (num-val val))\n        ((boolean? val) (bool-val val))\n        (else (error 'schemeval->expval \"Don't know how to convert ~s\" val))))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (expval->schemeval result)))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map schemeval->expval vals)\n               (empty-env)))\n\n(define eopl-3.11-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.11\"\n\n    (check-equal? (run \"+(1, +(2, 3))\") 6)\n\n    (check-equal? (run \"+(4, 5)\") 9)\n    (check-equal? (run \"*(7, 4)\") 28)\n    (check-equal? (run \"/(10, 3)\") 3)\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n))\n\n(exit (run-tests eopl-3.11-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/12-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../12.scm\")\n\n(define (run code)\n  (eval* code (empty-env)))\n\n(define (expval->schemeval val)\n  (cases expval val\n    (num-val (num) num)\n    (bool-val (bool) bool)\n    (emptylist-val () '())\n    (pair-val (car cdr)\n      (cons (expval->schemeval car)\n            (expval->schemeval cdr)))))\n\n(define (schemeval->expval val)\n  (cond ((null? val) (emptylist-val))\n        ((pair? val) (pair-val (schemeval->expval (car val)) (schemeval->expval (cdr val))))\n        ((number? val) (num-val val))\n        ((boolean? val) (bool-val val))\n        (else (error 'schemeval->expval \"Don't know how to convert ~s\" val))))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (expval->schemeval result)))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map schemeval->expval vals)\n               (empty-env)))\n\n(define eopl-3.12-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.12\"\n\n    (check-equal? (run \"cond zero?(0) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  0)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(0) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  1)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(0) ==> 2\n                             end\")\n                  2)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  #f)\n\n    (check-equal? (run \"list(1)\") '(1))\n    (check-equal? (run \"list(1, 2, 3)\") '(1 2 3))\n    (check-equal? (run \"let x = 4\n                        in list(x, -(x, 1), -(x, 3))\")\n                  '(4 3 1))\n\n    (check-equal? (run \"emptylist\") '())\n    (check-equal? (run \"cons(1, 2)\") '(1 . 2))\n    (check-equal? (run \"car(cons(1, 2))\") 1)\n    (check-equal? (run \"cdr(cons(1, 2))\") 2)\n\n    (check-true  (run \"null?(emptylist)\"))\n    (check-false (run \"null?(cons(1, 2))\"))\n\n    (check-equal? (run \"let x = 4\n                        in cons(x,\n                                cons(cons(-(x, 1),\n                                          emptylist),\n                                     emptylist))\")\n                  '(4 (3)))\n\n    (check-true (run \"equal?(1, 1)\"))\n    (check-false (run \"equal?(1, 2)\"))\n\n    (check-true (run \"less?(1, 2)\"))\n    (check-false (run \"less?(1, 1)\"))\n    (check-false (run \"less?(1, 0)\"))\n\n    (check-true (run \"greater?(1, 0)\"))\n    (check-false (run \"greater?(1, 1)\"))\n    (check-false (run \"greater?(1, 2)\"))\n\n    (check-equal? (run \"+(4, 5)\") 9)\n    (check-equal? (run \"*(7, 4)\") 28)\n    (check-equal? (run \"/(10, 3)\") 3)\n\n    (check-equal? (run \"minus(-(minus(5), 9))\") 14)\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n))\n\n(exit (run-tests eopl-3.12-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/13-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../13.scm\")\n\n(define (run code)\n  (eval* code (empty-env)))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    result))\n\n(define (env vars vals)\n  (extend-env* vars vals (empty-env)))\n\n(define eopl-3.13-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.13\"\n\n    (check-equal? (run \"cond zero?(0) ==> 1\n                             zero?(1) ==> 2\n                             zero?(1) ==> 3\n                             end\")\n                  1)\n    (check-equal? (run \"cond zero?(1) ==> 1\n                             zero?(0) ==> 2\n                             zero?(1) ==> 3\n                             end\")\n                  2)\n    (check-equal? (run \"cond zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             zero?(0) ==> 3\n                             end\")\n                  3)\n    (check-equal? (run \"cond zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             zero?(1) ==> 3\n                             end\")\n                  0)\n\n    (check-equal? (run \"equal?(1, 1)\") 1)\n    (check-equal? (run \"equal?(1, 2)\") 0)\n\n    (check-equal? (run \"less?(1, 2)\") 1)\n    (check-equal? (run \"less?(1, 1)\") 0)\n    (check-equal? (run \"less?(1, 0)\") 0)\n\n    (check-equal? (run \"greater?(1, 0)\") 1)\n    (check-equal? (run \"greater?(1, 1)\") 0)\n    (check-equal? (run \"greater?(1, 2)\") 0)\n\n    (check-equal? (run \"+(4, 5)\") 9)\n    (check-equal? (run \"*(7, 4)\") 28)\n    (check-equal? (run \"/(10, 3)\") 3)\n\n    (check-equal? (run \"minus(-(minus(5), 9))\") 14)\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") 1)\n    (check-equal? (run \"zero?(1)\") 0)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n))\n\n(exit (run-tests eopl-3.13-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/14-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../14.scm\")\n\n(define (run code)\n  (eval* code (empty-env)))\n\n(define (expval->schemeval val)\n  (cases expval val\n    (num-val (num) num)\n    (bool-val (bool) bool)\n    (emptylist-val () '())\n    (pair-val (car cdr)\n      (cons (expval->schemeval car)\n            (expval->schemeval cdr)))))\n\n(define (schemeval->expval val)\n  (cond ((null? val) (emptylist-val))\n        ((pair? val) (pair-val (schemeval->expval (car val)) (schemeval->expval (cdr val))))\n        ((number? val) (num-val val))\n        ((boolean? val) (bool-val val))\n        (else (error 'schemeval->expval \"Don't know how to convert ~s\" val))))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (expval->schemeval result)))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map schemeval->expval vals)\n               (empty-env)))\n\n(define eopl-3.14-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.14\"\n\n    (check-equal? (run \"cond zero?(0) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  0)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(0) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  1)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(0) ==> 2\n                             end\")\n                  2)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  #f)\n\n    (check-equal? (run \"list(1)\") '(1))\n    (check-equal? (run \"list(1, 2, 3)\") '(1 2 3))\n    (check-equal? (run \"let x = 4\n                        in list(x, -(x, 1), -(x, 3))\")\n                  '(4 3 1))\n\n    (check-equal? (run \"emptylist\") '())\n    (check-equal? (run \"cons(1, 2)\") '(1 . 2))\n    (check-equal? (run \"car(cons(1, 2))\") 1)\n    (check-equal? (run \"cdr(cons(1, 2))\") 2)\n\n    (check-equal? (run \"if null?(emptylist) then 1 else 0\") 1)\n    (check-equal? (run \"if null?(cons(1, 2)) then 1 else 0\") 0)\n\n    (check-equal? (run \"let x = 4\n                        in cons(x,\n                                cons(cons(-(x, 1),\n                                          emptylist),\n                                     emptylist))\")\n                  '(4 (3)))\n\n    (check-equal? (run \"if equal?(1, 1) then 1 else 0\") 1)\n    (check-equal? (run \"if equal?(1, 2) then 1 else 0\") 0)\n\n    (check-equal? (run \"if less?(1, 2) then 1 else 0\") 1)\n    (check-equal? (run \"if less?(1, 1) then 1 else 0\") 0)\n    (check-equal? (run \"if less?(1, 0) then 1 else 0\") 0)\n\n    (check-equal? (run \"if greater?(1, 0) then 1 else 0\") 1)\n    (check-equal? (run \"if greater?(1, 1) then 1 else 0\") 0)\n    (check-equal? (run \"if greater?(1, 2) then 1 else 0\") 0)\n\n    (check-equal? (run \"+(4, 5)\") 9)\n    (check-equal? (run \"*(7, 4)\") 28)\n    (check-equal? (run \"/(10, 3)\") 3)\n\n    (check-equal? (run \"minus(-(minus(5), 9))\") 14)\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"if zero?(0) then 1 else 0\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 0\") 0)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n))\n\n(exit (run-tests eopl-3.14-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/15-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../15.scm\")\n\n(define (run code)\n  (eval* code (empty-env)))\n\n(define (expval->schemeval val)\n  (cases expval val\n    (num-val (num) num)\n    (bool-val (bool) bool)\n    (emptylist-val () '())\n    (pair-val (car cdr)\n      (cons (expval->schemeval car)\n            (expval->schemeval cdr)))))\n\n(define (schemeval->expval val)\n  (cond ((null? val) (emptylist-val))\n        ((pair? val) (pair-val (schemeval->expval (car val)) (schemeval->expval (cdr val))))\n        ((number? val) (num-val val))\n        ((boolean? val) (bool-val val))\n        (else (error 'schemeval->expval \"Don't know how to convert ~s\" val))))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (expval->schemeval result)))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map schemeval->expval vals)\n               (empty-env)))\n\n(define eopl-3.15-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.15\"\n\n    (check-equal? (with-output-to-string (lambda () (run \"print 42\")))\n                  \"42\")\n    (check-equal? (with-output-to-string (lambda () (run \"print zero?(1)\")))\n                  \"#f\")\n    (check-equal? (with-output-to-string (lambda () (run \"print emptylist\")))\n                  \"emptylist\")\n    (check-equal? (with-output-to-string (lambda () (run \"print cons(1, emptylist)\")))\n                  \"cons(1, emptylist)\")\n\n    (check-equal? (run \"cond zero?(0) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  0)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(0) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  1)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(0) ==> 2\n                             end\")\n                  2)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  #f)\n\n    (check-equal? (run \"list(1)\") '(1))\n    (check-equal? (run \"list(1, 2, 3)\") '(1 2 3))\n    (check-equal? (run \"let x = 4\n                        in list(x, -(x, 1), -(x, 3))\")\n                  '(4 3 1))\n\n    (check-equal? (run \"emptylist\") '())\n    (check-equal? (run \"cons(1, 2)\") '(1 . 2))\n    (check-equal? (run \"car(cons(1, 2))\") 1)\n    (check-equal? (run \"cdr(cons(1, 2))\") 2)\n\n    (check-true  (run \"null?(emptylist)\"))\n    (check-false (run \"null?(cons(1, 2))\"))\n\n    (check-equal? (run \"let x = 4\n                        in cons(x,\n                                cons(cons(-(x, 1),\n                                          emptylist),\n                                     emptylist))\")\n                  '(4 (3)))\n\n    (check-true (run \"equal?(1, 1)\"))\n    (check-false (run \"equal?(1, 2)\"))\n\n    (check-true (run \"less?(1, 2)\"))\n    (check-false (run \"less?(1, 1)\"))\n    (check-false (run \"less?(1, 0)\"))\n\n    (check-true (run \"greater?(1, 0)\"))\n    (check-false (run \"greater?(1, 1)\"))\n    (check-false (run \"greater?(1, 2)\"))\n\n    (check-equal? (run \"+(4, 5)\") 9)\n    (check-equal? (run \"*(7, 4)\") 28)\n    (check-equal? (run \"/(10, 3)\") 3)\n\n    (check-equal? (run \"minus(-(minus(5), 9))\") 14)\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n))\n\n(exit (run-tests eopl-3.15-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/16-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../16.scm\")\n\n(define (run code)\n  (eval* code (empty-env)))\n\n(define (expval->schemeval val)\n  (cases expval val\n    (num-val (num) num)\n    (bool-val (bool) bool)\n    (emptylist-val () '())\n    (pair-val (car cdr)\n      (cons (expval->schemeval car)\n            (expval->schemeval cdr)))))\n\n(define (schemeval->expval val)\n  (cond ((null? val) (emptylist-val))\n        ((pair? val) (pair-val (schemeval->expval (car val)) (schemeval->expval (cdr val))))\n        ((number? val) (num-val val))\n        ((boolean? val) (bool-val val))\n        (else (error 'schemeval->expval \"Don't know how to convert ~s\" val))))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (expval->schemeval result)))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map schemeval->expval vals)\n               (empty-env)))\n\n(define eopl-3.16-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.16\"\n\n    (check-equal? (run \"let x = 10\n                            y = 20\n                            in +(x, y)\")\n                  30)\n\n    (check-equal? (with-output-to-string (lambda () (run \"print 42\")))\n                  \"42\")\n    (check-equal? (with-output-to-string (lambda () (run \"print zero?(1)\")))\n                  \"#f\")\n    (check-equal? (with-output-to-string (lambda () (run \"print emptylist\")))\n                  \"emptylist\")\n    (check-equal? (with-output-to-string (lambda () (run \"print cons(1, emptylist)\")))\n                  \"cons(1, emptylist)\")\n\n    (check-equal? (run \"cond zero?(0) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  0)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(0) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  1)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(0) ==> 2\n                             end\")\n                  2)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  #f)\n\n    (check-equal? (run \"list(1)\") '(1))\n    (check-equal? (run \"list(1, 2, 3)\") '(1 2 3))\n    (check-equal? (run \"let x = 4\n                        in list(x, -(x, 1), -(x, 3))\")\n                  '(4 3 1))\n\n    (check-equal? (run \"emptylist\") '())\n    (check-equal? (run \"cons(1, 2)\") '(1 . 2))\n    (check-equal? (run \"car(cons(1, 2))\") 1)\n    (check-equal? (run \"cdr(cons(1, 2))\") 2)\n\n    (check-true  (run \"null?(emptylist)\"))\n    (check-false (run \"null?(cons(1, 2))\"))\n\n    (check-equal? (run \"let x = 4\n                        in cons(x,\n                                cons(cons(-(x, 1),\n                                          emptylist),\n                                     emptylist))\")\n                  '(4 (3)))\n\n    (check-true (run \"equal?(1, 1)\"))\n    (check-false (run \"equal?(1, 2)\"))\n\n    (check-true (run \"less?(1, 2)\"))\n    (check-false (run \"less?(1, 1)\"))\n    (check-false (run \"less?(1, 0)\"))\n\n    (check-true (run \"greater?(1, 0)\"))\n    (check-false (run \"greater?(1, 1)\"))\n    (check-false (run \"greater?(1, 2)\"))\n\n    (check-equal? (run \"+(4, 5)\") 9)\n    (check-equal? (run \"*(7, 4)\") 28)\n    (check-equal? (run \"/(10, 3)\") 3)\n\n    (check-equal? (run \"minus(-(minus(5), 9))\") 14)\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n))\n\n(exit (run-tests eopl-3.16-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/17-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../17.scm\")\n\n(define (run code)\n  (eval* code (empty-env)))\n\n(define (expval->schemeval val)\n  (cases expval val\n    (num-val (num) num)\n    (bool-val (bool) bool)\n    (emptylist-val () '())\n    (pair-val (car cdr)\n      (cons (expval->schemeval car)\n            (expval->schemeval cdr)))))\n\n(define (schemeval->expval val)\n  (cond ((null? val) (emptylist-val))\n        ((pair? val) (pair-val (schemeval->expval (car val)) (schemeval->expval (cdr val))))\n        ((number? val) (num-val val))\n        ((boolean? val) (bool-val val))\n        (else (error 'schemeval->expval \"Don't know how to convert ~s\" val))))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (expval->schemeval result)))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map schemeval->expval vals)\n               (empty-env)))\n\n(define eopl-3.17-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.17\"\n\n    (check-equal? (run \"let x = 30\n                            in let* x = -(x, 1) y = -(x, 2)\n                                    in -(x, y)\")\n                  2)\n\n    (check-equal? (run \"let x = 10\n                            y = 20\n                            in +(x, y)\")\n                  30)\n\n    (check-equal? (with-output-to-string (lambda () (run \"print 42\")))\n                  \"42\")\n    (check-equal? (with-output-to-string (lambda () (run \"print zero?(1)\")))\n                  \"#f\")\n    (check-equal? (with-output-to-string (lambda () (run \"print emptylist\")))\n                  \"emptylist\")\n    (check-equal? (with-output-to-string (lambda () (run \"print cons(1, emptylist)\")))\n                  \"cons(1, emptylist)\")\n\n    (check-equal? (run \"cond zero?(0) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  0)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(0) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  1)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(0) ==> 2\n                             end\")\n                  2)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  #f)\n\n    (check-equal? (run \"list(1)\") '(1))\n    (check-equal? (run \"list(1, 2, 3)\") '(1 2 3))\n    (check-equal? (run \"let x = 4\n                        in list(x, -(x, 1), -(x, 3))\")\n                  '(4 3 1))\n\n    (check-equal? (run \"emptylist\") '())\n    (check-equal? (run \"cons(1, 2)\") '(1 . 2))\n    (check-equal? (run \"car(cons(1, 2))\") 1)\n    (check-equal? (run \"cdr(cons(1, 2))\") 2)\n\n    (check-true  (run \"null?(emptylist)\"))\n    (check-false (run \"null?(cons(1, 2))\"))\n\n    (check-equal? (run \"let x = 4\n                        in cons(x,\n                                cons(cons(-(x, 1),\n                                          emptylist),\n                                     emptylist))\")\n                  '(4 (3)))\n\n    (check-true (run \"equal?(1, 1)\"))\n    (check-false (run \"equal?(1, 2)\"))\n\n    (check-true (run \"less?(1, 2)\"))\n    (check-false (run \"less?(1, 1)\"))\n    (check-false (run \"less?(1, 0)\"))\n\n    (check-true (run \"greater?(1, 0)\"))\n    (check-false (run \"greater?(1, 1)\"))\n    (check-false (run \"greater?(1, 2)\"))\n\n    (check-equal? (run \"+(4, 5)\") 9)\n    (check-equal? (run \"*(7, 4)\") 28)\n    (check-equal? (run \"/(10, 3)\") 3)\n\n    (check-equal? (run \"minus(-(minus(5), 9))\") 14)\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n))\n\n(exit (run-tests eopl-3.17-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/18-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../18.scm\")\n\n(define (run code)\n  (eval* code (empty-env)))\n\n(define (expval->schemeval val)\n  (cases expval val\n    (num-val (num) num)\n    (bool-val (bool) bool)\n    (emptylist-val () '())\n    (pair-val (car cdr)\n      (cons (expval->schemeval car)\n            (expval->schemeval cdr)))))\n\n(define (schemeval->expval val)\n  (cond ((null? val) (emptylist-val))\n        ((pair? val) (pair-val (schemeval->expval (car val)) (schemeval->expval (cdr val))))\n        ((number? val) (num-val val))\n        ((boolean? val) (bool-val val))\n        (else (error 'schemeval->expval \"Don't know how to convert ~s\" val))))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (expval->schemeval result)))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map schemeval->expval vals)\n               (empty-env)))\n\n(define eopl-3.18-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.18\"\n\n    (check-equal? (run \"let u = 7\n                            in unpack x y = cons(u, cons(3, emptylist))\n                               in -(x, y)\")\n                  4)\n\n    (check-equal? (run \"let x = 30\n                            in let* x = -(x, 1) y = -(x, 2)\n                                    in -(x, y)\")\n                  2)\n\n    (check-equal? (run \"let x = 10\n                            y = 20\n                            in +(x, y)\")\n                  30)\n\n    (check-equal? (with-output-to-string (lambda () (run \"print 42\")))\n                  \"42\")\n    (check-equal? (with-output-to-string (lambda () (run \"print zero?(1)\")))\n                  \"#f\")\n    (check-equal? (with-output-to-string (lambda () (run \"print emptylist\")))\n                  \"emptylist\")\n    (check-equal? (with-output-to-string (lambda () (run \"print cons(1, emptylist)\")))\n                  \"cons(1, emptylist)\")\n\n    (check-equal? (run \"cond zero?(0) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  0)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(0) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  1)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(0) ==> 2\n                             end\")\n                  2)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  #f)\n\n    (check-equal? (run \"list(1)\") '(1))\n    (check-equal? (run \"list(1, 2, 3)\") '(1 2 3))\n    (check-equal? (run \"let x = 4\n                        in list(x, -(x, 1), -(x, 3))\")\n                  '(4 3 1))\n\n    (check-equal? (run \"emptylist\") '())\n    (check-equal? (run \"cons(1, 2)\") '(1 . 2))\n    (check-equal? (run \"car(cons(1, 2))\") 1)\n    (check-equal? (run \"cdr(cons(1, 2))\") 2)\n\n    (check-true  (run \"null?(emptylist)\"))\n    (check-false (run \"null?(cons(1, 2))\"))\n\n    (check-equal? (run \"let x = 4\n                        in cons(x,\n                                cons(cons(-(x, 1),\n                                          emptylist),\n                                     emptylist))\")\n                  '(4 (3)))\n\n    (check-true (run \"equal?(1, 1)\"))\n    (check-false (run \"equal?(1, 2)\"))\n\n    (check-true (run \"less?(1, 2)\"))\n    (check-false (run \"less?(1, 1)\"))\n    (check-false (run \"less?(1, 0)\"))\n\n    (check-true (run \"greater?(1, 0)\"))\n    (check-false (run \"greater?(1, 1)\"))\n    (check-false (run \"greater?(1, 2)\"))\n\n    (check-equal? (run \"+(4, 5)\") 9)\n    (check-equal? (run \"*(7, 4)\") 28)\n    (check-equal? (run \"/(10, 3)\") 3)\n\n    (check-equal? (run \"minus(-(minus(5), 9))\") 14)\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n))\n\n(exit (run-tests eopl-3.18-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/19-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../19.scm\")\n(load-relative \"helpers/proc.scm\")\n\n(define eopl-3.19-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.19\"\n\n    (check-equal? (run \"letproc dec (x) = -(x, 1)\n                                in (dec 2)\")\n                  1)\n\n    (check-equal? (run \"let a = 10\n                            in letproc augment (x) = -(x, a)\n                                       in let a = 20\n                                              in (augment a)\")\n                  10)\n))\n\n(exit (run-tests eopl-3.19-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/20-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../20.scm\")\n(load-relative \"helpers/proc.scm\")\n\n(define eopl-3.20-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.20\"\n\n    (check-equal? (run two-plus-three) 5)\n))\n\n(exit (run-tests eopl-3.20-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/21-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../21.scm\")\n(load-relative \"helpers/proc.scm\")\n\n(define eopl-3.21-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.21\"\n\n    (check-equal? (run \"let one = proc () 1\n                            in (one)\")\n                  1)\n    (check-equal? (run \"let minus = proc (x, y) -(x, y)\n                            in (minus 7 2)\")\n                  5)\n))\n\n(exit (run-tests eopl-3.21-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/22-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../22.scm\")\n(load-relative \"helpers/proc.scm\")\n\n(define eopl-3.22-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.22\"\n\n    (check-equal? (run \"let add = proc (x, y) -(x, -(0, y))\n                            in add(2, 3)\")\n                  5)\n))\n\n(exit (run-tests eopl-3.22-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/23-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../23.scm\")\n(load-relative \"helpers/proc.scm\")\n\n(define eopl-3.23-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.23\"\n\n    (check-equal? (run the-given-program) 12)\n    (check-equal? (run factorial-5-program) 120)\n))\n\n(exit (run-tests eopl-3.23-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/24-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../24.scm\")\n(load-relative \"helpers/proc.scm\")\n\n(define eopl-3.24-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.24\"\n\n    (check-equal? (run the-program) 0)\n))\n\n(exit (run-tests eopl-3.24-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/25-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../25.scm\")\n(load-relative \"helpers/proc.scm\")\n\n(define eopl-3.25-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.25\"\n\n    (check-equal? (run the-example-program) 12)\n))\n\n(exit (run-tests eopl-3.25-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/26-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../26.scm\")\n(load-relative \"helpers/proc.scm\")\n\n(define (free-vars code)\n  (free-variables (scan&parse code) '()))\n\n(define eopl-3.26-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.26\"\n\n    (test-suite \"Free-variables\"\n      (check-equal? (free-vars \"zero?(a)\") '(a))\n      (check-equal? (free-vars \"if a then b else c\") '(a b c))\n      (check-equal? (free-vars \"let a = b in -(a, c)\") '(b c))\n      (check-equal? (free-vars \"proc (x) -(a, x)\") '(a))\n      (check-equal? (free-vars \"(a b)\") '(a b))\n      (check-equal? (free-vars \"proc (x) proc (y) (y x)\") '()))\n\n    (test-suite \"Simplifying environments\"\n      (check-equal? (slice-env '(b c) '((a 1) (b 2) (c 3) (d 4)))\n                    '((b 2) (c 3)))\n      (check-equal? (slice-env '(c b) '((a 1) (b 2) (c 3) (d 4)))\n                    '((b 2) (c 3))))\n\n    (test-suite \"The evaluator\"\n      (check-equal? (run \"42\") 42)\n      (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n      (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n      (check-equal? (run \"% Comment\\n 1\") 1)\n\n      (check-equal? (run \"zero?(0)\") #t)\n      (check-equal? (run \"zero?(1)\") #f)\n\n      (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n      (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n      (check-equal? (run \"let x = 1 in x\") 1)\n      (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n      (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n      (check-equal? (run \"let x = 7                  % This is a comment\n                          in let y = 2               % This is another comment\n                             in let y = let x = -(x, 1) in -(x, y)\n                                in -(-(x, 8),y)\")\n                    -5)\n\n      (check-equal? (run \"let f = proc (x) -(x, 11)\n                          in (f (f 77))\")\n                    55)\n\n      (check-equal? (run \"(proc (f) (f (f 77))\n                           proc (x) -(x, 11))\")\n                    55)\n\n      (check-equal? (run \"let x = 200\n                          in let f = proc (z) -(z, x)\n                             in let x = 100\n                                in let g = proc (z) -(z, x)\n                                   in -((f 1), (g 1))\")\n                    -100))\n))\n\n(exit (run-tests eopl-3.26-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/27-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../27.scm\")\n(load-relative \"helpers/proc.scm\")\n\n(define (result-of code)\n  (parameterize ((current-output-port (open-output-string)))\n    (run code)))\n\n(define (output-of code)\n  (with-output-to-string\n    (lambda () (run code))))\n\n(define eopl-3.27-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.27\"\n\n    (check-equal? (output-of \"let f = traceproc(x) x\n                               in let g = traceproc(y) (f -(y, 1))\n                                  in (g 7)\")\n                  (string-join '(\"enter: y = (num-val 7)\"\n                                 \"enter: x = (num-val 6)\"\n                                 \"exit: x\"\n                                 \"exit: y\"\n                                 \"\")\n                               \"\\n\"))\n\n    (check-equal? (result-of \"let f = traceproc (x) -(x, 11)\n                              in (f (f 77))\")\n                  55)\n\n    (check-equal? (result-of \"(traceproc (f) (f (f 77))\n                               traceproc (x) -(x, 11))\")\n                  55)\n\n    (check-equal? (result-of \"let x = 200\n                              in let f = traceproc (z) -(z, x)\n                                 in let x = 100\n                                    in let g = traceproc (z) -(z, x)\n                                       in -((f 1), (g 1))\")\n                  -100)\n ))\n\n(exit (run-tests eopl-3.27-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/28-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../28.scm\")\n(load-relative \"helpers/proc.scm\")\n\n(define eopl-3.28-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.28\"\n\n    (check-equal? (run \"let a = 3\n                        in let p = proc (x) -(x, a)\n                           in let a = 5\n                              in -(a, (p 2))\")\n                  8)))\n\n(exit (run-tests eopl-3.28-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/29-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../29.scm\")\n(load-relative \"helpers/proc.scm\")\n\n(define eopl-3.29-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.29\"\n\n    (check-equal? (run the-hypothetical-program) 2)\n))\n\n(exit (run-tests eopl-3.29-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/31-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../31.scm\")\n(load-relative \"helpers/letrec.scm\")\n\n(define eopl-3.31-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.31\"\n\n    (check-equal? (run \"let one = proc () 1\n                            in (one)\")\n                  1)\n    (check-equal? (run \"let minus = proc (x, y) -(x, y)\n                            in (minus 7 2)\")\n                  5)\n\n    (check-equal? (run \"letrec double(x)\n                                = if zero?(x) then 0 else -((double -(x, 1)), -(0, 2))\n                        in (double 6)\")\n                  12)\n\n    (check-equal? (run \"let fib = proc (n)\n                          letrec iter(n, a, b) = if zero?(-(n, 1))\n                                                 then a\n                                                 else (iter -(n, 1) -(a, -(0, b)) a)\n                          in (iter n 1 0)\n                        in (fib 10)\")\n                        55)\n))\n\n(exit (run-tests eopl-3.31-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/32-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../32.scm\")\n(load-relative \"helpers/letrec.scm\")\n\n(define eopl-3.32-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.32\"\n\n    (check-equal? (run \"letrec\n                          even(x) = if zero?(x) then 1 else (odd -(x, 1))\n                          odd(x)  = if zero?(x) then 0 else (even -(x, 1))\n                        in (odd 13)\")\n                  1)\n))\n\n(exit (run-tests eopl-3.32-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/33-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../33.scm\")\n(load-relative \"helpers/letrec.scm\")\n\n(define eopl-3.33-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.33\"\n\n    (check-equal? (run \"letrec\n                          even(x, t, f) = if zero?(x) then t else (odd -(x, 1) t f)\n                          odd(x, t, f)  = if zero?(x) then f else (even -(x, 1) t f)\n                        in (odd 13 101 100)\")\n                  101)\n))\n\n(exit (run-tests eopl-3.33-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/34-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../34.scm\")\n(load-relative \"helpers/letrec.scm\")\n\n(define eopl-3.34-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.34\"\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n\n    (check-equal? (run \"let f = proc (x) -(x, 11)\n                        in (f (f 77))\")\n                  55)\n\n    (check-equal? (run \"(proc (f) (f (f 77))\n                         proc (x) -(x, 11))\")\n                  55)\n\n    (check-equal? (run \"let x = 200\n                        in let f = proc (z) -(z, x)\n                           in let x = 100\n                              in let g = proc (z) -(z, x)\n                                 in -((f 1), (g 1))\")\n                  -100)\n\n    (check-equal? (run \"letrec double(x)\n                                = if zero?(x) then 0 else -((double -(x, 1)), -(0, 2))\n                        in (double 6)\")\n                  12)\n))\n\n(exit (run-tests eopl-3.34-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/35-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../35.scm\")\n(load-relative \"helpers/letrec.scm\")\n\n(define eopl-3.35-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.35\"\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n\n    (check-equal? (run \"let f = proc (x) -(x, 11)\n                        in (f (f 77))\")\n                  55)\n\n    (check-equal? (run \"(proc (f) (f (f 77))\n                         proc (x) -(x, 11))\")\n                  55)\n\n    (check-equal? (run \"let x = 200\n                        in let f = proc (z) -(z, x)\n                           in let x = 100\n                              in let g = proc (z) -(z, x)\n                                 in -((f 1), (g 1))\")\n                  -100)\n\n    (check-equal? (run \"letrec double(x)\n                                = if zero?(x) then 0 else -((double -(x, 1)), -(0, 2))\n                        in (double 6)\")\n                  12)\n))\n\n(exit (run-tests eopl-3.35-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/36-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../36.scm\")\n(load-relative \"helpers/letrec.scm\")\n\n(define eopl-3.36-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.36\"\n\n    (check-equal? (run \"letrec\n                          even(x) = if zero?(x) then 1 else (odd -(x, 1))\n                          odd(x)  = if zero?(x) then 0 else (even -(x, 1))\n                        in (odd 13)\")\n                  1)\n))\n\n(exit (run-tests eopl-3.36-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/37-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../37.scm\")\n(load-relative \"helpers/proc.scm\")\n\n(define eopl-3.37-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.37\"\n\n    (check-equal? (run the-program) 1)\n))\n\n(exit (run-tests eopl-3.37-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/38-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../38.scm\")\n(load-relative \"helpers/nameless.scm\")\n\n(define eopl-3.38-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.38\"\n\n    (check-equal? (run \"let zero = 0\n                        in let one = 1\n                           in let two = 2\n                              in let three = 3\n                                 in cond zero?(0) ==> one\n                                         zero?(1) ==> two\n                                         zero?(1) ==> three\n                                    end\")\n                  1)\n    (check-equal? (run \"let zero = 0\n                        in let one = 1\n                           in let two = 2\n                              in let three = 3\n                                 in cond zero?(1) ==> one\n                                         zero?(0) ==> two\n                                         zero?(1) ==> three\n                                    end\")\n                  2)\n    (check-equal? (run \"let zero = 0\n                        in let one = 1\n                           in let two = 2\n                              in let three = 3\n                                 in cond zero?(1) ==> one\n                                         zero?(1) ==> two\n                                         zero?(0) ==> three\n                                    end\")\n                  3)\n    (check-equal? (run \"let zero = 0\n                        in let one = 1\n                           in let two = 2\n                              in let three = 3\n                                 in cond zero?(1) ==> one\n                                         zero?(zero) ==> two\n                                         zero?(1) ==> three\n                                    end\")\n                  2)\n    (check-equal? (run \"let zero = 0\n                        in let one = 1\n                           in let two = 2\n                              in let three = 3\n                                 in cond zero?(1) ==> one\n                                         zero?(1) ==> two\n                                         zero?(1) ==> three\n                                    end\")\n                  #f)\n\n    (check-equal? (run \"cond zero?(0) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  0)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(0) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  1)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(0) ==> 2\n                             end\")\n                  2)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  #f)\n\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  #f)\n\n\n    (check-equal? (run \"42\") 42)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n\n    (check-equal? (run \"let f = proc (x) -(x, 11)\n                        in (f (f 77))\")\n                  55)\n\n    (check-equal? (run \"(proc (f) (f (f 77))\n                         proc (x) -(x, 11))\")\n                  55)\n\n    (check-equal? (run \"let x = 200\n                        in let f = proc (z) -(z, x)\n                           in let x = 100\n                              in let g = proc (z) -(z, x)\n                                 in -((f 1), (g 1))\")\n                  -100)\n))\n\n(exit (run-tests eopl-3.38-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/39-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../39.scm\")\n(load-relative \"helpers/nameless.scm\")\n\n(define (expval->schemeval val)\n  (cases expval val\n    (num-val (num) num)\n    (bool-val (bool) bool)\n    (proc-val (proc) proc)\n    (emptylist-val () '())\n    (pair-val (car cdr)\n      (cons (expval->schemeval car)\n            (expval->schemeval cdr)))))\n\n(define eopl-3.39-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.39\"\n\n    (check-equal? (run \"let u = 7\n                            in unpack x y = cons(u, cons(3, emptylist))\n                               in -(x, y)\")\n                  4)\n    (check-equal? (run \"let u = 7\n                            in unpack x y z = list(u, 3, 42)\n                               in -(x, y)\")\n                  4)\n\n    (check-equal? (run \"list(1)\") '(1))\n    (check-equal? (run \"list(1, 2, 3)\") '(1 2 3))\n    (check-equal? (run \"let x = 4\n                        in list(x, -(x, 1), -(x, 3))\")\n                  '(4 3 1))\n\n    (check-equal? (run \"emptylist\") '())\n    (check-equal? (run \"cons(1, 2)\") '(1 . 2))\n    (check-equal? (run \"car(cons(1, 2))\") 1)\n    (check-equal? (run \"cdr(cons(1, 2))\") 2)\n\n    (check-true  (run \"null?(emptylist)\"))\n    (check-false (run \"null?(cons(1, 2))\"))\n\n    (check-equal? (run \"let x = 4\n                        in cons(x,\n                                cons(cons(-(x, 1),\n                                          emptylist),\n                                     emptylist))\")\n                  '(4 (3)))\n\n\n    (check-equal? (run \"cond zero?(0) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  0)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(0) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  1)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(0) ==> 2\n                             end\")\n                  2)\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  #f)\n\n    (check-equal? (run \"cond zero?(1) ==> 0\n                             zero?(1) ==> 1\n                             zero?(1) ==> 2\n                             end\")\n                  #f)\n\n\n    (check-equal? (run \"42\") 42)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n\n    (check-equal? (run \"let f = proc (x) -(x, 11)\n                        in (f (f 77))\")\n                  55)\n\n    (check-equal? (run \"(proc (f) (f (f 77))\n                         proc (x) -(x, 11))\")\n                  55)\n\n    (check-equal? (run \"let x = 200\n                        in let f = proc (z) -(z, x)\n                           in let x = 100\n                              in let g = proc (z) -(z, x)\n                                 in -((f 1), (g 1))\")\n                  -100)\n\n    (check-equal? (run \"let zero = 0\n                        in let one = 1\n                           in let two = 2\n                              in let three = 3\n                                 in cond zero?(0) ==> one\n                                         zero?(1) ==> two\n                                         zero?(1) ==> three\n                                    end\")\n                  1)\n    (check-equal? (run \"let zero = 0\n                        in let one = 1\n                           in let two = 2\n                              in let three = 3\n                                 in cond zero?(1) ==> one\n                                         zero?(0) ==> two\n                                         zero?(1) ==> three\n                                    end\")\n                  2)\n    (check-equal? (run \"let zero = 0\n                        in let one = 1\n                           in let two = 2\n                              in let three = 3\n                                 in cond zero?(1) ==> one\n                                         zero?(1) ==> two\n                                         zero?(0) ==> three\n                                    end\")\n                  3)\n    (check-equal? (run \"let zero = 0\n                        in let one = 1\n                           in let two = 2\n                              in let three = 3\n                                 in cond zero?(1) ==> one\n                                         zero?(zero) ==> two\n                                         zero?(1) ==> three\n                                    end\")\n                  2)\n    (check-equal? (run \"let zero = 0\n                        in let one = 1\n                           in let two = 2\n                              in let three = 3\n                                 in cond zero?(1) ==> one\n                                         zero?(1) ==> two\n                                         zero?(1) ==> three\n                                    end\")\n                  #f)\n))\n\n(exit (run-tests eopl-3.39-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/40-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../40.scm\")\n(load-relative \"helpers/nameless.scm\")\n\n(define eopl-3.40-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.40\"\n\n    (check-equal? (run \"42\") 42)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n\n    (check-equal? (run \"let f = proc (x) -(x, 11)\n                        in (f (f 77))\")\n                  55)\n\n    (check-equal? (run \"(proc (f) (f (f 77))\n                         proc (x) -(x, 11))\")\n                  55)\n\n    (check-equal? (run \"let x = 200\n                        in let f = proc (z) -(z, x)\n                           in let x = 100\n                              in let g = proc (z) -(z, x)\n                                 in -((f 1), (g 1))\")\n                  -100)\n\n    (check-equal? (run \"letrec double(x)\n                                = if zero?(x) then 0 else -((double -(x, 1)), -(0, 2))\n                        in (double 6)\")\n                  12)\n\n    (check-equal? (run \"letrec double(x) = let one = 1\n                                           in let two = 2\n                                              in if zero?(x)\n                                                 then 0\n                                                 else -((double -(x, one)), -(0, two))\n                        in (double 6)\")\n                  12)\n))\n\n(exit (run-tests eopl-3.40-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/41-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../41.scm\")\n(load-relative \"helpers/nameless.scm\")\n\n(define eopl-3.41-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.41\"\n\n    (check-equal? (run \"42\") 42)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n\n    (check-equal? (run \"let f = proc (x) -(x, 11)\n                        in (f (f 77))\")\n                  55)\n\n    (check-equal? (run \"(proc (f) (f (f 77))\n                         proc (x) -(x, 11))\")\n                  55)\n\n    (check-equal? (run \"let x = 200\n                        in let f = proc (z) -(z, x)\n                           in let x = 100\n                              in let g = proc (z) -(z, x)\n                                 in -((f 1), (g 1))\")\n                  -100)\n\n    (check-equal? (run \"let one = 1\n                            six = 6\n                        in -(six, one)\")\n                  5)\n    (check-equal? (run \"let one = proc () 1\n                            in (one)\")\n                  1)\n    (check-equal? (run \"let minus = proc (x y) -(x, y)\n                            in (minus 7 2)\")\n                  5)\n))\n\n(exit (run-tests eopl-3.41-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/42-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../42.scm\")\n(load-relative \"helpers/nameless.scm\")\n\n(define eopl-3.42-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.42\"\n\n    (check-equal? (run \"42\") 42)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n\n    (check-equal? (run \"let f = proc (x) -(x, 11)\n                        in (f (f 77))\")\n                  55)\n\n    (check-equal? (run \"(proc (f) (f (f 77))\n                         proc (x) -(x, 11))\")\n                  55)\n\n    (check-equal? (run \"let x = 200\n                        in let f = proc (z) -(z, x)\n                           in let x = 100\n                              in let g = proc (z) -(z, x)\n                                 in -((f 1), (g 1))\")\n                  -100)\n))\n\n(exit (run-tests eopl-3.42-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/43-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../43.scm\")\n(load-relative \"helpers/nameless.scm\")\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (expr (translation-of expr (empty-senv) (empty-kenv)))\n         (result (value-of expr env)))\n    (expval->schemeval result)))\n\n(define eopl-3.43-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.43\"\n\n    (check-equal? (run \"42\") 42)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n\n    (check-equal? (run \"let f = proc (x) -(x, 11)\n                        in (f (f 77))\")\n                  55)\n\n    (check-equal? (run \"(proc (f) (f (f 77))\n                         proc (x) -(x, 11))\")\n                  55)\n\n    (check-equal? (run \"let x = 200\n                        in let f = proc (z) -(z, x)\n                           in let x = 100\n                              in let g = proc (z) -(z, x)\n                                 in -((f 1), (g 1))\")\n                  -100)\n\n    (check-equal? (run \"let x = 3\n                        in let f = proc (y) -(y, x)\n                           in (f 13)\")\n                  10)\n\n    (check-equal? (run \"let apply10 = proc (y) (y 10)\n                        in let minus1 = proc (y) -(y, 1)\n                           in (apply10 minus1)\")\n                  9)\n))\n\n(exit (run-tests eopl-3.43-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/44-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../44.scm\")\n(load-relative \"helpers/nameless.scm\")\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (expr (translation-of expr (empty-senv) (empty-kenv)))\n         (result (value-of expr env)))\n    (expval->schemeval result)))\n\n(define eopl-3.44-tests\n  (test-suite\n    \"Tests for EOPL exercise 3.44\"\n\n    (check-equal? (run \"42\") 42)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n\n    (check-equal? (run \"let f = proc (x) -(x, 11)\n                        in (f (f 77))\")\n                  55)\n\n    (check-equal? (run \"(proc (f) (f (f 77))\n                         proc (x) -(x, 11))\")\n                  55)\n\n    (check-equal? (run \"let x = 200\n                        in let f = proc (z) -(z, x)\n                           in let x = 100\n                              in let g = proc (z) -(z, x)\n                                 in -((f 1), (g 1))\")\n                  -100)\n\n    (check-equal? (run \"let x = 3\n                        in let f = proc (y) -(y, x)\n                           in (f 13)\")\n                  10)\n\n    (check-equal? (run \"let apply10 = proc (y) (y 10)\n                        in let minus1 = proc (y) -(y, 1)\n                           in (apply10 minus1)\")\n                  9)\n\n    (check-equal? (run \"let minus1 = let f = proc (x) -(x, 1)\n                                     in f\n                        in (minus1 10)\")\n                  9)\n))\n\n(exit (run-tests eopl-3.44-tests))\n"
  },
  {
    "path": "scheme/eopl/03/tests/helpers/let.scm",
    "content": "(define (run code)\n  (eval* code (empty-env)))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (cases expval result\n      (num-val (num) num)\n      (bool-val (bool) bool))))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map (lambda (val)\n                      (if (boolean? val)\n                          (bool-val val)\n                          (num-val val)))\n                    vals)\n               (empty-env)))\n"
  },
  {
    "path": "scheme/eopl/03/tests/helpers/letrec.scm",
    "content": "(define (run code)\n  (eval* code (empty-env)))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (cases expval result\n      (num-val (num) num)\n      (bool-val (bool) bool)\n      (proc-val (proc) proc))))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map (lambda (val)\n                      (if (boolean? val)\n                          (bool-val val)\n                          (num-val val)))\n                    vals)\n               (empty-env)))\n"
  },
  {
    "path": "scheme/eopl/03/tests/helpers/nameless.scm",
    "content": "(define (run code)\n  (eval* code (empty-nameless-env)))\n\n(define (expval->schemeval val)\n  (cases expval val\n    (num-val (num) num)\n    (bool-val (bool) bool)\n    (proc-val (proc) proc)\n    (else (eopl:error 'eval* \"Don't know how to handle expval ~a\" val))))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (expr (translation-of expr (empty-senv)))\n         (result (value-of expr env)))\n    (expval->schemeval result)))\n"
  },
  {
    "path": "scheme/eopl/03/tests/helpers/proc.scm",
    "content": "(define (run code)\n  (eval* code (empty-env)))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (cases expval result\n      (num-val (num) num)\n      (bool-val (bool) bool)\n      (proc-val (proc) proc))))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map (lambda (val)\n                      (if (boolean? val)\n                          (bool-val val)\n                          (num-val val)))\n                    vals)\n               (empty-env)))\n"
  },
  {
    "path": "scheme/eopl/04/01.scm",
    "content": "; EOPL exercise 4.01\n\n; What would have happened had the program been instead\n;\n;   let g = proc (dummy)\n;             let counter = newref (0)\n;             in begin\n;                  setref(counter, -(deref(counter), -1));\n;                  deref(counter)\n;                end\n;   in let a = (g 11)\n;      in let b = (g 11)\n;         in -(a, b)\n\n; Each invocation of g will create a new location in memory, initialize it to\n; 0, increment it and return it. The result of the whole program will be 0.\n"
  },
  {
    "path": "scheme/eopl/04/02.scm",
    "content": "; EOPL exercise 4.02\n\n; Write down the specification for a zero?-exp\n\n;   (value-of exp₁ ρ σ₀) = (val₁, σ₁)\n;   -------------------------------\n;   (value-of (zero?-exp val₁) ρ σ₀)\n;     = { ((bool-val #t), σ₁)   if (expval->num val₁) = 0\n;       { ((bool-val #f), σ₁)   if (expval->num val₁) ≠ 0\n"
  },
  {
    "path": "scheme/eopl/04/03.scm",
    "content": "; EOPL exercise 4.03\n\n; Write down the specification for a call-exp\n\n;           (value-of exp₁ ρ σ₀) = (val₁, σ₁)\n;           (value-of exp₂ ρ σ₁) = (val₂, σ₂)\n;           (apply val₁ val₂ σ₂) = (val₃, σ₃)\n;   -------------------------------------------------\n;   (value-of (call-exp exp₁ exp₂) ρ σ₀) = (val₃, σ₃)\n"
  },
  {
    "path": "scheme/eopl/04/04.scm",
    "content": "; EOPL exercise 4.04\n;\n; Write down the specification for a begin expression.\n;\n;   Expression ::= begin Expression {; Expression}* end\n;\n; A begin expression may contain one or more subexpressions separated by\n; semicolons. These are evaluated in order and the value of the last is\n; returned.\n\n;              (value-of exp₁ ρ σ₀) = (val₁, σ₁)\n;              (value-of exp₂ ρ σ₁) = (val₂, σ₂)\n;                                  ...\n;          (value-of expᵢ ρ σ{i-1}) = (valᵢ, σᵢ)\n;   ───────────────────────────────────────────────────────\n;   (value-of (begin exp₁ exp₂ ... expᵢ) ρ σ₀) = (valᵢ, σᵢ)\n"
  },
  {
    "path": "scheme/eopl/04/05.scm",
    "content": "; EOPL exercise 4.05\n;\n; Write down the specification for list (exercise 3.10).\n\n;              (value-of exp₁ ρ σ₀) = (val₁, σ₁)\n;              (value-of exp₂ ρ σ₁) = (val₂, σ₂)\n;                                  ...\n;          (value-of expᵢ ρ σ{i-1}) = (valᵢ, σᵢ)\n;   ──────────────────────────────────────────────────────────────────────\n;   (value-of (list exp₁ exp₂ ... expᵢ) ρ σ₀) = ([val₁ val₂ ... valᵢ], σᵢ)\n"
  },
  {
    "path": "scheme/eopl/04/06.scm",
    "content": "; EOPL exercise 4.06\n;\n; Modify the rule given above so that setref-exp returns the value of the\n; right-hand side.\n\n;             (value-of exp₁ ρ σ₀) = (l, σ₁)\n;             (value-of exp₂ ρ σ₁) = (val, σ₂)\n;   ─────────────────────────────────────────────────────────\n;   (value-of (setref-exp exp₁ exp₂) ρ σ₀) = (val, [l=val]σ₂)\n"
  },
  {
    "path": "scheme/eopl/04/07.scm",
    "content": "; EOPL exercise 4.07\n;\n; Modify the rule given above so that setref-exp returns the old contents of\n; the location.\n\n;             (value-of exp₁ ρ σ₀) = (l, σ₁)\n;             (value-of exp₂ ρ σ₁) = (val, σ₂)\n;   ──────────────────────────────────────────────────────────\n;   (value-of (setref-exp exp₁ exp₂) ρ σ₀) = (σ₁(l), [l=val]σ₂)\n"
  },
  {
    "path": "scheme/eopl/04/08.scm",
    "content": "; EOPL exercise 4.08\n;\n; Show exactly where in our implementation of the store these operations take\n; linear time rather than constant time.\n\n; In newref, calculating the next reference takes linear time. Furthermore,\n; appending a new element to a list is also linear, since append needs to copy\n; the list.\n\n(define (newref val)\n  (let ((next-ref (length the-store)))             ; length is linear to the-store\n    (set! the-store (append the-store (list val))) ; append is linear to the-store\n    next-ref))\n\n; When dereferencing, scanning the list with list-ref is also linear\n\n(define (deref ref)\n  (list-ref the-store ref))\n\n; Finally, setref! needs to construct a new list with one element changed.\n; Since the element can be the last element in the array, this operation is\n; also linear.\n\n(define (setref! ref val)\n  (set! the-store\n    (let recur ((store1 the-store)\n                (ref1 ref))\n      (cond ((null? store1)\n             (eopl:error 'setref! \"Invalid reference ~s in ~s\" ref the-store))\n            ((zero? ref1)\n             (cons val (cdr store1)))\n            (else (cons (car store1)\n                        (recur (cdr store1) (- ref1 1))))))))\n"
  },
  {
    "path": "scheme/eopl/04/cases/explicit-refs/all.scm",
    "content": "(load-relative \"../../../support/eopl.scm\")\n(load-relative \"parser.scm\")\n(load-relative \"env.scm\")\n(load-relative \"eval.scm\")\n"
  },
  {
    "path": "scheme/eopl/04/cases/explicit-refs/env.scm",
    "content": "(define environment? (or/c pair? null?))\n\n(define (empty-env)\n  '())\n\n(define (extend-env var val env)\n  (cons (list var val)\n        env))\n\n(define (extend-env* vars vals env)\n  (if (null? vars)\n      env\n      (extend-env* (cdr vars)\n                   (cdr vals)\n                   (extend-env (car vars) (car vals) env))))\n\n(define (apply-env env var)\n  (cond ((null? env) (eopl:error 'apply-env \"Variable not found\"))\n        ((eqv? (caar env) var) (cadar env))\n        (#t (apply-env (cdr env) var))))\n"
  },
  {
    "path": "scheme/eopl/04/cases/explicit-refs/eval.scm",
    "content": "(define-datatype proc proc?\n  (procedure\n    (var symbol?)\n    (body expression?)\n    (saved-env environment?)))\n\n(define (apply-procedure proc1 val)\n  (cases proc proc1\n    (procedure (var body saved-env)\n      (value-of body (extend-env var val saved-env)))))\n\n(define-datatype expval expval?\n  (num-val\n    (num number?))\n  (bool-val\n    (bool boolean?))\n  (proc-val\n    (proc proc?))\n  (ref-val\n    (ref integer?)))\n\n(define (expval->num val)\n  (cases expval val\n    (num-val (num) num)\n    (else (eopl:error 'expval->num \"Invalid number: ~s\" val))))\n\n(define (expval->bool val)\n  (cases expval val\n    (bool-val (bool) bool)\n    (else (eopl:error 'expval->bool \"Invalid boolean: ~s\" val))))\n\n(define (expval->proc val)\n  (cases expval val\n    (proc-val (proc) proc)\n    (else (eopl:error 'expval->proc \"Invalid procedure: ~s\" val))))\n\n(define (expval->ref val)\n  (cases expval val\n    (ref-val (num) num)\n    (else (eopl:error 'expval->ref \"Invalid reference ~s\" val))))\n\n(define (value-of expr env)\n  (cases expression expr\n    (const-exp (num) (num-val num))\n    (var-exp (var) (apply-env env var))\n    (diff-exp (minuend subtrahend)\n      (let ((minuend-val (value-of minuend env))\n            (subtrahend-val (value-of subtrahend env)))\n        (let ((minuend-num (expval->num minuend-val))\n              (subtrahend-num (expval->num subtrahend-val)))\n          (num-val\n            (- minuend-num subtrahend-num)))))\n    (zero?-exp (arg)\n      (let ((value (value-of arg env)))\n        (let ((number (expval->num value)))\n          (if (zero? number)\n              (bool-val #t)\n              (bool-val #f)))))\n    (if-exp (predicate consequent alternative)\n      (let ((value (value-of predicate env)))\n        (if (expval->bool value)\n            (value-of consequent env)\n            (value-of alternative env))))\n    (let-exp (var value-exp body)\n      (let ((value (value-of value-exp env)))\n        (value-of body\n          (extend-env var value env))))\n    (proc-exp (var body)\n      (proc-val (procedure var body env)))\n    (call-exp (rator rand)\n      (let ((proc (expval->proc (value-of rator env)))\n            (arg (value-of rand env)))\n        (apply-procedure proc arg)))\n    (begin-exp (body)\n      (let* ((first (car body))\n             (rest (cdr body))\n             (value (value-of first env)))\n        (if (null? rest)\n            value\n            (value-of (begin-exp rest) env))))\n    (newref-exp (arg)\n      (ref-val (newref (value-of arg env))))\n    (deref-exp (arg)\n      (deref (expval->ref (value-of arg env))))\n    (setref-exp (ref-exp value-exp)\n      (let ((ref (value-of ref-exp env)))\n        (let ((value (value-of value-exp env)))\n          (setref! (expval->ref ref) value)\n          (num-val 42))))))\n\n; The store\n\n(define the-store 'uninitialized)\n\n(define (empty-store)\n  '())\n\n(define (get-store)\n  the-store)\n\n(define (initialize-store!)\n  (set! the-store (empty-store)))\n\n(define (reference? v)\n  (integer? v))\n\n(define (newref val)\n  (let ((next-ref (length the-store)))\n    (set! the-store (append the-store (list val)))\n    next-ref))\n\n(define (deref ref)\n  (list-ref the-store ref))\n\n(define (setref! ref val)\n  (set! the-store\n    (let recur ((store1 the-store)\n                (ref1 ref))\n      (cond ((null? store1)\n             (eopl:error 'setref! \"Invalid reference ~s in ~s\" ref the-store))\n            ((zero? ref1)\n             (cons val (cdr store1)))\n            (else (cons (car store1)\n                        (recur (cdr store1) (- ref1 1))))))))\n"
  },
  {
    "path": "scheme/eopl/04/cases/explicit-refs/parser.scm",
    "content": "(define-datatype expression expression?\n  (const-exp\n    (num number?))\n  (diff-exp\n    (minuend expression?)\n    (subtrahend expression?))\n  (zero?-exp\n    (expr expression?))\n  (if-exp\n    (predicate expression?)\n    (consequent expression?)\n    (alternative expression?))\n  (var-exp\n    (var symbol?))\n  (let-exp\n    (var symbol?)\n    (value expression?)\n    (body expression?))\n  (proc-exp\n    (var symbol?)\n    (body expression?))\n  (call-exp\n    (rator expression?)\n    (rand expression?))\n  (begin-exp\n    (body (list-of expression?)))\n  (newref-exp\n    (value expression?))\n  (setref-exp\n    (target expression?)\n    (value expression?))\n  (deref-exp\n    (target expression?)))\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (comment (\"%\" (arbno (not #\\newline))) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression (number) const-exp)\n    (expression (\"-\" \"(\" expression \",\" expression \")\") diff-exp)\n    (expression (\"zero?\" \"(\" expression \")\") zero?-exp)\n    (expression (\"if\" expression \"then\" expression \"else\" expression) if-exp)\n    (expression (identifier) var-exp)\n    (expression (\"proc\" \"(\" identifier \")\" expression) proc-exp)\n    (expression (\"newref\" \"(\" expression \")\") newref-exp)\n    (expression (\"setref\" \"(\" expression \",\" expression \")\") setref-exp)\n    (expression (\"deref\" \"(\" expression \")\") deref-exp)\n    (expression (\"let\" identifier \"=\" expression \"in\" expression) let-exp)\n    (expression (\"begin\" (separated-list expression \";\") \"end\") begin-exp)\n    (expression (\"(\" expression expression \")\") call-exp)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n"
  },
  {
    "path": "scheme/eopl/04/cases/explicit-refs/test-helpers.scm",
    "content": "(define (run code)\n  (eval* code (empty-env)))\n\n(define (eval* code env)\n  (let* ((expr (scan&parse code))\n         (result (value-of expr env)))\n    (cases expval result\n      (num-val (num) num)\n      (bool-val (bool) bool)\n      (proc-val (proc) proc)\n      (ref-val (num) (format \"<ref:~s>\" num)))))\n\n(define (env vars vals)\n  (extend-env* vars\n               (map (lambda (val)\n                      (if (boolean? val)\n                          (bool-val val)\n                          (num-val val)))\n                    vals)\n               (empty-env)))\n"
  },
  {
    "path": "scheme/eopl/04/cases/explicit-refs/tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"all.scm\")\n(load-relative \"test-helpers.scm\")\n\n(define explicit-refs-language-tests\n  (test-suite\n    \"Tests for the EXPLICIT-REFS language\"\n\n    (check-equal? (run \"42\") 42)\n    (check-equal? (eval* \"x\" (env '(x) '(10))) 10)\n    (check-equal? (eval* \"-(x, 7)\" (env '(x) '(10))) 3)\n\n    (check-equal? (run \"% Comment\\n 1\") 1)\n\n    (check-equal? (run \"zero?(0)\") #t)\n    (check-equal? (run \"zero?(1)\") #f)\n\n    (check-equal? (run \"if zero?(0) then 1 else 2\") 1)\n    (check-equal? (run \"if zero?(3) then 1 else 2\") 2)\n\n    (check-equal? (run \"let x = 1 in x\") 1)\n    (check-equal? (run \"let x = 1 in let x = 2 in x\") 2)\n    (check-equal? (run \"let x = 1 in let y = 2 in x\") 1)\n\n    (check-equal? (run \"let x = 7                  % This is a comment\n                        in let y = 2               % This is another comment\n                           in let y = let x = -(x, 1) in -(x, y)\n                              in -(-(x, 8),y)\")\n                  -5)\n\n    (check-equal? (run \"let f = proc (x) -(x, 11)\n                        in (f (f 77))\")\n                  55)\n\n    (check-equal? (run \"(proc (f) (f (f 77))\n                         proc (x) -(x, 11))\")\n                  55)\n\n    (check-equal? (run \"let x = 200\n                        in let f = proc (z) -(z, x)\n                           in let x = 100\n                              in let g = proc (z) -(z, x)\n                                 in -((f 1), (g 1))\")\n                  -100)\n\n    (check-equal? (run \"begin 1; 2 end\")\n                  2)\n\n    (initialize-store!)\n    (check-equal? (run \"let g = let counter = newref(0)\n                                in proc (dummy)\n                                     begin\n                                       setref(counter, -(deref(counter), -(0, 1)));\n                                       deref(counter)\n                                     end\n                        in let a = (g 11)\n                           in let b = (g 11)\n                              in -(a, b)\")\n                  -1)\n))\n\n(exit (run-tests explicit-refs-language-tests))\n"
  },
  {
    "path": "scheme/eopl/B/01.scm",
    "content": "; EOPL exercise B.01\n;\n; The following grammar for ordinary arithmetic expressions builds in the\n; usual precendence in the usual rules for arithmetic operations:\n;\n;   Arith-expr        ::= Arith-term {Additive-op Arith-term}*\n;   Arith-term        ::= Arith-factor {Multiplicative-op Arith-factor}*\n;   Arith-factor      ::= Number\n;                     ::= (Arith-expr)\n;   Additive-op       ::= + | -\n;   Multiplicative-op ::= * | /\n;\n; This grammar says that every arithmetic expression is the sum of a non-empty\n; sequence of terms; every term is the product of a non-empty sequence of\n; factors; and every factor is either a constant or a parenthesized\n; expression.\n;\n; Write a lexical specification and a grammar in SLLGEN that will scan and\n; parse strings according to this grammar. Verify that this grammar handles\n; precendence correctly, so that, for example 3+2*66-5 gets grouped correctly,\n; as 3 + (2 × 66) - 5.\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (additive-op ((or \"+\" \"-\")) symbol)\n    (multiplicative-op ((or \"*\" \"/\")) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression\n      (term (arbno additive-op term))\n      op)\n    (term\n      (factor (arbno multiplicative-op factor))\n      op)\n    (factor\n      (number)\n      number)\n    (factor\n      (\"(\" expression \")\")\n      factor)))\n\n(define-datatype ast ast?\n  (op\n    (first-operand ast?)\n    (operators (list-of symbol?))\n    (rest-operands (list-of ast?)))\n  (factor\n    (value ast?))\n  (number\n    (value integer?)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n"
  },
  {
    "path": "scheme/eopl/B/02.scm",
    "content": "; EOPL exercise B.02\n;\n; Why can't the grammar above be written with separated-list?\n\n; There are at least a few reasons. For one, it would allow empty expressions\n; which is something we don't want. Second, the separator needs to be a\n; terminal, otherwise SLLGEN just chokes. We can rewrite it if we introduce\n; add-exp, sub-exp, mul-exp and div-exp.\n"
  },
  {
    "path": "scheme/eopl/B/03.scm",
    "content": "; EOPL exercise B.03\n;\n; Define an interpreter that takes the syntax tree produced by the parser of\n; exercise B.1 and evaluates it as an arithmetic expression. The parser takes\n; care of the usual arithmetic precendence operations, but the interpreter\n; will have to take care of associativity, that is, making sure that the\n; operations at the same precendence level (e.g. additions and subtractions)\n; are performed from left to right. Since there are no variables in these\n; expressions, this interpreter need not take an environment parameter.\n\n(load-relative \"01.scm\")\n\n(define (eval* tree)\n  (cases ast tree\n    (op (first ops rest)\n      (apply-ops (eval* first) ops (map eval* rest)))\n    (number (val)\n      val)\n    (factor (expr)\n      (eval* expr))))\n\n(define (apply-ops first ops rest)\n  (if (null? ops)\n      first\n      (apply-ops ((eval (car ops)) first (car rest))\n                 (cdr ops)\n                 (cdr rest))))\n\n(define (value-of code)\n  ((compose eval* scan&parse) code))\n"
  },
  {
    "path": "scheme/eopl/B/04.scm",
    "content": "; EOPL exercise B.04\n;\n; Extend the language and interpreter of the preceding exercise to include\n; variables. This new interpreter will require an environment parameter.\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (additive-op ((or \"+\" \"-\")) symbol)\n    (multiplicative-op ((or \"*\" \"/\")) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression\n      (term (arbno additive-op term))\n      op)\n    (term\n      (factor (arbno multiplicative-op factor))\n      op)\n    (factor\n      (number)\n      number)\n    (factor\n      (identifier)\n      ref)\n    (factor\n      (\"(\" expression \")\")\n      factor)))\n\n(define-datatype ast ast?\n  (op\n    (first-operand ast?)\n    (operators (list-of symbol?))\n    (rest-operands (list-of ast?)))\n  (factor\n    (value ast?))\n  (ref\n    (name symbol?))\n  (number\n    (value integer?)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n(define (eval* tree env)\n  (cases ast tree\n    (op (first ops rest)\n      (apply-ops (eval* first env)\n                 ops\n                 (map (curryr eval* env) rest)))\n    (number (val)\n      val)\n    (ref (var)\n      (lookup var env))\n    (factor (expr)\n      (eval* expr env))))\n\n(define (apply-ops first ops rest)\n  (if (null? ops)\n      first\n      (apply-ops ((eval (car ops)) first (car rest))\n                 (cdr ops)\n                 (cdr rest))))\n\n(define (lookup var env)\n  (cond ((null? env)\n         (eopl:error 'lookup \"Variable not found: ~s\" var))\n        ((eqv? var (caar env))\n         (cadar env))\n        (else\n         (lookup var (cdr env)))))\n\n(define (value-of code env)\n  (eval* (scan&parse code) env))\n"
  },
  {
    "path": "scheme/eopl/B/05.scm",
    "content": "; EOPL exercise B.05\n;\n; Add unary minus to the language and interpreter, so that inputs like 3*-2\n; are handled correctly.\n\n(define scanner-spec\n  '((white-sp (whitespace) skip)\n    (identifier (letter (arbno (or letter digit))) symbol)\n    (additive-op ((or \"+\" \"-\")) symbol)\n    (multiplicative-op ((or \"*\" \"/\")) symbol)\n    (number (digit (arbno digit)) number)))\n\n(define grammar\n  '((expression\n      (term (arbno additive-op term))\n      op)\n    (term\n      (factor (arbno multiplicative-op factor))\n      op)\n    (factor\n      (number)\n      number)\n    (factor\n      (identifier)\n      ref)\n    (factor\n      (\"-\" factor)\n      neg)\n    (factor\n      (\"(\" expression \")\")\n      factor)))\n\n(define-datatype ast ast?\n  (op\n    (first-operand ast?)\n    (operators (list-of symbol?))\n    (rest-operands (list-of ast?)))\n  (factor\n    (value ast?))\n  (neg\n    (value ast?))\n  (ref\n    (name symbol?))\n  (number\n    (value integer?)))\n\n(define scan&parse\n  (sllgen:make-string-parser scanner-spec grammar))\n\n(define (eval* tree env)\n  (cases ast tree\n    (op (first ops rest)\n      (apply-ops (eval* first env)\n                 ops\n                 (map (curryr eval* env) rest)))\n    (number (val)\n      val)\n    (ref (var)\n      (lookup var env))\n    (neg (expr)\n      (- (eval* expr env)))\n    (factor (expr)\n      (eval* expr env))))\n\n(define (apply-ops first ops rest)\n  (if (null? ops)\n      first\n      (apply-ops ((eval (car ops)) first (car rest))\n                 (cdr ops)\n                 (cdr rest))))\n\n(define (lookup var env)\n  (cond ((null? env)\n         (eopl:error 'lookup \"Variable not found: ~s\" var))\n        ((eqv? var (caar env))\n         (cadar env))\n        (else\n         (lookup var (cdr env)))))\n\n(define (value-of code env)\n  (eval* (scan&parse code) env))\n"
  },
  {
    "path": "scheme/eopl/B/tests/01-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../01.scm\")\n\n(define eopl-B.01-tests\n  (test-suite\n    \"Tests for EOPL exercise B.01\"\n\n    (check-equal? (scan&parse \"3 + 2 * 66 - 5\")\n                  (op (op (number 3) '() '())\n                      '(+ -)\n                      (list\n                        (op (number 2) '(*) (list (number 66)))\n                        (op (number 5) '() '()))))\n))\n\n(exit (run-tests eopl-B.01-tests))\n"
  },
  {
    "path": "scheme/eopl/B/tests/03-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../03.scm\")\n\n(define eopl-B.03-tests\n  (test-suite\n    \"Tests for EOPL exercise B.03\"\n\n    (check-equal? (value-of \"1 + 2\") 3)\n    (check-equal? (value-of \"3 - 2\") 1)\n    (check-equal? (value-of \"3 - 2 - 1\") 0)\n    (check-equal? (value-of \"3 - 2 - 1 + 7\") 7)\n    (check-equal? (value-of \"3 * 4 / 2 * 5\") 30)\n    (check-equal? (value-of \"3 * 4 / 2 * 5 + 1\") 31)\n))\n\n(exit (run-tests eopl-B.03-tests))\n"
  },
  {
    "path": "scheme/eopl/B/tests/04-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../04.scm\")\n\n(define eopl-B.04-tests\n  (test-suite\n    \"Tests for EOPL exercise B.04\"\n\n    (check-equal? (value-of \"1 + x\" '((x 1))) 2)\n    (check-equal? (value-of \"x * y + z\" '((x 2) (y 3) (z 5))) 11)\n    (check-equal? (value-of \"x * (y + z)\" '((x 2) (y 3) (z 5))) 16)\n))\n\n(exit (run-tests eopl-B.04-tests))\n"
  },
  {
    "path": "scheme/eopl/B/tests/05-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"../05.scm\")\n\n(define eopl-B.05-tests\n  (test-suite\n    \"Tests for EOPL exercise B.05\"\n\n    (check-equal? (value-of \"-1\" '()) -1)\n    (check-equal? (value-of \"3*-2\" '()) -6)\n    (check-equal? (value-of \"-(x + y)\" '((x 2) (y 3))) -5)\n))\n\n(exit (run-tests eopl-B.05-tests))\n"
  },
  {
    "path": "scheme/eopl/Gemfile",
    "content": "source :rubygems\n\ngem 'guard'\ngem 'guard-shell'\ngem 'thor'\ngem 'term-ansicolor'\ngem 'rb-fsevent', require: false\ngem 'rb-inotify', require: false\n"
  },
  {
    "path": "scheme/eopl/Guardfile",
    "content": "interactor :off\n\nguard :shell do\n  watch(%r{^(\\d+|B)/(\\d+).scm$}) { |m| system \"clear && thor run exercise #{m[1]} #{m[2]}\" }\n  watch(%r{^(\\d+|B)/tests/(\\d+)-tests.scm$}) { |m| system \"clear && thor run exercise #{m[1]} #{m[2]}\" }\n  watch(%r{^(\\d+)/cases/(\\w+)/[^/]+.scm$}) { |m| system \"clear && racket -r #{m[1]}/cases/#{m[2]}/tests.scm\" }\nend\n"
  },
  {
    "path": "scheme/eopl/Thorfile",
    "content": "require './build/exercise'\nrequire 'term/ansicolor'\n\nclass Default < Thor\n  include Thor::Actions\n\n  def self.source_root\n    File.dirname(__FILE__)\n  end\n\n  method_option :chapter, type: :numeric, desc: 'The chapter number'\n  method_option :number, type: :numeric, desc: 'The exercise number'\n  option :skip_test, type: :boolean, desc: 'Skip generating a test case'\n  desc :exercise, 'Generates an exercise and a test'\n  def exercise(chapter, number)\n    exercise = Exercise.new chapter, number\n    config = {\n      name: exercise.name,\n      exercise_require_path: exercise.exercise_require_path\n    }\n\n    template 'build/templates/exercise.scm', exercise.file_path, config\n\n    unless options[:skip_test]\n      template 'build/templates/test.scm', exercise.test_path, config\n    end\n  end\n\n  desc :next, 'Generates the next exercise'\n  option :skip_test, type: :boolean, desc: 'Skip generating a test case'\n  def next\n    exercise = Exercise.next\n\n    invoke :exercise, [exercise.chapter, exercise.number], options\n\n    system \"mvim --remote-silent #{exercise.file_path}\"\n    system \"mvim --remote-tab-silent #{exercise.test_path}\" if exercise.has_test?\n\n    exec 'guard'\n  end\nend\n\nclass Run < Thor\n  include Term::ANSIColor\n\n  desc :exercise, 'Runs an exercise or its tests'\n  method_option :chapter, type: :numeric, desc: 'The chapter number'\n  method_option :number, type: :numeric, desc: 'The exercise number'\n  def exercise(chapter, number)\n    exercise = Exercise.new chapter, number\n\n    if exercise.has_test?\n      system \"racket -r #{exercise.test_path}\"\n    else\n      system \"racket -r #{exercise.file_path}\"\n    end\n  end\n\n  desc :test, 'Runs the tests of an exercise'\n  method_option :chapter, type: :numeric, desc: 'The chapter number'\n  method_option :number, type: :numeric, desc: 'The exercise number'\n  def test(chapter, number)\n    exercise = Exercise.new chapter, number\n\n    system \"racket -r #{exercise.test_path}\"\n  end\n\n  desc :all, 'Runs all the tests'\n  def all\n    Exercise.each_with_test do |exercise|\n      print bold(\"#{exercise.name}: \")\n      success = system \"racket -r #{exercise.test_path}\"\n      unless success\n        puts red(\"FAILURE AT #{exercise.name}\")\n        exit(1) unless success\n      end\n    end\n\n    puts green(\"OK\")\n  end\nend\n"
  },
  {
    "path": "scheme/eopl/build/exercise.rb",
    "content": "class Exercise\n  attr_reader :chapter, :number\n\n  def initialize(chapter, number)\n    @chapter = case chapter\n      when Integer then chapter\n      when /^\\d+$/ then chapter.to_i\n      when /^B$/ then 'B'\n      else raise \"Invalid chapter: #{chapter}\"\n    end\n    @number  = number.to_i\n  end\n\n  class << self\n    def next\n      current_chapter = chapters(false).last\n      last_exercise   = exercises_in_chapter(current_chapter).last\n      next_exercise   = last_exercise.to_i + 1\n\n      new current_chapter, next_exercise\n    end\n\n    def each\n      chapters.each do |chapter|\n        exercises_in_chapter(chapter).each do |number|\n          yield new chapter, number\n        end\n      end\n    end\n\n    def each_with_test\n      each do |exercise|\n        next unless exercise.has_test?\n        yield exercise\n      end\n    end\n\n    private\n\n    def chapters(include_appendices = true)\n      chapters = Dir['*'].grep(/^(\\d+|B)$/)\n      chapters -= %w[A B] unless include_appendices\n      chapters.sort\n    end\n\n    def exercises_in_chapter(chapter)\n      Dir[\"#{chapter}/*\"].grep(%r{^(?:\\d+|B)/(\\d+).scm$}) { $1 }.sort\n    end\n  end\n\n\n  def name\n    \"%s.%02d\" % [@chapter, @number]\n  end\n\n  def file_path\n    \"%s/%02d.scm\" % [formatted_chapter, @number]\n  end\n\n  def test_path\n    \"%s/tests/%02d-tests.scm\" % [formatted_chapter, @number]\n  end\n\n  def exercise_require_path\n    \"../%02d.scm\" % @number\n  end\n\n  def has_test?\n    File.exist? test_path\n  end\n\n  private\n\n  def formatted_chapter\n    case @chapter\n      when Integer then \"%02d\" % @chapter\n      else @chapter\n    end\n  end\nend\n"
  },
  {
    "path": "scheme/eopl/build/templates/exercise.scm",
    "content": "; EOPL exercise <%= config[:name] %>\n"
  },
  {
    "path": "scheme/eopl/build/templates/test.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"../../support/eopl.scm\")\n(load-relative \"<%= config[:exercise_require_path] %>\")\n\n(define eopl-<%= config[:name] %>-tests\n  (test-suite\n    \"Tests for EOPL exercise <%= config[:name] %>\"\n\n))\n\n(exit (run-tests eopl-<%= config[:name] %>-tests))\n"
  },
  {
    "path": "scheme/eopl/notes/week-01.markdown",
    "content": "# Week 1 (2013-01-01 - 2013-01-06)\n\n## The `let*` pattern\n\nI just love using `let*` like in the solution of exercise 1.35:\n\n    (let* ((node-data (contents-of tree))\n           (lson-result (traverse (lson tree) counter))\n           (counter-after-lson (car lson-result))\n           (result-lson (cdr lson-result))\n           (rson-result (traverse (rson tree) counter-after-lson))\n           (result-counter (car rson-result))\n           (result-rson (cdr rson-result))\n           (result-tree (interior-node node-data result-lson result-rson)))\n      (cons result-counter result-tree))))\n\nIt builds long computation, giving names to the intermediate values involved. In this particular computation, the algorithm might not be as clear as it would if I use a procedure to determine the count in the last node of lson, but it is still a great way to write it. I end up doing that quite often in JavaScript, where I would have code like this:\n\n    var oldBag    = $('div[data-bag]'),\n        newBag    = $(response),\n        sizeError = $('#size-required'),\n        title     = newBag.find('.title'),\n        contents  = newBag.find('.contents');\n\nI find this very readable, because all the right-hand sides of the assignment are short and use specific names defined earlier. It makes me focus on the code (instead of quickly scanning it), but I still find it very useful.\n\n## Multiple levels of interface\n\nI love this idea of multiple levels of interface that can be seen in exercise 2.03. There are four levels of abstraction.\n\n1. The constructors and the observers that are a very thin wrap over the representation.\n2. `minuend` and `subtrahend` that work with the previous layer to provide an uniform view of the two possible representations in the grammar.\n3. The four operations for numbers that use minuend and subtrahend. Note that they also can be viewed as an interface implementation.\n4. Operations built ontop of those four procedures like `plus`.\n\nIn an object-oriented language, all those layers are easily lost since they end up being in the same class.\n"
  },
  {
    "path": "scheme/eopl/notes/week-02.markdown",
    "content": "# Week 2 (2013-01-06 - 2013-01-13)\n\nNothing noteworthy this week. SLLGEN was fun, but it is kinda simplistic.\n"
  },
  {
    "path": "scheme/eopl/notes/week-03.markdown",
    "content": "# Week 3 (2013-05-19 - 2013-05-25)\n\nI dropped the book for quite a while. Now I am picking it up again. This is not really the third week, but I will consider it so for the record keeping.\n\n## Recursion without the Y-combinator\n\nExercises 3.23 - 3.25 show recursion in a language that can only bind variables with `let`. I knew that you can use the Y-combinator to accomoplish this, but I was not aware that there was a way to write a recursive function without it.\n\n## Recursion with dynamic binding\n\nIt appears that recursion with dynamic binding is pretty straightforward - the interpreter did not need any modification in order to run.\n"
  },
  {
    "path": "scheme/eopl/support/eopl.scm",
    "content": "(require eopl)\n"
  },
  {
    "path": "scheme/sicp/.gitignore",
    "content": ".rvmrc\n"
  },
  {
    "path": "scheme/sicp/01/01.scm",
    "content": "; SICP exercise 1.01\n;\n; Below is a sequence of expressions. What is the result printed by the\n; interpreter in response to each expression? Assume that the sequence is to be\n; evaluated in the order in which it is presented\n\n; 10\n10\n\n; (+ 5 3 4)\n12\n\n; (- 9 1)\n8\n\n; (/ 6 2)\n3\n\n; (+ (* 2 4) (- 4 6))\n6\n\n; (define a 3)\n; (define b (+ a 1))\n\n; (+ a b (* a b))\n19\n\n; (= a b)\n#t\n\n; (if (and (> b a) (< b (* a b)))\n;     b\n;     a)\n4\n\n; (cond ((= a 4) 6)\n;       ((= b 4) (+ 6 7 a))\n;       (else 25))\n16\n\n; (+ 2 (if (> b a) b a))\n6\n\n; (* (cond ((> a b) a)\n;          ((< a b) b)\n;          (else -1))\n;    (+ a 1)\n16\n"
  },
  {
    "path": "scheme/sicp/01/02.scm",
    "content": "; SICP exercise 1.02\n;\n; Translate the following expression into prefix form:\n;\n; http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-10.html#%_thm_1.2\n\n(/ (+ 5\n      4\n      (- 2 (- 3 (+ 6 (/ 4 5)))))\n   (* 3\n      (- 6 2)\n      (- 2 7)))\n"
  },
  {
    "path": "scheme/sicp/01/03.scm",
    "content": "; SICP exercise 1.03\n;\n; Define a procedure that takes three numbers as arguments and returns the sum\n; of the squares of the two larger numbers.\n\n(define (sum-of-squares a b)\n  (+ (* a a) (* b b)))\n\n(define (sum-of-two-largest-squares a b c)\n  (cond ((and (<= a b) (<= a c)) (sum-of-squares b c))\n        ((and (<= b a) (<= b c)) (sum-of-squares a c))\n        (else (sum-of-squares a b))))\n"
  },
  {
    "path": "scheme/sicp/01/04.scm",
    "content": "; SICP exercise 1.04\n;\n; Observe that our model of evaluation allows for combinations whose operators\n; are compound expressions. Use this observation to describe the behavior of\n; the following procedure\n;\n; (define (a-plus-abs-b a b)\n;   ((if (> b 0) + -) a b))\n\n; The procedure adds a to the absolute value of b, pretty much as it name\n; suggests. Instead of calculating the absolute value of b and adding it\n; directly to a, we use the fact that:\n;\n;   a + |b| = { a + b     if b is positive\n;             { a - b     if b is negative\n;\n; In both cases we have an expression with similar structure, but a different\n; operator: (<operator> a b). We can determine which operator to use by\n; comparing b to 0, which is what (if (> b 0) + -) does. In the former case\n; it evaluates to +, while in the later it evaluates to -.\n"
  },
  {
    "path": "scheme/sicp/01/05.scm",
    "content": "; SICP exercise 1.05\n;\n; Ben Bitdiddle has invented a test to determine whether the interpreter he is\n; faced with is using applicative-order evaluation or normal-order evaluation.\n; He defines the following two procedures:\n;\n; (define (p) (p))\n;\n; (define (test x y)\n;   (if (= x 0)\n;       0\n;       y))\n;\n; Then he evaluates he expression\n;\n; (test 0 (p))\n;\n; What behavior will Ben observe with an interpreter that uses\n; applicative-order evaluation? What behavior will he observe with an\n; interpreter that users normal-order evaluation? Explain your answer. (Assume\n; that the evaluation rule of the special form if is the same whether the\n; interpreter is using normal or applicative order: The predicate expression is\n; evaluated first, and the result determines whether to evaluate the consequent\n; or the alternative expression.)\n\n; p does not depend on the type of evaluation, while test does.\n;\n; (p) is an infinite loop - the interpreter will never stop evaluating it,\n; since on every evaluation it has to evaluate it again.\n;\n; If the first argument of x equals 0, it does not use the second. Within\n; normal-order evaluation, the second argument will never be evaluated. Within\n; applicative-order evaluation, the second argument gets evaluated before test\n; is evaluated. Thus, we can tell the type of evaluation by observing if the\n; second argument gets evaluated.\n;\n; Within applicative-order evaluation the second argument will be evaluated\n; before test and the interpreter will get stuck in an infinite loop. Within\n; normal-order evaluation the second argument will never get evaluated and the\n; interpreter will finish successfully. We can use that to tell which\n; evaluation type we are using.\n"
  },
  {
    "path": "scheme/sicp/01/06.scm",
    "content": "; SICP exercise 1.06\n;\n; Alyssa P. Hacker doesn't see why if needs to be provided as a special form.\n; \"Why can't I just define it as an ordinary procedure in terms of cond?\" she\n; asks. Alyssa's friend Eva Lu Ator claims this can indeed be done, and she\n; defines a new version of if:\n;\n; (define (new-if predicate then-clause else-clause)\n;   (cond (predicate then-clause)\n;         (else else-clause)))\n;\n; Eva demonstrates the program for Alyssa:\n;\n; (new-if (= 2 3) 0 5)\n; 5\n;\n; (new-if (= 1 1) 0 5)\n; 0\n;\n; Delighted, Alyssa uses new-if to rewrite the square-root program:\n;\n; (define (sqrt-iter guess x)\n;   (new-if (good-enough? guess x)\n;           guess\n;           (sqrt-iter (improve guess x)\n;                      x)))\n;\n; What happens when Alyssa attempts to use this to compute square roots?\n; Explain.\n\n; The interpreter gets stuck in an infinite loop.\n;\n; There is a crucial difference between if and new-if - the former does not\n; evaluate both of its clauses, while the later does. This means, that despite\n; whether the guess is good enough, sqrt-iter will call itself with an improved\n; guess, ending up in an infinite recursion.\n;\n; Suffice to say, Eva was wrong.\n"
  },
  {
    "path": "scheme/sicp/01/07.scm",
    "content": "; SICP exercise 1.07\n;\n; The good-enough? test used in computing square roots will not be very\n; effective for finding the square roots of very small numbers. Also, in real\n; computers, arithmetic operations are almost always performed with limited\n; precision. This makes our test inadequate for very large numbers. Explain\n; these statements, with examples showing how the tests fails for small and\n; large numbers. An alternative strategy for implementing good-enough? is to\n; watch how guess changes from one iteration to the next and to stop when the\n; change is a very small fraction of the guess. Design a square-root procedure\n; that uses this kind of end test. Does this work better for small and large\n; numbers?\n\n; It is very easy to demonstrate how this version of good-enough? fails with\n; small numbers. Let's try finding the squre of 0.00000004. The result we\n; expect is 0.0002.\n;\n; On the third iteration the guess will be 0.0312. The square of the guess is\n; 0.0009, which is just below 0.001. Thus good-enough concludes that 0.0312 is\n; the correct answer, if if it is two orders of magnitude apart from the\n; desired answer, 0.0002.\n;\n; Simply put, when the number we are square rooting is below the precision,\n; there error is quite big.\n;\n; As for large numbers, we can demonstrate it by attempting to find the square\n; root of 10e+48. On my machine, this simply gets stuck in an infinite loop.\n;\n; Eventually, (improve guess x) starts getting evaluated to x. While\n; (/ x guess) is different from guess, there is not enough precision to\n; accurately calculate their average, causing  the interpreter to end up\n; rounding towards guess. The guess never gets good enough, since it stops\n; improving. Infinite loop follows.\n;\n; Finally, here is the suggested improvement. It works fine in both cases:\n\n(define (sqrt x)\n  (sqrt-iter 1.0 x))\n\n(define (sqrt-iter guess x)\n  (if (good-enough? guess x)\n    guess\n    (sqrt-iter (improve guess x)\n               x)))\n\n(define (good-enough? guess x)\n  (< (/ (abs (- (improve guess x) guess))\n        guess)\n     1e-15))\n\n(define (improve guess x)\n  (average guess (/ x guess)))\n\n(define (average x y)\n  (/ (+ x y) 2))\n"
  },
  {
    "path": "scheme/sicp/01/08.scm",
    "content": "; SICP exercise 1.08\n;\n; Newton's method for cube roots is based on the fact that if y is an\n; approximation to the cube root of x, then a better approximation is given by\n; the value:\n;\n; x/y² + 2y\n; ─────────\n;     3\n;\n; Use this formula to implement a cube-root procedure analogous to the\n; square-root procedure. (In section 1.3.4 we will see how to implement\n; Newton's method in general as an abstraction of these square-root and\n; cube-root procedures).\n\n(define (cube-root x)\n  (cube-root-iter 1.0 x))\n\n(define (cube-root-iter guess x)\n  (if (good-enough? guess x)\n    guess\n    (cube-root-iter (improve guess x)\n               x)))\n\n(define (good-enough? guess x)\n  (< (abs (- (cube guess) x)) 0.001))\n\n(define (cube x)\n  (* x x x))\n\n(define (improve guess x)\n  (/ (+ (/ x (* guess guess))\n        (* 2 guess))\n     3))\n"
  },
  {
    "path": "scheme/sicp/01/09.scm",
    "content": "; SICP exercise 1.09\n;\n; Each of the following two procedures defines a method for adding two positive\n; integers in terms of the procedures inc, which increments its argument by 1,\n; and dec, which decrements its argument by 1.\n;\n; (define (+ a b)\n;   (if (= a 0)\n;       b\n;       (inc (+ (dec a) b))))\n;\n; (define (+ a b)\n;   (if (= a 0)\n;       b\n;       (+ (dec a) (inc b))))\n;\n; Using the substitution model, illustrate the process generated by each\n; procedure in evaluating (+ 4 5). Are these processes iterative or recursive?\n\n; The first one expans as follows:\n;\n; (+ 4 5)\n; (inc (+ 3 5))\n; (inc (inc (+ 2 5)))\n; (inc (inc (inc (+ 1 5))))\n; (inc (inc (inc (inc (+ 0 5)))))\n; (inc (inc (inc (inc 5))))\n; (inc (inc (inc 6)))\n; (inc (inc 7))\n; (inc 8)\n; 9\n;\n; This is obviously a recursive process.\n;\n; The seconds expands as follows:\n;\n; (+ 4 5)\n; (+ 3 6)\n; (+ 2 7)\n; (+ 1 8)\n; (+ 0 9)\n; 9\n;\n; This, in in turn, is obviously an iterative process.\n"
  },
  {
    "path": "scheme/sicp/01/10.scm",
    "content": "; SICP exercise 1.10\n;\n; The following procedure computes a mathematical function called Ackermann's\n; function:\n;\n; (define (A x y)\n;   (cond ((= y 0) 0)\n;         ((= x 0) (* 2 y))\n;         ((= y 1) 2)\n;         (else (A (- x 1)\n;                  (A x (- y 1))))))\n;\n; What are the values of the following expressions?\n;\n; (A 1 10)\n;\n; (A 2 4)\n;\n; (A 3 3)\n;\n; Consider the following procedures, where A is the procedure defined above:\n;\n; (define (f n) (A 0 n))\n;\n; (define (g n) (A 1 n))\n;\n; (define (h n) (A 2 n))\n;\n; (define (k n) (* 5 n n))\n;\n; Give consice mathematical definition for the functions computed by the procedures f, g and h\n; for positive integer values of n. For example, (k n) computes 5n².\n\n; (A 1 10)\n; (A 0 (A 1 9))\n; (A 0 (A 0 (A 1 8)))\n; (A 0 (A 0 (A 0 (A 1 7))))\n; (A 0 (A 0 (A 0 (A 0 (A 1 6)))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 5))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 4)))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 3))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 2)))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 1))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 2)))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 4))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 8)))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 16))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 32)))))\n; (A 0 (A 0 (A 0 (A 0 64))))\n; (A 0 (A 0 (A 0 128)))\n; (A 0 (A 0 256))\n; (A 0 512)\n; 1024\n;\n; (A 2 4)\n; (A 1 (A 2 3))\n; (A 1 (A 1 (A 2 2)))\n; (A 1 (A 1 (A 1 (A 2 1))))\n; (A 1 (A 1 (A 1 2)))\n; (A 1 (A 1 (A 0 (A 1 1))))\n; (A 1 (A 1 (A 0 2)))\n; (A 1 (A 1 4))\n; (A 1 (A 0 (A 1 3)))\n; (A 1 (A 0 (A 0 (A 1 2))))\n; (A 1 (A 0 (A 0 (A 0 (A 1 1)))))\n; (A 1 (A 0 (A 0 (A 0 2))))\n; (A 1 (A 0 (A 0 4)))\n; (A 1 (A 0 8))\n; (A 1 16)\n; (A 0 (A 1 15))\n; (A 0 (A 0 (A 1 14)))\n; (A 0 (A 0 (A 0 (A 1 13))))\n; (A 0 (A 0 (A 0 (A 0 (A 1 12)))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 11))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 10)))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 9))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 8)))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 7))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 6)))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 5))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 4)))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 3))))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 2)))))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 1))))))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 2)))))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 4))))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 8)))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 16))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 32)))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 64))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 128)))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 256))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 512)))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 1024))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 2048)))))\n; (A 0 (A 0 (A 0 (A 0 4096))))\n; (A 0 (A 0 (A 0 8192)))\n; (A 0 (A 0 16384))\n; (A 0 32768)\n; 65536\n;\n; (A 3 3)\n; (A 2 (A 3 2))\n; (A 2 (A 2 (A 3 1)))\n; (A 2 (A 2 2))\n; (A 2 (A 1 (A 2 1)))\n; (A 2 (A 1 2))\n; (A 2 (A 0 (A 1 1)))\n; (A 2 (A 0 2))\n; (A 2 4)\n; (A 1 (A 2 3))\n; (A 1 (A 1 (A 2 2)))\n; (A 1 (A 1 (A 1 (A 2 1))))\n; (A 1 (A 1 (A 1 2)))\n; (A 1 (A 1 (A 0 (A 1 1))))\n; (A 1 (A 1 (A 0 2)))\n; (A 1 (A 1 4))\n; (A 1 (A 0 (A 1 3)))\n; (A 1 (A 0 (A 0 (A 1 2))))\n; (A 1 (A 0 (A 0 (A 0 (A 1 1)))))\n; (A 1 (A 0 (A 0 (A 0 2))))\n; (A 1 (A 0 (A 0 4)))\n; (A 1 (A 0 8))\n; (A 1 16)\n; (A 0 (A 1 15))\n; (A 0 (A 0 (A 1 14)))\n; (A 0 (A 0 (A 0 (A 1 13))))\n; (A 0 (A 0 (A 0 (A 0 (A 1 12)))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 11))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 10)))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 9))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 8)))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 7))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 6)))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 5))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 4)))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 3))))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 2)))))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 1))))))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 2)))))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 4))))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 8)))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 16))))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 32)))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 64))))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 128)))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 256))))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 512)))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 1024))))))\n; (A 0 (A 0 (A 0 (A 0 (A 0 2048)))))\n; (A 0 (A 0 (A 0 (A 0 4096))))\n; (A 0 (A 0 (A 0 8192)))\n; (A 0 (A 0 16384))\n; (A 0 32768)\n; 65536\n;\n; As for the defined functions.\n;\n; (define (f n) (A 0 n))\n; (define (g n) (A 1 n))\n; (define (h n) (A 2 n))\n;\n; (f n) is 2 * n\n; (g n) is 2 ^ n\n; (h n) is 2 ^ 2 ^ .. ^ 2 (n times)\n"
  },
  {
    "path": "scheme/sicp/01/11.scm",
    "content": "; SICP exercise 1.11\n;\n; A function f is defined by the rule that:\n;\n;     f(n) = n                            if n < 3\n;     f(n) = f(n-1) + 2f(n-2) + 3f(n-3)   if n ≥ 3\n;\n; Write a procedure that computes f by means of a recursive process. Write a\n; procedure that computes f by means of an iterative process.\n\n(define (f n)\n  (if (< n 3)\n    n\n    (+ (f (- n 1))\n       (* 2 (f (- n 2)))\n       (* 3 (f (- n 3))))))\n\n(define (f-iter n)\n  (define (iter a b c count)\n    (if (= count 0)\n        c\n        (iter (+ a (* 2 b) (* 3 c))\n              a\n              b\n              (- count 1))))\n\n  (iter 2 1 0 n))\n"
  },
  {
    "path": "scheme/sicp/01/12.scm",
    "content": "; SICP exercise 1.12\n;\n; The following pattern of numbers is called Pascal's triangle.\n;\n;       1\n;      1 1\n;     1 2 1\n;    1 3 3 1\n;   1 4 6 4 1\n;      ...\n;\n; The numbers at the edge of the triange are all 1, and each number inside the\n; triangle is the sum of the two numbers above it. Write a procedure that\n; computes the elements of Pascal's triangle by means of recursive process.\n\n(define (binom row index)\n  (cond ((= index 1) 1)\n        ((= index row) 1)\n        (else (+ (binom (- row 1) (- index 1))\n                 (binom (- row 1) index)))))\n"
  },
  {
    "path": "scheme/sicp/01/13.scm",
    "content": "; SICP exercise 1.13\n;\n; Prove that Fib(n) is the closest integer to 𝜙ⁿ/√5, where 𝜙 = (1 + √5)/2.\n;\n; Hint: Let 𝜓 = (1 - √5)/2. Use induction and the definition of Fibonacci numbers\n; (see section 1.2.2) to prove that Fib(n) = (𝜙ⁿ - 𝜓ⁿ)/√5\n\n; Seriously? Anyway...\n;\n; First, let's establish that |𝜓ⁿ| < ½ for n > 1. It holds, because:\n;\n; 𝜓 ≈ -0.61803\n; 𝜓² ≈ 0.38196\n;\n; As n grows, it converges to 0.\n;\n; Next, let's illustrate that 𝜓² = 𝜓 + 1:\n;\n; 𝜓² = (1 - √5)²/2² = (6 - 2√5)/4 = (3 - √5)/2 = 2/2 + (1 - √5)/2 = 1 + 𝜓\n;\n; Afterwards let's prove Fib(n) = (𝜙ⁿ - 𝜓ⁿ)/√5, using induction.\n;\n; Basis. We will show it holds true for n = 0 and n = 1.\n;\n; (𝜙⁰ - 𝜓⁰)/√5 = (1 - 1)/√5 = 0/√5 = 0 = Fib(0)\n; (𝜙 - 𝜓)/√5 = (1 + √5 - 1 + √5)/2√5 = 2√5/2√5 = 1 = Fib(1)\n;\n; Inductive step. We can assume that the following hold:\n;\n; (𝜙ⁿ - 𝜓ⁿ)/√5 = Fib(n)\n; (𝜙ⁿ⁺¹ - 𝜓ⁿ⁺¹)/√5 = Fib(n + 1)\n;\n; Let's prove that (𝜙ⁿ⁺² - 𝜓ⁿ⁺²)/√5 = Fib(n + 2).\n;\n; Fib(n + 2) = Fib(n + 1) + Fib(n) = (𝜙ⁿ⁺¹ - 𝜓ⁿ⁺¹)/√5 + (𝜙ⁿ - 𝜓ⁿ)/√5 =\n;            = (𝜙ⁿ⁺¹ + 𝜙ⁿ - 𝜓ⁿ⁺¹ - 𝜓ⁿ)/√5 = (𝜙ⁿ(𝜙 + 1) - 𝜓ⁿ(𝜓 + 1))/√5 =\n;            = (𝜙ⁿ⁺² - 𝜓ⁿ⁺²)/√5\n;\n; The only thing left is to relate (𝜙ⁿ - 𝜓ⁿ)/√5 to the statement we are\n; proving - Fib(n) is the closest integer to 𝜙ⁿ/√5.\n;\n; Fib(n) - 𝜙ⁿ/√5 = 𝜓ⁿ/√5\n;\n; We already know that 𝜓ⁿ/√5 is less than ½, which makes Fib(n) the closest\n; integer to 𝜙ⁿ/√5.\n"
  },
  {
    "path": "scheme/sicp/01/14.scm",
    "content": "; SICP exercise 1.14\n;\n; Draw the tree illustrating the process generated by the count-change\n; procedure of section 1.2.2 in making charge for 11 cents. What are the orders\n; of growth of the space and number of steps used by this process as the amount\n; to be changed increases.\n\n; The spaces grows in Θ(n), since the maximum depth of the tree is a function\n; of n (number-of-denominations + n / smallest-denomination + 1).\n;\n; I believe the time is Θ(aˣ), but I'm not certain. The amount of nodes seem to\n; roughly double every time we add 5 to n, but this is oversimplifying it (it\n; gets more complex when we start adding 50 in increments.\n;\n; And about draing a tree? In ASCII? Seriously? Meh, sure:\n;\n;                                                                                                                                                                (count-change 11 5)\n;                                                                                                                                                                         |\n;                                                                                                                                                               ._____(cc 11 5)_____.\n;                                                                                                                                                        ._____/                     \\_____.\n;                                                                                                                                   .___________(cc 11 4)__________.                        (cc -39 5)\n;                                                                                                                      .___________/                                \\____________.               |\n;                                                                                     ._______________________(cc 11 3)_______________________.                                   (cc -14 4)     0\n;                                                       .____________________________/                                                         \\________________________.             |\n;                                      .__________(cc 11 2)____________.                                                                                                 (cc 1 3)     0\n;                    .________________/                                 \\___________________.                                                                           /        \\\n;           (cc 11 1)                                                              ._________(cc 6 2)________.                                                  (cc 1 2)          (cc -9 3)\n;          /         \\                                                  ._________/                           \\_________.                                      /        \\             |\n; (cc 11 0)           (cc 10 1)                                 (cc 6 1)                                                 (cc 1 2)                      (cc 1 1)          (cc -4 2)    0\n;     |              /         \\                               /        \\                                               /        \\                    /        \\             |\n;     0     (cc 10 0)           (cc 9 1)               (cc 6 0)          (cc 5 1)                               (cc 1 1)          (cc -4 2)   (cc 0 1)          (cc 1 0)     0\n;               |              /        \\                  |            /        \\                             /        \\             |           |                 |\n;               0      (cc 9 0)          (cc 8 1)          0    (cc 5 0)          (cc 4 1)             (cc 1 0)          (cc 0 1)     0           0                 1\n;                          |            /        \\                  |            /        \\                |                 |\n;                          0    (cc 8 0)          (cc 7 1)          0    (cc 4 0)          (cc 3 1)        0                 1\n;                                   |            /        \\                  |            /        \\\n;                                   0    (cc 7 0)          (cc 6 1)          0    (cc 3 0)          (cc 2 1)\n;                                            |            /        \\                  |            /        \\\n;                                            0    (cc 6 0)          (cc 5 1)          0    (cc 2 0)          (cc 1 1)\n;                                                     |            /        \\                  |            /        \\\n;                                                     0    (cc 5 0)          (cc 4 1)          0    (cc 1 0)          (cc 0 1)\n;                                                              |            /        \\                  |                 |\n;                                                              0    (cc 4 0)          (cc 3 1)          0                 1\n;                                                                       |            /        \\\n;                                                                       0    (cc 3 0)          (cc 2 1)\n;                                                                                |            /        \\\n;                                                                                0    (cc 2 0)          (cc 1 1)\n;                                                                                         |            /        \\\n;                                                                                         0    (cc 1 0)          (cc 0 1)\n;                                                                                                  |                 |\n;                                                                                                  0                 1\n;\n; It fits my MacBook Pro screen like a boss\n"
  },
  {
    "path": "scheme/sicp/01/15.scm",
    "content": "; SICP exercise 1.15\n;\n; The sine of an angle (specified in radians) can be computed by making use of\n; the approximation sin(x) ≈ x if x is sufficiently small, and the\n; trigonometric identity\n;\n; sin(r) = 3sin(r/3) - 4sin³(r/3)\n;\n; to reduce the size of the argument of sin. (For purposes of this exercise an\n; angle is considered \"sufficiently small\" if its magnitude is not greater than\n; 0.1 radians.) These ideas are incorporated in the following procedures:\n;\n; (define (cube x) (* x x x))\n; (define (p x) (- (* 3 x) (* 4 (cube x))))\n; (define (sine angle)\n;   (if (not (> (abs angle) 0.1))\n;       angle\n;       (p (sine (/ angle 3.0)))))\n;\n; a. How many times is the procedure p applied when (sine 12.15) is evaluted?\n;\n; b. What is the order of growth in space and number of steps (as a function\n;    of a) used by the process generated by the sine procedure when (sine a)\n;    is evaluated?\n\n; This is how the function expands.\n;\n; (sine 12.15)\n; (p (sine 4.05))\n; (p (p (sine 1.35)))\n; (p (p (p (sine 0.45))))\n; (p (p (p (p (sine 0.15)))))\n; (p (p (p (p (p (sine 0.05))))))\n; (p (p (p (p (p 0.05)))))\n; (p (p (p (p 0.1495))))\n; (p (p (p 0.4351345505)))\n; (p (p 0.975846533167877))\n; (p -0.789563114470823)\n; -0.39980345741334\n;\n; As for the questions:\n;\n; a. p is applied 5 times for (sine 12.15), which also happens to be n / 3,\n;    rounded up.\n;\n; b. The space of (sine n) is n / 3. Its order of growth is Θ(n). The number of\n;   steps is (n / 3)C, where C is the number of steps it takes to calculate p\n;   once. The number of steps (time taken) has order of growth Θ(logn).\n"
  },
  {
    "path": "scheme/sicp/01/16.scm",
    "content": "; SICP exercise 1.16\n;\n; Design a procedure that evolves an iterative exponentiation process that uses\n; successive squaring and uses a logarithmic number of steps, as does\n; fast-expt.\n;\n; Hint: Using the observation that (b^(n/2))^2 = (b^2)^(n/2), keep along with\n; the exponent n and the base b, an additional state variable a, and define the\n; state transformation in such a way that the product ab^n is unchanged from\n; state to state. At the beginning of the process a is taken to be 1, and the\n; answer is given by the value of a at the end of the process. In general, the\n; technique of defining an invariant quantity that remains unchanged from state\n; to state is a powerful way to think about the design of iterative algorithms.\n\n(define (fast-expt base power)\n  (define (iter a b n)\n    (cond ((= n 0) a)\n          ((even? n) (iter a (* b b) (/ n 2)))\n          (else (iter (* a b) b (- n 1)))))\n\n  (iter 1 base power))\n"
  },
  {
    "path": "scheme/sicp/01/17.scm",
    "content": "; SICP exercise 1.17\n;\n; The exponentiation algorithms in this section are based on performing\n; exponentiation by means of repeated multiplication. In a similar way, one can\n; perform integer multiplication by means of repeated addition. The following\n; multiplication procedure (in which it is assumed that our language can only\n; add, not multiply) is analogous to the expt procedure.\n;\n; (define (* a b)\n;   (if (= b 0)\n;       0\n;       (+ add (* a (- b 1)))))\n;\n; This algorithm takes a number of steps that is linear in b. Now suppose we\n; include together with addition, operations double, which doubles an integer,\n; and halve, which divides an (even) integer by 2. Using these, design a\n; multiplication procedure analogous to fast-expt that uses a logarithmic\n; number of steps.\n\n(define (double a)\n  (+ a a))\n\n(define (halve a)\n  (/ a 2))\n\n(define (** a b)\n  (cond ((= b 0) 0)\n        ((even? b) (** (double a) (halve b)))\n        (else (+ a (** a (- b 1))))))\n"
  },
  {
    "path": "scheme/sicp/01/18.scm",
    "content": "; SICP exercise 1.18\n;\n; Using the results of exercises 1.16 and 1.17, devise a procedure that\n; generates an iterative process for multiplying two integers in terms of\n; adding, doubling and halving and uses a logarithmic number of steps.\n\n; Say we want to multiply a by b. We are going to do this iteratively and our\n; invariant quantitiy will be ab + c, with c initially being 0. We iteratively\n; apply the following transformations:\n;\n; ab + c = { 2a(b/2) + c       if b is even\n;          { a(b-1) + a + c    if b is odd\n;\n; We conclude the result is c when b is zero.\n\n(define (double a)\n  (+ a a))\n\n(define (halve a)\n  (/ a 2))\n\n(define (** a b)\n  (define (iter a b c)\n    (cond ((= b 0) c)\n          ((even? b) (iter (double a) (halve b) c))\n          (else (iter a (- b 1) (+ a c)))))\n\n  (iter a b 0))\n"
  },
  {
    "path": "scheme/sicp/01/19.scm",
    "content": "; SICP exercise 1.19\n;\n; There is a clever algorithm for computing the Fibonacci numbers in a\n; logarithmic number of steps. Recall the transformation of the state variables\n; a and b in the fib-iter process of section 1.2.2: a ← a + b and b ← a. Call\n; this transformation T, and observe that applying T over and over again n\n; times, starting with 1 and 0, produces the pair Fib(n+1) and Fib(n). In other\n; words, the Fibonacci numbers are produced by applying Tⁿ, the nth power of\n; the transformation T, starting with the pair (1, 0). Now consider T to be the\n; special case of p = 0 and q = 1 in a family of transformations T(p,q), where\n; T(p,q) transforms the pair (a,b) according to a ← bq + aq + ap and\n; b ← bp + aq. Show that if we apply such a transformation T(p,q) twice, the\n; effect is the same as using a single transformation T(p',q') of the same\n; form, and compute p' and q' in terms of p and q.\n;\n; This gives us an explicit way to square these transformations, and thus we\n; can compute Tⁿ using successive squaring, as in the fast-expt procedure. Put\n; this all together to complete the following procedure, which runs in a\n; logarithmic number of steps.\n;\n; (define (fib n)\n;   (fib-iter 1 0 0 1 n))\n;\n; (define (fib-iter a b p q count)\n;   (cond ((= count 0) b)\n;         ((even? count) (fib-iter a\n;                                  b\n;                                  <??>   ; compute p'\n;                                  <??>   ; compute q'\n;                                  (/ count 2)))\n;         (else (fib-iter (+ (* b q) (* a q) (* a p))\n;                         (+ (* b p) (* a q))\n;                         p\n;                         q\n;                         (- count 1)))))\n\n; Here are some inferences:\n;\n; After T(p,q)\n;\n; a = bq + aq + ap\n; b = bp + aq\n;\n; If we apply T(p,q) again, we get:\n;\n; a = bpq + aqq + bqq + aqq + apq + bpq + apq + app\n; b = bpp + apq + bqq + aqq + apq\n;\n; If we normalize it:\n;\n; a = 2bpq + bq² + 2aq² + 2apq + ap²\n; b = bp² + bq² + 2apq + aq²\n;\n; If we group it:\n;\n; a = b(q² + 2pq) + a(q² + 2pq) + a(p² + q²)\n; b = b(p² + q²) + a(q² + 2pq)\n;\n; Clearly:\n;\n; p' = p² + q²\n; q' = q² + 2pq\n\n(define (fib n)\n  (fib-iter 1 0 0 1 n))\n\n(define (fib-iter a b p q count)\n  (cond ((= count 0) b)\n        ((even? count) (fib-iter a\n                                 b\n                                 (+ (* p p) (* q q))\n                                 (+ (* q q) (* 2 p q))\n                                 (/ count 2)))\n        (else (fib-iter (+ (* b q) (* a q) (* a p))\n                        (+ (* b p) (* a q))\n                        p\n                        q\n                        (- count 1)))))\n"
  },
  {
    "path": "scheme/sicp/01/20.scm",
    "content": "; SICP exercise 1.20\n;\n; The process that a procedures generates is of course dependent on the rules\n; used by the interpreter. As an example, consider the iterative gcd procedure\n; given above. Suppose we were to interpret this procedure using normal-order\n; evaluation, as discussed in section 1.1.5. (The normal-order-evaluation rule\n; for if is described in exercise 1.5.) Using the substitution method (for\n; normal order), illustrate the process generated in evaluating (gcd 206 40)\n; and indicate the remainder operations that are actually performed. How many\n; remainder operations are actually performed in the normal-order evaluation of\n; (gcd 206 40)? In the applicative-order evaluation?\n\n; The procedure is:\n;\n; (define (gcd a b)\n;   (if (= b 0)\n;       a\n;       (gcd b (remainder a b))))\n;\n; I am going to abbreviate (remainder a b) to (r a b) to keep things managable.\n;\n; Using normal-order evaluation, we take the following steps:\n;\n; (gcd 206 40)\n; (if (= 40 0) 206 (gcd 40 (r 206 40)))\n; (gcd 40 (r 206 40))\n; (if (= (r 206 40) 0) 40 (gcd (r 206 40) (r 40 (r 206 40))))\n; (if (= 6 0) 40 (gcd (r 206 40) (r 40 (r 206 40))))\n; (gcd (r 206 40) (r 40 (r 206 40)))\n; (if (= (r 40 (r 206 40)) 0) (r 206 40) (gcd (r 40 (r 206 40)) (r (r 206 40) (r 40 (r 206 40)))))\n; (if (= (r 40 6) 0) (r 206 40) (gcd (r 40 (r 206 40)) (r (r 206 40) (r 40 (r 206 40)))))\n; (if (= 4 0) (r 206 40) (gcd (r 40 (r 206 40)) (r (r 206 40) (r 40 (r 206 40)))))\n; (gcd (r 40 (r 206 40)) (r (r 206 40) (r 40 (r 206 40))))\n; (if (= (r (r 206 40) (r 40 (r 206 40))) 0) (r 40 (r 206 40)) (gcd (r (r 206 40) (r 40 (r 206 40))) (r (r 40 (r 206 40)) (r (r 206 40) (r 40 (r 206 40))))\n; ...\n;\n; If we just take a look at each iteration, we see:\n;\n; (gcd 206 40)\n; (gcd 40 (r 206 40))\n; (gcd (r 206 40) (r 40 (r 206 40)))\n; (gcd (r 40 (r 206 40)) (r (r 206 40) (r 40 (r 206 40))))\n; (gcd (r (r 206 40) (r 40 (r 206 40))) (r (r 40 (r 206 40)) (r (r 206 40) (r 40 (r 206 40)))))\n; (r (r 206 40) (r 40 (r 206 40)))\n;\n; On each step we calculate b and then we calculate the final a. Thus, we use\n; 18 remainder operations.\n;\n; Using applicative order-evaluation, we take the following steps\n;\n; (gcd 206 40)\n; (gcd 40 (r 206 40))\n; (gcd 6 (r 40 6))\n; (gcd 4 (r 6 4))\n; (gcd 2 (r 4 2))\n; 2\n;\n; We end up using 4 remainder operations.\n"
  },
  {
    "path": "scheme/sicp/01/21.scm",
    "content": "; SICP exercise 1.21\n;\n; Use the smallest-divisor procedure to find the smallest divisor of each of\n; the following numbers: 199, 1999, 19999.\n\n(define (smallest-divisor n)\n  (find-divisor n 2))\n\n(define (find-divisor n test-divisor)\n  (cond ((> (square test-divisor) n) n)\n        ((divides? test-divisor n) test-divisor)\n        (else (find-divisor n (+ test-divisor 1)))))\n\n(define (square a)\n  (* a a))\n\n(define (divides? a b)\n  (= (remainder b a) 0))\n\n(printf \"(smallest divisor of 199)   is ~a\\n\" (smallest-divisor 199))   ; 199\n(printf \"(smallest divisor of 1999   is ~a\\n\" (smallest-divisor 1999))  ; 1999\n(printf \"(smallest divisor of 19999) is ~a\\n\" (smallest-divisor 19999)) ; 7\n"
  },
  {
    "path": "scheme/sicp/01/22.scm",
    "content": "; SICP exercise 1.22\n;\n; Most Lisp implementations include a primitve called runtime that returns an\n; integer that specifies the amount of time the system has been running\n; (measured, for example, in microseconds). The following timed-prime-test\n; procedures, when called with an integer n, prints n and checks to see if n is\n; prime. If n is prime, the procedure prints three asterisks followed by the\n; amount of time used in performing the test.\n;\n; (define (timed-prime-test n)\n;   (newline)\n;   (display n)\n;   (start-prime-test n (runtime)))\n;\n; (define (start-prime-test n start-time)\n;   (if (prime? n)\n;       (report-prime (- (runtime) start-time))))\n;\n; (define (report-prime elapsed-time)\n;   (display \" *** \")\n;   (display elapsed-time)\n;\n; Using this procedure, write a procedure search-for-primes that checks the\n; primality of consecutive odd integers in a specified range. Use your\n; procedure to find the three smallest primes larger than 1000; larger than\n; 10,000; larger than 100,000; larger than 1,000,000. Note the time neeed to\n; test each prime. Since the testing algorithm has order of growth Θ(√n), you\n; should expect that testing for primes around 10,000 should take about √10\n; times as long as testing for primes around 1000. Do your timing data bear\n; this out? How well do the data for testing for 100,000 and 1,000,000 support\n; the √n prediction? Is your result compatible with the notion that programs on\n; your machine run in time proportional to the number of steps required in the\n; computation?\n\n; Here are the numbers:\n;\n; 1009, 1013, 1019, 10007, 10009, 10037, 100003, 100019, 100043, 1000003,\n; 1000033, 1000037\n;\n; Here is the time it takes to see if they are prime on my computer:\n;\n; 1009 *** 0.001953125\n; 1013 *** 0.001953125\n; 1019 *** 0.0029296875\n; 10007 *** 0.0068359375\n; 10009 *** 0.007080078125\n; 10037 *** 0.007080078125\n; 100003 *** 0.018798828125\n; 100019 *** 0.01806640625\n; 100043 *** 0.01904296875\n; 1000003 *** 0.055908203125\n; 1000033 *** 0.055908203125\n; 1000037 *** 0.055908203125\n;\n; Even with numbers as 1,000,000, it is easily illustrated that the √n\n; prediction is true. Programs do run in time proportional to the number of\n; steps required in the computation, at least on this machine. Just run the\n; program to verify.\n;\n; I wonder if some day I will run this on a machine, that will show different\n; results.\n\n(define (timed-prime-test n)\n  (newline)\n  (display n)\n  (start-prime-test n (runtime)))\n\n(define (start-prime-test n start-time)\n  (if (prime? n)\n      (report-prime (- (runtime) start-time))\n      (void)))\n\n(define (runtime)\n  (current-inexact-milliseconds))\n\n(define (report-prime elapsed-time)\n  (display \" *** \")\n  (display elapsed-time))\n\n\n\n(define (prime? n)\n  (= n (smallest-divisor n)))\n\n(define (smallest-divisor n)\n  (find-divisor n 2))\n\n(define (find-divisor n test-divisor)\n  (cond ((> (square test-divisor) n) n)\n        ((divides? test-divisor n) test-divisor)\n        (else (find-divisor n (+ test-divisor 1)))))\n\n(define (square a)\n  (* a a))\n\n(define (divides? a b)\n  (= (remainder b a) 0))\n\n\n\n(define (search-for-primes lower-limit)\n  (newline)\n  (define (iter n number)\n    (cond ((= n 0) 0)\n          ((prime? number)\n            (display number)\n            (newline)\n            (iter (- n 1) (+ number 1)))\n          (else (iter n (+ number 1)))))\n\n  (iter 3 lower-limit))\n\n\n\n(search-for-primes 1000)\n(search-for-primes 10000)\n(search-for-primes 100000)\n(search-for-primes 1000000)\n\n(timed-prime-test 1009)\n(timed-prime-test 1013)\n(timed-prime-test 1019)\n\n(timed-prime-test 10007)\n(timed-prime-test 10009)\n(timed-prime-test 10037)\n\n(timed-prime-test 100003)\n(timed-prime-test 100019)\n(timed-prime-test 100043)\n\n(timed-prime-test 1000003)\n(timed-prime-test 1000033)\n(timed-prime-test 1000037)\n"
  },
  {
    "path": "scheme/sicp/01/23.scm",
    "content": "; SICP exercise 1.23\n;\n; The smallest-divisor procedure shown at the start of this section does lots\n; of needless testing: After it checks to see if the number is divisible by 2\n; there is no pint in checking to see if it is divisible by any larger even\n; numbers.  This suggests that the values used for test-divisor should not be\n; 2, 3, 4, 5, 6, ..., but rather 2, 3, 5, 7, 9, .... To implement this change,\n; define a procedure next that returns 3 if its input is equal to 2 and\n; otherwise returns its input plus 2. Modify the smallest-divisor procedure to\n; use (next test-divisor) instead of (+ test-divisor 1). With timed-prime-test\n; incorporating this modified version of smallest-divisor, run the test for\n; each of the 11 primes found in exercise 1.22. Since this modification halves\n; the number of test steps, you should expect it to run about twice as fast. Is\n; this expectation confirmed? If not, what is the observed ratio of the speeds\n; of the two algorithms and how do you explain the fact that it is different\n; from 2?\n\n; Let's compare the numbers:\n;\n; +---------+----------------+----------------+\n; | Number  | (+ divisor 1)  | (next divisor) |\n; +---------+----------------+----------------+\n; | 1009    | 0.001953125000 | 0.001953125000 |\n; | 1013    | 0.001953125000 | 0.001953125000 |\n; | 1019    | 0.002929687500 | 0.001953125000 |\n; | 10007   | 0.006835937500 | 0.004150390625 |\n; | 10009   | 0.007080078125 | 0.005126953125 |\n; | 10037   | 0.007080078125 | 0.004150390625 |\n; | 100003  | 0.018798828125 | 0.012939453125 |\n; | 100019  | 0.018066406250 | 0.011962890625 |\n; | 100043  | 0.019042968750 | 0.011962890625 |\n; | 1000003 | 0.055908203125 | 0.035888671875 |\n; | 1000033 | 0.055908203125 | 0.035888671875 |\n; | 1000037 | 0.055908203125 | 0.036132812500 |\n; +---------+----------------+----------------+\n;\n; The ratio is between 3/2 and 2. We can approximate it to 3/2. We get less\n; than 2, because even if we halve the steps, we add an additional overhead for\n; each step - testing whether the number is 2.\n\n(define (next test-divisor)\n  (if (= test-divisor 2)\n      3\n      (+ test-divisor 2)))\n\n(define (prime? n)\n  (= n (smallest-divisor n)))\n\n(define (smallest-divisor n)\n  (find-divisor n 2))\n\n(define (find-divisor n test-divisor)\n  (cond ((> (square test-divisor) n) n)\n        ((divides? test-divisor n) test-divisor)\n        (else (find-divisor n (next test-divisor)))))\n\n(define (square a)\n  (* a a))\n\n(define (divides? a b)\n  (= (remainder b a) 0))\n\n\n\n(define (timed-prime-test n)\n  (newline)\n  (display n)\n  (start-prime-test n (runtime)))\n\n(define (start-prime-test n start-time)\n  (if (prime? n)\n      (report-prime (- (runtime) start-time))\n      (void)))\n\n(define (runtime)\n  (current-inexact-milliseconds))\n\n(define (report-prime elapsed-time)\n  (display \" *** \")\n  (display elapsed-time))\n\n\n\n(timed-prime-test 1009)\n(timed-prime-test 1013)\n(timed-prime-test 1019)\n\n(timed-prime-test 10007)\n(timed-prime-test 10009)\n(timed-prime-test 10037)\n\n(timed-prime-test 100003)\n(timed-prime-test 100019)\n(timed-prime-test 100043)\n\n(timed-prime-test 1000003)\n(timed-prime-test 1000033)\n(timed-prime-test 1000037)\n"
  },
  {
    "path": "scheme/sicp/01/24.scm",
    "content": "; SICP exercise 1.24\n;\n; Modify the timed-prime-test procedure of exercise 1.22 to use fast-prime?\n; (the Fermat method), and test each of the 12 primes you found in that\n; exercise. Since the Fermat test has Θ(logn) growth, how would you expect the\n; time to test primes near 1,000,000 to compare with the time needed to test\n; primes near 1000? Do your data bear this out? Can you explain any discrepancy\n; you find?\n\n; Let's elaborate on the numbers we already have:\n;\n; +---------+----------------+----------------+----------------+\n; | Number  | (+ divisor 1)  | (next divisor) | fermat test    |\n; +---------+----------------+----------------+----------------+\n; | 1009    | 0.001953125000 | 0.001953125000 | 0.010009765625 |\n; | 1013    | 0.001953125000 | 0.001953125000 | 0.010009765625 |\n; | 1019    | 0.002929687500 | 0.001953125000 | 0.010009765625 |\n; | 10007   | 0.006835937500 | 0.004150390625 | 0.012207031250 |\n; | 10009   | 0.007080078125 | 0.005126953125 | 0.011962890625 |\n; | 10037   | 0.007080078125 | 0.004150390625 | 0.011962890625 |\n; | 100003  | 0.018798828125 | 0.012939453125 | 0.014160156250 |\n; | 100019  | 0.018066406250 | 0.011962890625 | 0.013916015625 |\n; | 100043  | 0.019042968750 | 0.011962890625 | 0.013916015625 |\n; | 1000003 | 0.055908203125 | 0.035888671875 | 0.015869140625 |\n; | 1000033 | 0.055908203125 | 0.035888671875 | 0.015869140625 |\n; | 1000037 | 0.055908203125 | 0.036132812500 | 0.015869140620 |\n; +---------+----------------+----------------+----------------+\n;\n; I expect fast-prime? to be faster. The growth is as I expected. I am\n; surprised that it is slower for smaller numbers.\n;\n; I have two problems with this exercise: (1) they complete too quickly on\n; modern architectures and (2) (random) is limited to integers, which we\n; quickly run out of before the execution times start getting interesting.\n\n(define (expmod base exp m)\n  (cond ((= exp 0) 1)\n        ((even? exp)\n         (remainder (square (expmod base (/ exp 2) m))\n                    m))\n        (else\n         (remainder (* base (expmod base (- exp 1) m))\n                    m))))\n\n(define (square n)\n  (* n n))\n\n(define (fermat-test n)\n  (define (try-it a)\n    (= (expmod a n n) a))\n  (try-it (+ 1 (random (- n 1)))))\n\n(define (fast-prime? n times)\n  (cond ((= times 0) true)\n        ((fermat-test n) (fast-prime? n (- times 1)))\n        (else false)))\n\n\n\n(define (timed-prime-test n)\n  (newline)\n  (display n)\n  (start-prime-test n (runtime)))\n\n(define (start-prime-test n start-time)\n  (if (fast-prime? n 1)\n      (report-prime (- (runtime) start-time))\n      (void)))\n\n(define (runtime)\n  (current-inexact-milliseconds))\n\n(define (report-prime elapsed-time)\n  (display \" *** \")\n  (display elapsed-time))\n\n\n\n(timed-prime-test 1009)\n(timed-prime-test 1013)\n(timed-prime-test 1019)\n\n(timed-prime-test 10007)\n(timed-prime-test 10009)\n(timed-prime-test 10037)\n\n(timed-prime-test 100003)\n(timed-prime-test 100019)\n(timed-prime-test 100043)\n\n(timed-prime-test 1000003)\n(timed-prime-test 1000033)\n(timed-prime-test 1000037)\n"
  },
  {
    "path": "scheme/sicp/01/25.scm",
    "content": "; SICP exercise 1.25\n;\n; Allysa P. Hacker complains that we went to a lot of extra work in writing\n; expmod. After all, she says, since we already know how to compute exponents,\n; we could have simply written\n;\n; (define (expmod base exp m)\n;   (remainder (fast-expt base exp) m))\n;\n; Is she correct? Would this procedure serve as well for our fast prime tester?\n; Explain.\n\n; She is correct. We can define expmod that way and it would certainly return\n; correct results. However, it will not deserve being called \"fast-prime?\",\n; since it quickly becomes dramatically slower. Here is a comparison:\n;\n; +----------------+--------------------+\n; | exercise 24    | exercise 25        |\n; +----------------+--------------------+\n; | 0.101074218750 |     0.751953125000 |\n; | 0.004150390625 |     0.282958984375 |\n; | 0.002929687500 |     0.229980468750 |\n; | 0.003173828125 |     7.984863281250 |\n; | 0.004150390625 |    10.800781250000 |\n; | 0.003173828125 |     5.987060546875 |\n; | 0.077880859375 |   419.326904296875 |\n; | 0.024169921875 |   460.801025390625 |\n; | 0.022949218750 |   401.984130859375 |\n; | 0.028076171875 | 12811.398193359375 |\n; | 0.020019531250 | 15219.705078125000 |\n; | 0.028076171870 | 18424.709228515620 |\n; +----------------+--------------------+\n;\n; This happens, because we end up calculating exponents with very large numbers\n; Multiplication and division is particularly slow with those. Allysa's expmod\n; quickly starts multiplying them, while the one we wrote goes into great\n; lengths of avoiding it.\n\n(define (fast-expt base power)\n  (define (iter a b n)\n    (cond ((= n 0) a)\n          ((even? n) (iter a (* b b) (/ n 2)))\n          (else (iter (* a b) b (- n 1)))))\n\n  (iter 1 base power))\n\n(define (expmod base exp m)\n  (remainder (fast-expt base exp) m))\n\n(define (square n)\n  (* n n))\n\n(define (fermat-test n)\n  (define (try-it a)\n    (= (expmod a n n) a))\n  (try-it (+ 1 (random (- n 1)))))\n\n(define (fast-prime? n times)\n  (cond ((= times 0) true)\n        ((fermat-test n) (fast-prime? n (- times 1)))\n        (else false)))\n\n\n\n(define (timed-prime-test n)\n  (newline)\n  (display n)\n  (start-prime-test n (runtime)))\n\n(define (start-prime-test n start-time)\n  (if (fast-prime? n 1)\n      (report-prime (- (runtime) start-time))\n      (void)))\n\n(define (runtime)\n  (current-inexact-milliseconds))\n\n(define (report-prime elapsed-time)\n  (display \" *** \")\n  (display elapsed-time))\n\n\n\n(timed-prime-test 1009)\n(timed-prime-test 1013)\n(timed-prime-test 1019)\n\n(timed-prime-test 10007)\n(timed-prime-test 10009)\n(timed-prime-test 10037)\n\n(timed-prime-test 100003)\n(timed-prime-test 100019)\n(timed-prime-test 100043)\n\n(timed-prime-test 1000003)\n(timed-prime-test 1000033)\n(timed-prime-test 1000037)\n"
  },
  {
    "path": "scheme/sicp/01/26.scm",
    "content": "; SICP exercise 1.26\n;\n; Louis Reasoner is having great difficulty doing exercise 1.24. His\n; fast-prime?  test seems to run more slowly than his prime? test. Louis calls\n; his friend Eva Lu Ator over to help. When they examine Louis's code, they\n; find that he has rewritten the expmod procedure to use an explicit\n; multiplication, rather than calling square:\n;\n; (define (expmod base exp m)\n;   (cond ((= exp 0) 1)\n;         ((even? exp)\n;          (remainder (* (expmod base (/ exp 2) m)\n;                        (expmod base (/ exp 2) m))\n;                     m))\n;         (else\n;          (remainder (* base (expmod base\n;                                     (- exp 1)\n;                                     m))\n;                     m))))\n;\n; \"I don't see what difference that could make\", says Louis. \"I do.\" says Eva.\n; \"By writing the procedure like that, you have transformed the Θ(logn) process\n; into a Θ(n) process.\" Explain.\n\n; It is quite similar to the recursive fibonacci. The expmod function halves m\n; on every iteration, which would lead to Θ(logn). However, it does perform\n; expmod twice, which in turn doubles the work on every step. This leads to\n; an Θ(n) order of growth.\n"
  },
  {
    "path": "scheme/sicp/01/27.scm",
    "content": "; SICP exercise 1.27\n;\n; Demonstrate that the Carmichael numbers listed in footnote 1.17 really do\n; fool the Fermat test. That is, write a procedure that takes an integer n and\n; tests whether aⁿ is congruent to a modulo n for every a < n, and try your\n; procedure on the given Carmichael numbers.\n\n; Just use the function carmichael?, although do note, that it should be named\n; carmichael-or-prime?\n\n(define (carmichael? number)\n  (define (congruent-to-number-below a)\n    (cond ((= a 1) #t)\n          ((= (expmod a number number) (remainder a number))\n           (congruent-to-number-below (- a 1)))\n          (else #f)))\n\n  (congruent-to-number-below (- number 1)))\n\n(define (expmod base exp m)\n  (cond ((= exp 0) 1)\n        ((even? exp)\n         (remainder (square (expmod base (/ exp 2) m))\n                    m))\n        (else\n         (remainder (* base (expmod base (- exp 1) m))\n                    m))))\n\n(define (square n)\n  (* n n))\n"
  },
  {
    "path": "scheme/sicp/01/28.scm",
    "content": "; SICP exercise 1.28\n;\n; One variant of the Fermat test that cannot be fooled is called the\n; Miller-Rabin test. This starts from an alternate form of Fermat's Little\n; Theorem, which states that if n is a prime number and a is any positive\n; integer less than n, then a raised to the (n - 1)-st power is congruent to 1\n; modulo n. To test the primality of a number n by the Miller-Rabin test, we\n; pick a random number a < n and raise a to the (n - 1)-st power module n using\n; the expmod procedure. However, whenever we perform the squaring step in\n; expmod, we check to see if we have discovered a \"nontrivial square root of 1\n; modulo n,\" that is, a number not equal to 1 or n - 1 whose square is equal to\n; 1 modulo n. It is possible to prove that if such a nontrivial square root of\n; 1 exists, then n is not prime. It is also possible to prove that if n is an\n; odd number that is not prime, then, for at least half of the numbers a < n,\n; computing aⁿ⁻¹ in this way will reveal a nontrivial square root of 1 modulo\n; n. (This is why the Miller-Rabin test cannot be fooled.) Modify the expmod\n; procedure to signal if it discovers a nontrivial square root of 1, and use\n; this to implement the Miller-Rabin test with a procedure analogous to\n; fermat-test. Check your procedure by testing various known primes and\n; non-primes. Hint: One convenient way to make expmod singal is to have it\n; return 0.\n\n; Changing the algorithm produces produces results I did not expect.\n;\n; Let's take a look at the amount of numbers a, such that a < n, for which aⁿ⁻¹\n; is congruent to 1 modulo n. If n is prime, this is true for all numbers\n; 1 < a < n. I expected that to be true for Carmichael numbers, but I turned\n; out to be wrong - it's not all numbers, but a fairly large percent of them.\n; For example, if n = 66011, for approximatelly 80% of the numbers a < n, aⁿ⁻¹\n; is congruent to 1 modulo n. The large the percentage, the more likely the\n; test will be fooled.\n;\n; However, if we introduce the check for non-trivial square root of 1 modulo n,\n; the amount of numbers that fool the test drops dramatically. Here's a table\n; for the Carmichael numbers in said footnote:\n;\n; +------+-----------+----------+\n; | n    | w/o sqrt1 | w/ sqrt1 |\n; +------+-----------+----------+\n; | 561  |       57% |       2% |\n; | 1105 |       70% |       3% |\n; | 1729 |       75% |       9% |\n; | 2465 |       73% |       3% |\n; | 2821 |       77% |      10% |\n; | 6601 |       80% |       5% |\n; +------+-----------+----------+\n;\n; Anyway, here's the code. I cannot shake the feeling that I am getting\n; something wrong.\n\n(define (fast-prime? n times)\n  (cond ((= times 0) true)\n        ((miller-rabin-test n) (fast-prime? n (- times 1)))\n        (else false)))\n\n(define (miller-rabin-test n)\n  (define (try-it a)\n    (= (miller-rabin-expmod a (- n 1) n) 1))\n  (try-it (+ 1 (random (- n 1)))))\n\n(define (miller-rabin-expmod base exp m)\n  (cond ((= exp 0) 1)\n        ((even? exp)\n         (remainder (square \n                      (zero-if-non-trivial-sqrt \n                        (miller-rabin-expmod base (/ exp 2) m)\n                        m))\n                    m))\n        (else\n         (remainder (* base (miller-rabin-expmod base (- exp 1) m))\n                    m))))\n\n(define (square n)\n  (* n n))\n\n(define (zero-if-non-trivial-sqrt x n)\n  (if (and (not (= x 1))\n           (not (= x (- n 1)))\n           (= (remainder (square x) n) 1))\n      0\n      x))\n"
  },
  {
    "path": "scheme/sicp/01/29.scm",
    "content": "; SICP exercise 1.29\n;\n; Simpson's Rule is a more accurate method of numerical integration than the\n; method illustrated above. Using Simpson's Rule, the integral of a function f\n; between a and b is approximated as\n;\n; h\n; ─(y₀ + 4y₁ + 2y₂ + 4y₃ + 2y₄ + ... + 2yₙ₋₂ + 4yₙ₋₁ + yₙ)\n; 3\n;\n; where h = (b - a)/n, for some even integer n, and yₖ = f(a + kh). (Increasing\n; n increases the accuracy of the approximation.) Define a procedure that takes\n; as arguments f, a, b and n and returns the value of the integral, computed\n; using Simpson's Rule. Use your procedure to integrate cube between 0 and 1\n; (with n = 100 and n = 1000), and compare the results to those of the integral\n; procedure shown above.\n\n; Implementing the integral with Simpson's Rule is easy. Check it out below.\n; Comparing the results to integral, however, appears way harder. The results\n; do not match my expectation, at least. Here's what I get from integral:\n;\n; +----------------+---------------------+---------------------+\n; | Iterations     | integral            | simpson-integral    |\n; +----------------+---------------------+---------------------+\n; |   100   (0.01) | 0.24998750000000042 | 0.24671666666666678 |\n; |  1000  (0.001) | 0.24999987500000100 | 0.24966716666666610 |\n; | 10000 (0.0001) | 0.24999999874993412 | 0.24996667166666647 |\n; +----------------+---------------------+---------------------+\n;\n; I have no idea why it doesn't match my expectation.\n\n(define (simpson-integral f a b n)\n  (define h (/ (- b a) n))\n  (define (next k)\n    (+ 1 k))\n  (define (coefficient k)\n    (cond ((= k 0) 1)\n          ((= k n) 1)\n          ((odd? k) 2)\n          (else 4)))\n  (define (term k)\n    (* (coefficient k)\n       (f (+ a (* k h)))))\n  (* (/ h 3)\n     (sum term 0 next n)))\n\n(define (sum term a next b)\n  (if (> a b)\n      0\n      (+ (term a)\n         (sum term (next a) next b))))\n\n(define (integral f a b dx)\n  (define (add-dx x) (+ x dx))\n  (* (sum f (+ a (/ dx 2.0)) add-dx b) dx))\n\n(define (cube x)\n  (* x x x))\n"
  },
  {
    "path": "scheme/sicp/01/30.scm",
    "content": "; SICP exercise 1.30\n;\n; The sum procedure above generates a linear recursion. The procedure can be\n; rewritten so that the sum is performed iteratively. Show how to do this\n; by filling in the missing expressions in the following definition:\n;\n; (define (sum term a next b)\n;   (define (iter a result)\n;     (if <??>\n;         <??>\n;         (iter <??> <??>)))\n;   (iter <??> <??>))\n\n(define (sum term a next b)\n  (define (iter a result)\n    (if (> a b)\n        result\n        (iter (next a) (+ (term a) result))))\n  (iter a 0))\n"
  },
  {
    "path": "scheme/sicp/01/31.scm",
    "content": "; SICP exercise 1.31\n;\n; a. The sum procedure is only the simplest of a vast number of similar\n; abstractions that can be captured as higher-order procedures. Write an\n; analogous procedure called product that returns the product of the values of\n; a function at points over a given range. Show how to define factorial in\n; terms of product. Also use product to compute approximations of π using the\n; formula:\n;\n; π   2·4·4·6·6·8…\n; ─ = ────────────\n; 4   3·3·5·5·7·7…\n;\n; b. If your product procedure generates a recursive process, write one that\n; generates an iterative process. If it generates an iterative process, write\n; one that generates a recursive process.\n\n(define (product term a next b)\n  (if (> a b)\n      1\n      (* (term a)\n         (product term (next a) next b))))\n\n(define (factorial n)\n  (define (term n)\n    n)\n  (define (next n)\n    (+ 1 n))\n  (product term 1 next n))\n\n(define (approximated-pi precision)\n  (define (term n)\n    (/ (* 2 (quotient (+ n 2) 2))\n       (+ 1 (* 2 (quotient (+ n 1) 2)))))\n  (define (next n)\n    (+ n 1))\n  (product term 1.0 next precision))\n\n\n\n(define (iterative-product term a next b)\n  (define (iter a result)\n    (if (> a b)\n        result\n        (iter (next a) (* (term a) result))))\n  (iter 1 a))\n\n(define (i-factorial n)\n  (define (term n)\n    n)\n  (define (next n)\n    (+ 1 n))\n  (iterative-product term 1 next n))\n\n(define (i-approximated-pi precision)\n  (define (term n)\n    (/ (* 2 (quotient (+ n 2) 2))\n       (+ 1 (* 2 (quotient (+ n 1) 2)))))\n  (define (next n)\n    (+ n 1))\n  (iterative-product term 1.0 next precision))\n"
  },
  {
    "path": "scheme/sicp/01/32.scm",
    "content": "; SICP exercise 1.32\n;\n; a. Show that sum and product (exercise 1.31) are both special cases of a\n; still more general notion called accumulate that combines a collection of\n; terms, using some general accumulation function:\n;\n; (accumulate combiner null-value term a next b)\n;\n; accumulate takes as arguments the same term and range specifications as sum\n; and product, together with a combiner procedure (of two arguments) that\n; specifies how the current term is to be combined with the accumulation of the\n; preceding terms and a null-value that specifies the base value to use when\n; the terms run out. Write accumulate and show how both sum and product can be\n; defined as simple calls to accumulate.\n;\n; b. If your accumulate procedure generates a recursive process, write one that\n; generates an iterative. If it generates an iterative process, run one that\n; generates a recursive process.\n\n(define (accumulate combiner null-value term a next b)\n  (if (> a b)\n      null-value\n      (combiner (term a) (accumulate combiner null-value term (next a) next b))))\n\n(define (product term a next b)\n  (accumulate * 1 term a next b))\n\n(define (sum term a next b)\n  (accumulate + 0 term a next b))\n\n\n\n(define (i-accumulate combiner null-value term a next b)\n  (define (iter a result)\n    (if (> a b)\n        result\n        (iter (next a) (combiner (term a) result))))\n  (iter a null-value))\n\n(define (i-product term a next b)\n  (i-accumulate * 1 term a next b))\n\n(define (i-sum term a next b)\n  (i-accumulate + 0 term a next b))\n"
  },
  {
    "path": "scheme/sicp/01/33.scm",
    "content": "; SICP exercise 1.33\n;\n; You can obtain an even more general version of accumulate (exercise 1.32) by\n; introducing the notion of a filter on the terms to be combined. That is,\n; combine only those terms derived from values in the range that satisfy a\n; specified condition. The resulting filtered-accumulate abstraction takes the\n; same arguments as accumulate, together with an additional predicate of one\n; argument that specifies the filter. Write filtered-accumulate as a procedure.\n; Show how to express the following using filtered-accumulate:\n;\n; a. the sum of the squares of the prime numbers in the interval a to b\n; (assuming that you have a prime? predicate already written)\n;\n; b. the product of all the positive integers less than n that are relatively\n; prime to n (i.e. all positive integer i < n such that GCD(i,n) = 1).\n\n; I shall implemented filtered-accumulate both recursively and iteratively,\n; just for the fun of it.\n\n(define (filtered-accumulate combiner null-value term a next b use?)\n  (define (iter a result)\n    (cond ((> a b) result)\n          ((use? a) (iter (next a) (combiner (term a) result)))\n          (else (iter (next a) result))))\n  (iter a null-value))\n\n(define (filtered-accumulate-rec combiner null-value term a next b use?)\n  (cond ((> a b) null-value)\n        ((use? a)\n         (combiner (term a)\n                   (filtered-accumulate-rec combiner null-value term (next a) next b use?)))\n        (else\n          (filtered-accumulate-rec combiner null-value term (next a) next b use?))))\n\n\n\n(define (sum-of-prime-squares a b)\n  (filtered-accumulate + 0 square a increment b prime?))\n\n(define (square a)\n  (* a a))\n\n(define (increment n)\n  (+ n 1))\n\n(define (prime? n)\n  (= n (smallest-divisor n)))\n\n(define (smallest-divisor n)\n  (find-divisor n 2))\n\n(define (find-divisor n test-divisor)\n  (cond ((> (square test-divisor) n) n)\n        ((divides? test-divisor n) test-divisor)\n        (else (find-divisor n (+ 1 test-divisor)))))\n\n(define (divides? a b)\n  (= (remainder b a) 0))\n\n\n\n(define (product-of-relative-primes-to n)\n  (define (relatively-prime-to-n? x)\n    (= (gcd n x) 1))\n  (filtered-accumulate * 1 identity 1 increment n relatively-prime-to-n?))\n\n(define (identity n)\n  n)\n\n(define (gcd a b)\n  (if (= b 0)\n      a\n      (gcd b (remainder a b))))\n"
  },
  {
    "path": "scheme/sicp/01/34.scm",
    "content": "; SICP exercise 1.34\n;\n; Suppose we define the procedure\n;\n; (define (f g)\n;   (g 2))\n;\n; Then we have\n;\n; (f square)\n; 4\n; \n; (f (lambda (z) (* z (+ z 1))))\n; 6\n; \n; What happens if we (perversely) ask the interpreter to evaluate the\n; combination (f f)? Explain.\n\n; We get an error. In Racket it looks like this:\n;\n; procedure application: expected procedure, given: 2; arguments were: 2\n;\n; It is fairly obvious why it happens. Let's expand it:\n;\n; (f f)\n; (f 2)\n; (2 2)\n;\n; It ends up invoking 2 as a procedure, when it is not really a procedure.\n"
  },
  {
    "path": "scheme/sicp/01/35.scm",
    "content": "; SICP exercise 1.35\n;\n; Show that the golden ratio 𝜙 (section 1.2.2) is a fixed point of the\n; transformation x ↦ 1 + 1/x, and use this fact to compute 𝜙 by means of the\n; fixed-point procedure.\n\n; Showing that 𝜙 is a fixed point is trivial. We have that:\n;\n; 𝜙 = (1 + √5)/2\n;\n; When we apply the transformation, we get\n;\n;     1   𝜙 + 1   (1 + √5)/2 + 2/2   3 + √5   (3 + √5)(1 - √5)\n; 1 + ─ = ───── = ──────────────── = ────── = ──────────────── =\n;     𝜙     𝜙        (1 + √5)/2      1 + √5   (1 + √5)(1 - √5)\n;\n;   3 - 3√5 + √5 - 5   -2 - 2√5   1 + √5\n; = ──────────────── = ──────── = ────── = 𝜙\n;          -4             -4        2\n;\n; Clearly, it is a fixed point.\n;\n; As for computing it:\n\n(define tolerance 0.00001)\n(define (fixed-point f first-guess)\n  (define (close-enough? v1 v2)\n    (< (abs (- v1 v2)) tolerance))\n  (define (try guess)\n    (let ((next (f guess)))\n      (if (close-enough? guess next)\n        next\n        (try next))))\n  (try first-guess))\n\n(define golden-ratio\n  (fixed-point (lambda (x) (+ 1 (/ 1 x))) 1.0))\n"
  },
  {
    "path": "scheme/sicp/01/36.scm",
    "content": "; SICP exercise 1.36\n;\n; Modify the fixed-point so that it prints the sequence of approximations it\n; generates, using the newline and display primitives shown in exercise 1.22.\n; Then find a solution to xˣ = 1000 by finding a fixed point of\n; x ↦ log(1000)/log(x). (Use Scheme's primitive log procedure, which computes\n; natural logarithms.) Compare the number of step this takes with and without\n; average damping. (Note that you cannot start fixed-point with a guess of 1,\n; as this ould cause divisino by log(1) = 0.)\n\n; Curiously enough, the version with average damping takes significantly less\n; steps. I expected it to be the other way around. I believe the reason is that\n; without average damping, the guesses oscillate around the answer, while with\n; it, the guesses approaches steadily from one direction.\n\n(define tolerance 0.00001)\n\n(define (fixed-point f first-guess)\n  (define (close-enough? v1 v2)\n    (< (abs (- v1 v2)) tolerance))\n  (define (try guess iteration)\n    (let ((next (f guess)))\n      (display iteration)\n      (display \". \")\n      (display next)\n      (newline)\n      (if (close-enough? guess next)\n        next\n        (try next (+ iteration 1)))))\n  (try first-guess 1))\n\n(define (average x y)\n  (/ (+ x y) 2))\n\n(display \"Without average damping:\")\n(newline)\n(fixed-point (lambda (x) (/ (log 1000) (log x))) 2.0)\n\n(newline)\n(display \"With average damping:\")\n(newline)\n(fixed-point (lambda (x) (average x (/ (log 1000) (log x)))) 2.0)\n"
  },
  {
    "path": "scheme/sicp/01/37.scm",
    "content": "; SICP exercise 1.37\n;\n; a. An infinite continued fraction is an expression of the form:\n;\n;            N₁\n; f = ────────────────\n;              N₂\n;     D₁ + ───────────\n;                 N₃\n;          D₂ + ──────\n;               D₃ + …\n;\n; As an example, one can show that the infinite continued fraction expansion\n; with the Nᵢ and the Dᵢ all equal to 1 produces 1/𝜙, where 𝜙 is the golden\n; ratio (described in section 1.2.2). One way to approximate an infinite\n; continued fraction is to truncate the expansion after a given number of\n; terms. Such a truncation — a so called k-term finite continued fraction — has\n; the form\n;\n;     N₁\n; ──────────\n;        N₂\n; D₁ + ─────\n;     ⋱   Nᵢ\n;       + ──\n;         Dᵢ\n;\n; Suppose that n and d are procedures of one argument (the term index i) that\n; return the Nᵢ and the Dᵢ of the terms of the continued fraction. Defined a\n; procedure cont-frac such that evaluating (cont-frac n d k) computes the value\n; of the k-term finite continued fraction. Check your procedure by\n; approximating 1/𝜙 using\n;\n; (cont-frac (lambda (i) 1.0)\n;            (lambda (i) 1.0)\n;            k)\n;\n; for successive values of k. How large must you make k in order to get an\n; approximation that is accurate to 4 decimal places?\n;\n; b. If your cont-frac procedure generates a recursive process, write one that\n; generates an iterative process. If it generates an iterative process, write\n; one that generates a recursive process.\n\n; k must be 11 in order to get an approximation, accurate to 4 decimal places\n;\n; Here are the functions:\n\n(define (cont-frac n d k)\n  (define (frac i)\n    (if (= k i)\n        (/ (n i) (d i))\n        (/ (n i) (+ (d i) (frac (+ i 1))))))\n  (frac 1))\n\n(define (cont-frac-i n d k)\n  (define (iter i result)\n    (if (= i 0)\n        result\n        (iter (- i 1)\n              (/ (n i) (+ (d i) result)))))\n  (iter k 0))\n"
  },
  {
    "path": "scheme/sicp/01/38.scm",
    "content": "; SICP exercise 1.38\n;\n; In 1737, the Swiss mathematician Leonhard Euler published a memoir De\n; Fractionibus Continuis, which included a continued fraction expansion of e-2,\n; where e is the base of the natural logarithms. In this fraction, Nᵢ are all\n; 1, and the Dᵢ are successively 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8,…. Write a\n; program that uses your cont-frac procedure from exercise 1.37 to approximate\n; e, based on Euler's expansion.\n\n(define (cont-frac n d k)\n  (define (iter i result)\n    (if (= i 0)\n        result\n        (iter (- i 1)\n              (/ (n i) (+ (d i) result)))))\n  (iter k 0))\n\n(define (approximate-e)\n  (define (term n)\n    (if (= (remainder (+ n 1) 3) 0)\n        (* 2 (/ (+ n 1) 3))\n        1.0))\n\n  (+ (cont-frac (lambda (x) 1.0) term 20)\n     2))\n"
  },
  {
    "path": "scheme/sicp/01/39.scm",
    "content": "; SICP exercise 1.39\n;\n; A continued fraction representation of tangent function was published in\n; 1770 by the German mathematician J. H. Lambert:\n;\n;                x\n; tan(x) = ─────────────\n;                  x²\n;          1 - ─────────\n;                    x²\n;              3 - ─────\n;                  5 - ⋱\n;\n; where x is in radians. Define a procedure (tan-cf x k) that computes an\n; approximation to the tangent function based on Lambert's formula. x specifies\n; the number of terms to compute, as in exercise 1.37.\n\n(define (cont-frac n d k)\n  (define (iter i result)\n    (if (= i 0)\n        result\n        (iter (- i 1)\n              (/ (n i) (+ (d i) result)))))\n  (iter k 0))\n\n(define (tan-cf x k)\n  (let ((neg-x-squared (- (* x x))))\n    (cont-frac (lambda (n) (if (= n 1) x neg-x-squared))\n               (lambda (n) (- (* n 2) 1))\n               k)))\n"
  },
  {
    "path": "scheme/sicp/01/40.scm",
    "content": "; SICP exercise 1.40\n;\n; Define a procedure cubic that can be used together with newtons-method\n; procedure in expressions of the form\n;\n; (newtons-method (cubic a b c) 1)\n;\n; to approximate zeroes of the cubic x³ + ax² + bx + c\n\n; It is simpler than it sounds - we just define a lambda, that computes\n; x³ + ax² + bx + c\n\n(define (cubic a b c)\n  (lambda (x)\n    (+ (* x x x)\n       (* a x x)\n       (* b x)\n       c)))\n\n(define (newtons-method g guess)\n  (fixed-point (newton-transform g) guess))\n\n(define (newton-transform g)\n  (lambda (x)\n    (- x (/ (g x) ((deriv g) x)))))\n\n(define (deriv g)\n  (lambda (x)\n    (/ (- (g (+ x dx)) (g x))\n       dx)))\n\n(define (fixed-point f first-guess)\n  (define (close-enough? v1 v2)\n    (< (abs (- v1 v2)) tolerance))\n  (define (try guess)\n    (let ((next (f guess)))\n      (if (close-enough? guess next)\n        next\n        (try next))))\n  (try first-guess))\n\n(define dx 0.00001)\n(define tolerance 0.00001)\n"
  },
  {
    "path": "scheme/sicp/01/41.scm",
    "content": "; SICP exercise 1.41\n;\n; Define a procedure double that takes a procedure of one argument as argument\n; and returns a procedure that applies the original procedure twice. For\n; example, if inc is a procedure that adds 1 to its argument, then (double inc)\n; should be a procedure that adds 2. What value is returned by\n\n; (((double (double double)) inc) 5)\n;\n; (double double) returns (lambda (f) (double (double x))), which in turn\n; returns a procedure, that applies f four times.\n;\n; (double (double double)) returns:\n;\n; (lambda (f) (double (double (double (double f)))))\n;\n; When we apply double to inc numerous times, we get:\n;\n; (double inc)                              +2\n; (double (double inc))                     +4\n; (double (double (double inc)))            +8\n; (double (double (double (double inc))))   +16\n;\n; Thus, returns 21\n\n(define (double function)\n  (lambda (x) (function (function x))))\n\n(define (inc x)\n  (+ x 1))\n"
  },
  {
    "path": "scheme/sicp/01/42.scm",
    "content": "; SICP exercise 1.42\n;\n; Let f and g be two one-argument functions. The composition f after g is defined to be\n; the function x ↦ f(g(x)). Define a procedure compose that implements composition. For\n; example, if inc is a procedure that adds 1 to its argument,\n;\n; ((compose square inc) 6)\n; 49\n\n(define (compose f g)\n  (lambda (x) (f (g x))))\n"
  },
  {
    "path": "scheme/sicp/01/43.scm",
    "content": "; SICP exercise 1.43\n;\n; If f is a numerical function and n is a positive integer, then we can form\n; the nth repeated application of f, which is defined to be the function whose\n; value at x is f(f(…(f(x))…)). For example, if f is the function x ↦ x + 1,\n; then the nth repeated application of f is the function x ↦ x + n. If f is the\n; operation of squaring a number, then the nth repeated application of f is the\n; function that raises its argument to the 2ⁿth power. Write a procedure that\n; takes as inputs a procedure that computes f and a positive integer n and\n; returns the procedures that computes the nth repeated application of f. Your\n; procedure should be able to be used as follows:\n;\n; ((repeated square 2) 5)\n; 625\n;\n; Hint: You may find it convenient to use compose from exercise 1.42\n\n(define (repeated f n)\n  (if (= n 1)\n      f\n      (compose f (repeated f (- n 1)))))\n\n(define (compose f g)\n  (lambda (x) (f (g x))))\n"
  },
  {
    "path": "scheme/sicp/01/44.scm",
    "content": "; SICP exercise 1.44\n;\n; The idea of smoothing a function is an important concept in signal\n; processing.  If f is a function and dx is some small number, then the\n; smoothed version of f is the function whose value at a point x is the average\n; f(x - dx), f(x) and f(x + dx). Write a procedure smooth that takes as input a\n; procedure that computes f and returns a procedure that computes the smoothed\n; f. It is sometimes valuable to repeatedly smooth a function (that is, smooth\n; the smoothed function, and so on) to obtain the n-fold smoothed function.\n; Show how to generate the n-fold smoothed function of any given function using\n; smooth and repeated from exercise 1.43.\n\n(define (smoothed f)\n  (lambda (x)\n    (/ (+ (f (- x dx))\n          (f x)\n          (f (+ x dx)))\n       3)))\n\n(define (n-fold-smoothed f n)\n  ((repeated smoothed n) f))\n\n(define (repeated f n)\n  (if (= n 1)\n      f\n      (compose f (repeated f (- n 1)))))\n\n(define (compose f g)\n  (lambda (x) (f (g x))))\n\n(define dx 0.0000001)\n"
  },
  {
    "path": "scheme/sicp/01/45.scm",
    "content": "; SICP exercise 1.45\n;\n; We saw in section 1.3.3 that attempting to compute square roots by naively\n; finding a fixed point of x ↦ x/y does not converge, and that this can be\n; fixed by average damping. The same method works for finding cube roots as\n; fixed points of the average-damped y ↦ x/y². Unfortunatelly, the process does\n; not work for fourth roots — a single average damp is not enough to make a\n; fixed-point search for y ↦ x/y³ converge. On the other hand, if we average\n; damp twice (i.e., use the average damp of the average damp of y ↦ x/y³) the\n; fixed-point search does converge. Do some experiments to determine how many\n; average damps are required to compute nth roots as a fixed-point search based\n; upon repeated average damping of y ↦ x/yⁿ⁻¹. Use this to implement a simple\n; procedure for computing nth roots using fixed-point, average-damp, and the\n; repeated procedure of exercise 1.43. Assume that any arithmetic operations\n; you need are available as primitives.\n\n; After a few experiments, I found out that we need to do log₂n avergage damps\n; to approximate the nth root. So, here's the function\n\n(define (nth-root n x)\n  (fixed-point-of-transform (lambda (y) (/ x (expt y (- n 1))))\n                            (repeated average-damp (ceiling (/ (log n) (log 2))))\n                            1.0))\n\n; And here is all the code we need to get it to run\n\n(define (fixed-point-of-transform g transform guess)\n  (fixed-point (transform g) guess))\n\n(define (fixed-point f first-guess)\n  (define (close-enough? v1 v2)\n    (< (abs (- v1 v2)) tolerance))\n  (define (try guess)\n    (let ((next (f guess)))\n      (if (close-enough? guess next)\n        next\n        (try next))))\n  (try first-guess))\n\n(define (average-damp f)\n  (lambda (x)\n    (/ (+ (f x) x)\n       2)))\n\n(define (repeated f n)\n  (if (= n 1)\n      f\n      (compose f (repeated f (- n 1)))))\n\n(define (compose f g)\n  (lambda (x) (f (g x))))\n\n(define tolerance 0.000001)\n"
  },
  {
    "path": "scheme/sicp/01/46.scm",
    "content": "; SICP exercise 1.46\n;\n; Several of the numerical methods described in this chapter are instances of\n; an extremely general computational strategy known as iterative improvement.\n; Iterative improvement says that, to compute something, we start with an\n; initial guess for the answer, test if the guess is good enough, and otherwise\n; improve the guess and continue the process using the improved guess as the\n; new guess. Write a procedure iterative-improve that takes two procedures as\n; arguments: a method for telling whether a guess is good enough and a method\n; for improving a guess. iterative-improve should return as its value a\n; procedure that takes a guess as argument and keeps improving the guess until\n; it is good enough. Rwerite the sqrt procedure of section 1.1.7 and the\n; fixed-point procedure of section 1.3.3 in terms of iterative-improve.\n\n(define (iterative-improve good-enough? improve)\n  (define (iter guess)\n    (if (good-enough? guess)\n        guess\n        (iter (improve guess))))\n  iter)\n\n(define (sqrt x)\n  ((iterative-improve (lambda (guess) (< (abs (- (* guess guess) x))\n                                         0.000001))\n                      (lambda (guess) (/ (+ guess (/ x guess)) 2)))\n   1.0))\n\n(define (fixed-point f first-guess)\n  ((iterative-improve (lambda (guess) (< (abs (- guess (f guess)))\n                                         0.000001))\n                      f)\n   first-guess))\n"
  },
  {
    "path": "scheme/sicp/01/tests/03-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../03.scm\")\n\n(define sicp-1.03-tests\n  (test-suite\n    \"Tests for SICP exercise 1.03\"\n\n    (check-equal? (sum-of-two-largest-squares 2 3 4) 25)\n    (check-equal? (sum-of-two-largest-squares 2 4 3) 25)\n    (check-equal? (sum-of-two-largest-squares 3 4 2) 25)\n    (check-equal? (sum-of-two-largest-squares 3 2 4) 25)\n    (check-equal? (sum-of-two-largest-squares 4 2 3) 25)\n    (check-equal? (sum-of-two-largest-squares 4 3 2) 25)\n\n    (check-equal? (sum-of-two-largest-squares 3 3 4) 25)\n    (check-equal? (sum-of-two-largest-squares 3 4 3) 25)\n    (check-equal? (sum-of-two-largest-squares 4 3 3) 25)\n\n    (check-equal? (sum-of-two-largest-squares 3 3 3) 18)\n))\n\n(run-tests sicp-1.03-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/07-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../07.scm\")\n\n(define sicp-1.07-tests\n  (test-suite\n    \"Tests for SICP exercise 1.07\"\n\n    (check-= (sqrt 4e-8) 2e-4 1e-16)\n    (check-= (* (sqrt 10e+48) (sqrt 10e+48)) 10e+48 10e+33)\n))\n\n(run-tests sicp-1.07-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/08-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../08.scm\")\n\n(define sicp-1.08-tests\n  (test-suite\n    \"Tests for SICP exercise 1.08\"\n\n    (check-= (cube-root 8) 2 0.00001)\n    (check-= (cube-root 27) 3 0.00001)\n    (check-= (cube-root 1000) 10 0.00001)\n))\n\n(run-tests sicp-1.08-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/11-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../11.scm\")\n\n(define sicp-1.11-tests\n  (test-suite\n    \"Tests for SICP exercise 1.11\"\n\n    (check-equal? (f 0) 0)\n    (check-equal? (f 1) 1)\n    (check-equal? (f 2) 2)\n    (check-equal? (f 3) 4)\n    (check-equal? (f 4) 11)\n    (check-equal? (f 5) 25)\n    (check-equal? (f 6) 59)\n\n    (check-equal? (f-iter 0) 0)\n    (check-equal? (f-iter 1) 1)\n    (check-equal? (f-iter 2) 2)\n    (check-equal? (f-iter 3) 4)\n    (check-equal? (f-iter 4) 11)\n    (check-equal? (f-iter 5) 25)\n    (check-equal? (f-iter 6) 59)\n))\n\n(run-tests sicp-1.11-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/12-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../12.scm\")\n\n(define sicp-1.12-tests\n  (test-suite\n    \"Tests for SICP exercise 1.12\"\n\n    (check-equal? (binom 1 1) 1)\n    (check-equal? (binom 2 1) 1)\n    (check-equal? (binom 2 2) 1)\n    (check-equal? (binom 3 1) 1)\n    (check-equal? (binom 3 2) 2)\n    (check-equal? (binom 3 3) 1)\n    (check-equal? (binom 4 1) 1)\n    (check-equal? (binom 4 2) 3)\n    (check-equal? (binom 4 3) 3)\n    (check-equal? (binom 4 4) 1)\n    (check-equal? (binom 5 1) 1)\n    (check-equal? (binom 5 2) 4)\n    (check-equal? (binom 5 3) 6)\n    (check-equal? (binom 5 4) 4)\n    (check-equal? (binom 5 5) 1)\n))\n\n(run-tests sicp-1.12-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/16-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../16.scm\")\n\n(define sicp-1.16-tests\n  (test-suite\n    \"Tests for SICP exercise 1.16\"\n\n    (check-equal? (fast-expt 2 0) 1)\n    (check-equal? (fast-expt 2 1) 2)\n    (check-equal? (fast-expt 2 2) 4)\n    (check-equal? (fast-expt 2 3) 8)\n    (check-equal? (fast-expt 2 4) 16)\n    (check-equal? (fast-expt 2 5) 32)\n    (check-equal? (fast-expt 2 6) 64)\n    (check-equal? (fast-expt 2 7) 128)\n    (check-equal? (fast-expt 2 8) 256)\n\n    (check-equal? (fast-expt 3 0) 1)\n    (check-equal? (fast-expt 3 1) 3)\n    (check-equal? (fast-expt 3 2) 9)\n    (check-equal? (fast-expt 3 3) 27)\n    (check-equal? (fast-expt 3 4) 81)\n    (check-equal? (fast-expt 3 5) 243)\n))\n\n(run-tests sicp-1.16-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/17-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../17.scm\")\n\n(define sicp-1.17-tests\n  (test-suite\n    \"Tests for SICP exercise 1.17\"\n\n    (check-equal? (** 5 1) 5)\n    (check-equal? (** 5 2) 10)\n    (check-equal? (** 5 3) 15)\n    (check-equal? (** 5 4) 20)\n    (check-equal? (** 5 5) 25)\n\n    (check-equal? (** 1 2) 2)\n    (check-equal? (** 2 2) 4)\n    (check-equal? (** 3 2) 6)\n    (check-equal? (** 4 2) 8)\n    (check-equal? (** 5 2) 10)\n))\n\n(run-tests sicp-1.17-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/18-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../18.scm\")\n\n(define sicp-1.18-tests\n  (test-suite\n    \"Tests for SICP exercise 1.18\"\n\n    (check-equal? (** 5 1) 5)\n    (check-equal? (** 5 2) 10)\n    (check-equal? (** 5 3) 15)\n    (check-equal? (** 5 4) 20)\n    (check-equal? (** 5 5) 25)\n\n    (check-equal? (** 1 2) 2)\n    (check-equal? (** 2 2) 4)\n    (check-equal? (** 3 2) 6)\n    (check-equal? (** 4 2) 8)\n    (check-equal? (** 5 2) 10)\n))\n\n(run-tests sicp-1.18-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/19-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../19.scm\")\n\n(define sicp-1.19-tests\n  (test-suite\n    \"Tests for SICP exercise 1.19\"\n    \n    (check-equal? (fib 0) 0)\n    (check-equal? (fib 1) 1)\n    (check-equal? (fib 2) 1)\n    (check-equal? (fib 3) 2)\n    (check-equal? (fib 4) 3)\n    (check-equal? (fib 5) 5)\n    (check-equal? (fib 6) 8)\n    (check-equal? (fib 7) 13)\n    (check-equal? (fib 8) 21)\n    (check-equal? (fib 9) 34)\n    (check-equal? (fib 10) 55)\n    (check-equal? (fib 11) 89)\n    (check-equal? (fib 12) 144)\n))\n\n(run-tests sicp-1.19-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/27-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../27.scm\")\n\n(define sicp-1.27-tests\n  (test-suite\n    \"Tests for SICP exercise 1.27\"\n\n    (check-true (carmichael? 561))\n    (check-true (carmichael? 1105))\n    (check-true (carmichael? 1729))\n    (check-true (carmichael? 2465))\n    (check-true (carmichael? 2821))\n    (check-true (carmichael? 6601))\n\n    (check-false (carmichael? 27))\n    (check-false (carmichael? 1001))\n))\n\n(run-tests sicp-1.27-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/28-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../28.scm\")\n\n(define sicp-1.28-tests\n  (test-suite\n    \"Tests for SICP exercise 1.28\"\n\n    (check-true (fast-prime? 11 3))\n    (check-true (fast-prime? 101 3))\n    (check-true (fast-prime? 1009 3))\n    (check-true (fast-prime? 1013 3))\n    (check-true (fast-prime? 1019 3))\n    (check-true (fast-prime? 10007 3))\n    (check-true (fast-prime? 10009 3))\n    (check-true (fast-prime? 10037 3))\n    (check-true (fast-prime? 10037 3))\n\n    (check-false (fast-prime? 561 3))\n    (check-false (fast-prime? 1105 3))\n    (check-false (fast-prime? 1729 3))\n    (check-false (fast-prime? 2465 3))\n    (check-false (fast-prime? 2821 3))\n    (check-false (fast-prime? 6601 3))\n))\n\n(run-tests sicp-1.28-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/29-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../29.scm\")\n\n(define sicp-1.29-tests\n  (test-suite\n    \"Tests for SICP exercise 1.29\"\n\n    (check-= (integral cube 0 1 0.001) 0.25 0.001)\n    (check-= (integral (lambda (x) x) 0 1 0.001) 0.5 0.001)\n    \n    (check-= (simpson-integral cube 0 1 100) 0.25 0.01)\n    (check-= (simpson-integral (lambda (x) x) 0 1 100) 0.5 0.01)\n    (check-= (simpson-integral (lambda (x) x) 0 1 1000) 0.5 0.001)\n))\n\n(run-tests sicp-1.29-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/30-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../30.scm\")\n\n(define sicp-1.30-tests\n  (test-suite\n    \"Tests for SICP exercise 1.30\"\n\n    (check-equal? (sum (lambda (x) x) 1 (lambda (x) (+ 1 x)) 100) 5050)\n    (check-equal? (sum (lambda (x) x) 0 (lambda (x) (+ 1 x)) 1) 1)\n    (check-equal? (sum (lambda (x) x) 0 (lambda (x) (+ 1 x)) 0) 0)\n    (check-equal? (sum (lambda (x) x) 0 (lambda (x) (+ 2 x)) 10) 30)\n\n    (check-= (sum (lambda (x) (/ 1 (expt 2 x))) 1.0 (lambda (x) (+ 1 x)) 100) 1.0 0.01)\n))\n\n(run-tests sicp-1.30-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/31-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../31.scm\")\n\n(define sicp-1.31-tests\n  (test-suite\n    \"Tests for SICP exercise 1.31\"\n\n    (check-equal? (factorial 1) 1)\n    (check-equal? (factorial 5) 120)\n\n    (check-= (approximated-pi 1000) (/ 3.14 4) 0.001)\n\n    (check-equal? (i-factorial 1) 1)\n    (check-equal? (i-factorial 5) 120)\n\n    (check-= (i-approximated-pi 1000) (/ 3.14 4) 0.001)\n))\n\n(run-tests sicp-1.31-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/32-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../32.scm\")\n\n(define (increment n)\n  (+ n 1))\n(define (one-over-pow-of-2 n)\n  (/ 1 (expt 2 n)))\n\n(define sicp-1.32-tests\n  (test-suite\n    \"Tests for SICP exercise 1.32\"\n\n    (check-equal? (accumulate * 1 identity 1 increment 5) 120)\n    (check-equal? (product identity 1 increment 5) 120)\n    (check-equal? (sum identity 1 increment 10) 55)\n    (check-= (accumulate + 0 one-over-pow-of-2 0 increment 1000) 2 0.001)\n\n    (check-equal? (i-accumulate * 1 identity 1 increment 5) 120)\n    (check-equal? (i-product identity 1 increment 5) 120)\n    (check-equal? (i-sum identity 1 increment 10) 55)\n    (check-= (i-accumulate + 0 one-over-pow-of-2 0 increment 1000) 2 0.001)\n))\n\n(run-tests sicp-1.32-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/33-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../33.scm\")\n\n(define sicp-1.33-tests\n  (test-suite\n    \"Tests for SICP exercise 1.33\"\n\n    (check-equal? (sum-of-prime-squares 2 10) 87)\n    (check-equal? (sum-of-prime-squares 10 15) 290)\n\n    (check-equal? (product-of-relative-primes-to 10) 189)\n    (check-equal? (product-of-relative-primes-to 12) 385)\n))\n\n(run-tests sicp-1.33-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/35-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../35.scm\")\n\n(define sicp-1.35-tests\n  (test-suite\n    \"Tests for SICP exercise 1.35\"\n\n    (check-= (* golden-ratio golden-ratio) (+ 1 golden-ratio) 0.00001)\n))\n\n(run-tests sicp-1.35-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/37-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../37.scm\")\n\n(define one (lambda (i) 1.0))\n(define two (lambda (i) 2.0))\n\n(define sicp-1.37-tests\n  (test-suite\n    \"Tests for SICP exercise 1.37\"\n\n    (check-equal? (cont-frac one one 1) 1.0)\n    (check-equal? (cont-frac one two 1) 0.5)\n    (check-equal? (cont-frac two one 1) 2.0)\n    (check-= (cont-frac one one 11) 0.6180 0.00006)\n\n    (check-equal? (cont-frac-i one one 1) 1.0)\n    (check-equal? (cont-frac-i one two 1) 0.5)\n    (check-equal? (cont-frac-i two one 1) 2.0)\n    (check-= (cont-frac-i one one 11) 0.6180 0.00006)\n))\n\n(run-tests sicp-1.37-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/38-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../38.scm\")\n\n(define sicp-1.38-tests\n  (test-suite\n    \"Tests for SICP exercise 1.38\"\n\n    (check-= (approximate-e) 2.71828183 0.00000001)\n))\n\n(run-tests sicp-1.38-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/39-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../39.scm\")\n\n(define sicp-1.39-tests\n  (test-suite\n    \"Tests for SICP exercise 1.39\"\n\n    (check-= (tan-cf 0 100) 0 0.00001)\n    (check-= (tan-cf 1.0 100) 1.55740 0.00001)\n    (check-= (tan-cf 2.0 100) -2.18503 0.00001)\n    (check-= (tan-cf 3.141592 100) 0.0 0.00001)\n))\n\n(run-tests sicp-1.39-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/40-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../40.scm\")\n\n(define sicp-1.40-tests\n  (test-suite\n    \"Tests for SICP exercise 1.40\"\n\n    (check-= (newtons-method (cubic 0 0 -1) 2.0) 1.0 0.00001)\n    (check-= (newtons-method (cubic 0 0 -27) 2.0) 3.0 0.00001)\n))\n\n(run-tests sicp-1.40-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/41-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../41.scm\")\n\n(define sicp-1.41-tests\n  (test-suite\n    \"Tests for SICP exercise 1.41\"\n\n    (check-equal? (((double (double double)) inc) 5) 21)\n))\n\n(run-tests sicp-1.41-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/42-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../42.scm\")\n\n(define (square x)\n  (* x x))\n\n(define (inc x)\n  (+ x 1))\n\n(define sicp-1.42-tests\n  (test-suite\n    \"Tests for SICP exercise 1.42\"\n\n    (check-equal? ((compose square inc) 6) 49)\n))\n\n(run-tests sicp-1.42-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/43-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../43.scm\")\n\n(define (square x)\n  (* x x))\n\n(define sicp-1.43-tests\n  (test-suite\n    \"Tests for SICP exercise 1.43\"\n\n    (check-equal? ((repeated square 2) 5) 625)\n))\n\n(run-tests sicp-1.43-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/44-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../44.scm\")\n\n(define sicp-1.44-tests\n  (test-suite\n    \"Tests for SICP exercise 1.44\"\n\n    ; A rather flaky way of testing it\n    (check-not-equal? ((smoothed abs) 0) 0)\n    (check-= ((smoothed abs) 0) 0 0.00001)\n\n    (check-not-equal? ((n-fold-smoothed abs 4) 0) 0)\n    (check-= ((n-fold-smoothed abs 4) 0) 0 0.00001)\n))\n\n(run-tests sicp-1.44-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/45-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../45.scm\")\n\n(define sicp-1.45-tests\n  (test-suite\n    \"Tests for SICP exercise 1.45\"\n\n    (check-= (nth-root 2 4) 2 0.000001)\n    (check-= (nth-root 3 8) 2 0.000001)\n    (check-= (nth-root 4 16) 2 0.000001)\n    (check-= (nth-root 5 32) 2 0.000001)\n    (check-= (nth-root 8 256) 2 0.000001)\n    (check-= (nth-root 9 512) 2 0.000001)\n))\n\n(run-tests sicp-1.45-tests)\n"
  },
  {
    "path": "scheme/sicp/01/tests/46-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../46.scm\")\n\n(define sicp-1.46-tests\n  (test-suite\n    \"Tests for SICP exercise 1.46\"\n\n    (check-= (sqrt 9) 3 0.0000001)\n    (check-= (sqrt 256) 16 0.0000001)\n\n    (check-= (fixed-point cos 1.0) 0.739084 0.00001)\n))\n\n(run-tests sicp-1.46-tests)\n"
  },
  {
    "path": "scheme/sicp/02/01.scm",
    "content": "; SICP exercise 2.01\n;\n; Define a better version of make-rat that handles both positive and negative\n; arguments. make-rat should normalize the sign so that if the rational number\n; is positive, both the numerator and denominator are positive, and if the\n; rational number is negative, only the numerator is negative.\n\n(define (make-rat n d)\n  (let ((g (gcd n d)))\n    (let ((n (/ n g))\n          (d (/ d g)))\n      (if (< d 0)\n          (cons (- n) (- d))\n          (cons n d)))))\n\n(define (numer x)\n  (car x))\n\n(define (denom x)\n  (cdr x))\n"
  },
  {
    "path": "scheme/sicp/02/02.scm",
    "content": "; SICP exercise 2.02\n;\n; Consider the problem of representing line segments in a plane. Each segment\n; is represented as a pair of points: a starting point and an ending point.\n; Define a constructor make-segment and selectors start-segment and end-segment\n; that define the representation of segments in terms of points. Furthermore, a\n; point can be represented as a pair of numbers: the x coordinate and the y\n; coordinate. Accordingly, specify a constructor make-point and selectors\n; x-point and y-point that define this representation. Finally, using your\n; selectors and constructors, define a procedure midpoint-segment that takes a\n; line segment as argument and returns its midpoint (the point whose\n; coordinates are the average of the coordinates of the endpoints). To try your\n; procedures, you'll need a way to print points:\n;\n; (define (print-point p)\n;   (newline)\n;   (display \"(\")\n;   (display (x-point p))\n;   (display \",\")\n;   (display (y-point p))\n;   (display \")\"))\n\n(define (make-point x y)\n  (cons x y))\n\n(define (x-point point)\n  (car point))\n\n(define (y-point point)\n  (cdr point))\n\n(define (make-segment start-point end-point)\n  (cons start-point end-point))\n\n(define (start-segment segment)\n  (car segment))\n\n(define (end-segment segment)\n  (cdr segment))\n\n(define (midpoint-segment segment)\n  (let ((start (start-segment segment))\n        (end (end-segment segment)))\n    (make-point (average (x-point start) (x-point end))\n                (average (y-point start) (y-point end)))))\n\n(define (average a b)\n  (/ (+ a b)\n     2))\n\n(define (print-point p)\n  (newline)\n  (display \"(\")\n  (display (x-point p))\n  (display \",\")\n  (display (y-point p))\n  (display \")\"))\n"
  },
  {
    "path": "scheme/sicp/02/03.scm",
    "content": "; SICP exercise 2.03\n;\n; Implement a representation for rectangles in a plane. (Hint: You may want to\n; make use of exercise 2.2.) In terms of your constructors and selectors,\n; create procedures that compute the perimeter and the area of a given\n; rectangle. Now implement a different representation of rectangles. Can you\n; design your system with suitable abstraction barriers, so that the same\n; perimeter and area procedures will work using either representation?\n\n; Of course I can! Here it is:\n\n(define (perimeter rectangle)\n  (let ((top-left (top-left-rectangle rectangle))\n        (bottom-right (bottom-right-rectangle rectangle)))\n    (* (+ (abs (- (x-point bottom-right) (x-point top-left)))\n          (abs (- (y-point bottom-right) (y-point top-left))))\n       2)))\n\n(define (area rectangle)\n  (let ((top-left (top-left-rectangle rectangle))\n        (bottom-right (bottom-right-rectangle rectangle)))\n    (abs (* (- (x-point bottom-right) (x-point top-left))\n            (- (y-point bottom-right) (y-point top-left))))))\n\n; This is the first representation of rectangles I used:\n\n(define (make-rectangle top-left bottom-right)\n  (cons top-left bottom-right))\n\n(define (top-left-rectangle rectangle)\n  (car rectangle))\n\n(define (bottom-right-rectangle rectangle)\n  (cdr rectangle))\n\n; This is the second:\n\n(define (make-rectangle top-left bottom-right)\n  (let ((width (abs (- (x-point bottom-right) (x-point top-left))))\n        (height (abs (- (y-point bottom-right) (y-point top-left)))))\n    (cons top-left (cons width height))))\n\n(define (top-left-rectangle rectangle)\n  (car rectangle))\n\n(define (bottom-right-rectangle rectangle)\n  (let ((top-left (car rectangle))\n        (width (car (cdr rectangle)))\n        (height (cdr (cdr rectangle))))\n  (make-point (+ (x-point top-left) width)\n              (+ (y-point top-left) height))))\n\n; And this is the point:\n\n(define (make-point x y)\n  (cons x y))\n\n(define (x-point point)\n  (car point))\n\n(define (y-point point)\n  (cdr point))\n"
  },
  {
    "path": "scheme/sicp/02/04.scm",
    "content": "; SICP exercise 2.04\n;\n; Here is an alternative procedural representation of pairs. For this\n; representation, verify that (car (cons x y)) yields x for any objects x and\n; y.\n;\n; (define (cons x y)\n;   (lambda (m) (m x y)))\n;\n; (define (car z)\n;   (z (lambda (p q) p)))\n;\n; What is the corresponding definition of cdr? (Hint: To verify that this\n; works, make use of the substitution model of section 1.1.5.)\n\n; Let's first expand it:\n;\n; (car (cons x y))\n; (car (lambda (m) (m x y)))\n; ((lambda (m) (m x y)) (lambda (p q) p))\n; ((lambda (p q) p) x y)\n; x\n;\n; Duh.\n;\n; As for cdr:\n;\n; (define (cdr z)\n;   (z (lambda (p q) q)))\n"
  },
  {
    "path": "scheme/sicp/02/05.scm",
    "content": "; SICP exercise 2.05\n;\n; Show that we can represent pairs of nonnegative integers using only numbers\n; and arithmetic operations if we represent the pair a and b as the integer\n; that is the product 2ª3ᵇ. Give the corresponding definitions of the\n; procedures cons, car and cdr.\n\n(define (cons a b)\n  (* (expt 2 a)\n     (expt 3 b)))\n\n(define (car pair)\n  (count-divisor pair 2))\n\n(define (cdr pair)\n  (count-divisor pair 3))\n\n(define (count-divisor number divisor)\n  (define (iter number result)\n    (if (= (remainder number divisor) 0)\n        (iter (quotient number divisor) (+ result 1))\n        result))\n  (iter number 0))\n"
  },
  {
    "path": "scheme/sicp/02/06.scm",
    "content": "; SICP exercise 2.06\n;\n; In case representing pairs as procedures wasn't mind-boggling enough,\n; consider that, in a language that can manipulate procedures, we can get by\n; without numbers (at least insofar as nonnegative integers are concerned) by\n; implementing 0 and the operation of adding 1 as\n;\n; (define zero (lambda (f) (lambda (x) x)))\n;\n; (define (add-1 n)\n;   (lambda (f) (lambda (x) (f ((n f) x)))))\n;\n; This representation is known as Church numerals, after its inventor, Alonzo\n; Church, the logician who invented the λ calculus.\n;\n; Define one and two directly (not in terms of zero and add-1). (Hint: Use\n; substitution to evaluate (add-1 zero)). Give a direct definition of the\n; addition procedure (not in terms of repeated application of add-1).\n\n; It was mind-boggling enough, but I am going to do the exercise anyway.\n;\n; This is one:\n;\n; (add-1 zero)\n; (add-1 (lambda (f) (lambda (x) x)))\n; (lambda (f) (lambda (x) (f (((lambda (f) (lambda (x) x)) f) x))))\n; ...which essentially is...\n; (lambda (f) (lambda (x) (f x)))\n\n(define one\n  (lambda (f) (lambda (x) (f x))))\n\n; And this is two:\n;\n; (add-1 one)\n; (add-1 (lambda (f) (lambda (x) (f x))))\n; (lambda (f) (lambda (x) (f (((lambda (f) (lambda (x) (f x))) f) x))))\n; ...which essentially is...\n; (lambda (f) (lambda (x) (f (f x))))\n\n(define two\n  (lambda (f) (lambda (x) (f (f x)))))\n\n; Therefore, to add a to b, we have to apply f a + b times.\n\n(define (add a b)\n  (lambda (f) (lambda (x) ((a f) ((b f) x)))))\n"
  },
  {
    "path": "scheme/sicp/02/07.scm",
    "content": "; SICP exercise 2.07\n;\n; Alyssa's program is incomplete because she has not specified the\n; implementation of the interval abstraction. Here is a definition of the\n; interval constructor:\n;\n; (define (make-interval a b) (cons a b))\n;\n; Define selectors upper-bound and lower-bound to complete the implementation.\n\n(define (make-interval a b)\n  (cons a b))\n\n(define (upper-bound interval)\n  (cdr interval))\n\n(define (lower-bound interval)\n  (car interval))\n"
  },
  {
    "path": "scheme/sicp/02/08.scm",
    "content": "; SICP exercise 2.08\n;\n; Using reasoning analogous to Alyssa's, describe how the difference of two\n; intervals may be computed. Define a corresponding subtraction procedure,\n; called sub-interval.\n\n; We can be extremely elaborate here, but I don't really want to go there.\n; Simply, the minimum is the lower bound of the minuend minus the upper bound\n; of the subtrahend and vica-versa.\n;\n; Here's the code.\n\n(define (sub-interval x y)\n  (make-interval (- (lower-bound x) (upper-bound y))\n                 (- (upper-bound x) (lower-bound y))))\n\n(define (make-interval a b)\n  (cons a b))\n\n(define (upper-bound interval)\n  (cdr interval))\n\n(define (lower-bound interval)\n  (car interval))\n"
  },
  {
    "path": "scheme/sicp/02/09.scm",
    "content": "; SICP exercise 2.09\n;\n; The width of an interval is half of the difference between its upper and\n; lower bounds. The width is a measure of the uncertainty of the number\n; specified by the interval. For some arithmetic operations the width of the\n; result of combining two intervals is a function only of the widths of the\n; argument intervals, whereas for others the width of the combination is not a\n; function of the widths of the argument intervals. Show that the width of the\n; sum (or difference) of two intervals is a function only of the widths of the\n; intervals being added (or subtracted). Give examples to show that this is not\n; true for multiplication or division.\n\n; Let's have two intervals:\n;\n; i₁ = (l₁, u₁)\n; i₂ = (l₂, u₂)\n;\n; With respective widths:\n;\n; w₁ = (u₁ - l₁)/2\n; w₂ = (u₂ - l₂)/2\n;\n; When adding i₁ to i₂, we get:\n;\n; i₃ = i₂ + i₁ = (l₁ + l₂, u₁ + u₂)\n; w₃ = (u₁ + u₂)/2 - (l₁ + l₂)/2 = (u₁ - l₁)/2 + (u₂ - l₂)/2 = (w₁ + w₂)/2\n;\n; When subtracting, we get:\n;\n; i₃ = i₂ - i₁ = (l₂ - u₁, u₂ - l₁)\n; w₃ = (u₂ - l₁)/2 - (l₂ - u₁)/2 = (u₁ + u₂)/2 - (l₁ + l₂)/2 = (w₁ + w₂)/2\n;\n; Now, let's take a look at multiplication. Let's take two pairs:\n;\n; (1, 2) x (3, 4) = (3, 8)\n; (3, 4) x (5, 6) = (15, 24)\n;\n; Both pairs have intervals with the same width, but the the resulting\n; intervals have different widths.\n;\n; Let's take a look at division:\n;\n; (1, 2) ÷ (3, 4) = (1/4, 2/3)\n; (3, 4) ÷ (5, 6) = (1/2, 4/5)\n;\n; Again, the intervals have different widths.\n"
  },
  {
    "path": "scheme/sicp/02/10.scm",
    "content": "; SICP exercise 2.10\n;\n; Ben Bitdiddle, an expert systems programmer, looks over Alyssa's shoulder and\n; comments that it is not clear what it means to divide by an interval that\n; spans zero. Modify Alyssa's code to check for this condition and to signal an\n; error if it occurs.\n\n(define (div-interval x y)\n  (if (and (<= (lower-bound y) 0) (<= 0 (upper-bound y)))\n      (error \"Cannot divide by an interval that spans zero\")\n      (mul-interval x\n                    (make-interval (/ 1.0 (upper-bound y))\n                                   (/ 1.0 (lower-bound y))))))\n\n(define (mul-interval x y)\n  (let ((p1 (* (lower-bound x) (lower-bound y)))\n        (p2 (* (lower-bound x) (upper-bound y)))\n        (p3 (* (upper-bound x) (lower-bound y)))\n        (p4 (* (upper-bound x) (upper-bound y))))\n    (make-interval (min p1 p2 p3 p4)\n                   (max p1 p2 p3 p4))))\n\n(define (make-interval a b)\n  (cons a b))\n\n(define (upper-bound interval)\n  (cdr interval))\n\n(define (lower-bound interval)\n  (car interval))\n"
  },
  {
    "path": "scheme/sicp/02/11.scm",
    "content": "; SICP exercise 2.11\n;\n; In passing, Ben also cryptically comments: \"By testing the signs of the\n; endpoints of the intervals, it is possible to break mul-interval into nine\n; cases, only one of which requires more than two multiplications.\" Rewrite\n; this procedure using Ben's suggestion.\n\n; Let's have (a, b) x (c, d).\n;\n; We know that a ≤ b and c ≤ d. Thus, we have the following cases:\n;\n; +---+---+---+---+----------------------------+\n; | a | b | c | d | result                     |\n; +---+---+---+---+----------------------------+\n; | + | + | + | + | (ac, bd)                   |\n; +---+---+---+---+----------------------------+\n; | + | + | - | + | (bc, bd)                   |\n; +---+---+---+---+----------------------------+\n; | + | + | - | - | (bc, ad)                   |\n; +---+---+---+---+----------------------------+\n; | - | + | + | + | (ad, bd)                   |\n; +---+---+---+---+----------------------------+\n; | - | + | - | + | (min(ad, bc), max(ac, bd)) |\n; +---+---+---+---+----------------------------+\n; | - | + | - | - | (bc, ac)                   |\n; +---+---+---+---+----------------------------+\n; | - | - | + | + | (ad, bc)                   |\n; +---+---+---+---+----------------------------+\n; | - | - | - | + | (ad, ac)                   |\n; +---+---+---+---+----------------------------+\n; | - | - | - | - | (bd, ac)                   |\n; +---+---+---+---+----------------------------+\n;\n; Hence, the code\n\n(define (mul-interval x y)\n  (define (pos? number)\n    (<= 0 number))\n  (define (neg? number)\n    (<= number 0))\n  (let ((a (lower-bound x))\n        (b (upper-bound x))\n        (c (lower-bound y))\n        (d (upper-bound y)))\n    (cond ((and (pos? a) (pos? b) (pos? c) (pos? d)) (make-interval (* a c) (* b d)))\n          ((and (pos? a) (pos? b) (neg? c) (pos? d)) (make-interval (* b c) (* b d)))\n          ((and (pos? a) (pos? b) (neg? c) (neg? d)) (make-interval (* b c) (* a d)))\n          ((and (neg? a) (pos? b) (pos? c) (pos? d)) (make-interval (* a d) (* b d)))\n          ((and (neg? a) (pos? b) (neg? c) (pos? d))\n           (make-interval (min (* a d) (* b c)) (max (* a c) (* b d))))\n          ((and (neg? a) (pos? b) (neg? c) (neg? d)) (make-interval (* b c) (* a c)))\n          ((and (neg? a) (neg? b) (pos? c) (pos? d)) (make-interval (* a d) (* b c)))\n          ((and (neg? a) (neg? b) (neg? c) (pos? d)) (make-interval (* a d) (* a c)))\n          ((and (neg? a) (neg? b) (neg? c) (neg? d)) (make-interval (* b d) (* a c))))))\n\n(define (make-interval a b)\n  (cons a b))\n\n(define (upper-bound interval)\n  (cdr interval))\n\n(define (lower-bound interval)\n  (car interval))\n"
  },
  {
    "path": "scheme/sicp/02/12.scm",
    "content": "; SICP exercise 2.12\n;\n; Define a constructor make-center-percent that takes a center and a percentage\n; tolerance and produces the desired interval. You must also define a selector\n; percent that produces the percentage tolerance for a given interval. The\n; center selector is the same as the one shown above.\n\n(define (make-center-percent value tolerance)\n  (let ((width (* value (/ tolerance 100))))\n    (make-interval (- value tolerance) (+ value tolerance))))\n\n(define (percent i)\n  (* (/ (width i) (center i))\n     100))\n\n(define (center i)\n  (/ (+ (lower-bound i) (upper-bound i)) 2))\n\n(define (width i)\n  (/ (- (upper-bound i) (lower-bound i)) 2))\n\n(define (make-interval x y)\n  (cons x y))\n\n(define (upper-bound i)\n  (cdr i))\n\n(define (lower-bound i)\n  (car i))\n"
  },
  {
    "path": "scheme/sicp/02/13.scm",
    "content": "; SICP exercise 2.13\n;\n; Show that under the assumption of small percentage tolerances there is a\n; simple formula for the approximate percentage tolerance of the product of two\n; intevals in terms of the tolerances of the factors. You may simplify the\n; problem by assuming that all numbers are positive.\n\n; Let's assume have the following intervals\n;\n; i₁ = ((1 - 0.5t₁)x, (1 + 0.5t₁)x)\n; i₂ = ((1 - 0.5t₂)y, (1 + 0.5t₂)y)\n;\n; If we multiply them, we get\n;\n; i₃ = i₁i₂ = (l, u), where\n;\n; l = (1 - 0.5t₁)(1 - 0.5t₂)xy = 1 - 0.5t₁ - 0.5t₂ + 0.25t₁t₂\n; u = (1 + 0.5t₁)(1 + 0.5t₂)xy = 1 + 0.5t₁ + 0.5t₂ + 0.25t₁t₂\n;\n; We know that t₁ and t₂ are very small, which means that t₁t₂ is neglectable.\n; If we ignore it, we get the interval:\n;\n; i₃ = ((1 - 0.5(t₁ + t₂))xy, (1 + 0.5(t₁ + t₂))xy)\n;\n; Thus, the formula is:\n;\n; t₃ = t₁ + t₂\n"
  },
  {
    "path": "scheme/sicp/02/14.scm",
    "content": "; SICP exercise 2.14\n;\n; Demonstrate that Lem is right. Investigate the behavior of the system on a\n; variety of arithmetic expressions. Make some intervals A and B, and use them\n; in computing the expressions A/A and A/B. You will get the most insight by\n; using intervals whose width is a small percentage of the center value.\n; Examine the results of the computation in center-percent form (see exercise\n; 2.12).\n\n; Here is all the code we will need:\n\n(define (par1 r1 r2)\n  (div-interval (mul-interval r1 r2)\n                (add-interval r1 r2)))\n\n(define (par2 r1 r2)\n  (let ((one (make-interval 1 1)))\n    (div-interval one\n                  (add-interval (div-interval one r1)\n                                (div-interval one r2)))))\n\n(define (add-interval x y)\n  (make-interval (+ (lower-bound x) (lower-bound y))\n                 (+ (upper-bound x) (upper-bound y))))\n\n(define (mul-interval x y)\n  (let ((p1 (* (lower-bound x) (lower-bound y)))\n        (p2 (* (lower-bound x) (upper-bound y)))\n        (p3 (* (upper-bound x) (lower-bound y)))\n        (p4 (* (upper-bound x) (upper-bound y))))\n    (make-interval (min p1 p2 p3 p4)\n                   (max p1 p2 p3 p4))))\n\n(define (div-interval x y)\n  (mul-interval x\n                (make-interval (/ 1.0 (upper-bound y))\n                               (/ 1.0 (lower-bound y)))))\n\n(define (make-interval x y)\n  (cons x y))\n\n(define (lower-bound x)\n  (car x))\n\n(define (upper-bound x)\n  (cdr x))\n\n(define (percent i)\n  (* (/ (width i) (center i))\n     100))\n\n(define (center i)\n  (/ (+ (lower-bound i) (upper-bound i)) 2))\n\n(define (width i)\n  (/ (- (upper-bound i) (lower-bound i)) 2))\n\n(define (display-interval leading-text interval)\n  (display leading-text)\n  (display \": center = \")\n  (display (center interval))\n  (display \", percent = \")\n  (display (percent interval))\n  (newline))\n\n; Here are the A and B intervals\n\n(define A (make-interval  99.9 100.1))\n(define B (make-interval 199.9 200.1))\n(define one (make-interval 1.0 1.0))\n(define parallel-resistance (/ 1.0 \n                               (+ (/ 1.0 (center A)) \n                                  (/ 1.0 (center B)))))\n\n(display-interval \"A\" A)\n(display-interval \"B\" B)\n\n(display-interval \"par1\" (par1 A B))\n(display-interval \"par2\" (par2 A B))\n\n(display \"The parallel resistance of the two is \")\n(display parallel-resistance)\n(newline)\n\n(newline)\n\n; So far we have the following output\n; \n; A:    center = 100.0,             percent = 0.09999999999999432\n; B:    center = 200.0,             percent = 0.04999999999999716\n; par1: center = 66.66679629635391, percent = 0.2166663750004245\n; par2: center = 66.66666296296133, percent = 0.08333334166667185\n;\n; The parallel resistance of the two is 66.66666666666667\n;\n; We can see that par2 has smaller width and more accurate center. Let's check\n; out A/A and A/B\n\n(display-interval \"A/A\" (div-interval A A))\n(display-interval \"A/B\" (div-interval A B))\n(display-interval \"A+A\" (add-interval A A))\n\n(newline)\n\n; This time we get:\n;\n; A/A: center = 1.000002000002,     percent = 0.19999980000019435\n; A/B: center = 0.5000003750000938, percent = 0.14999992500003134\n; A+A: center = 200.0,              percent = 0.09999999999999432\n; \n; We see that addition preserves the tolerance in percentage, but\n; multiplication and division add them together. Let's take a look at the\n; parts of par1 and par2\n\n(display \"Let's do par1 first:\\n\")\n(display-interval \"AB\" (mul-interval A B))\n(display-interval \"A + B\" (add-interval A B))\n(display-interval \"AB/(A + B)\" (div-interval (mul-interval A B)\n                                             (add-interval A B)))\n(newline)\n\n(display \"Now par2:\\n\")\n(display-interval \"1/A\" (div-interval one A))\n(display-interval \"1/B\" (div-interval one B))\n(display-interval \"1/A + 1/B\" (add-interval (div-interval one A)\n                                            (div-interval one B)))\n(display-interval \"1/(1/A + 1/B)\" (par2 A B))\n(newline)\n\n; This is the output:\n;\n; Let's do par1 first:\n; AB:            center = 20000.010000000002,    percent = 0.14999992500002837\n; A + B:         center = 300.0,                 percent = 0.06666666666666288\n; AB/(A + B):    center = 66.66679629635391,     percent = 0.2166663750004245\n; \n; Now par2:\n; 1/A:           center = 0.010000010000009999,  percent = 0.09999999999999962\n; 1/B:           center = 0.0050000012500003126, percent = 0.04999999999999587\n; 1/A + 1/B:     center = 0.015000011250010312,  percent = 0.08333334166666921\n; 1/(1/A + 1/B): center = 66.66666296296133,     percent = 0.08333334166667185\n;\n; We can see that we loose precision on every multiplication and division - the\n; tolerance in percentage is of both factors is added together. Generally,\n; addition decreases the tolerance in percentage whe adding positive numbers\n; (that's not entirely true).\n;\n; In par2 we just do one addition, which decreases the tolerance under 0.01%,\n; while in par1 we first do a multiplication and then a division, that gets the\n; tolerance up to 0.21%.\n;\n; And just for a final illustration:\n\n(display-interval \"A*A/A\" (div-interval (mul-interval A A)\n                                        A))\n\n; This resuls to:\n;\n; A*A/A: center = 100.00040000039999, percent = 0.29999920000237845\n;\n; The real answer he is A, but the arithmetic gymnastics triple the tolerance.\n"
  },
  {
    "path": "scheme/sicp/02/15.scm",
    "content": "; SICP exercise 2.15\n;\n; Eva Lu Ator, another user, has also noticed the different intervals computed\n; by different but algebraically equivalent expressions. She says that a\n; formula to compute with intervals using Alyssa's system will produce tighter\n; error bounds if it can be written in such a form that no variable that\n; represents an uncertain number is repeated. Thus, she says, par2 is a\n; \"better\" program for parallel resistances than par1. Is she right? Why?\n\n; She is definitelly right.\n;\n; It is easy to see from the results of exercise 2.14 that the more we perform\n; operations with uncertain quantities, the bigger error we get. It is\n; important to note, that this applies mainly to multiplication and division.\n; 2A is exactly the same as AA.\n"
  },
  {
    "path": "scheme/sicp/02/16.scm",
    "content": "; SICP exercise 2.16\n;\n; Explain, in general, why equivalent algebraic expressions may lead to\n; different answers. Can you devise an interval-arithmetic package that does\n; not have this shortcoming, or is this task impossible? (Warning: This problem\n; is very difficult.)\n\n; After doing exercise 2.14, it is very easy to see that multiplying and\n; dividing uncertain quantities increases the uncertainty. AA/A is equivalent\n; to A, but the error margin is three times bigger. The less we use an\n; uncertain quantity in an operation, the smaller tolerance we get.\n;\n; As for addressing the shortcoming, the only way I can figure out is to\n; have the program simplify the expression as much as possible before\n; calculating it. I assume that this requires some serious mathematical\n; and computer science foundations, that I currently lack.\n;\n; One idea is to calculate this the expressions lazily. We can collect a tree\n; that represents the expression, until the result needs to be calculated. At\n; that point, we can simplify the expression and return the result. This won't\n; reduce the error margin, but may provide a nicer API.\n"
  },
  {
    "path": "scheme/sicp/02/17.scm",
    "content": "; SICP exercise 2.17\n;\n; Define a procedure last-pair that returns the list that contains only the last\n; element of a given (nonempty) list:\n;\n; (list-pair (list 23 72 149 34))\n; (34)\n\n(define (last-pair items)\n  (if (null? (cdr items))\n      items\n      (last-pair (cdr items))))\n"
  },
  {
    "path": "scheme/sicp/02/18.scm",
    "content": "; SICP exercise 2.18\n;\n; Define a procedure reverse that takes a list as argument and returns a list\n; of the same elements in reverse order:\n;\n; (reverse (list 1 4 9 16 25))\n; (25 16 9 4 1)\n\n; Here is a lame version:\n\n(define (reverse items)\n  (if (null? items)\n      items\n      (append (reverse (cdr items)) (list (car items)))))\n\n; Here's an alternative that's way better:\n\n(define (reverse items)\n  (define (iter items result)\n    (if (null? items)\n        result\n        (iter (cdr items) (cons (car items) result))))\n    \n  (iter items (list)))\n"
  },
  {
    "path": "scheme/sicp/02/19.scm",
    "content": "; SICP exercise 2.19\n;\n; Consider the change-counting program of Section 1.2.2. It would be nice to be\n; able to easily change the currency used by the program, so that we could\n; compute the number of ways to change a British pound, for example. As the\n; program is written, the knowledge of the currency is distributed partly into\n; the procedure first-denomination and partly into the procedure count-change\n; (which knows that there are five kinds of U.S. coins). It would be nicer to\n; be able to supply a list of coins to be used for making change.\n;\n; We want to rewrite the procedure cc so that its second argument is a list\n; of the values of the coins to use rather than an integer specifying which\n; coins to use. We could then have lists that defined each kind of currency:\n;\n; (define us-coins (list 50 25 10 5 1))\n; (define uk-coins (list 100 50 20 10 5 2 1 0.5))\n;\n; We could then call cc as follows:\n;\n; (cc 100 us-coins)\n; 292\n;\n; To do this will require changing the program cc somewhat. It will still have\n; the same form, but it will access its second argument differently, as follows:\n;\n; (define (cc amount coin-values)\n;   (cond ((= amount 0) 1)\n;         ((or (< amount 0) (no-more? coin-values)) 0)\n;         (else\n;           (+ (cc amount\n;                  (except-first-denomination\n;                    coin-values))\n;              (cc (- amount\n;                     (first-denomination coin-values))\n;                  coin-values)))))\n;\n; Define the procedures first-denomination, except-first-denomination and\n; no-more? in terms of primitive operations on list structures. Does the order\n; of the list coin-values affect the answer produced by cc? Why or why not?\n\n; The definitions are below.\n;\n; The order does not affect the value produced by cc. The procedure does not\n; depend on it in any way. There can be a difference in the time takes to\n; calculate the result, though.\n\n(define (cc amount coin-values)\n  (cond ((= amount 0) 1)\n        ((or (< amount 0) (no-more? coin-values)) 0)\n        (else\n          (+ (cc amount\n                 (except-first-denomination\n                   coin-values))\n             (cc (- amount\n                    (first-denomination coin-values))\n                 coin-values)))))\n\n(define (no-more? coins)\n  (null? coins))\n\n(define (first-denomination coins)\n  (car coins))\n\n(define (except-first-denomination coins)\n  (cdr coins))\n"
  },
  {
    "path": "scheme/sicp/02/20.scm",
    "content": "; SICP exercise 2.20\n;\n; The procedures +, * and list take arbitrary number of arguments. One way to\n; define such procedures is to use define with dotted-tail notation. In a\n; procedure definition, a parameter list that has a dot before the last\n; parameter name indicates that, when a procedure is called, the initial\n; parameters (if any) will have as values the initial arguments, as usual, but\n; the final parameter's value will be a list of any remaining arguments. For\n; instance, given the definition\n;\n; (define (f x y . z) <body>)\n;\n; the procedure f can be called with two or more arguments. If we evaluate\n;\n; (f 1 2 3 4 5 6)\n;\n; then in the body of f, x will be 1, y will be 2, and z will be the list (3 4 5 6).\n; Given the definition\n;\n; (define (g . w) <body>)\n;\n; the procedure g can be called with zero or more arguments. If we evaluate\n;\n; (g 1 2 3 4 5 6)\n;\n; then in the body of g, w will be the list (1 2 3 4 5 6).\n;\n; Use this notation to write a procedure same-parity that takes one or more\n; integers and returns a list of all the arguments that have the same even-odd\n; parity as the first argument. For example:\n;\n; (same-parity 1 2 3 4 5 6 7)\n; (1 3 5 7)\n;\n; (same-parity 2 3 4 5 6 7)\n; (2 4 6)\n\n(define (same-parity number . numbers)\n  (define (same-parity? n)\n    (= (remainder number 2) (remainder n 2)))\n\n  (define (filter-list numbers)\n    (cond ((null? numbers) (list))\n          ((same-parity? (car numbers)) (cons (car numbers)\n                                              (filter-list (cdr numbers))))\n          (else (filter-list (cdr numbers)))))\n\n  (cons number (filter-list numbers)))\n\n"
  },
  {
    "path": "scheme/sicp/02/21.scm",
    "content": "; SICP exercise 2.21\n;\n; The procedure square-list takes a list of numbers as arguments and returns a\n; list of the squares of those numbers.\n;\n; (square-list (list 1 2 3 4))\n; (1 4 9 16)\n;\n; Here are two different definitions of square-list. Complete both of the by\n; filling in the missing expressions:\n;\n; (define (square-list items)\n;   (if (null? items)\n;       nil\n;       (cons <??> <??>)))\n;\n; (define (square-list items)\n;   (map <??> <??>))\n\n(define (square-list-1 items)\n  (if (null? items)\n      '()\n      (cons (square (car items))\n            (square-list-1 (cdr items)))))\n\n(define (square-list-2 items)\n  (map square items))\n\n(define (square x)\n  (* x x))\n"
  },
  {
    "path": "scheme/sicp/02/22.scm",
    "content": "; SICP exercise 2.22\n;\n; Louis Reasoner tries to rewrite the first square-list procedure on Exercise 2.21\n; so that it evolves an iterative process:\n;\n; (define (square-list items)\n;   (define (iter things answer)\n;     (if (null? things)\n;         answer\n;         (iter (cdr things)\n;               (cons (square (car things))\n;                     answer))))\n;   (iter items nil))\n;\n; Unfortunatelly, defining square-list this way produces the answer list in the\n; reverse order of the one desired. Why?\n;\n; Louis then tries to fix his bug by interchanging the arguments to cons:\n;\n; (define (square-list items)\n;   (define (iter things answer)\n;     (if (null? things)\n;         answer\n;         (iter (cdr things)\n;               (cons answer\n;                     (square (car things))))))\n;   (iter items nil))\n;\n; This doesn't work either. Explain.\n\n; In the first program, we are accumulating the answer by adding the square of\n; each item to the front of the list. It is easy to see that (car items)\n; becomes the last element of answer, (cadr items) becomes the second to last\n; and so on.\n;\n; As for the second version, the result is not a list. It is a pair, where the\n; cdr in the squared item and the car is a pair with the next square (stored in\n; the cadr of result). Furthermore, it is still in the wrong order.\n"
  },
  {
    "path": "scheme/sicp/02/23.scm",
    "content": "; SICP exercise 2.23\n;\n; The procedure for-each is similar to map. It takes as arguments a procedure\n; and a list of elements. However, rather than forming a list of the results,\n; for-each just applies the procedure to each of the elements in turn, from\n; left to right. The values returned by applying the procedure to the elements\n; are not used at all - for-each is used with procedures that perform an action\n; such as printing. For example,\n;\n; (for-each (lambda (x) (newline) (display x))\n;           (list 57 321 88))\n;\n; The value returned by the call to for-each (not illustrated above) can be\n; something arbitrary, such as true. Give an implementation of for-each.\n\n(define (for-each function items)\n  (cond ((null? items) true)\n        (else (function (car items))\n              (for-each function (cdr items)))))\n"
  },
  {
    "path": "scheme/sicp/02/24.scm",
    "content": "; SICP exercise 2.24\n;\n; Suppose we evaluate the expression (list 1 (list 2 (list 3 4))). Give the\n; result printed by the interpreter, the corresponding box-and-pointer\n; structure, and the interpretation of this as a tree (as in Figure 2.6).\n\n; The interpreter will print:\n;\n; (1 (2 (3 4)))\n;\n; This is the \"box-and-pointer\" structure. I quote it because of the ASCII.\n;\n;     +---+---+      +---+---+\n; --> | o | o-+----> | o | / |\n;     +-|-+---+      +-|-+---+\n;       |              |\n;       |              |\n;     +---+          +---+---+      +---+---+\n;     | 1 |          | o | o------> | o | / |\n;     +---+          +-|-+---+      +-|-+---+\n;                      |              |\n;                      |              |\n;                    +---+          +---+---+      +---+---+\n;                    | 2 |          | o | o------> | o | / |\n;                    +---+          +-|-+---+      +-|-+---+\n;                                     |              |\n;                                     |              |\n;                                   +---+          +---+\n;                                   | 3 |          | 4 |\n;                                   +---+          +---+\n;\n; Here's the tree:\n;\n;               o  (1 (2 (3 4)))\n;             /   \\\n;           /       \\ \n;         1          o  (2 (3 4)\n;                  /   \\\n;                /       \\\n;               2         o  (3 4)\n;                       /   \\\n;                     /       \\\n;                    3         4\n"
  },
  {
    "path": "scheme/sicp/02/25.scm",
    "content": "; SICP exercise 2.25\n;\n; Give combinations of cars and cdrs that will pick 7 from each of the\n; following lists:\n;\n; (1 3 (5 7) 9)\n; ((7))\n; (1 (2 (3 (4 (5 (6 7))))))\n\n; Simple:\n;\n; (car (cdr (car (cdr (cdr '(1 3 (5 7) 9))))))\n; 7\n; (car (car '((7))))\n; 7\n; (car (cdr (car (cdr (car (cdr (car (cdr (car (cdr (car (cdr '(1 (2 (3 (4 (5 (6 7))))))))))))))))))\n; 7\n"
  },
  {
    "path": "scheme/sicp/02/26.scm",
    "content": "; SICP exercise 2.26\n;\n; Suppose we define x and y to be two lists:\n;\n; (define x (list 1 2 3))\n;\n; (define y (list 4 5 6))\n;\n; What result is printed by the interpreter in response evaluating each of the\n; following expressions:\n;\n; (append x y)\n;\n; (cons x y)\n;\n; (list x y)\n\n; Another simple one:\n;\n; (append x y)\n; (1 2 3 4 5 6)\n;\n; (cons x y)\n; ((1 2 3) 4 5 6)\n;\n; (list x y)\n; ((1 2 3) (4 5 6))\n"
  },
  {
    "path": "scheme/sicp/02/27.scm",
    "content": "; SICP exercise 2.27\n;\n; Modify your reverse procedure in exercise 2.18 to produce a deep-reverse\n; procedure that takes a list as argument and returns as its value the list\n; with its elements reversed and with all sublists deep-reversed as well. For\n; example,\n;\n; (define x (list (list 1 2) (list 3 4)))\n;\n; x\n; ((1 2) (3 4))\n;\n; (reverse x)\n; ((3 4) (1 2))\n;\n; (deep-reverse x)\n; ((4 3) (2 1))\n\n(define (deep-reverse items)\n  (define (iter items result)\n    (cond ((null? items) result)\n          ((pair? (car items))\n           (iter (cdr items) (cons (deep-reverse (car items)) result)))\n          (else (iter (cdr items) (cons (car items) result)))))\n    \n  (iter items (list)))\n"
  },
  {
    "path": "scheme/sicp/02/28.scm",
    "content": "; SICP exercise 2.28\n;\n; Write a procedure fringe that takes as argument a tree (represented as a\n; list) and returns a list whose elements are all the leaves of the tree\n; arranged in left-to-right order. For example,\n;\n; (define x (list (list 1 2) (list 3 4)))\n;\n; (fringe x)\n; (1 2 3 4)\n;\n; (fringe (list x x))\n; (1 2 3 4 1 2 3 4)\n\n; Here's a recursive version:\n\n(define (fringe tree)\n  (cond ((null? tree) tree)\n        ((pair? tree) (append (fringe (car tree)) (fringe (cdr tree))))\n        (else (list tree))))\n\n; I'm not too happy about it, so I am also going to make an iterative version\n; that does not use append or reverse.\n\n(define (fringe tree)\n  (define (iter left bottom result)\n    (cond ((and (null? left) (null? bottom)) result)\n          ((null? bottom) (iter (cdr left) (car left) result))\n          ((pair? bottom) (iter (cons (car bottom) left) (cdr bottom) result))\n          (else (iter left '() (cons bottom result)))))\n\n  (iter '() tree '()))\n"
  },
  {
    "path": "scheme/sicp/02/29.scm",
    "content": "; SICP exercise 2.29\n;\n; A binary mobile consists of two branches, a left branch and a right branch.\n; Each branch is a rod of certain length, from which hangs either a weight or\n; another binary mobile. We can represent a binary mobile using compund data by\n; constructing it from two branches (for example, using list):\n;\n; (define (make-mobile left right)\n;   (list left right))\n;\n; A branch is constructed from a length (which must be a number) together with\n; a structure, which may be either a number (representing a simple weight) or\n; another mobile:\n;\n; (define (make-branch length structure)\n;   (list length structure))\n;\n; a. Write the corresponding selectors left-branch and right-branch, which\n; return the branches of a mobile, and branch-length and branch-structure,\n; which return the components of a branch.\n;\n; b. Using your selectors, define a procedure total-weight that returns the\n; total weight of a mobile.\n;\n; c. A mobile is said to be balanced if the torque applied by its top-left\n; branch is equal to that applied by its top-right branch (that is, if the\n; length of the left rod multiplied by the weight hanging from that rod is\n; equal to the corresponding product of the right side) and if each of the\n; submobiles hanging off its branches is balanced. Design a predicate that\n; tests whether a binary mobile is balanced.\n;\n; d. Suppose we change the representation of mobiles so that the constructors\n; are\n;\n; (define (make-mobile left right)\n;   (cons left right))\n;\n; (define (make-branch length structure)\n;   (cons length structure))\n;\n; How much do you need to change your programs to convert to the new\n; representation?\n\n(define (make-mobile left right)\n  (list left right))\n\n(define (make-branch length structure)\n  (list length structure))\n\n; a.\n;\n; Here are the selectors, with a little extra:\n\n(define (left-branch mobile)\n  (car mobile))\n\n(define (right-branch mobile)\n  (cadr mobile))\n\n(define (branch-length branch)\n  (car branch))\n\n(define (branch-structure branch)\n  (cadr branch))\n\n(define (weight? structure)\n  (not (pair? structure)))\n\n; b.\n;\n; This is total-weight. It depends on an additional selector.\n\n(define (total-weight structure)\n  (if (weight? structure)\n      structure\n      (+ (total-weight (branch-structure (left-branch structure)))\n         (total-weight (branch-structure (right-branch structure))))))\n\n; c.\n;\n; Testing whether a mobile is balanced is a bit messy. It also makes use of\n; weight?\n\n(define (balanced? mobile)\n  (define (torque branch)\n    (* (branch-length branch)\n       (total-weight (branch-structure branch))))\n  (define (balanced-submobile? branch)\n    (or (weight? (branch-structure branch))\n        (balanced? (branch-structure branch))))\n  (let ((left (left-branch mobile))\n        (right (right-branch mobile)))\n    (and (= (torque left) (torque right))\n         (balanced-submobile? left)\n         (balanced-submobile? right))))\n\n; d.\n;\n; Let's just do it:\n\n(define (make-mobile left right)\n  (cons left right))\n\n(define (make-branch length structure)\n  (cons length structure))\n\n; This is what has to change\n\n(define (right-branch mobile)\n  (cdr mobile))\n\n(define (branch-structure branch)\n  (cdr branch))\n\n; That way we accomplish a neat abstraction barrier. If we delete the last four\n; definitions, the tests will continue to pass.\n"
  },
  {
    "path": "scheme/sicp/02/30.scm",
    "content": "; SICP exercise 2.30\n;\n; Define a procedure square-tree analogous to the square-list procedure of\n; exercise 2.21. Thas is, square-tree should behave as follows:\n;\n; (square-tree \n;   (list 1\n;         (list 2 (list 3 4) 5)\n;         (list 6 7)))\n; (1 (4 (9 16) 25) (36 49)))\n;\n; Define square-tree both directly (i.e., without using any higher-order\n; procedures) and also by using map and recursion.\n\n(define (square-tree tree)\n  (cond ((null? tree) '())\n        ((not (pair? tree)) (* tree tree))\n        (else (cons (square-tree (car tree))\n                    (square-tree (cdr tree))))))\n\n(define (square-tree tree)\n  (map (lambda (tree)\n         (if (pair? tree)\n             (square-tree tree)\n             (* tree tree)))\n       tree))\n"
  },
  {
    "path": "scheme/sicp/02/31.scm",
    "content": "; SICP exercise 2.31\n;\n; Abstract your answers to exercise 2.30 to produce a procedure tree-map with\n; the property that square-tree could be defined as\n;\n; (define (square-tree tree) (tree-map square tree))\n\n(define (tree-map function tree)\n  (cond ((null? tree) (list))\n        ((not (pair? tree)) (function tree))\n        (else (cons (tree-map function (car tree))\n                    (tree-map function (cdr tree))))))\n\n(define (square-tree tree)\n  (tree-map square tree))\n\n(define (square x)\n  (* x x))\n"
  },
  {
    "path": "scheme/sicp/02/32.scm",
    "content": "; SICP exercise 2.32\n;\n; We can represent a set as a list of distinct elements, and we can represent\n; the set of all subsets of the set as a list of lists. For example, if the set\n; is (1 2 3), then the set of all subsets is (() (3) (2) (2 3) (1) (1 3) (1 2)\n; (1 2 3)). Complete the following definition of a procedure that generates the\n; set of subsets of a set and give a clear explanation of why it works:\n; \n; (define (subsets s)\n;   (if (null? s)\n;       (list (list))\n;       (let ((rest (subsets (cdr s))))\n;         (append rest (map <??> rest)))))\n\n; Easy\n\n(define (subsets s)\n  (if (null? s)\n      (list (list))\n      (let ((rest (subsets (cdr s))))\n        (append rest\n                (map (lambda (subset) (cons (car s) subset)) \n                     rest)))))\n\n; It works, because the subsets of a set are all the subsets that don't contain\n; the first element plus all the subsets that do.\n"
  },
  {
    "path": "scheme/sicp/02/33.scm",
    "content": "; SICP exercise 2.33\n;\n; Fill in the missing expressions to complete the following definitions of some\n; basic list-manipulation operations as accumulations:\n;\n; (define (map p sequence)\n;   (accumulate (lambda (x y) <??>) nil sequence))\n;\n; (define (append seq1 seq2)\n;   (accumulate cons <??> <??>))\n;\n; (define (length sequence)\n;   (accumulate <??> 0 sequence))\n\n(define (map p sequence)\n  (accumulate (lambda (x y) (cons (p x) y)) nil sequence))\n\n(define (append seq1 seq2)\n  (accumulate cons seq2 seq1))\n\n(define (length sequence)\n  (accumulate (lambda (_ result) (+ result 1)) 0 sequence))\n\n\n\n(define (accumulate op initial sequence)\n  (if (null? sequence)\n      initial\n      (op (car sequence)\n          (accumulate op initial (cdr sequence)))))\n\n(define nil '())\n"
  },
  {
    "path": "scheme/sicp/02/34.scm",
    "content": "; SICP exercise 2.34\n;\n; Evaluating a polynomial in x at a given value of x can be formulated as an\n; accumulation. We evaluate the polynomial\n;\n; aᵢxⁱ + aᵢ₋₁xⁱ⁻¹ + … + a₁x + a₀\n;\n; using a well-known algorithm called Horner's rule, which structures the\n; computation as\n;\n; (…(aᵢx + aᵢ₋₁)x + … + a₁)x + a₀\n;\n; In other words, we start with aᵢ, multiply by x, add aᵢ₋₁, multiply by x, and\n; so on, until we reach a₀.\n;\n; Fill in the following template to produce a procedure that evaluates a\n; polynomial using Horner's rule. Assume that the coefficients of the\n; polynomial are arranged in a sequence, from a₀ through aᵢ.\n;\n; (define (horner-eval x coefficient-sequence)\n;   (accumulate (lambda (this-coeff higher-terms) <??>)\n;               0\n;               coefficient-sequence)\n;\n; For example, to compute 1 + 3x + 5x³ + x⁵ at x = 2 you would evaluate\n;\n; (horner-eval 2 (list 1 3 0 5 0 1))\n\n(define (horner-eval x coefficient-sequence)\n  (accumulate (lambda (this-coeff higher-terms) (+ (* higher-terms x) this-coeff))\n              0\n              coefficient-sequence))\n\n(define (accumulate op initial sequence)\n  (if (null? sequence)\n      initial\n      (op (car sequence)\n          (accumulate op initial (cdr sequence)))))\n"
  },
  {
    "path": "scheme/sicp/02/35.scm",
    "content": "; SICP exercise 2.35\n;\n; Redefine count-leaves from section 2.2.2 as an accumulation:\n;\n; (define (count-leaves t)\n;   (accumulate <??> <??> (map <??> <??>)))\n\n(define (count-leaves tree)\n  (accumulate +\n              0\n              (map (lambda (x) (if (pair? x) (count-leaves x) 1))\n                   tree)))\n\n(define (accumulate op initial sequence)\n  (if (null? sequence)\n      initial\n      (op (car sequence)\n          (accumulate op initial (cdr sequence)))))\n"
  },
  {
    "path": "scheme/sicp/02/36.scm",
    "content": "; SICP exercise 2.36\n;\n; The procedure accumulate-n is similar to accumulate except that it takes as\n; its third argument a sequence of sequences, which are all assumed to have the\n; same number of elements. It applies the designated accumulation procedure to\n; combine all the first elements of the sequences, all the second elements of\n; the sequences, and so on, and returns a sequence of the results. For\n; instance, if s is a sequence containing four sequences,\n; ((1 2 3) (4 5 6) (7 8 9) (10 11 12)), then the value of (accumulate-n + 0 s)\n; should be the sequences (22 26 30). Fill in the missing expressions in the\n; following definition of accumulate-n:\n;\n; (define (accumulate-n op init seqs)\n;   (if (null? (car seqs))\n;       nil\n;       (cons (accumulate op init <??>)\n;             (accumulate-n op init <??>))))\n\n(define (accumulate-n op init seqs)\n  (if (null? (car seqs))\n      nil\n      (cons (accumulate op init (map car seqs))\n            (accumulate-n op init (map cdr seqs)))))\n\n\n\n(define (accumulate op initial sequence)\n  (if (null? sequence)\n      initial\n      (op (car sequence)\n          (accumulate op initial (cdr sequence)))))\n\n(define nil '())\n"
  },
  {
    "path": "scheme/sicp/02/37.scm",
    "content": "; SICP exercise 2.37\n;\n; Suppose we represent vectors v = (vᵢⱼ) as sequences of numbers, and matrices\n; m = (mᵢⱼ) as sequences of vectors (rows of the matrix). For example, the\n; matrix\n;\n;   1 2 3 4\n;   4 5 6 6\n;   6 7 8 9\n;\n; is represented as the sequence ((1 2 3 4) (4 5 6 6) (6 7 8 9)). With this\n; representation, we can use sequence operations to concisely express the basic\n; matrix and vector operations. These operations (which are described in any\n; book on matrix algebra) are the following:\n;\n;     (dot-product v w) returns the sum Σᵢvᵢwᵢ\n; (matrix-*-vector m v) returns the vector t, where tᵢ = Σⱼmᵢⱼvⱼ\n; (matrix-*-matrix m n) returns the matrix p, where pᵢⱼ = Σᵤmᵢᵤvᵤⱼ\n;         (transpose m) returns the matrix n, where nᵢⱼ = mⱼᵢ\n;\n; We can define the dot product as\n;\n; (define (dot-product v w)\n;   (accumulate + 0 (map * v w)))\n;\n; Fill in the missing expressions in the following procedures for computing the\n; other matrix operations. (The procedure accumulate-n is defined exercise 2.36.)\n;\n; (define (matrix-*-vector m v)\n;   (map <??> m))\n;\n; (define (transpose mat)\n;   (accumulate-n <??> <??> mat))\n;\n; (define (matrix-*-matrix m n)\n;   (let ((cols (transpose n)))\n;     (map <??> m)))\n\n(define (dot-product v w)\n  (accumulate + 0 (map * v w)))\n\n(define (matrix-*-vector m v)\n  (map (lambda (x) (dot-product x v)) m))\n\n(define (transpose mat)\n  (accumulate-n cons nil mat))\n\n(define (matrix-*-matrix m n)\n  (let ((cols (transpose n)))\n    (map (lambda (row) (matrix-*-vector cols row)) m)))\n\n\n\n(define (accumulate-n op init seqs)\n  (if (null? (car seqs))\n      nil\n      (cons (accumulate op init (map car seqs))\n            (accumulate-n op init (map cdr seqs)))))\n\n(define (accumulate op initial sequence)\n  (if (null? sequence)\n      initial\n      (op (car sequence)\n          (accumulate op initial (cdr sequence)))))\n\n(define nil '())\n"
  },
  {
    "path": "scheme/sicp/02/38.scm",
    "content": "; SICP exercise 2.38\n;\n; The accumulate procedure is also knows as fold-right, because it combines the\n; first element of the sequence with the result of combining all the elements\n; to the right. There is also a fold-left, which is similar to fold-right,\n; except that it combines elements working in the opposite direction:\n;\n; (define (fold-left op initial sequence)\n;   (define (iter result rest)\n;     (if (null? rest)\n;         result\n;         (iter (op result (car rest))\n;               (cdr rest))))\n;   (iter initial sequence))\n;\n; What are the values of\n; \n; (fold-right / 1 (list 1 2 3))\n; (1 / (2 / (3 / 1)))\n; (1 / (2 / 3))\n; 3 / 2\n;\n; (fold-left / 1 (list 1 2 3))\n; (((1 / 1) / 2) / 3)\n; (1 / 2) / 3\n; 3 / 2\n;\n; (fold-right list nil (list 1 2 3))\n; '(1 (2 (3 '())))\n;\n; (fold-left list nil (list 1 2 3))\n; ((('() 1) 2) 3)\n;\n; Give a property that op should satisfy to guarantee that fold-right and\n; fold-left will produce the same values for any sequence.\n\n; Here are the answers:\n;\n; (fold-right / 1 (list 1 2 3))\n; (/ 1 (/ 2 (/ 3 1)))\n; (/ 1 (/ 2 3))\n; (/ 1 2/3)\n; 3/2\n;\n; (fold-left / 1 (list 1 2 3))\n; (/ (/ (/ 1 1) 2) 3)\n; (/ (/ 1 2) 3)\n; (/ 1/2 3)\n; 1/6\n;\n; (fold-right list nil (list 1 2 3))\n; (1 (2 (3 ())))\n;\n; (fold-left list nil (list 1 2 3))\n; (((() 1) 2) 3)\n;\n; The property is associativity, that is:\n;\n; a * (b * c) = (a * b) * c\n;\n; where * denotes the operation\n"
  },
  {
    "path": "scheme/sicp/02/39.scm",
    "content": "; SICP exercise 2.39\n;\n; Complete the following definitions of reverse (exercise 2.18) in terms of\n; fold-right and fold-left from exercise 2.38:\n;\n; (define (reverse sequence)\n;   (fold-right (lambda (x y) <??>) nil sequence))\n;\n; (define (reverse sequence)\n;   (fold-left (lambda (x y) <??>) nil sequence))\n\n(define (reverse-r sequence)\n  (fold-right (lambda (x y) (append y (list x)))\n              nil\n              sequence))\n\n(define (reverse-l sequence)\n  (fold-left (lambda (x y) (cons y x))\n             nil\n             sequence))\n\n\n\n(define (fold-left op initial sequence)\n  (define (iter result rest)\n    (if (null? rest)\n        result\n        (iter (op result (car rest))\n              (cdr rest))))\n  (iter initial sequence))\n\n(define (fold-right op initial sequence)\n  (if (null? sequence)\n      initial\n      (op (car sequence)\n          (fold-right op initial (cdr sequence)))))\n\n(define nil '())\n"
  },
  {
    "path": "scheme/sicp/02/40.scm",
    "content": "; SICP exercise 2.40\n;\n; Define a procedure unique-pairs that, given an integer n, generates the\n; sequence of pairs (i, j) with 1 ≤ j < i ≤ n. Use unique-pairs to simplify the\n; definition of prime-sum-pairs given above.\n\n(define (unique-pairs n)\n  (flatmap (lambda (a)\n             (map (lambda (b) (list a b))\n                  (enumerate-interval (+ a 1) n)))\n           (enumerate-interval 1 n)))\n\n(define (prime-sum-pairs n)\n  (filter (lambda (pair)\n            (prime? (+ (car pair)\n                       (cadr pair))))\n          (unique-pairs n)))\n\n\n\n\n(define (enumerate-interval a b)\n  (if (> a b)\n    (list)\n    (cons a\n          (enumerate-interval (+ a 1) b))))\n\n(define (flatmap proc seq)\n  (accumulate append nil (map proc seq)))\n\n(define (accumulate op initial sequence)\n  (if (null? sequence)\n      initial\n      (op (car sequence)\n          (accumulate op initial (cdr sequence)))))\n\n(define (prime? n)\n  (null?\n    (filter (lambda (x) (= 0 (remainder n x)))\n            (enumerate-interval 2 (- n 1)))))\n\n(define nil '())\n"
  },
  {
    "path": "scheme/sicp/02/41.scm",
    "content": "; SICP exercise 2.41\n;\n; Write a procedure to find all ordered priples of distinct positive integers\n; i, j, and k less than or equal to a given integer n that sums to a given\n; integer s.\n\n(define (triples-sum n s)\n  (filter (lambda (triple) (= s (sum triple)))\n          (enumerate-triples n)))\n\n(define (enumerate-triples n)\n  (flatmap (lambda (a)\n             (flatmap (lambda (b)\n                        (map (lambda (c) (list a b c))\n                             (enumerate-interval (+ b 1) n)))\n                      (enumerate-interval (+ a 1) n)))\n           (enumerate-interval 1 n)))\n\n\n\n(define (sum numbers)\n  (accumulate + 0 numbers))\n\n(define (enumerate-interval a b)\n  (if (> a b)\n    (list)\n    (cons a\n          (enumerate-interval (+ a 1) b))))\n\n(define (flatmap proc seq)\n  (accumulate append nil (map proc seq)))\n\n(define (accumulate op initial sequence)\n  (if (null? sequence)\n      initial\n      (op (car sequence)\n          (accumulate op initial (cdr sequence)))))\n\n(define nil '())\n"
  },
  {
    "path": "scheme/sicp/02/42.scm",
    "content": "; SICP exercise 2.42\n;\n; The \"eight-queens puzzle\" asks how to place eight queens on a chessboard so\n; that no queen is in check from any other (i.e., no two queens are in the same\n; row, column, or diagonal). One possible solution is shown in Figure 2.8. One\n; way to solve the puzzle is to work accross the board, placing a queen in each\n; column. Once we have placed k - 1 queens, we must place the kth queen in a\n; position where it does not check any of the queens already on the board. We\n; can formulate this approach recursively: Assume that we have already\n; generated the sequence of all possible ways to place k - 1 queens in the\n; first k - 1 columns of the board. For each of these ways, generate an\n; extended set of positions by placing a queen in each row of the kth column.\n; Now filter these, keeping only the positions for which the queen in the kth\n; column is safe with respect to other queens. This produces the sequence of\n; all ways to place k queens in the first k columns. By continuation of this\n; process, we will produce not only one solution, but all solutions to the\n; puzzle.\n;\n; We implement this solution as a procedure queens, which returns a sequence\n; of all solutions to the problem of placing n queens on n ╳ n chessboard.\n; queens has an internal procedure queen-cols that returns the sequence of all\n; ways to place queens in the first k columns of the board.\n;\n; (define (queens board-size)\n;   (define (queen-cols k)\n;     (if (= k 0)\n;         (list empty-board)\n;         (filter\n;           (lambda (positions) (safe? k positions))\n;           (flatmap\n;             (lambda (rest-of-queens)\n;               (map (lambda (new-row)\n;                      (adjoin-position new-row\n;                                       k\n;                                       rest-of-queens))\n;                    (enumerate-interval 1 board-size)))\n;             (queen-cols (- k 1))))))\n;   (queen-cols board-size))\n;\n; In this procedure rest-of-queens is a way to place k - 1 queens in the first\n; k - 1 columns, and new-row is a proposed row in which to place the queen for\n; the kth column. Complete the program by implementing the representation for\n; sets of board positions, including the procedure adjoin-position, which\n; adjoins a new row-column position to a set of positions, and empty-board,\n; which represents an empty set of positions. You must also write the procedure\n; safe?, which determines for a set of positions whether the queen in the kth\n; column is safe with respect to the others. (Note that we need only check\n; whether the new queen is safe - the other queens are already guaranteed safe\n; with respet to each other).\n\n(define (queens board-size)\n  (define (queen-cols k)\n    (if (= k 0)\n        (list empty-board)\n        (filter\n          (lambda (positions) (safe? k positions))\n          (flatmap\n            (lambda (rest-of-queens)\n              (map (lambda (new-row)\n                     (adjoin-position new-row\n                                      k\n                                      rest-of-queens))\n                   (enumerate-interval 1 board-size)))\n            (queen-cols (- k 1))))))\n  (queen-cols board-size))\n\n\n\n(define empty-board '())\n\n(define (adjoin-position new-row k rest-of-queens)\n  (cons (list new-row k) rest-of-queens))\n\n(define (safe? k positions)\n  (define queen-position (queen-at k positions))\n  (let ((q1r (car queen-position))\n        (q1c (cadr queen-position)))\n    (all?\n      (lambda (position)\n        (let ((q2r (car position))\n              (q2c (cadr position)))\n          (or (and (= q1r q2r)\n                   (= q1c q2c))\n              (and (not (= q1r q2r))\n                   (not (= q1c q2c))\n                   (not (= (+ q1r q1c)\n                           (+ q2r q2c)))\n                   (not (= (- q1r q1c)\n                           (- q2r q2c)))))))\n      positions)))\n\n\n\n(define (queen-at column positions)\n  (if (= column (cadar positions))\n      (car positions)\n      (queen-at column (cdr positions))))\n\n(define (all? proc seq)\n  (cond ((null? seq) #t)\n        ((proc (car seq)) (all? proc (cdr seq)))\n        (else #f)))\n\n\n\n(define (enumerate-interval a b)\n  (if (> a b)\n    (list)\n    (cons a\n          (enumerate-interval (+ a 1) b))))\n\n(define (flatmap proc seq)\n  (accumulate append '() (map proc seq)))\n\n(define (accumulate op initial sequence)\n  (if (null? sequence)\n      initial\n      (op (car sequence)\n          (accumulate op initial (cdr sequence)))))\n"
  },
  {
    "path": "scheme/sicp/02/43.scm",
    "content": "; SICP exercise 2.43\n;\n; Louis Reasoner is having a terrible time doing Exercise 2.42. His queens\n; procedure seems to work, but it runs extremely slow. (Louis never does manage\n; to wait long enough for it to solve even the 6x6 case.) When Louis asks Eva\n; Lu Ator for help, she points out that he has interchanged the order of the\n; nested mappings in the flatmap, writing it as\n;\n; (flatmap\n;   (lambda (new-row)\n;     (map (lambda (rest-of-queens)\n;            (adjoin-position new-row k rest-of-queens))\n;          (queen-cols (- k 1))))\n;   (enumerate-interval 1 board-size))\n;\n; Explain why this interchange makes the program run slowly. Estimate how long\n; it will take Louis's program to solve the eight-queens puzzle, assuming that\n; the program in Exercise 2.42 solves the puzzle in time T.\n\n; It appears Mr. Reasoner has a lot to learn - he keeps fumbling. Anyhow:\n;\n; In 2.42 we generated a valid nxn board with (queen-cols) and then extended it\n; with n + 1 queens. In Louis's program, when generating a nxn board, we\n; calculate the (n-1)x(n-1) boards n times. This means, that we end up doing\n; the full calculation 1 time for the 2x2 board, 2 times for the 3x3 board, 3\n; times for the 4x4 board and so forth. In the end, we end up doing it 7!\n; times. So if the program in 2.42 solves the puzzle in time T, Louis's would\n; do it in 7!T. Pretty bad.\n;\n; Let's see what the numbers tell us.\n;\n; Slow queens: 24892.343017578125\n; Fast queens: 5.5859375\n;\n; The result I expected is ~28152 milliseconds, which is 13% off. Oh well.\n; At least I can wait for it :)\n\n(define (slow-queens board-size)\n  (define (queen-cols k)\n    (if (= k 0)\n        (list empty-board)\n        (filter\n          (lambda (positions) (safe? k positions))\n            (flatmap\n              (lambda (new-row)\n                (map (lambda (rest-of-queens)\n                       (adjoin-position new-row k rest-of-queens))\n                     (queen-cols (- k 1))))\n              (enumerate-interval 1 board-size)))))\n  (queen-cols board-size))\n\n(define (fast-queens board-size)\n  (define (queen-cols k)\n    (if (= k 0)\n        (list empty-board)\n        (filter\n          (lambda (positions) (safe? k positions))\n          (flatmap\n            (lambda (rest-of-queens)\n              (map (lambda (new-row)\n                     (adjoin-position new-row\n                                      k\n                                      rest-of-queens))\n                   (enumerate-interval 1 board-size)))\n            (queen-cols (- k 1))))))\n  (queen-cols board-size))\n\n\n\n(define empty-board '())\n\n(define (adjoin-position new-row k rest-of-queens)\n  (cons (list new-row k) rest-of-queens))\n\n(define (safe? k positions)\n  (define queen-position (queen-at k positions))\n  (let ((q1r (car queen-position))\n        (q1c (cadr queen-position)))\n    (all?\n      (lambda (position)\n        (let ((q2r (car position))\n              (q2c (cadr position)))\n          (or (and (= q1r q2r)\n                   (= q1c q2c))\n              (and (not (= q1r q2r))\n                   (not (= q1c q2c))\n                   (not (= (+ q1r q1c)\n                           (+ q2r q2c)))\n                   (not (= (- q1r q1c)\n                           (- q2r q2c)))))))\n      positions)))\n\n\n\n(define (queen-at column positions)\n  (if (= column (cadar positions))\n      (car positions)\n      (queen-at column (cdr positions))))\n\n(define (all? proc seq)\n  (cond ((null? seq) #t)\n        ((proc (car seq)) (all? proc (cdr seq)))\n        (else #f)))\n\n\n\n(define (enumerate-interval a b)\n  (if (> a b)\n    (list)\n    (cons a\n          (enumerate-interval (+ a 1) b))))\n\n(define (flatmap proc seq)\n  (accumulate append '() (map proc seq)))\n\n(define (accumulate op initial sequence)\n  (if (null? sequence)\n      initial\n      (op (car sequence)\n          (accumulate op initial (cdr sequence)))))\n\n\n\n(define (time message proc)\n  (let ((start (current-inexact-milliseconds)))\n    (proc)\n    (let ((time-taken (- (current-inexact-milliseconds) start)))\n      (printf \"~a: ~a\\n\" message time-taken))))\n\n\n\n; Warm up\n(slow-queens 2)\n(fast-queens 2)\n\n; Timing\n(time \"Slow queens\" (lambda () (slow-queens 8)))\n(time \"Fast queens\" (lambda () (fast-queens 8)))\n"
  },
  {
    "path": "scheme/sicp/02/44.scm",
    "content": "; SICP exercise 2.44\n;\n; Define the procedure up-split used by corner-split. It is similar to\n; right-split, except that it switches the roles of below and beside.\n\n(define (up-split painter n)\n  (if (= n 0)\n      painter\n      (let ((smaller (up-split painter (- n 1))))\n        (below painter (beside smaller smaller)))))\n"
  },
  {
    "path": "scheme/sicp/02/45.scm",
    "content": "; SICP exercise 2.45\n;\n; right-split and up-split can be expressed as instances of a general splitting\n; operation. Define a procedure split with the property that evaluating\n;\n;   (define right-split (split beside below))\n;   (define up-split (split below beside))\n;\n; produces right-split and up-split with the same behaviors as the ones already\n; defined.\n\n(define (split op1 op2)\n  (define (split-proc painter n)\n    (if (= n 0)\n        painter\n        (let ((smaller (split-proc painter (- n 1))))\n          (op1 painter (op2 smaller smaller)))))\n  split-proc)\n\n(define right-split (split beside below))\n(define up-split (split below beside))\n"
  },
  {
    "path": "scheme/sicp/02/46.scm",
    "content": "; SICP exercise 2.46\n;\n; A two-dimensional vector v running from the origin to a point can be\n; represented as a pair consisting of an x-coordinate and a y-coordinate.\n; Implement a data abstraction for vectors by giving a constructor make-vect\n; and corresponding selectors xcor-vect and ycor-vect. In terms of your\n; selectors and constructor, implement procedures add-vect, sub-vect, and\n; scale-vect that perform the operations vector addition, vector subtraction,\n; and multiplying a vector by a scalar.\n;\n; (x₁,y₁) + (x₂,y₂) = (x₁ + x₂,y₁ + y₂)\n; (x₁,y₁) - (x₂,y₂) = (x₁ - x₂,y₁ - y₂)\n;            s(x,y) = (sx,sy)\n\n(define (make-vect x y)\n  (list x y))\n\n(define (xcor-vect vect)\n  (car vect))\n\n(define (ycor-vect vect)\n  (cadr vect))\n\n(define (add-vect v1 v2)\n  (make-vect (+ (xcor-vect v1)\n                (xcor-vect v2))\n             (+ (ycor-vect v1)\n                (ycor-vect v2))))\n\n(define (sub-vect v1 v2)\n  (make-vect (- (xcor-vect v1)\n                (xcor-vect v2))\n             (- (ycor-vect v1)\n                (ycor-vect v2))))\n\n(define (scale-vect s v)\n  (make-vect (* s (xcor-vect v))\n             (* s (ycor-vect v))))\n"
  },
  {
    "path": "scheme/sicp/02/47.scm",
    "content": "; SICP exercise 2.47\n;\n; Here are two possible constructors for frames:\n;\n; (define (make-frame origin edge1 edge2)\n;   (list origin edge1 edge2))\n;\n; (define (make-frame origin edge1 edge2)\n;   (cons origin (cons edge1 edge2)))\n;\n; For each constructor supply the appropriate selectors to produce\n; an implementation for frames.\n\n(define (make-frame1 origin edge1 edge2)\n  (list origin edge1 edge2))\n\n(define (origin-frame1 frame)\n  (car frame))\n\n(define (edge1-frame1 frame)\n  (cadr frame))\n\n(define (edge2-frame1 frame)\n  (caddr frame))\n\n\n\n(define (make-frame2 origin edge1 edge2)\n  (cons origin (cons edge1 edge2)))\n\n(define (origin-frame2 frame)\n  (car frame))\n\n(define (edge1-frame2 frame)\n  (cadr frame))\n\n(define (edge2-frame2 frame)\n  (cddr frame))\n"
  },
  {
    "path": "scheme/sicp/02/48.scm",
    "content": "; SICP exercise 2.48\n;\n; A directed line segment in the plane can be represented as a pair of\n; vectors - the vector running from the origin to the start-point of the\n; segment, and the vector running from the origin to the end-point of the\n; segment. Use your vector representation from Exercise 2.46 to define a\n; representation for segments with a constructor make-segment and selectors\n; start-segment and end-segment.\n\n(define (make-segment start end)\n  (list start end))\n\n(define (start-segment segment)\n  (car segment))\n\n(define (end-segment segment)\n  (cadr segment))\n\n(define (make-vect x y)\n  (list x y))\n"
  },
  {
    "path": "scheme/sicp/02/49.scm",
    "content": "; SICP exercise 2.49\n;\n; Use segments->painter to define the following primitive painters:\n;\n; a. The painter that draws the outline of the designated frame.\n; b. The painter that draws an \"X\" by connecting the opposite corners of the\n;    frame\n; c. The painter that draws a diamond shape by connecting the mid-points of\n;    the sides of the frame.\n; d. The wave painter.\n\n; Here you go.\n;\n; Note, that I wrote a program that takes a bunch of path coordinates and\n; generates make-segment calls for each line segment in the path in order to\n; implement wave.\n\n; a. The painter that draws the outline of the designated frame.\n(define outline\n  (segments->painter\n    (list (make-segment (make-vect 0.0 0.0) (make-vect 0.0 1.0))\n          (make-segment (make-vect 0.0 1.0) (make-vect 1.0 1.0))\n          (make-segment (make-vect 1.0 1.0) (make-vect 1.0 0.0))\n          (make-segment (make-vect 1.0 0.0) (make-vect 0.0 0.0)))))\n\n; b. The painter that draws an \"X\" by connecting the opposite corners of the\n;    frame\n(define cross\n  (segments->painter\n    (list (make-segment (make-vect 0.0 0.0) (make-vect 1.0 1.0))\n          (make-segment (make-vect 1.0 0.0) (make-vect 0.0 1.0)))))\n\n; c. The painter that draws a diamond shape by connecting the mid-points of\n;    the sides of the frame.\n(define diamond\n  (segments->painter\n    (list (make-segment (make-vect 0.5 0.0) (make-vect 1.0 0.5))\n          (make-segment (make-vect 1.0 0.5) (make-vect 0.5 1.0))\n          (make-segment (make-vect 0.5 1.0) (make-vect 0.0 0.5))\n          (make-segment (make-vect 0.0 0.5) (make-vect 0.5 0.0)))))\n\n; d. The wave painter.\n(define wave\n  (segments->painter\n    (list (make-segment (make-vect 0.00 0.70) (make-vect 0.16 0.57))\n          (make-segment (make-vect 0.16 0.57) (make-vect 0.30 0.67))\n          (make-segment (make-vect 0.30 0.67) (make-vect 0.37 0.67))\n          (make-segment (make-vect 0.37 0.67) (make-vect 0.40 0.64))\n          (make-segment (make-vect 0.40 0.64) (make-vect 0.42 0.68))\n          (make-segment (make-vect 0.42 0.68) (make-vect 0.32 0.80))\n          (make-segment (make-vect 0.32 0.80) (make-vect 0.33 0.85))\n          (make-segment (make-vect 0.33 0.85) (make-vect 0.36 1.00))\n\n          (make-segment (make-vect 0.60 1.00) (make-vect 0.62 0.84))\n          (make-segment (make-vect 0.62 0.84) (make-vect 0.62 0.78))\n          (make-segment (make-vect 0.62 0.78) (make-vect 0.53 0.70))\n          (make-segment (make-vect 0.53 0.70) (make-vect 0.57 0.64))\n          (make-segment (make-vect 0.57 0.64) (make-vect 0.63 0.67))\n          (make-segment (make-vect 0.63 0.67) (make-vect 0.68 0.66))\n          (make-segment (make-vect 0.68 0.66) (make-vect 0.87 0.51))\n          (make-segment (make-vect 0.87 0.51) (make-vect 1.00 0.40))\n\n          (make-segment (make-vect 1.00 0.30) (make-vect 0.73 0.52))\n          (make-segment (make-vect 0.73 0.52) (make-vect 0.61 0.53))\n          (make-segment (make-vect 0.61 0.53) (make-vect 0.67 0.25))\n          (make-segment (make-vect 0.67 0.25) (make-vect 0.71 0.00))\n\n          (make-segment (make-vect 0.60 0.00) (make-vect 0.56 0.23))\n          (make-segment (make-vect 0.56 0.23) (make-vect 0.51 0.28))\n          (make-segment (make-vect 0.51 0.28) (make-vect 0.46 0.28))\n          (make-segment (make-vect 0.46 0.28) (make-vect 0.40 0.12))\n          (make-segment (make-vect 0.40 0.12) (make-vect 0.36 0.00))\n\n          (make-segment (make-vect 0.23 0.00) (make-vect 0.34 0.30))\n          (make-segment (make-vect 0.34 0.30) (make-vect 0.36 0.52))\n          (make-segment (make-vect 0.36 0.52) (make-vect 0.32 0.55))\n          (make-segment (make-vect 0.32 0.55) (make-vect 0.28 0.55))\n          (make-segment (make-vect 0.28 0.55) (make-vect 0.17 0.45))\n          (make-segment (make-vect 0.17 0.45) (make-vect 0.00 0.60)))))\n"
  },
  {
    "path": "scheme/sicp/02/50.scm",
    "content": "; SICP exercise 2.50\n;\n; Define the transformation flip-horiz, which flips painters horizontally, and\n; transformations that rotate painters counterclockwise by 180 degrees and 270\n; degrees.\n\n(define (flip-horiz painter)\n  (transform-painter painter\n                     (make-vect 1.0 0.0)\n                     (make-vect 0.0 0.0)\n                     (make-vect 1.0 1.0)))\n\n(define (rotate180 painter)\n  (transform-painter painter\n                     (make-vect 1.0 1.0)\n                     (make-vect 0.0 1.0)\n                     (make-vect 1.0 0.0)))\n\n(define (rotate270 painter)\n  (transform-painter painter\n                     (make-vect 0.0 1.0)\n                     (make-vect 0.0 0.0)\n                     (make-vect 1.0 1.0)))\n"
  },
  {
    "path": "scheme/sicp/02/51.scm",
    "content": "; SICP exercise 2.51\n;\n; Define the below operations for painters. below takes two painters as\n; arguments. The resulting painter, given the frame, draws the first painter in\n; the bottom of the frame and with the second painter on the top.  Define below\n; in two different ways - first by writing a procedure that is analogous to the\n; beside procedure given above, and again in terms of beside and suitable\n; rotation operations.\n\n(define (below painter1 painter2)\n  (let ((split-point (make-vect 0.0 0.5)))\n    (let ((paint-bottom\n            (transform-painter painter1\n                               (make-vect 0.0 0.0)\n                               (make-vect 1.0 0.0)\n                               split-point))\n          (paint-top\n            (transform-painter painter2\n                               split-point\n                               (make-vect 1.0 0.5)\n                               (make-vect 0.0 1.0))))\n      (lambda (frame)\n        (paint-bottom frame)\n        (paint-top frame)))))\n\n(define (below2 painter1 painter2)\n  (rotate270 (beside (rotate90 painter1)\n                     (rotate90 painter2))))\n"
  },
  {
    "path": "scheme/sicp/02/52.scm",
    "content": "; SICP exercise 2.52\n;\n; Make changes to the square limit of wave show in Figure 2.9 by working at\n; each of the levels described above. In particular:\n;\n; a. Add some segments to the primitive wave painter of Exercise 2.49 (to add a\n;    smile, for example).\n; b. Change the pattern constructed by corner-split (for example, by using one\n;    copy of the up-split and right-split images instead of two).\n; c. Modify the version of square-limit that uses square-of-four as to assemble\n;    the corners in a different pattern. (For example, you might make the big\n;    Mr. Rogers look outward from each corner of the square)\n\n; a. Add some segments to the primitive wave painter of Exercise 2.49 (to add a\n;    smile, for example).\n(define smiling-wave\n  (segments->painter\n    (list (make-segment (make-vect 0.00 0.70) (make-vect 0.16 0.57))\n          (make-segment (make-vect 0.16 0.57) (make-vect 0.30 0.67))\n          (make-segment (make-vect 0.30 0.67) (make-vect 0.37 0.67))\n          (make-segment (make-vect 0.37 0.67) (make-vect 0.40 0.64))\n          (make-segment (make-vect 0.40 0.64) (make-vect 0.42 0.68))\n          (make-segment (make-vect 0.42 0.68) (make-vect 0.32 0.80))\n          (make-segment (make-vect 0.32 0.80) (make-vect 0.33 0.85))\n          (make-segment (make-vect 0.33 0.85) (make-vect 0.36 1.00))\n\n          (make-segment (make-vect 0.60 1.00) (make-vect 0.62 0.84))\n          (make-segment (make-vect 0.62 0.84) (make-vect 0.62 0.78))\n          (make-segment (make-vect 0.62 0.78) (make-vect 0.53 0.70))\n          (make-segment (make-vect 0.53 0.70) (make-vect 0.57 0.64))\n          (make-segment (make-vect 0.57 0.64) (make-vect 0.63 0.67))\n          (make-segment (make-vect 0.63 0.67) (make-vect 0.68 0.66))\n          (make-segment (make-vect 0.68 0.66) (make-vect 0.87 0.51))\n          (make-segment (make-vect 0.87 0.51) (make-vect 1.00 0.40))\n\n          (make-segment (make-vect 1.00 0.30) (make-vect 0.73 0.52))\n          (make-segment (make-vect 0.73 0.52) (make-vect 0.61 0.53))\n          (make-segment (make-vect 0.61 0.53) (make-vect 0.67 0.25))\n          (make-segment (make-vect 0.67 0.25) (make-vect 0.71 0.00))\n\n          (make-segment (make-vect 0.60 0.00) (make-vect 0.56 0.23))\n          (make-segment (make-vect 0.56 0.23) (make-vect 0.51 0.28))\n          (make-segment (make-vect 0.51 0.28) (make-vect 0.46 0.28))\n          (make-segment (make-vect 0.46 0.28) (make-vect 0.40 0.12))\n          (make-segment (make-vect 0.40 0.12) (make-vect 0.36 0.00))\n\n          (make-segment (make-vect 0.23 0.00) (make-vect 0.34 0.30))\n          (make-segment (make-vect 0.34 0.30) (make-vect 0.36 0.52))\n          (make-segment (make-vect 0.36 0.52) (make-vect 0.32 0.55))\n          (make-segment (make-vect 0.32 0.55) (make-vect 0.28 0.55))\n          (make-segment (make-vect 0.28 0.55) (make-vect 0.17 0.45))\n          (make-segment (make-vect 0.17 0.45) (make-vect 0.00 0.60))\n\n          (make-segment (make-vect 0.41 0.78) (make-vect 0.54 0.78))\n          (make-segment (make-vect 0.54 0.78) (make-vect 0.52 0.76))\n          (make-segment (make-vect 0.52 0.76) (make-vect 0.43 0.76))\n          (make-segment (make-vect 0.43 0.76) (make-vect 0.41 0.78)))))\n\n; b. Change the pattern constructed by corner-split (for example, by using one\n;    copy of the up-split and right-split images instead of two).\n(define (simpler-corner-split painter n)\n  (if (= n 0)\n      painter\n      (let ((up (up-split painter (- n 1)))\n            (right (right-split painter (- n 1))))\n        (beside (below painter up)\n                (below right (corner-split painter (- n 1)))))))\n\n; c. Modify the version of square-limit that uses square-of-four as to assemble\n;    the corners in a different pattern. (For example, you might make the big\n;    Mr. Rogers look outward from each corner of the square)\n(define (inverted-square-limit painter n)\n  (let ((combine4 (square-of-four flip-vert rotate180\n                                  identity flip-horiz)))\n    (combine4 (corner-split painter n))))\n"
  },
  {
    "path": "scheme/sicp/02/53.scm",
    "content": "; SICP exercise 2.53\n;\n; What would be the interpreter print in response to evaluating each of the\n; following expressions?\n;\n; (list 'a 'b 'c)\n; (list (list 'george))\n; (cdr '((x1 x2) (y1 y2)))\n; (cadr '((x1 x2) (y1 y2)))\n; (pair? (car '(a short list)))\n; (memq 'red '((red shoes) (blue socks)))\n; (memq 'red '(red shoes blue coks))\n\n; (list 'a 'b 'c)\n; '(a b c)\n;\n; (list (list 'george))\n; '((george))\n;\n; (cdr '((x1 x2) (y1 y2)))\n; '((y1 y2))\n;\n; (cadr '((x1 x2) (y1 y2)))\n; '(y1 y2)\n;\n; (pair? (car '(a short list)))\n; #f\n;\n; (memq 'red '((red shoes) (blue socks)))\n; #f\n;\n; (memq 'red '(red shoes blue socks))\n; '(red shoes blue socks)\n"
  },
  {
    "path": "scheme/sicp/02/54.scm",
    "content": "; SICP exercise 2.54\n;\n; Two lists are said to be equal? if they contain equal elements arranged in\n; the same order. For example,\n;\n; (equal? '(this is a list) '(this is a list))\n;\n; is there, but\n;\n; (equal? '(this is a list) '(this (is a) list))\n;\n; is false. To be more precise, we can define equal? recursively in terms of\n; the basic eq? equality of symbols by saying that a and b are eq?, or if they\n; are both lists such that (car a) is equal? to (car b) and (cdr a) is equal?\n; to (cdr b). Using this idea, implement equal? as a procedure.\n\n(define (equal2? a b)\n  (cond ((and (null? a) (null? b)) #t)\n        ((and (pair? a) (pair? b))\n         (and (equal2? (car a) (car b))\n              (equal2? (cdr a) (cdr b))))\n        (else (eq? a b))))\n"
  },
  {
    "path": "scheme/sicp/02/55.scm",
    "content": "; SICP exercise 2.55\n;\n; Eva Lu Ator types to the interpreter the expression\n;\n; (car ''abracadabra)\n;\n; To her surprise, the interpreter prints back quote. Explain.\n\n; Simple.\n;\n; 'foo  is short for (quote foo)\n; ''foo is short for (quote (quote foo))\n;\n; When you (car (quote (quote foo))) you get 'quote.\n"
  },
  {
    "path": "scheme/sicp/02/56.scm",
    "content": "; SICP exercise 2.56\n;\n; Show how to extend the basic differentiator to handle more kinds of\n; expressions. For instance, implement the differentiation rule\n;\n; d(uⁿ)        du\n; ───── = nuⁿ⁻¹──\n;  dx          dx\n;\n; by adding a new clause to the deriv program and defining appropriate\n; procedures exponentiation?, base, exponent, and make-exponentiation. (You may\n; use the symbol ** to denote exponentiation.) Build in the rules that anything\n; raised to the power 0 is 1 and anything raised to the power 1 is the thing\n; itself.\n\n(define (deriv expr var)\n  (cond ((number? expr) 0)\n        ((variable? expr)\n         (if (same-variable? expr var) 1 0))\n        ((sum? expr)\n         (make-sum (deriv (addend expr) var)\n                   (deriv (augend expr) var)))\n        ((product? expr)\n         (make-sum\n           (make-product (multiplier expr)\n                         (deriv (multiplicand expr) var))\n           (make-product (deriv (multiplier expr) var)\n                         (multiplicand expr))))\n        ((exponentiation? expr)\n         (make-product\n           (make-product (power expr)\n                         (make-exponentiation (base expr)\n                                              (- (power expr) 1)))\n           (deriv (base expr) var)))\n        (else\n          (error \"unknown expression type - DERIV\" expr))))\n\n(define (variable? x)\n  (symbol? x))\n\n(define (same-variable? v1 v2)\n  (and (variable? v1)\n       (variable? v2)\n       (eq? v1 v2)))\n\n(define (make-sum a1 a2)\n  (cond ((=number? a1 0) a2)\n        ((=number? a2 0) a1)\n        ((and (number? a1) (number? a2)) (+ a1 a2))\n        (else (list '+ a1 a2))))\n\n(define (make-product m1 m2)\n  (cond ((or (=number? m1 0) (=number? m2 0)) 0)\n        ((=number? m1 1) m2)\n        ((=number? m2 1) m1)\n        ((and (number? m1) (number? m2)) (* m1 m2))\n        (else (list '* m1 m2))))\n\n(define (make-exponentiation base power)\n  (cond ((=number? power 0) 1)\n        ((=number? power 1) base)\n        (else (list '** base power))))\n\n(define (sum? x)\n  (and (pair? x)\n       (eq? (car x) '+)))\n\n(define (addend s)\n  (cadr s))\n\n(define (augend s)\n  (caddr s))\n\n(define (product? x)\n  (and (pair? x)\n       (eq? (car x) '*)))\n\n(define (multiplier p)\n  (cadr p))\n\n(define (multiplicand p)\n  (caddr p))\n\n(define (exponentiation? expr)\n  (and (pair? expr)\n       (eq? (car expr) '**)))\n\n(define (base expr)\n  (cadr expr))\n\n(define (power expr)\n  (caddr expr))\n\n(define (=number? expr num)\n  (and (number? expr)\n       (= expr num)))\n"
  },
  {
    "path": "scheme/sicp/02/57.scm",
    "content": "; SICP exercise 2.57\n;\n; Extend the differentiation program to handle sums and products of\n; arbitrary numbers of (two or more) terms. Then the last example above\n; could be expressed as\n;\n; (deriv '(* x y (+ x 3)) 'x)\n;\n; Try to do this by changing only the representation for sums and products,\n; without changing the deriv procedure at all. For example, the addend of\n; a sum would be the first term, and the augend would be the sum of the\n; rest of the terms\n\n(define (deriv expr var)\n  (cond ((number? expr) 0)\n        ((variable? expr)\n         (if (same-variable? expr var) 1 0))\n        ((sum? expr)\n         (make-sum (deriv (addend expr) var)\n                   (deriv (augend expr) var)))\n        ((product? expr)\n         (make-sum\n           (make-product (multiplier expr)\n                         (deriv (multiplicand expr) var))\n           (make-product (deriv (multiplier expr) var)\n                         (multiplicand expr))))\n        (else\n          (error \"unknown expression type - DERIV\" expr))))\n\n(define (variable? x)\n  (symbol? x))\n\n(define (same-variable? v1 v2)\n  (and (variable? v1)\n       (variable? v2)\n       (eq? v1 v2)))\n\n(define (make-sum a1 a2)\n  (cond ((=number? a1 0) a2)\n        ((=number? a2 0) a1)\n        ((and (number? a1) (number? a2)) (+ a1 a2))\n        (else (list '+ a1 a2))))\n\n(define (make-product m1 m2)\n  (cond ((or (=number? m1 0) (=number? m2 0)) 0)\n        ((=number? m1 1) m2)\n        ((=number? m2 1) m1)\n        ((and (number? m1) (number? m2)) (* m1 m2))\n        (else (list '* m1 m2))))\n\n(define (sum? x)\n  (and (pair? x)\n       (eq? (car x) '+)))\n\n(define (addend s)\n  (cadr s))\n\n(define (augend s)\n  (if (null? (cdddr s))\n      (caddr s)\n      (cons '+ (cddr s))))\n\n(define (product? x)\n  (and (pair? x)\n       (eq? (car x) '*)))\n\n(define (multiplier p)\n  (cadr p))\n\n(define (multiplicand p)\n  (if (null? (cdddr p))\n      (caddr p)\n      (cons '* (cddr p))))\n\n(define (=number? expr num)\n  (and (number? expr)\n       (= expr num)))\n"
  },
  {
    "path": "scheme/sicp/02/58.scm",
    "content": "; SICP exercise 2.58\n;\n; Suppose we want to modify the differentiation program so that it works with\n; ordinary mathematical notation, in which + and * are infix rather than prefix\n; operators. Since the differentiation program is defined in terms of abstract\n; data, we can modify it to work with different representations of expressions\n; solely by changing the predicates, selectors and constructors that define the\n; representation of algebraic expressions on which the differentiator is to\n; operate.\n;\n; a. Show how to do this in order to differentiate algebraic expressions\n;    presented in infix form, such as (x + (3 * (x + (y + 2)))). To simplify\n;    the task, assume that + and * always take two arguments and that\n;    expressions are fully parenthesized.\n; b. The problem becomes substantially harder if we allow standard algebraic\n;    notation, such as (x + 3 * (x + y + 2)), which drops unnecessary\n;    parentheses and assumes that multiplication is done before addition. Can\n;    you design appropriate predicates, selectors, and constructors for this\n;    notation such that our derivative program still works?\n\n; a. Sure enough. See code below\n; b. Yup. I'm just going to sketch it (too lazy to write it down) - we need\n;    to parse the sexp and put parentheses where they should be. Afterwards,\n;    it is just as easy as calling a. Parsing the code is not that hard, but\n;    I'm not in the mood for a parsing exercise at this point.\n\n(define (deriv expr var)\n  (cond ((number? expr) 0)\n        ((variable? expr)\n         (if (same-variable? expr var) 1 0))\n        ((sum? expr)\n         (make-sum (deriv (addend expr) var)\n                   (deriv (augend expr) var)))\n        ((product? expr)\n         (make-sum\n           (make-product (multiplier expr)\n                         (deriv (multiplicand expr) var))\n           (make-product (deriv (multiplier expr) var)\n                         (multiplicand expr))))\n        (else\n          (error \"unknown expression type - DERIV\" expr))))\n\n(define (variable? x)\n  (symbol? x))\n\n(define (same-variable? v1 v2)\n  (and (variable? v1)\n       (variable? v2)\n       (eq? v1 v2)))\n\n(define (make-sum a1 a2)\n  (cond ((=number? a1 0) a2)\n        ((=number? a2 0) a1)\n        ((and (number? a1) (number? a2)) (+ a1 a2))\n        (else (list a1 '+ a2))))\n\n(define (make-product m1 m2)\n  (cond ((or (=number? m1 0) (=number? m2 0)) 0)\n        ((=number? m1 1) m2)\n        ((=number? m2 1) m1)\n        ((and (number? m1) (number? m2)) (* m1 m2))\n        (else (list m1 '* m2))))\n\n(define (sum? x)\n  (and (pair? x)\n       (eq? (cadr x) '+)))\n\n(define (addend s)\n  (car s))\n\n(define (augend s)\n  (caddr s))\n\n(define (product? x)\n  (and (pair? x)\n       (eq? (cadr x) '*)))\n\n(define (multiplier p)\n  (car p))\n\n(define (multiplicand p)\n  (caddr p))\n\n(define (=number? expr num)\n  (and (number? expr)\n       (= expr num)))\n"
  },
  {
    "path": "scheme/sicp/02/59.scm",
    "content": "; SICP exercise 2.59\n;\n; Implement the union-set operation for the unordered list representation of\n; sets.\n\n(define (element-of-set? x set)\n  (cond ((null? set) false)\n        ((equal? x (car set)) true)\n        (else (element-of-set? x (cdr set)))))\n\n(define (adjoin-set x set)\n  (if (element-of-set? x set)\n      set\n      (cons x set)))\n\n(define (union-set set1 set2)\n  (cond ((null? set1) set2)\n        ((element-of-set? (car set1) set2) (union-set (cdr set1) set2))\n        (else (cons (car set1) (union-set (cdr set1) set2)))))\n"
  },
  {
    "path": "scheme/sicp/02/60.scm",
    "content": "; SICP exercise 2.60\n;\n; We specified that a set would be represented as a list with no duplicates.\n; Now suppose we allow duplicates. For instance, the set {1, 2, 3} could be\n; represented as the list (2 3 2 1 3 2 2). Design procedures element-of-set?,\n; adjoin-set, union-set, and intersection-set that operate on this\n; representation. How does the efficiency of each compare with the\n; corresponding procedure for the non-duplicate representation? Are there any\n; applications for which you would use this representation in preference to the\n; non-duplicate one?\n\n; The procedures are below.\n;\n; In comparison, the set representation in this exercise allows implementing\n; adjoin-set and union-set in constant time. In that sense, the implementation\n; is way faster than when having no duplicates.\n;\n; On the down side, element-of-set? can be way slower. Its complexity is Θ(n),\n; where n is the number of times and element was added to the set, not the\n; number of elements in the set. intersection-set is potentially slower for the\n; same reason.\n;\n; I would prefer using the duplicate version when I have a lot of unions and\n; adjoins and a lot fewer tests and intersections. I would probably try to\n; normalize the set after all the unions, though.\n\n(define (element-of-set? x set)\n  (and (not (null? set))\n       (or (eq? (car set) x)\n           (element-of-set? x (cdr set)))))\n\n(define (adjoin-set x set)\n  (cons x set))\n\n(define (union-set set1 set2)\n  (append set1 set2))\n\n(define (intersection-set set1 set2)\n  (cond ((null? set1) '())\n        ((element-of-set? (car set1) set2)\n         (cons (car set1) (intersection-set (cdr set1) set2)))\n        (else\n          (intersection-set (cdr set1) set2))))\n"
  },
  {
    "path": "scheme/sicp/02/61.scm",
    "content": "; SICP exercise 2.61\n;\n; Give an implementation of adjoin-set using the ordered representation. By\n; analogy with element-of-set? show how to take advantage of the ordering to\n; produce a procedure that requires on the average about half as many steps as\n; with the unordered representation.\n\n(define (adjoin-set x set)\n  (cond ((null? set) (list x))\n        ((= x (car set)) set)\n        ((> x (car set)) (cons (car set) (adjoin-set x (cdr set))))\n        ((< x (car set)) (cons x set))))\n"
  },
  {
    "path": "scheme/sicp/02/62.scm",
    "content": "; SICP exercise 2.62\n;\n; Given an Θ(n) implementation of union-set for the sets represented as ordered\n; lists.\n\n(define (union-set set1 set2)\n  (cond ((null? set1) set2)\n        ((null? set2) set1)\n        ((= (car set1) (car set2))\n         (cons (car set1) (union-set (cdr set1) (cdr set2))))\n        ((< (car set1) (car set2))\n         (cons (car set1) (union-set (cdr set1) set2)))\n        ((> (car set1) (car set2))\n         (cons (car set2) (union-set set1 (cdr set2))))))\n"
  },
  {
    "path": "scheme/sicp/02/63.scm",
    "content": "; SICP exercise 2.63\n;\n; Each of the following two procedures converts a binary tree to a list.\n;\n; (define (tree->list-1 tree)\n;   (if (null? tree)\n;       '()\n;       (append (tree->list-1 (left-branch tree))\n;               (cons (entry tree)\n;                     (tree->list-1 (right-branch tree))))))\n;\n; (define (tree->list-2 tree)\n;   (define (copy-to-list tree result-list)\n;     (if (null? tree)\n;         result-list\n;         (copy-to-list (left-branch tree)\n;                       (cons (entry tree)\n;                             (copy-to-list (right-branch tree) result-list)))))\n;   (copy-to-list tree '()))\n;\n; a. Do the two procedures produce the same result for every tree? If not, how\n;    do the results differ? What lists do the two procedures produce for the\n;    trees in Figure 2.16?\n; b. Do the two procedures have the same order of growth in the number of steps\n;    required to convert a balanced tree with n elements to a list? If not,\n;    which one grows more slowly?\n\n; a. Yes. They don't. All six variants generate (1 3 5 7 9 11)\n;\n; b. No. tree->list-2 tends to grow slower, both in space and time.\n;\n; First of all, it is recursive only on the right branches, but iterative on\n; the left ones, and second, it does not invlove any calls to append (which is\n; linear to the size of the first list). In all cases tree->list-2 finishes in\n; Θ(n).\n"
  },
  {
    "path": "scheme/sicp/02/64.scm",
    "content": "; SICP exercise 2.64\n;\n; The following procedure list->tree converts an ordered list to a balanced\n; binary tree. The helper procedure partial-tree takes as arguments an integer n\n; and a list of at least n elements and constructs a balanced tree containing\n; the first n elements of the list. The result returned by partial-tree is a pair\n; (formed with cons) whose car is the constructed tree and whose cdr is the list\n; of elements not included in the tree.\n;\n; (define (list->tree elements)\n;   (car (partial-tree elements (length elements))))\n;\n; (define (partial-tree elts n)\n;   (if (= n 0)\n;       (cons '() elts)\n;       (let* ((left-size (quotient (- n 1) 2))\n;              (left-result (partial-tree elts left-size))\n;              (left-tree (car left-result))\n;              (non-left-elts (cdr left-result))\n;              (right-size (- n (+ left-size 1)))\n;              (this-entry (car non-left-elts))\n;              (right-result (partial-tree (cdr non-left-elts) right-size))\n;              (right-tree (car right-result))\n;              (remaining-elts (cdr right-result)))\n;         (cons (make-tree this-entry left-tree right-tree) remaining-elts))))\n;\n; a. Write a short paragraph explaining as clearly as you can how partial-tree\n;    works. Draw the tree produced by list->tree for the list (1 3 5 7 9 11)\n; b. What is the order of growth in the number of steps required by list->tree\n;    to convert a list of n elements?\n\n; a. The procedure works in a fairly simple fashion.\n;\n; It splits the list in three parts - a left sub-list, a right sub-list and the\n; element between them. The parts are roughly equal in size. The result is a\n; tree whose entry is the middle element and whose branches are the sub-lists\n; transformed to trees with the same procedure (recursively).\n;\n; Once the procedure arrives to a list with size <= 3, it is trivial to\n; visualize how the tree would look like. Lists of sizes > 3 get reduced to\n; those cases with recursion.\n;\n; The final tree is binary, because the left branch contains elements that are\n; smaller than the middle element and the right branch contains only elements\n; that are greater than the middle element. It is balanced, because the\n; algorithm halves the list size on each step, which means that the maximum\n; depth of the tree will be log(n).\n;\n; FYI, (list->tree '(1 3 5 7 9 11)) produces:\n;\n;       5\n;     /   \\\n;   1       9\n;    \\     / \\\n;     3   7   11\n;\n; b. Θ(n)\n;\n; Each list item is visited only once and each visit performs a single cons.\n"
  },
  {
    "path": "scheme/sicp/02/65.scm",
    "content": "; SICP exercise 2.65\n;\n; Use the results of exercise 2.63 and 2.64 to give Θ(n) implementations of\n; union-set and intersection-set for sets implemented as (balanced) binary\n; trees.\n\n(define (intersection-set set1 set2)\n  (list->tree (intersection-set-list (tree->list set1)\n                                     (tree->list set2))))\n\n(define (union-set set1 set2)\n  (list->tree (union-set-list (tree->list set1)\n                              (tree->list set2))))\n\n\n\n(define (make-tree entry left right) (list entry left right))\n(define (entry tree) (car tree))\n(define (left-branch tree) (cadr tree))\n(define (right-branch tree) (caddr tree))\n\n(define (tree->list tree)\n  (define (copy-to-list tree result-list)\n    (if (null? tree)\n        result-list\n        (copy-to-list (left-branch tree)\n                      (cons (entry tree)\n                            (copy-to-list (right-branch tree) result-list)))))\n  (copy-to-list tree '()))\n\n(define (list->tree elements)\n  (define (partial-tree elts n)\n    (if (= n 0)\n        (cons '() elts)\n        (let* ((left-size (quotient (- n 1) 2))\n               (left-result (partial-tree elts left-size))\n               (left-tree (car left-result))\n               (non-left-elts (cdr left-result))\n               (right-size (- n (+ left-size 1)))\n               (this-entry (car non-left-elts))\n               (right-result (partial-tree (cdr non-left-elts) right-size))\n               (right-tree (car right-result))\n               (remaining-elts (cdr right-result)))\n          (cons (make-tree this-entry left-tree right-tree) remaining-elts))))\n  (car (partial-tree elements (length elements))))\n\n(define (union-set-list list1 list2)\n  (cond ((null? list1) list2)\n        ((null? list2) list1)\n        ((= (car list1) (car list2))\n         (cons (car list1) (union-set-list (cdr list1) (cdr list2))))\n        ((< (car list1) (car list2))\n         (cons (car list1) (union-set-list (cdr list1) list2)))\n        ((> (car list1) (car list2))\n         (cons (car list2) (union-set-list list1 (cdr list2))))))\n\n(define (intersection-set-list list1 list2)\n  (if (or (null? list1) (null? list2))\n      '()\n      (let ((x1 (car list1))\n            (x2 (car list2)))\n        (cond ((= x1 x2) (cons x1 (intersection-set-list (cdr list1) (cdr list2))))\n              ((< x1 x2) (intersection-set-list (cdr list1) list2))\n              ((> x1 x2) (intersection-set-list list1 (cdr list2)))))))\n"
  },
  {
    "path": "scheme/sicp/02/66.scm",
    "content": "; SICP exercise 2.66\n;\n; Implement the lookup procedure for the case where the set of records is\n; structured as a binary tree, ordered by the numerical values of the keys.\n\n(define (lookup given-key set-of-records)\n  (if (null? set-of-records)\n      #f\n      (let* ((record (entry set-of-records))\n             (record-key (key record)))\n        (cond ((= given-key record-key) record)\n              ((< given-key record-key) (lookup given-key (left-branch set-of-records)))\n              ((> given-key record-key) (lookup given-key (right-branch set-of-records)))))))\n\n(define (entry tree) (car tree))\n(define (left-branch tree) (cadr tree))\n(define (right-branch tree) (caddr tree))\n\n(define (key record) (car record))\n(define (name record) (cadr record))\n"
  },
  {
    "path": "scheme/sicp/02/67.scm",
    "content": "; SICP exercise 2.67\n;\n; Define an encoding tree and a sample message:\n;\n; (define sample-tree\n;   (make-code-tree (make-leaf 'A 4)\n;                   (make-code-tree\n;                     (make-leaf 'B 2)\n;                     (make-code-tree (make-leaf 'D 1)\n;                                     (make-leaf 'C 1)))))\n;\n; (define sample-message '(0 1 1 0 0 1 0 1 0 1 1 1 0))\n;\n; Use the decode procedure to decode the message, and give the result.\n\n(define (make-leaf symbol weight)\n  (list 'leaf symbol weight))\n\n(define (leaf? object)\n  (eq? (car object) 'leaf))\n\n(define (symbol-leaf x)\n  (cadr x))\n\n(define (weight-leaf x)\n  (caddr x))\n\n(define (symbols tree)\n  (if (leaf? tree)\n      (list (symbol-leaf tree))\n      (caddr tree)))\n\n(define (left-branch tree)\n  (car tree))\n\n(define (right-branch tree)\n  (cadr tree))\n\n(define (weight tree)\n  (if (leaf? tree)\n      (weight-leaf tree)\n      (cadddr tree)))\n\n(define (make-code-tree left right)\n  (list left\n        right\n        (append (symbols left) (symbols right))\n        (+ (weight left) (weight right))))\n\n\n\n(define (decode bits tree)\n  (define (decode-1 bits current-branch)\n    (if (null? bits)\n        '()\n        (let ((next-branch (choose-branch (car bits) current-branch)))\n          (if (leaf? next-branch)\n              (cons (symbol-leaf next-branch)\n                    (decode-1 (cdr bits) tree))\n              (decode-1 (cdr bits) next-branch)))))\n  (decode-1 bits tree))\n\n(define (choose-branch bit branch)\n  (cond ((= bit 0) (left-branch branch))\n        ((= bit 1) (right-branch branch))\n        (else (error \"bad bit - CHOOSE-BRANCH\" bit))))\n\n\n\n(define (adjoin-set x set)\n  (cond ((null? set) (list x))\n        ((< (weight x) (weight (car set))) (cons x set))\n        (else (cons (car set)\n                    (adjoin-set x (cdr set))))))\n\n(define (make-leaf-set pairs)\n  (if (null? pairs)\n      '()\n      (let ((pair (car pairs)))\n        (adjoin-set (make-leaf (cdr pair)\n                               (cadr pair))\n                    (make-leaf-set (cdr pairs))))))\n\n\n\n(define sample-tree\n  (make-code-tree (make-leaf 'A 4)\n                  (make-code-tree\n                    (make-leaf 'B 2)\n                    (make-code-tree (make-leaf 'D 1)\n                                    (make-leaf 'C 1)))))\n\n(define sample-message '(0 1 1 0 0 1 0 1 0 1 1 1 0))\n"
  },
  {
    "path": "scheme/sicp/02/68.scm",
    "content": "; SICP exercise 2.68\n;\n; The encode procedure takes as arguments a message and a tree and produces the\n; list of bits that gives the encoded message.\n;\n; (define (encode message tree)\n;   (if (null? message)\n;       '()\n;       (append (encode-symbol (car message) tree)\n;               (encode (cdr message) tree))))\n;\n; encode-symbol is a procedure, which you must write, that returns the lists of\n; bits that encodes a given symbol according to a given tree. You should design\n; encode-symbol so that it signals an error if the symbol is not in the tree at\n; all. The your procedure by encoding the result you obtained in exercise 2.67\n; with the sample tree and seeing whether it is the same as the original sample\n; message.\n\n(define (make-leaf symbol weight)\n  (list 'leaf symbol weight))\n\n(define (leaf? object)\n  (eq? (car object) 'leaf))\n\n(define (symbol-leaf x)\n  (cadr x))\n\n(define (weight-leaf x)\n  (caddr x))\n\n(define (symbols tree)\n  (if (leaf? tree)\n      (list (symbol-leaf tree))\n      (caddr tree)))\n\n(define (left-branch tree)\n  (car tree))\n\n(define (right-branch tree)\n  (cadr tree))\n\n(define (weight tree)\n  (if (leaf? tree)\n      (weight-leaf tree)\n      (cadddr tree)))\n\n(define (make-code-tree left right)\n  (list left\n        right\n        (append (symbols left) (symbols right))\n        (+ (weight left) (weight right))))\n\n\n\n(define (encode message tree)\n  (if (null? message)\n      '()\n      (append (encode-symbol (car message) tree)\n              (encode (cdr message) tree))))\n\n(define (encode-symbol symbol tree)\n  (let ((left (left-branch tree))\n        (right (right-branch tree)))\n    (cond ((leaf? tree) '())\n          ((member symbol (symbols left)) (cons 0 (encode-symbol symbol left)))\n          ((member symbol (symbols right)) (cons 1 (encode-symbol symbol right)))\n          (else (error \"bad symbol - ENCODE-SYMBOL\" symbol)))))\n"
  },
  {
    "path": "scheme/sicp/02/69.scm",
    "content": "; SICP exercise 2.69\n;\n; The following procedure as its arguments a list of symbol-frequency pairs\n; (where no symbol appears in more than one pair) and generates a Huffman\n; encoding tree according to the Huffman algorithm.\n;\n;   (define (generate-huffman-tree pairs)\n;     (successive-merge (make-leaf-set pairs)))\n;\n; make-leaf-set is the procedure given above that transforms the list of pairs\n; into an ordered set of leaves. successive-merge is the procedure you must\n; write, using make-code-tree to successively merge the smallest-weight\n; elements of the set until there is only one element left, which is the\n; desired Huffman tree. (This procedure is slightly tricky; but not really\n; complicated. If you find yourself designing a complex procedure, then you\n; are almost certainly doing something wrong. You can take significant\n; advantage of the fact that we are using ordered set representation).\n\n(define (make-leaf symbol weight)\n  (list 'leaf symbol weight))\n\n(define (leaf? object)\n  (eq? (car object) 'leaf))\n\n(define (symbol-leaf x)\n  (cadr x))\n\n(define (weight-leaf x)\n  (caddr x))\n\n(define (symbols tree)\n  (if (leaf? tree)\n      (list (symbol-leaf tree))\n      (caddr tree)))\n\n(define (left-branch tree)\n  (car tree))\n\n(define (right-branch tree)\n  (cadr tree))\n\n(define (weight tree)\n  (if (leaf? tree)\n      (weight-leaf tree)\n      (cadddr tree)))\n\n(define (make-code-tree left right)\n  (list left\n        right\n        (append (symbols left) (symbols right))\n        (+ (weight left) (weight right))))\n\n\n\n(define (adjoin-set x set)\n  (cond ((null? set) (list x))\n        ((< (weight x) (weight (car set))) (cons x set))\n        (else (cons (car set)\n                    (adjoin-set x (cdr set))))))\n\n(define (make-leaf-set pairs)\n  (if (null? pairs)\n      '()\n      (let ((pair (car pairs)))\n        (adjoin-set (make-leaf (car pair) (cadr pair))\n                    (make-leaf-set (cdr pairs))))))\n\n(define (generate-huffman-tree pairs)\n  (successive-merge (make-leaf-set pairs)))\n\n(define (successive-merge leaf-set)\n  (if (null? (cdr leaf-set))\n      (car leaf-set)\n      (let ((first (car leaf-set))\n            (second (cadr leaf-set))\n            (rest (cddr leaf-set)))\n        (successive-merge (adjoin-set (make-code-tree first second)\n                                      rest)))))\n"
  },
  {
    "path": "scheme/sicp/02/70.scm",
    "content": "; SICP exercise 2.70\n;\n; The following eight-symbol alphabet with associated relative frequencies was\n; designed to efficiently encode the lyrics of 1950s rock songs. (Note that\n; \"symbols\" of an \"alphabet\" need not be individual letters.)\n;\n;   A    2   NA  16\n;   BOOM 1   SHA  3\n;   GET  2   YIP  9\n;   JOB  2   WAH  1\n;\n; Use generate-huffman-tree (exercise 2.69) to generate a corresponding\n; Huffman-tree, and use encode (exercise 2.68) to encode the following\n; message:\n;\n;   Get a job\n;   Sha na na na na na na na na\n;   Get a job\n;   Sha na na na na na na na na\n;   Wah yip yip yip yip yip yip yip yip yip\n;   Sha boom\n;\n; How many bits are required for the encoding? What is the smallest number of\n; bits that would be needed to encode this song if we used a fix-length code\n; for the eight symbol alphabet?\n\n; The encoded message has 84 bits. If we used a fixed-length code, each symbol\n; would require at least 3 bits (because there are 8 symbols). The message has\n; 36 symbols, which makes the smallest number of bits that would be needed to\n; encode the message equal to 108.\n;\n; You can run this file to verify.\n\n(define (make-leaf symbol weight)\n  (list 'leaf symbol weight))\n\n(define (leaf? object)\n  (eq? (car object) 'leaf))\n\n(define (symbol-leaf x)\n  (cadr x))\n\n(define (weight-leaf x)\n  (caddr x))\n\n(define (symbols tree)\n  (if (leaf? tree)\n      (list (symbol-leaf tree))\n      (caddr tree)))\n\n(define (left-branch tree)\n  (car tree))\n\n(define (right-branch tree)\n  (cadr tree))\n\n(define (weight tree)\n  (if (leaf? tree)\n      (weight-leaf tree)\n      (cadddr tree)))\n\n(define (make-code-tree left right)\n  (list left\n        right\n        (append (symbols left) (symbols right))\n        (+ (weight left) (weight right))))\n\n\n\n(define (adjoin-set x set)\n  (cond ((null? set) (list x))\n        ((< (weight x) (weight (car set))) (cons x set))\n        (else (cons (car set)\n                    (adjoin-set x (cdr set))))))\n\n(define (make-leaf-set pairs)\n  (if (null? pairs)\n      '()\n      (let ((pair (car pairs)))\n        (adjoin-set (make-leaf (car pair) (cadr pair))\n                    (make-leaf-set (cdr pairs))))))\n\n\n\n(define (encode message tree)\n  (if (null? message)\n      '()\n      (append (encode-symbol (car message) tree)\n              (encode (cdr message) tree))))\n\n(define (encode-symbol symbol tree)\n  (let ((left (left-branch tree))\n        (right (right-branch tree)))\n    (cond ((leaf? tree) '())\n          ((member symbol (symbols left)) (cons 0 (encode-symbol symbol left)))\n          ((member symbol (symbols right)) (cons 1 (encode-symbol symbol right)))\n          (else (error \"bad symbol - ENCODE-SYMBOL\" symbol)))))\n\n\n\n(define (generate-huffman-tree pairs)\n  (successive-merge (make-leaf-set pairs)))\n\n(define (successive-merge leaf-set)\n  (if (null? (cdr leaf-set))\n      (car leaf-set)\n      (let ((first (car leaf-set))\n            (second (cadr leaf-set))\n            (rest (cddr leaf-set)))\n        (successive-merge (adjoin-set (make-code-tree first second)\n                                      rest)))))\n\n\n(define tree\n  (generate-huffman-tree '((a 2)\n                           (na 16)\n                           (boom 1)\n                           (sha 3)\n                           (get 2)\n                           (yip 9)\n                           (job 2)\n                           (wah 1))))\n\n(define message\n  '(get a job\n    sha na na na na na na na na\n    get a job\n    sha na na na na na na na na\n    wah yip yip yip yip yip yip yip yip yip\n    sha boom))\n\n(define encoded-message (encode message tree))\n\n(printf \"The encoded message is ~a\\n\" encoded-message)\n(printf \"It has ~a bits\\n\" (length encoded-message))\n(printf \"The message has ~a symbols\\n\" (length message))\n(printf \"This means, that a fixed-length code would take ~a bits\\n\" (* (length message) 3))\n"
  },
  {
    "path": "scheme/sicp/02/71.scm",
    "content": "; SICP exercise 2.71\n;\n; Suppose we have a Huffman tree for an alphabet of n symbols, and the\n; relative frequencies of the symbols are 1, 2, 4,..., 2ⁿ⁻¹. Sketch the tree\n; for n = 5; for n = 10. In such a tree (for general n) how many bits are\n; required to encode the most frequent symbol? The least frequent symbol?\n\n; Here's the tree for n = 5:\n;\n;              .\n;             / \\\n;           .    16\n;          / \\\n;        .    8\n;       / \\\n;     .    4\n;    / \\\n;   1   2\n;\n; The tree for n = 10 is quite similar.\n;\n; Obviously, the most frequent symbol takes 1 bit and the least frequent\n; symbol takes n - 1 (since the depth of the tree is n - 1)\n"
  },
  {
    "path": "scheme/sicp/02/72.scm",
    "content": "; SICP exercise 2.72\n;\n; Consider the encoding procedure that you designed in exercise 2.68. What is\n; the order of growth in the number of steps needed to encode a symbol? Be\n; sure to include the number of steps needed to search the symbol list at each\n; node encountered. To answer this question in general is difficult. Consider\n; the special case where the relative frequencies of the n symbols are as\n; described in exercise 2.71, and give the order of growth (as a function of\n; n) of the number of steps needed to encode the most frequent and the least\n; frequent symbols in the alphabet.\n\n; The most frequent symbol is obviously O(1). As for the least frequent, in\n; the worst case, we need to search a list of size n on the first step, a list\n; of size n - 1 on the second and so forth until only two leaf nodes remain.\n; Thus, the complexity is 1 + 2 + 3 + … + n ≈ O(n²).\n"
  },
  {
    "path": "scheme/sicp/02/73.scm",
    "content": "; SICP exercise 2.73\n;\n; Section 2.3.2 described a program that performs symbolic differentiation:\n;\n; (define (deriv exp var)\n;   (cond ((number? exp) 0)\n;         ((variable? exp) (if (same-variable? exp var) 1 0))\n;         ((sum? exp)\n;          (make-sum (deriv (addend exp) var)\n;                    (deriv (augend exp) var)))\n;         ((product? exp)\n;          (make-sum\n;            (make-product (multiplier exp)\n;                          (deriv (multiplicand exp) var))\n;            (make-product (deriv (multiplicand exp) var)\n;                          (multiplier exp))))\n;         ; ...more rules can be added here\n;         (else (error \"unknown expression type - DERIV\" exp))))\n;\n; We can regard this program as performing a dispatch on the type of the\n; expression to be differentiated. In this situation the \"type tag\" of the\n; datum is the algebraic operator symbol (such as +) and the operation being\n; performed is deriv. We can transform this program into data-directed style by\n; rewriting the basic derivative procedure as\n;\n; (define (deriv exp var)\n;   (cond ((number? exp) 0)\n;         ((variable? exp)\n;          (if (same-variable? exp var) 1 0))\n;         (else\n;           ((get 'deriv (operator exp))\n;            (operands exp)\n;            var))))\n;\n; (define (operator exp) (car exp))\n;\n; (define (operands exp) (cdr exp))\n;\n; a. Explain what was done above. Why can't we assimilate the predicates\n;    number? and variable? into the data-directed dispatch?\n;\n; b. Write the procedures for derivatives of sums and products, and the\n;    auxiliary code required to install them in the table used by the program\n;    above.\n;\n; c. Choose any additional differentiation rule that you like, such as the one\n;    for exponents (exercise 2.56), and install it in this data-directed\n;    system.\n;\n; d. In this simple algebraic manipulator the type of an expression is the\n;    algebraic operator that binds it together. Suppose, however, we indexed\n;    the procedures in the opposite way, so that the dispatch line in deriv\n;    looked like\n;\n;    ((get (operator exp) 'deriv) (operands exp) var)\n;\n;    What corresponding changes to the derivative system are required?\n\n; a. It's rather trivial what was done.\n;\n;    Anyway, we can't assimilate number? and variable? because they don't have\n;    a type tag that can be indexed in the table.\n;\n; b. Check out below.\n;\n; c. Ditto.\n;\n; d. Simple. We just need to flip the op and type args to put.\n\n; The whole shebang\n(define (install-deriv-package)\n  (define (make-sum a1 a2)\n    (cond ((=number? a1 0) a2)\n          ((=number? a2 0) a1)\n          ((and (number? a1) (number? a2)) (+ a1 a2))\n          (else (list '+ a1 a2))))\n  (define (deriv-sum args var)\n    (make-sum (deriv (addend args) var)\n              (deriv (augend args) var)))\n  (define (addend opers)\n    (car opers))\n  (define (augend opers)\n    (cadr opers))\n\n  (define (make-product m1 m2)\n    (cond ((or (=number? m1 0) (=number? m2 0)) 0)\n          ((=number? m1 1) m2)\n          ((=number? m2 1) m1)\n          ((and (number? m1) (number? m2)) (* m1 m2))\n          (else (list '* m1 m2))))\n  (define (deriv-product args var)\n    (make-sum\n      (make-product (multiplier args)\n                    (deriv (multiplicand args) var))\n      (make-product (deriv (multiplier args) var)\n                    (multiplicand args))))\n  (define (multiplier opers)\n    (car opers))\n  (define (multiplicand opers)\n    (cadr opers))\n\n  (define (make-exponentiation base power)\n    (cond ((=number? power 0) 1)\n          ((=number? power 1) base)\n          (else (list '** base power))))\n  (define (deriv-exponentiation args var)\n    (make-product\n      (make-product (power args)\n                    (make-exponentiation (base args)\n                                         (- (power args) 1)))\n      (deriv (base args) var)))\n  (define (base opers)\n    (car opers))\n  (define (power opers)\n    (cadr opers))\n\n  (define (=number? expr num)\n    (and (number? expr)\n         (= expr num)))\n\n  (put 'deriv '+ deriv-sum)\n  (put 'deriv '* deriv-product)\n  (put 'deriv '** deriv-exponentiation))\n\n\n\n; The code you gave me\n(define (deriv expr var)\n  (cond ((number? expr) 0)\n        ((variable? expr)\n         (if (same-variable? expr var) 1 0))\n        (else\n          ((get 'deriv (operator expr))\n           (operands expr)\n           var))))\n\n(define (operator expr)\n  (car expr))\n\n(define (operands expr)\n  (cdr expr))\n\n\n\n; The auxiliary stuff\n(define (variable? x)\n  (symbol? x))\n\n(define (same-variable? v1 v2)\n  (and (variable? v1)\n       (variable? v2)\n       (eq? v1 v2)))\n\n\n\n; The table that we assumed is built-in. Don't peek.\n(define table (make-hash))\n\n(define (put op type item)\n  (hash-set! table (list op type) item))\n\n(define (get op type)\n  (hash-ref table (list op type)))\n\n\n\n(install-deriv-package)\n"
  },
  {
    "path": "scheme/sicp/02/74.scm",
    "content": "; SICP exercise 2.74\n;\n; Insatiable Enterprises, Inc. is a highly decentralized conglomerate\n; consisting of a large number of independent divisions located all over the\n; world. The company's computer facilities have just been interconnected by\n; means of a clever network-interfacing scheme that makes the entire network\n; appear to any user to be a single computer. Insatiable's president, in her\n; first attempt to exploit the ability of the network to extract\n; administrative information from division files, is dismayed to discover\n; that, alhough all the division files have been implemeted as data structures\n; in Scheme, the particular data structure used varies from division to\n; division. A meeting of division managers is hastily called to search for a\n; strategy to integrate the files that will satisfy headquarters' needs while\n; preserving the existing autonomy of the divisions.\n;\n; Show how such a strategy can be implemeted with data-directed programming.\n; As an example, suppose that each division personnel records consist of a\n; single file, which contains a set of records keyed on employees' names.\n; Furthermore, each employee's record is itself a set (structured differently\n; from division to division) that contains information keyed under identifiers\n; such as address and salary. In particular:\n;\n; a. Implement for headquarters a get-record procedure that retrieves a\n; specified employee's record from a specified personnel file. The procedure\n; should be applicable to any division's file. Explain how the individual\n; divisions' files should be structured. In partucular, what type information\n; must be supplied?\n;\n; b. Implement for headquarters a get-salary procedure that returns the salary\n; information from a given employee's record from any division's personnel\n; file. How should the record be structured in order to make this operation\n; work?\n;\n; c. Implement for headquarters a find-employee-record procedure. This should\n; search al the divisions' files for the record of a given employee and return\n; the record. Assume that this procedure takes as arguments an employee's name\n; and a list of all the divisions' files.\n;\n; d. WHen Insatiable takes over a new company, what changes must be made in\n; order to incorporate the new personnel information into the central system?\n\n; Alright then. Let's interpretate \"a set of records\" a bit loosely and have\n; it as an s-expr, as opposed to having a specific set module. We'll have two\n; divisions - Atreides and Fremen. Here's how their sets look like:\n\n(define atreides\n  '((\"Paul Atreides\"\n     ((salary 2000)\n      (address \"Arrakeen Palace\")))\n    (\"Gurney Halleck\"\n     ((salary 1500)\n      (address \"Here and there\")))\n    (\"Duke Leto\"\n     ((salary 2500)\n      (address \"The Caladan planet\")))))\n\n(define fremen\n  '((\"Stilgar\" .\n    ((income . 1000)\n     (location . \"Sietch Tabr\")))\n    (\"Chani\" .\n     ((income . 800)\n      (location . \"Whenever Paul is\")))))\n\n; Note that each division file has a type tag. Also note that while Atreides\n; have each record as an a-list, Fremen have their records as a list of pairs.\n; That way we have two data structures, which we should call a-lists and\n; p-lists (for pair lists). Let's write some code for handling them:\n\n(define (a-list-get a-list key)\n  (cond ((null? a-list) '())\n        ((equal? (caar a-list) key) (cadar a-list))\n        (else (a-list-get (cdr a-list) key))))\n\n(define (p-list-get p-list key)\n  (cond ((null? p-list) '())\n        ((equal? (caar p-list) key) (cdar p-list))\n        (else (p-list-get (cdr p-list) key))))\n\n; We will be working with tagged data, so we a couple of functions for that:\n\n(define (attach-tag type-tag contents)\n  (cons type-tag contents))\n\n(define (type-tag datum)\n  (if (pair? datum)\n      (car datum)\n      (error \"Bad tagged datum - TYPE-TAG\" datum)))\n\n(define (contents datum)\n  (if (pair? datum)\n      (cdr datum)\n      (error \"Bad tagged datum - CONTENTS\" datum)))\n\n(define (apply-generic op . args)\n  (let ((type-tags (map type-tag args)))\n    (let ((proc (get op type-tags)))\n      (if proc\n          (apply proc (map contents args))\n          (error \"No method for these types - APPLY-GENERIC\" (list op type-tags))))))\n\n; Finally, we need to implement the infrastructure we need for data-directed\n; programming, i.e. the get and put procedures. We shall use Racket hashes for\n; that one.\n\n(define table (make-hash))\n\n(define (put op type item)\n  (hash-set! table (list op type) item))\n\n(define (get op type)\n  (hash-ref table (list op type)))\n\n; a. get-record is just a simple generic procedure, implemented in a\n; data-directed way. The generic implementation is below, while the specific\n; implementation for each file is in the install-*-package procedure. Note\n; that we attach a tag to the name to be consistent with apply-generic.\n\n(define (get-record name file)\n  (apply-generic 'get-record (attach-tag 'string name) file))\n\n; b. get-salary is fairly similar to get-record:\n\n(define (get-salary record)\n  (apply-generic 'get-salary record))\n\n; c. The list of divisions taken by find-employee-record should be type\n; tagged. That said, here's the implementation:\n\n(define (find-employee-record name division-files)\n  (if (null? division-files)\n      '()\n      (let ((record (get-record name (car division-files))))\n        (if (null? record)\n            (find-employee-record name (cdr division-files))\n            record))))\n\n; Here are the Atreides and Fremen packages:\n\n(define (install-atreides-package)\n  (define (tag record)\n    (if (null? record)\n        record\n        (attach-tag 'atreides record)))\n  (define (get-record name file) (a-list-get file name))\n  (define (get-salary record) (a-list-get record 'salary))\n\n  (put 'get-record '(string atreides-file)\n       (lambda (name file) (tag (get-record name file))))\n  (put 'get-salary '(atreides) get-salary))\n\n(define (install-fremen-package)\n  (define (tag record)\n    (if (null? record)\n        record\n        (attach-tag 'fremen record)))\n  (define (get-record name file) (p-list-get file name))\n  (define (get-salary record) (p-list-get record 'income))\n\n  (put 'get-record '(string fremen-file)\n       (lambda (name file) (tag (get-record name file))))\n  (put 'get-salary '(fremen) get-salary))\n\n; And here's how we install them:\n\n(install-atreides-package)\n(install-fremen-package)\n\n; d. Whenever a new company is bought, there is only one change needed. The\n; company needs to provide a procedure analogous to install-atreides-package\n; that is able to work with their file.\n;\n; A question that is left unanswered is how to get the file for each division\n; and tag it accodingly. One idea would be that each division has a name and\n; we implement a procedure get-division-file that takes as an argument the\n; division name and returns the file. This can be implemented in a number of\n; ways, but all of those I can think of involve knowing something about state.\n"
  },
  {
    "path": "scheme/sicp/02/75.scm",
    "content": "; SICP exercise 2.75\n;\n; Implement the constructor make-from-mag-ang in message-passing style. This\n; procedure should be analogousto the make-from-real-imag procedure given\n; above.\n\n(define (apply-generic op arg) (arg op))\n\n(define (magnitute imag) (apply-generic 'magnitute imag))\n(define (angle imag) (apply-generic 'angle imag))\n(define (real-part imag) (apply-generic 'real-part imag))\n(define (imag-part imag) (apply-generic 'imag-part imag))\n\n(define (make-from-mag-ang mag ang)\n  (define (dispatch op)\n    (cond ((eq? op 'magnitute) mag)\n          ((eq? op 'angle) ang)\n          ((eq? op 'real-part) (* mag (cos ang)))\n          ((eq? op 'imag-part) (* mag (sin ang)))\n          (else (error \"Unknown op - MAKE-FROM-MAG-ANG\" op))))\n  dispatch)\n\n"
  },
  {
    "path": "scheme/sicp/02/76.scm",
    "content": "; SICP exercise 2.76\n;\n; As a large system with generic operations evolves, new types of data objects\n; or new operations may be needed. For each of the three strategies - generic\n; operations with explicit dispatch, data-directed style and\n; message-passing-style - describe the changes that must be made to a system\n; in order to add new types or new operations. Which organization would be\n; most appropriate for a system in which new types must often be added? Which\n; would be most appropriate for a system in which new operations must often be\n; added?\n\n; This is very similar to Uncle Bob's dichotomy about structures vs. objects.\n;\n; With generic operations with explicit dispatch, we need to modify every\n; existing procedure when we add a new type. Adding a new operation is\n; simpler, since we just need to add one procedure.\n;\n; With message-passing-style, we need to modify all existing types when we add\n; a new operation, but we can add a new type without additively.\n;\n; Data-directed style is a bit more complicated. The structure in the examples\n; we've seen so far implies that it is similar to message-passing-style - i.e.\n; we can add a new type easily, but adding operations requires modifying the\n; existing modules. But this is not true - we can write a module that adds a\n; new operation as well, although it needs to know about the types that exist\n; so far. To be fair, the packages we've seen so far have been centered around\n; a type, but we can organize them around operations too. That way, it is not\n; a matter of possibility, but consistency - we can add either new operations\n; and new types, but if we have type-centered packages, creating one that\n; defines a new operation would be inconsistent. It becomes more complex when\n; the packages that are installed need to know about each other - i.e. package\n; A introduces an operation and package B introduces a type that implements\n; the operation from package A. In all cases, this is the most flexible\n; solution.\n;\n; In object-oriented lingo, generic operations with explicit dispatch is\n; similar to structures, message-passing-style is similar to objects and\n; data-directed style is quite similar to a sparse Visitor design pattern.\n;\n; As for the questions, generic operations with explicit dispatch are more\n; appropriate for adding a new operation, while message-passing style is more\n; appropriate for adding a new type. Data-directed style is less optimal than\n; either, but enables both in an additive way.\n"
  },
  {
    "path": "scheme/sicp/02/77.scm",
    "content": "; SICP exercise 2.77\n;\n; Louis Reasoner tries to evaluate the expression (magnitute z) where z is the\n; object shown in Figure 2.24. To his surprise, instead of the answer 5 he\n; gets an error message from apply-generic, saying there is no method for the\n; operation magnitute on the types (complex). He shows this interaction to\n; Alyssa P. Hacker, who says \"The problem is that the complex-number selectors\n; were never defined for complex numbers, just for polar and rectangular\n; numbers. All you have to do to make this work is add the following to the\n; complex package:\"\n;\n; (put 'real-part '(complex) real-part)\n; (put 'imag-part '(complex) imag-part)\n; (put 'magnitute '(complex) magnitute)\n; (put 'angle '(complex) angle)\n;\n; Describe in details why this works. As an example, trace through all the\n; procedures called in evaluating the expression (magnitute z) where z is the\n; object shown in Figure 2.24. In particular, how many times is apply-generic\n; invoked? What procedure is dispatched in each case?\n\n; It's straightforward.\n;\n; Whenever we call (magnitute z) we get to:\n;\n; (apply-generic 'magnitute z)\n;\n; where z is (complex (rectangular (3 . 4))). This, of course, fails since\n; magnitute is not installed for complex. As soon as we install it, though, it\n; would resolve to calling:\n;\n; (apply-generic 'magnitute '(rectangular (3 . 4)))\n;\n; That's because apply-generic strips the type tags whenever it passes the\n; datum. This will dispatch to the code in the rectangular package, which\n; would return 5.\n;\n; That said, apply-generic is called twice. The first time it is dispatched to\n; back to magnitute, while the second - to the code in the rectangular\n; package.\n"
  },
  {
    "path": "scheme/sicp/02/78.scm",
    "content": "; SICP exercise 2.78\n;\n; The internal procedures in the scheme-number package are essentially nothing\n; more than calls to the primitive procedures +, -, etc. It was not possible\n; to use the primitives of the language directly because our type-tag system\n; requires that each data object have a type attached to it. In fact, however,\n; all Lisp implementations do have a type system, which they use internally.\n; Primitive predicates such as symbol? and number? determine whether data\n; objects have particular types. Modify the definitions of type-tag, contents\n; and attach-tag form Section 2.4.2 so that our generic system takes advantage\n; of Scheme's internal type system. That is to say, the system should work as\n; before except that ordinary numbers should be represented simply as Scheme\n; numbers rather than as pairs whose car is the symbol scheme-number.\n\n; Boy, that's though. We need to implement a chunk of the code we had so far\n; in the chapter. Let's do it, since we are going to need it for the next few\n; exercises. The actual solution of the exercise is at the end.\n\n; First, let's start with the dispatch table.\n\n(define table (make-hash))\n\n(define (put op type item)\n  (hash-set! table (list op type) item))\n\n(define (get op type)\n  (hash-ref table (list op type)))\n\n; Now the procedures we need for the type system:\n\n(define (attach-tag type-tag contents)\n  (cons type-tag contents))\n\n(define (type-tag datum)\n  (if (pair? datum)\n      (car datum)\n      (error \"Bad tagged datum - TYPE-TAG\" datum)))\n\n(define (contents datum)\n  (if (pair? datum)\n      (cdr datum)\n      (error \"Bad tagged datum - CONTENTS\" datum)))\n\n(define (apply-generic op . args)\n  (let ((type-tags (map type-tag args)))\n    (let ((proc (get op type-tags)))\n      (if proc\n          (apply proc (map contents args))\n          (error \"No method for these types - APPLY-GENERIC\" (list op type-tags))))))\n\n; Some auxilary functions:\n\n(define (square a) (* a a))\n\n; Now the generic arithmemtic procedures:\n\n(define (add x y) (apply-generic 'add x y))\n(define (sub x y) (apply-generic 'sub x y))\n(define (mul x y) (apply-generic 'mul x y))\n(define (div x y) (apply-generic 'div x y))\n\n; And now - the scheme number package:\n\n(define (install-scheme-number-package)\n  (define (tag x) (attach-tag 'scheme-number x))\n  (put 'add '(scheme-number scheme-number)\n       (lambda (x y) (tag (+ x y))))\n  (put 'sub '(scheme-number scheme-number)\n       (lambda (x y) (tag (- x y))))\n  (put 'mul '(scheme-number scheme-number)\n       (lambda (x y) (tag (* x y))))\n  (put 'div '(scheme-number scheme-number)\n       (lambda (x y) (tag (/ x y))))\n\n  (put 'make 'scheme-number\n       (lambda (x) (tag x)))\n\n  'done)\n\n(define (make-scheme-number n)\n  ((get 'make 'scheme-number) n))\n\n; The next one is the rational numbers:\n\n(define (install-rational-package)\n  (define (numer x) (car x))\n  (define (denom x) (cdr x))\n  (define (make-rat n d)\n    (let ((g (gcd n d)))\n      (cons (/ n g) (/ d g))))\n\n  (define (add-rat x y)\n    (make-rat (+ (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (sub-rat x y)\n    (make-rat (- (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (mul-rat x y)\n    (make-rat (* (numer x) (numer y))\n              (* (denom x) (denom y))))\n  (define (div-rat x y)\n    (make-rat (* (numer x) (denom y))\n              (* (denom x) (numer y))))\n\n  (define (tag x) (attach-tag 'rational x))\n  (put 'add '(rational rational)\n       (lambda (x y) (tag (add-rat x y))))\n  (put 'sub '(rational rational)\n       (lambda (x y) (tag (sub-rat x y))))\n  (put 'mul '(rational rational)\n       (lambda (x y) (tag (mul-rat x y))))\n  (put 'div '(rational rational)\n       (lambda (x y) (tag (div-rat x y))))\n  (put 'make 'rational\n       (lambda (n d) (tag (make-rat n d))))\n  'done)\n\n(define (make-rational n d)\n  ((get 'make 'rational) n d))\n\n; Now we need the complex numbers. They are trickier. We start with the\n; selector procedures:\n\n(define (real-part z) (apply-generic 'real-part z))\n(define (imag-part z) (apply-generic 'imag-part z))\n(define (magnitude z) (apply-generic 'magnitude z))\n(define (angle z) (apply-generic 'angle z))\n\n(define (make-from-real-imag x y)\n  ((get 'make-from-real-imag 'rectangular) x y))\n\n(define (make-from-mag-ang r a)\n  ((get 'make-from-mag-ang 'polar) r a))\n\n; They are followed by the rectangular package:\n\n(define (install-rectangular-package)\n  (define (real-part z) (car z))\n  (define (imag-part z) (cdr z))\n  (define (make-from-real-imag x y) (cons x y))\n  (define (magnitude z)\n    (sqrt (+ (square (real-part z))\n             (square (imag-part z)))))\n  (define (angle z)\n    (atan (imag-part z) (real-part z)))\n  (define (make-from-mag-ang r a)\n    (cons (* r (cos a)) (* r (sin a))))\n\n  (define (tag x) (attach-tag 'rectangular x))\n  (put 'real-part '(rectangular) real-part)\n  (put 'imag-part '(rectangular) imag-part)\n  (put 'angle '(rectangular) angle)\n  (put 'magnitude '(rectangular) magnitude)\n  (put 'make-from-real-imag 'rectangular\n       (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'rectangular\n       (lambda (r a) (tag (make-from-mag-ang r a))))\n  'done)\n\n; Second, the polar package:\n\n(define (install-polar-package)\n  (define (magnitude z) (car z))\n  (define (angle z) (cdr z))\n  (define (make-from-mag-ang r a) (cons r a))\n  (define (real-part z)\n    (* (magnitude z) (cos (angle z))))\n  (define (imag-part z)\n    (* (magnitude z) (sin (angle z))))\n  (define (make-from-real-imag x y)\n    (cons (sqrt (+ (square x) (square y)))\n          (atan y x)))\n\n  (define (tag x) (attach-tag 'polar x))\n  (put 'real-part '(polar) real-part)\n  (put 'imag-part '(polar) imag-part)\n  (put 'magnitude '(polar) magnitude)\n  (put 'angle '(polar) angle)\n  (put 'make-from-real-imag 'polar\n       (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'polar\n       (lambda (r a) (tag (make-from-mag-ang r a))))\n  'done)\n\n; And finally, the complex package:\n\n(define (install-complex-package)\n  (define (make-from-real-imag x y)\n    ((get 'make-from-real-imag 'rectangular) x y))\n  (define (make-from-mag-ang r a)\n    ((get 'make-from-mag-ang 'polar) r a))\n\n  (define (add-complex z1 z2)\n    (make-from-real-imag (+ (real-part z1) (real-part z2))\n                         (+ (imag-part z1) (imag-part z2))))\n  (define (sub-complex z1 z2)\n    (make-from-real-imag (- (real-part z1) (real-part z2))\n                         (- (imag-part z1) (imag-part z2))))\n  (define (mul-complex z1 z2)\n    (make-from-mag-ang (* (magnitude z1) (magnitude z2))\n                       (+ (angle z1) (angle z2))))\n  (define (div-complex z1 z2)\n    (make-from-mag-ang (/ (magnitude z1) (magnitude z2))\n                       (- (angle z1) (angle z2))))\n\n  (define (tag x) (attach-tag 'complex x))\n  (put 'real-part '(complex) real-part)\n  (put 'imag-part '(complex) imag-part)\n  (put 'magnitude '(complex) magnitude)\n  (put 'angle '(complex) angle)\n  (put 'add '(complex complex)\n       (lambda (z1 z2) (tag (add-complex z1 z2))))\n  (put 'sub '(complex complex)\n       (lambda (z1 z2) (tag (sub-complex z1 z2))))\n  (put 'mul '(complex complex)\n       (lambda (z1 z2) (tag (mul-complex z1 z2))))\n  (put 'div '(complex complex)\n       (lambda (z1 z2) (tag (div-complex z1 z2))))\n  (put 'make-from-real-imag 'complex\n       (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'complex\n       (lambda (r a) (tag (make-from-mag-ang r a))))\n  'done)\n\n(define (make-complex-from-real-imag x y)\n  ((get 'make-from-real-imag 'complex) x y))\n\n(define (make-complex-from-mag-ang r a)\n  ((get 'make-from-mag-ang 'complex) r a))\n\n; Finally, we install the packages:\n\n(install-scheme-number-package)\n(install-rational-package)\n(install-rectangular-package)\n(install-polar-package)\n(install-complex-package)\n\n; And now - the solution. We just redefine some functions. The solution is\n; neat, since it does not involve modifying the internals of scheme-package,\n; which is very weird. It is way slower, however, since there is a bunch of\n; no-op calls to type-tag and contents whenever the operations is performed.\n; It is not optimal, but it definitelly introduces an interesting thought -\n; the modification the exercises required can be implemented just in the code\n; for the \"type system\", without modification of\n; install-scheme-number-package. It has just one global dependency, which is\n; the name of the type - scheme-number.\n\n(define (attach-tag type-tag contents)\n  (if (equal? type-tag 'scheme-number)\n      contents\n      (cons type-tag contents)))\n\n(define (type-tag datum)\n  (cond ((pair? datum) (car datum))\n        ((number? datum) 'scheme-number)\n        (else (error \"Bad tagged datum - TYPE-TAG\" datum))))\n\n(define (contents datum)\n  (cond ((pair? datum) (cdr datum))\n        ((number? datum) datum)\n        (else (error \"Bad tagged datum - CONTENTS\" datum))))\n"
  },
  {
    "path": "scheme/sicp/02/79.scm",
    "content": "; SICP exercise 2.79\n;\n; Define a generic equality predicate equ? that tests the equality of two\n; numbers, and install it in the generic arithmetic package. The operation\n; should work for ordinary numbers, rational numbers, and complex numbers.\n\n; Simple enough. We shall define a package that just defines a single\n; operation - equ?. The alternative would be to spread this over in the\n; existing packages. The solution is in the end, since we need to define\n; install-equ?-package after we have redefined real-part and imag-part.\n\n; First, let's start with the dispatch table.\n\n(define table (make-hash))\n\n(define (put op type item)\n  (hash-set! table (list op type) item))\n\n(define (get op type)\n  (hash-ref table (list op type)))\n\n; Now the procedures we need for the type system:\n\n(define (attach-tag type-tag contents)\n  (cons type-tag contents))\n\n(define (type-tag datum)\n  (if (pair? datum)\n      (car datum)\n      (error \"Bad tagged datum - TYPE-TAG\" datum)))\n\n(define (contents datum)\n  (if (pair? datum)\n      (cdr datum)\n      (error \"Bad tagged datum - CONTENTS\" datum)))\n\n(define (apply-generic op . args)\n  (let ((type-tags (map type-tag args)))\n    (let ((proc (get op type-tags)))\n      (if proc\n          (apply proc (map contents args))\n          (error \"No method for these types - APPLY-GENERIC\" (list op type-tags))))))\n\n; Some auxilary functions:\n\n(define (square a) (* a a))\n\n; Now the generic arithmemtic procedures:\n\n(define (add x y) (apply-generic 'add x y))\n(define (sub x y) (apply-generic 'sub x y))\n(define (mul x y) (apply-generic 'mul x y))\n(define (div x y) (apply-generic 'div x y))\n\n; And now - the scheme number package:\n\n(define (install-scheme-number-package)\n  (define (tag x) (attach-tag 'scheme-number x))\n  (put 'add '(scheme-number scheme-number)\n       (lambda (x y) (tag (+ x y))))\n  (put 'sub '(scheme-number scheme-number)\n       (lambda (x y) (tag (- x y))))\n  (put 'mul '(scheme-number scheme-number)\n       (lambda (x y) (tag (* x y))))\n  (put 'div '(scheme-number scheme-number)\n       (lambda (x y) (tag (/ x y))))\n\n  (put 'make 'scheme-number\n       (lambda (x) (tag x)))\n\n  'done)\n\n(define (make-scheme-number n)\n  ((get 'make 'scheme-number) n))\n\n; The next one is the rational numbers:\n\n(define (install-rational-package)\n  (define (numer x) (car x))\n  (define (denom x) (cdr x))\n  (define (make-rat n d)\n    (let ((g (gcd n d)))\n      (cons (/ n g) (/ d g))))\n\n  (define (add-rat x y)\n    (make-rat (+ (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (sub-rat x y)\n    (make-rat (- (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (mul-rat x y)\n    (make-rat (* (numer x) (numer y))\n              (* (denom x) (denom y))))\n  (define (div-rat x y)\n    (make-rat (* (numer x) (denom y))\n              (* (denom x) (numer y))))\n\n  (define (tag x) (attach-tag 'rational x))\n  (put 'add '(rational rational)\n       (lambda (x y) (tag (add-rat x y))))\n  (put 'sub '(rational rational)\n       (lambda (x y) (tag (sub-rat x y))))\n  (put 'mul '(rational rational)\n       (lambda (x y) (tag (mul-rat x y))))\n  (put 'div '(rational rational)\n       (lambda (x y) (tag (div-rat x y))))\n  (put 'make 'rational\n       (lambda (n d) (tag (make-rat n d))))\n  'done)\n\n(define (make-rational n d)\n  ((get 'make 'rational) n d))\n\n; Now we need the complex numbers. They are trickier. We start with the\n; selector procedures:\n\n(define (real-part z) (apply-generic 'real-part z))\n(define (imag-part z) (apply-generic 'imag-part z))\n(define (magnitude z) (apply-generic 'magnitude z))\n(define (angle z) (apply-generic 'angle z))\n\n(define (make-from-real-imag x y)\n  ((get 'make-from-real-imag 'rectangular) x y))\n\n(define (make-from-mag-ang r a)\n  ((get 'make-from-mag-ang 'polar) r a))\n\n; They are followed by the rectangular package:\n\n(define (install-rectangular-package)\n  (define (real-part z) (car z))\n  (define (imag-part z) (cdr z))\n  (define (make-from-real-imag x y) (cons x y))\n  (define (magnitude z)\n    (sqrt (+ (square (real-part z))\n             (square (imag-part z)))))\n  (define (angle z)\n    (atan (imag-part z) (real-part z)))\n  (define (make-from-mag-ang r a)\n    (cons (* r (cos a)) (* r (sin a))))\n\n  (define (tag x) (attach-tag 'rectangular x))\n  (put 'real-part '(rectangular) real-part)\n  (put 'imag-part '(rectangular) imag-part)\n  (put 'angle '(rectangular) angle)\n  (put 'magnitude '(rectangular) magnitude)\n  (put 'make-from-real-imag 'rectangular\n       (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'rectangular\n       (lambda (r a) (tag (make-from-mag-ang r a))))\n  'done)\n\n; Second, the polar package:\n\n(define (install-polar-package)\n  (define (magnitude z) (car z))\n  (define (angle z) (cdr z))\n  (define (make-from-mag-ang r a) (cons r a))\n  (define (real-part z)\n    (* (magnitude z) (cos (angle z))))\n  (define (imag-part z)\n    (* (magnitude z) (sin (angle z))))\n  (define (make-from-real-imag x y)\n    (cons (sqrt (+ (square x) (square y)))\n          (atan y x)))\n\n  (define (tag x) (attach-tag 'polar x))\n  (put 'real-part '(polar) real-part)\n  (put 'imag-part '(polar) imag-part)\n  (put 'magnitude '(polar) magnitude)\n  (put 'angle '(polar) angle)\n  (put 'make-from-real-imag 'polar\n       (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'polar\n       (lambda (r a) (tag (make-from-mag-ang r a))))\n  'done)\n\n; And finally, the complex package:\n\n(define (install-complex-package)\n  (define (make-from-real-imag x y)\n    ((get 'make-from-real-imag 'rectangular) x y))\n  (define (make-from-mag-ang r a)\n    ((get 'make-from-mag-ang 'polar) r a))\n\n  (define (add-complex z1 z2)\n    (make-from-real-imag (+ (real-part z1) (real-part z2))\n                         (+ (imag-part z1) (imag-part z2))))\n  (define (sub-complex z1 z2)\n    (make-from-real-imag (- (real-part z1) (real-part z2))\n                         (- (imag-part z1) (imag-part z2))))\n  (define (mul-complex z1 z2)\n    (make-from-mag-ang (* (magnitude z1) (magnitude z2))\n                       (+ (angle z1) (angle z2))))\n  (define (div-complex z1 z2)\n    (make-from-mag-ang (/ (magnitude z1) (magnitude z2))\n                       (- (angle z1) (angle z2))))\n\n  (define (tag x) (attach-tag 'complex x))\n  (put 'real-part '(complex) real-part)\n  (put 'imag-part '(complex) imag-part)\n  (put 'magnitude '(complex) magnitude)\n  (put 'angle '(complex) angle)\n  (put 'add '(complex complex)\n       (lambda (z1 z2) (tag (add-complex z1 z2))))\n  (put 'sub '(complex complex)\n       (lambda (z1 z2) (tag (sub-complex z1 z2))))\n  (put 'mul '(complex complex)\n       (lambda (z1 z2) (tag (mul-complex z1 z2))))\n  (put 'div '(complex complex)\n       (lambda (z1 z2) (tag (div-complex z1 z2))))\n  (put 'make-from-real-imag 'complex\n       (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'complex\n       (lambda (r a) (tag (make-from-mag-ang r a))))\n  'done)\n\n(define (make-complex-from-real-imag x y)\n  ((get 'make-from-real-imag 'complex) x y))\n\n(define (make-complex-from-mag-ang r a)\n  ((get 'make-from-mag-ang 'complex) r a))\n\n; Finally, we install the packages:\n\n(install-scheme-number-package)\n(install-rational-package)\n(install-rectangular-package)\n(install-polar-package)\n(install-complex-package)\n\n; Finally, the solution. Note that comparing rational is slightly hacky (it\n; compares representation, not values), since rational numbers do not expose\n; selectors like numer and denom.\n\n(define (install-equ?-package)\n  (put 'equ? '(scheme-number scheme-number) =)\n       (lambda (x y) (= x y))\n  (put 'equ? '(rational rational)\n       (lambda (x y) (equal? x y)))\n  (put 'equ? '(complex complex)\n       (lambda (x y) (and (= (real-part x) (real-part y))\n                          (= (imag-part x) (imag-part y)))))\n  'done)\n\n(define (equ? x y)\n  (apply-generic 'equ? x y))\n\n(install-equ?-package)\n"
  },
  {
    "path": "scheme/sicp/02/80.scm",
    "content": "; SICP exercise 2.80\n;\n; Define a generic predicate =zero? that tests if its argument is zero, and\n; instal it in the generic artihmetic package. The operation should work for\n; ordinary numbers, rational numbers, and complex numbers.\n\n; It would have been awesome if we could base this on the previous exercise.\n; Our type system, however, unboxes the type tags and we cannot directly\n; delegate to equ?. Unfortunatelly, we need to implement it ourselves. Again,\n; we shall define it in a separate package. The solution, due to Racket\n; scoping rules, is at the end. We start with the arithmetic package.\n\n; First, let's start with the dispatch table.\n\n(define table (make-hash))\n\n(define (put op type item)\n  (hash-set! table (list op type) item))\n\n(define (get op type)\n  (hash-ref table (list op type)))\n\n; Now the procedures we need for the type system:\n\n(define (attach-tag type-tag contents)\n  (cons type-tag contents))\n\n(define (type-tag datum)\n  (if (pair? datum)\n      (car datum)\n      (error \"Bad tagged datum - TYPE-TAG\" datum)))\n\n(define (contents datum)\n  (if (pair? datum)\n      (cdr datum)\n      (error \"Bad tagged datum - CONTENTS\" datum)))\n\n(define (apply-generic op . args)\n  (let ((type-tags (map type-tag args)))\n    (let ((proc (get op type-tags)))\n      (if proc\n          (apply proc (map contents args))\n          (error \"No method for these types - APPLY-GENERIC\" (list op type-tags))))))\n\n; Some auxilary functions:\n\n(define (square a) (* a a))\n\n; Now the generic arithmemtic procedures:\n\n(define (add x y) (apply-generic 'add x y))\n(define (sub x y) (apply-generic 'sub x y))\n(define (mul x y) (apply-generic 'mul x y))\n(define (div x y) (apply-generic 'div x y))\n\n; And now - the scheme number package:\n\n(define (install-scheme-number-package)\n  (define (tag x) (attach-tag 'scheme-number x))\n  (put 'add '(scheme-number scheme-number)\n       (lambda (x y) (tag (+ x y))))\n  (put 'sub '(scheme-number scheme-number)\n       (lambda (x y) (tag (- x y))))\n  (put 'mul '(scheme-number scheme-number)\n       (lambda (x y) (tag (* x y))))\n  (put 'div '(scheme-number scheme-number)\n       (lambda (x y) (tag (/ x y))))\n\n  (put 'make 'scheme-number\n       (lambda (x) (tag x)))\n\n  'done)\n\n(define (make-scheme-number n)\n  ((get 'make 'scheme-number) n))\n\n; The next one is the rational numbers:\n\n(define (install-rational-package)\n  (define (numer x) (car x))\n  (define (denom x) (cdr x))\n  (define (make-rat n d)\n    (let ((g (gcd n d)))\n      (cons (/ n g) (/ d g))))\n\n  (define (add-rat x y)\n    (make-rat (+ (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (sub-rat x y)\n    (make-rat (- (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (mul-rat x y)\n    (make-rat (* (numer x) (numer y))\n              (* (denom x) (denom y))))\n  (define (div-rat x y)\n    (make-rat (* (numer x) (denom y))\n              (* (denom x) (numer y))))\n\n  (define (tag x) (attach-tag 'rational x))\n  (put 'add '(rational rational)\n       (lambda (x y) (tag (add-rat x y))))\n  (put 'sub '(rational rational)\n       (lambda (x y) (tag (sub-rat x y))))\n  (put 'mul '(rational rational)\n       (lambda (x y) (tag (mul-rat x y))))\n  (put 'div '(rational rational)\n       (lambda (x y) (tag (div-rat x y))))\n  (put 'make 'rational\n       (lambda (n d) (tag (make-rat n d))))\n  'done)\n\n(define (make-rational n d)\n  ((get 'make 'rational) n d))\n\n; Now we need the complex numbers. They are trickier. We start with the\n; selector procedures:\n\n(define (real-part z) (apply-generic 'real-part z))\n(define (imag-part z) (apply-generic 'imag-part z))\n(define (magnitude z) (apply-generic 'magnitude z))\n(define (angle z) (apply-generic 'angle z))\n\n(define (make-from-real-imag x y)\n  ((get 'make-from-real-imag 'rectangular) x y))\n\n(define (make-from-mag-ang r a)\n  ((get 'make-from-mag-ang 'polar) r a))\n\n; They are followed by the rectangular package:\n\n(define (install-rectangular-package)\n  (define (real-part z) (car z))\n  (define (imag-part z) (cdr z))\n  (define (make-from-real-imag x y) (cons x y))\n  (define (magnitude z)\n    (sqrt (+ (square (real-part z))\n             (square (imag-part z)))))\n  (define (angle z)\n    (atan (imag-part z) (real-part z)))\n  (define (make-from-mag-ang r a)\n    (cons (* r (cos a)) (* r (sin a))))\n\n  (define (tag x) (attach-tag 'rectangular x))\n  (put 'real-part '(rectangular) real-part)\n  (put 'imag-part '(rectangular) imag-part)\n  (put 'angle '(rectangular) angle)\n  (put 'magnitude '(rectangular) magnitude)\n  (put 'make-from-real-imag 'rectangular\n       (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'rectangular\n       (lambda (r a) (tag (make-from-mag-ang r a))))\n  'done)\n\n; Second, the polar package:\n\n(define (install-polar-package)\n  (define (magnitude z) (car z))\n  (define (angle z) (cdr z))\n  (define (make-from-mag-ang r a) (cons r a))\n  (define (real-part z)\n    (* (magnitude z) (cos (angle z))))\n  (define (imag-part z)\n    (* (magnitude z) (sin (angle z))))\n  (define (make-from-real-imag x y)\n    (cons (sqrt (+ (square x) (square y)))\n          (atan y x)))\n\n  (define (tag x) (attach-tag 'polar x))\n  (put 'real-part '(polar) real-part)\n  (put 'imag-part '(polar) imag-part)\n  (put 'magnitude '(polar) magnitude)\n  (put 'angle '(polar) angle)\n  (put 'make-from-real-imag 'polar\n       (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'polar\n       (lambda (r a) (tag (make-from-mag-ang r a))))\n  'done)\n\n; And finally, the complex package:\n\n(define (install-complex-package)\n  (define (make-from-real-imag x y)\n    ((get 'make-from-real-imag 'rectangular) x y))\n  (define (make-from-mag-ang r a)\n    ((get 'make-from-mag-ang 'polar) r a))\n\n  (define (add-complex z1 z2)\n    (make-from-real-imag (+ (real-part z1) (real-part z2))\n                         (+ (imag-part z1) (imag-part z2))))\n  (define (sub-complex z1 z2)\n    (make-from-real-imag (- (real-part z1) (real-part z2))\n                         (- (imag-part z1) (imag-part z2))))\n  (define (mul-complex z1 z2)\n    (make-from-mag-ang (* (magnitude z1) (magnitude z2))\n                       (+ (angle z1) (angle z2))))\n  (define (div-complex z1 z2)\n    (make-from-mag-ang (/ (magnitude z1) (magnitude z2))\n                       (- (angle z1) (angle z2))))\n\n  (define (tag x) (attach-tag 'complex x))\n  (put 'real-part '(complex) real-part)\n  (put 'imag-part '(complex) imag-part)\n  (put 'magnitude '(complex) magnitude)\n  (put 'angle '(complex) angle)\n  (put 'add '(complex complex)\n       (lambda (z1 z2) (tag (add-complex z1 z2))))\n  (put 'sub '(complex complex)\n       (lambda (z1 z2) (tag (sub-complex z1 z2))))\n  (put 'mul '(complex complex)\n       (lambda (z1 z2) (tag (mul-complex z1 z2))))\n  (put 'div '(complex complex)\n       (lambda (z1 z2) (tag (div-complex z1 z2))))\n  (put 'make-from-real-imag 'complex\n       (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'complex\n       (lambda (r a) (tag (make-from-mag-ang r a))))\n  'done)\n\n(define (make-complex-from-real-imag x y)\n  ((get 'make-from-real-imag 'complex) x y))\n\n(define (make-complex-from-mag-ang r a)\n  ((get 'make-from-mag-ang 'complex) r a))\n\n; Finally, we install the packages:\n\n(install-scheme-number-package)\n(install-rational-package)\n(install-rectangular-package)\n(install-polar-package)\n(install-complex-package)\n\n; Finally, the solution. Note that, again, it is slightly hacky because the\n; rational package does not expose enough interface to have a clean level of\n; abstraction. We end up having to compare representations.\n\n(define (install-=zero?-package)\n  (put '=zero? '(scheme-number)\n       (lambda (x) (= x 0)))\n  (put '=zero? '(rational)\n       (lambda (x) (equal? x (contents (make-rational 0 1)))))\n  (put '=zero? '(complex)\n       (lambda (z) (and (= (real-part z) 0)\n                        (= (imag-part z) 0))))\n  'done)\n\n(define (=zero? x)\n  (apply-generic '=zero? x))\n\n(install-=zero?-package)\n"
  },
  {
    "path": "scheme/sicp/02/81.scm",
    "content": "; SICP exercise 2.81\n;\n; Louis Reasoner has noticed that apply-generic may try to coerce arguments to\n; each other's types even if they already have the same type. Therefore, he\n; reasons, we need to put procedures in the coercion table to coerce arguments\n; of each type to their own type. For exapmle, in addition to the\n; scheme-number->complex coercion shown above, he would do:\n;\n;   (define (scheme-number->scheme-number n) n)\n;   (define (complex->complex z) z)\n;   (put-coercion 'scheme-number 'scheme-number\n;                 scheme-number->scheme-number)\n;   (put-coercion 'complex 'complex complex->complex)\n;\n; a. With Louis' coercion procedures installed, what happens if apply-generic\n; is called with two arguments of type scheme-number or two arguments of type\n; complex for an operation that is not found in the table for those types? For\n; example, assume that we've defined a generic exponentiation operation:\n;\n;   (define (exp x y) (apply-generic 'exp x y))\n;\n; and have put a procedure for exponentiation in the Scheme number package but\n; not in any other package:\n;\n;   ;; following added to Scheme-number package\n;   (put 'exp '(scheme-number scheme-number)\n;        (lambda (x y) (tag (expt x y)))) ; using primitive expt\n;\n; What happens if we call exp with two complex numbers as arguments?\n;\n; b. Is Louis correct that something had to be done about coercion with\n; arguments of the same type, or does apply-generic work correctly as is?\n;\n; c. Modify apply-generic so that it doesn't try coercion if the two arguments\n; have the same type.\n\n; a. Well, naturally, when exp is called with two complex numbers, it would\n; not be found in the table. Since a coercion procedure is found, though, it\n; would recursively call itself with the same two complex numbers, leading to\n; an infinite recursion. Given the tail position of the recursive call, the\n; program would just loop infinitely.\n;\n; b. He is right, although he does not provide a good reason for being right.\n; Trying to coerce numbers to the same type does not hurt. It slows the\n; computation down, but in no way makes it incorrect. The real problem is that\n; installing those coercion procedures causes operations to end up in an\n; infinite loop. What we can do is avoid coercing numbers that are the same\n; type. That way installing those procedures (which are logically right) would\n; not cause the program to get stuck.\n;\n; c. I will not provide a test for this, just the code. I hope I am forgiven,\n; since otherwise I would need to drag in a lot of code in order to test it:\n\n(define (apply-generic op . args)\n  (let ((type-tags (map type-tag args)))\n    (let ((proc (get op type-tags)))\n      (if proc\n          (apply proc (map contents args))\n          (if (= (length args) 2)\n              (let ((type1 (car type-tags))\n                    (type2 (cadr type-tags))\n                    (a1 (car args))\n                    (a2 (cadr args)))\n                (if (not (eq? type1 type2))\n                    (let ((t1->t2 (get-coercion type1 type2))\n                          (t2->t1 (get-coercion type2 type1)))\n                      (cond (t1->t2\n                              (apply-generic op (t1->t2 a1) a2))\n                            (t2->t1\n                              (apply-generic op a1 (t2->t1 a2)))\n                            (else\n                              (error \"No method for these types\" (list op type-tags)))))\n                    (error \"No method for these types\" (list op type-tags))))\n              (error \"No method for these types\" (list op type-tags)))))))\n"
  },
  {
    "path": "scheme/sicp/02/82.scm",
    "content": "; SICP exercise 2.82\n;\n; Show how the generalize apply-generic to handle coercion in the general case\n; of multiple arguments. One strategy is to attempt to coerce all the\n; arguments to the type of the first argument, then to the type of the second\n; argument, and so on. Give an example of a situation where this strategy (and\n; likewise the two-argument version given above) is not sufficiently general.\n; (Hint: consider the case where there are some suitable mixed-type operations\n; present in the table that will not be tried.)\n\n; We want to test this. So first, we are going to implement all the necessary\n; infrastructure. We shall not use real types, however, and we shall not\n; introduce real operations. We would just have dummy operations and dummy\n; conversions.\n\n; Let's assume we have three types - a, b and c, where we have conversions\n; a->b and b->c. Thus, c is the most generic type and a is the least generic\n; one.\n\n; Let's have the usual infrastructure. First, the table:\n\n(define table (make-hash))\n\n(define (put op type item)\n  (hash-set! table (list op type) item))\n\n(define (get op type)\n  (hash-ref table (list op type) #f))\n\n; Next, the coercion operations:\n\n(define (put-coercion from to op)\n  (put 'coerce (list from to) op))\n\n(define (get-coercion from to)\n  (get 'coerce (list from to)))\n\n; Then, the type operations:\n\n(define (attach-tag type-tag contents)\n  (cons type-tag contents))\n\n(define (type-tag datum)\n  (if (pair? datum)\n      (car datum)\n      (error \"Bad tagged datum - TYPE-TAG\" datum)))\n\n(define (contents datum)\n  (if (pair? datum)\n      (cdr datum)\n      (error \"Bad tagged datum - CONTENTS\" datum)))\n\n; Here's an intermediate version of apply-generic:\n\n(define (apply-generic op . args)\n  (define (id x) x)\n  (define (get-coercion-or-id from to)\n    (if (equal? from to)\n        id\n        (get-coercion from to)))\n  (define (coerce-to args target-type)\n    (let* ((type-tags (map type-tag args))\n           (coercions (map (lambda (type) (get-coercion-or-id type target-type)) type-tags))\n           (coerced-all? (not (memq #f coercions))))\n      (if coerced-all?\n        (map (lambda (coerce datum) (coerce datum)) coercions args)\n        #f)))\n  (define (find-coercion type-tags)\n    (if (null? type-tags)\n        #f\n        (or (coerce-to args (car type-tags))\n            (find-coercion (cdr type-tags)))))\n  (let ((type-tags (map type-tag args)))\n    (let ((proc (get op type-tags)))\n      (if proc\n          (apply proc (map contents args))\n          (let ((coerced-args (find-coercion type-tags)))\n            (if coerced-args\n              (apply apply-generic op coerced-args)\n              (error \"No method for these types\" (list op type-tags))))))))\n\n; Now, let's introduce our types:\n\n(define (make-a) (attach-tag 'a \"a\"))\n(define (make-b) (attach-tag 'b \"b\"))\n(define (make-c) (attach-tag 'c \"c\"))\n\n; Not some coercion operations:\n\n(put-coercion 'a 'b (lambda (x) (attach-tag 'b (string-append (contents x) \"->\" \"b\"))))\n\n; Our operations would be nonsensical - foo, bar and baz. \n\n(define (foo x y) (apply-generic 'foo x y))\n(define (bar x y z) (apply-generic 'bar x y z))\n(define (baz w x y z) (apply-generic 'baz w x y z))\n\n(put 'foo '(a a) (lambda args (cons 'foo-a-a (map string->symbol args))))\n(put 'foo '(b b) (lambda args (cons 'foo-b-b (map string->symbol args))))\n(put 'bar '(a a a) (lambda args (cons 'bar-a-a-a (map string->symbol args))))\n(put 'bar '(b b b) (lambda args (cons 'bar-b-b-b (map string->symbol args))))\n(put 'baz '(a a a a) (lambda args (cons 'baz-a-a-a-a (map string->symbol args))))\n(put 'baz '(b b b b) (lambda args (cons 'baz-b-b-b-b (map string->symbol args))))\n\n; As for when this not sufficiently general - consider having foo defined for\n; '(c c), but passing 'a and 'b - coercing just to b won't be enough. We need\n; to coerce both arguments to c, but our apply-generic has no way of knowing\n; that. Another example is if (foo b c) is defined and we call it with a and\n; c. apply-generic will attempt to convert either to a or to c, but foo would\n; not be defined for both.\n"
  },
  {
    "path": "scheme/sicp/02/83.scm",
    "content": "; SICP exercise 2.83\n;\n; Suppose you are designing a generic artihmetic system for dealing with the\n; tower of types shown in Figure 2.25: integer, rational, real and complex.\n; For each type (except complex), design a procedure that raises objects of\n; that type one level in the tower. Show how to install a generic raise\n; operation that will work with each type (except complex).\n\n; Ugh. We end up having tons of code again. Ok, let's start with the\n; boilerplate. We shall use a simplified version of our previous code that\n; does not support all the operations. Furthermore, we shall not hide stuff\n; behind install-*-package.\n\n; Let's have the usual infrastructure. First, the table:\n\n(define table (make-hash))\n\n(define (put op type item)\n  (hash-set! table (list op type) item))\n\n(define (get op type)\n  (hash-ref table (list op type) #f))\n\n; Next, the coercion operations:\n\n(define (put-coercion from to op)\n  (put 'coerce (list from to) op))\n\n(define (get-coercion from to)\n  (get 'coerce (list from to)))\n\n; Then, the type operations:\n\n(define (attach-tag type-tag contents)\n  (cons type-tag contents))\n\n(define (type-tag datum)\n  (if (pair? datum)\n      (car datum)\n      (error \"Bad tagged datum - TYPE-TAG\" datum)))\n\n(define (contents datum)\n  (if (pair? datum)\n      (cdr datum)\n      (error \"Bad tagged datum - CONTENTS\" datum)))\n\n(define (apply-generic op . args)\n  (let ((type-tags (map type-tag args)))\n    (let ((proc (get op type-tags)))\n      (if proc\n          (apply proc (map contents args))\n          (error \"No method for these types - APPLY-GENERIC\" (list op type-tags))))))\n\n; Now our types\n\n(define (make-integer n) (attach-tag 'integer n))\n(define (make-rational r d) (attach-tag 'rational (cons r d)))\n(define (make-real x) (attach-tag 'real x))\n(define (make-complex r i) (attach-tag 'complex (cons r i)))\n\n(put 'raise '(integer) (lambda (n) (make-rational n 1)))\n(put 'raise '(rational) (lambda (r) (make-real (* 1.0 (/ (car r) (cdr r))))))\n(put 'raise '(real) (lambda (x) (make-complex x 0)))\n\n(define (raise x)\n  (apply-generic 'raise x))\n"
  },
  {
    "path": "scheme/sicp/02/84.scm",
    "content": "; SICP exercise 2.84\n;\n; Using the raise operation in Exercise 2.83, modify the apply-generic\n; procedure so that it coerces its arguments to have the same type by the\n; method of succesive raising, as discussed in this section. You will need to\n; devise a way to test which of two types is higher in the tower. Do this in a\n; manner that is compatible with the rest of the system and will not lead to\n; problems in adding new levels to the tower.\n\n; Since we don't know about state yet, we have to accept some constraints.\n; First, if new types can be added, they can make it only on the top or bottom\n; of the type tower. Second, for simplicity, the operations supported by\n; apply-generic will accept only two arguments. If we have that, we can\n; implement the exercise nicely.\n\n; Again, we start with our usual infrastructure. First, the table:\n\n(define table (make-hash))\n\n(define (put op type item)\n  (hash-set! table (list op type) item))\n\n(define (get op type)\n  (hash-ref table (list op type) #f))\n\n; Next, the coercion operations:\n\n(define (put-coercion from to op)\n  (put 'coerce (list from to) op))\n\n(define (get-coercion from to)\n  (get 'coerce (list from to)))\n\n; Then, the type operations:\n\n(define (attach-tag type-tag contents)\n  (cons type-tag contents))\n\n(define (type-tag datum)\n  (if (pair? datum)\n      (car datum)\n      (error \"Bad tagged datum - TYPE-TAG\" datum)))\n\n(define (contents datum)\n  (if (pair? datum)\n      (cdr datum)\n      (error \"Bad tagged datum - CONTENTS\" datum)))\n\n; Now our types and the raise procedure.\n\n(define (make-integer n) (attach-tag 'integer n))\n(define (make-rational r d) (attach-tag 'rational (cons r d)))\n(define (make-real x) (attach-tag 'real x))\n(define (make-complex r i) (attach-tag 'complex (cons r i)))\n\n(put 'raise '(integer) (lambda (n) (make-rational n 1)))\n(put 'raise '(rational) (lambda (r) (make-real (* 1.0 (/ (car r) (cdr r))))))\n(put 'raise '(real) (lambda (x) (make-complex x 0)))\n\n(define (raise x) (apply-generic 'raise x))\n\n; Now, we are going to implement a procedure that returns the supertype of\n; another type.\n\n(put 'supertype 'integer 'rational)\n(put 'supertype 'rational 'real)\n(put 'supertype 'real 'complex)\n\n(define (supertype type)\n  (get 'supertype type))\n\n; Next, we implement a predicate that tells us whether one type is the\n; supertype of another.\n\n(define (supertype? parent child)\n  (let ((type (supertype child)))\n    (cond ((equal? type parent) #t)\n          ((not type) #f)\n          (else (supertype? parent type)))))\n\n; Now we can define apply-generic:\n\n(define (apply-generic op . args)\n  (let ((type-tags (map type-tag args)))\n    (let ((proc (get op type-tags)))\n      (cond (proc (apply proc (map contents args)))\n            ((= (length type-tags) 2)\n             (let ((type1 (car type-tags))\n                   (type2 (cadr type-tags))\n                   (x (car args))\n                   (y (cadr args)))\n               (cond ((supertype? type1 type2) (apply-generic op x (raise y)))\n                     ((supertype? type2 type1) (apply-generic op (raise x) y))\n                     (else (error \"No method for these types - APPLY-GENERIC\" (list op type-tags))))))\n            (else (error \"No method for these types - APPLY-GENERIC\" (list op type-tags)))))))\n\n; Finally, we have an operation we can test with:\n\n(put 'foo '(integer integer) (lambda (x y) 'foo-integer))\n(put 'foo '(rational rational) (lambda (x y) 'foo-rational))\n(put 'foo '(real real) (lambda (x y) 'foo-real))\n(put 'foo '(complex complex) (lambda (x y) 'foo-complex))\n\n(define (foo x y) (apply-generic 'foo x y))\n\n; Now if we need to add another supertype on the top or the bottom of the\n; tower, we need to do two things - first, add it as a supertype of complex\n; (if it is on the top) or add it as the supertype of integer (if it is on the\n; bottom) and second, we need to provide a coercion procedure.\n"
  },
  {
    "path": "scheme/sicp/02/85.scm",
    "content": "; SICP exercise 2.85\n;\n; This section mentioned a method for \"simplifying\" a data object by lowering\n; it in the tower of types as far as possible. Design a procedure drop that\n; accomplishes this for the tower described in Exercise 2.83. The key is to\n; decide, in some general way, whether an object can be lowered. For example,\n; the complex number 1.5 + 0i can be lowered as far as real, the complex\n; number 1 + 0i can be lowered as far s integer, and the complex number 2 + 3i\n; cannot be lowered at all. Here is a plan for determining whether an object\n; can be lowered: begin by defining a generic operation project that \"pushes\"\n; an object down in the tower. For example, projecting a complex number would\n; involve throwing away the imaginary part. Then a number can be dropped if,\n; when we project it and raise the result back to the type we started with, we\n; end up with something equal to what we started with. Show how to implement\n; this idea in detail, by writing a drop procedure that drops an object as far\n; as possible. You will need to design the various projection operations and\n; install project as a generic operation in the system. You will also need to\n; make use of a generic equality predicate, such as described in exercise\n; 2.79. Finally, use drop to rewrite apply-generic from exercise 2.84 so that\n; it \"simplifies\" its answers.\n\n; We base our work on the solution of the previous exercise. The\n; implementation will be a bit flaky, since it is in no way the responsibility\n; of apply-generic to simplify types. Instead, each operation should indicate\n; whether it wants simplification. We shall just assume that every\n; two-argument generic operation that returns a pair (i.e., tagged data) does\n; simplificaiton. Otherwise, the result from drop and project would try to get\n; simplified, which would lead to an infinite recursion. Furthermore, we shall\n; call our procedure drop-down instead of drop, since the name drop is used in\n; Racket and there are some weird rules going on.\n\n; Again, we start with our usual infrastructure. First, the table:\n\n(define table (make-hash))\n(define (put op type item) (hash-set! table (list op type) item))\n(define (get op type) (hash-ref table (list op type) #f))\n\n; Next, the coercion operations:\n\n(define (put-coercion from to op) (put 'coerce (list from to) op))\n(define (get-coercion from to) (get 'coerce (list from to)))\n\n; Then, the type operations:\n\n(define (attach-tag type-tag contents)\n  (cons type-tag contents))\n\n(define (type-tag datum)\n  (if (pair? datum)\n      (car datum)\n      (error \"Bad tagged datum - TYPE-TAG\" datum)))\n\n(define (contents datum)\n  (if (pair? datum)\n      (cdr datum)\n      (error \"Bad tagged datum - CONTENTS\" datum)))\n\n; Now our types and the raise procedure.\n\n(define (round-to-int x)\n  (inexact->exact (truncate x)))\n\n(define (make-integer n) (attach-tag 'integer n))\n(define (make-rational n d)\n  (let ((g (gcd n d)))\n    (attach-tag 'rational (cons (round-to-int (/ n g))\n                                (round-to-int (/ d g))))))\n(define (make-real x) (attach-tag 'real x))\n(define (make-complex r i) (attach-tag 'complex (cons r i)))\n\n(put 'raise '(integer) (lambda (n) (make-rational n 1)))\n(put 'raise '(rational) (lambda (r) (make-real (* 1.0 (/ (car r) (cdr r))))))\n(put 'raise '(real) (lambda (x) (make-complex x 0)))\n\n(define (raise x) (apply-generic 'raise x))\n\n; Now, we are going to implement a procedure that returns the supertype of\n; another type.\n\n(put 'supertype 'integer 'rational)\n(put 'supertype 'rational 'real)\n(put 'supertype 'real 'complex)\n\n(define (supertype type)\n  (get 'supertype type))\n\n; Next, we implement a predicate that tells us whether one type is the\n; supertype of another.\n\n(define (supertype? parent child)\n  (let ((type (supertype child)))\n    (cond ((equal? type parent) #t)\n          ((not type) #f)\n          (else (supertype? parent type)))))\n\n; Now we can define apply-generic:\n\n(define (apply-generic op . args)\n  (let ((type-tags (map type-tag args)))\n    (let ((proc (get op type-tags)))\n      (if proc\n          (let ((result (apply proc (map contents args))))\n            (if (and (= (length args) 2) (projectable? result))\n                (drop-down result)\n                result))\n          (error \"No method for these types - APPLY-GENERIC\" (list op type-tags))))))\n\n; Let's have an add operation we can use:\n\n(put 'add '(integer integer) (lambda (x y) (make-integer (+ x y))))\n(put 'add '(rational rational)\n     (lambda (x y)\n       (let* ((n1 (car x))\n              (d1 (cdr x))\n              (n2 (car y))\n              (d2 (cdr y)))\n         (make-rational (+ (* n1 d2) (* n2 d1))\n                        (* d1 d2)))))\n(put 'add '(real real) (lambda (x y) (make-real (+ x y))))\n(put 'add '(complex complex)\n     (lambda (z1 z2) (make-complex (+ (car z1) (car z2))\n                                   (+ (cdr z1) (cdr z2)))))\n\n(define (add x y) (apply-generic 'add x y))\n\n; The equ? procedure:\n\n(put 'equ? '(integer integer) =)\n(put 'equ? '(rational rational) equal?)\n(put 'equ? '(real real) =)\n(put 'equ? '(complex complex) equal?)\n\n(define (equ? x y) (apply-generic 'equ? x y))\n\n; The project procedure:\n\n(put 'project '(complex)\n     (lambda (z) (make-real (car z))))\n(put 'project '(real)\n     (lambda (x) (make-rational (round-to-int (numerator x))\n                                (round-to-int (denominator x)))))\n(put 'project '(rational)\n     (lambda (x) (make-integer (round-to-int (/ (car x) (cdr x))))))\n\n(define (project x) (apply-generic 'project x))\n(define (projectable? x) (and (pair? x) (get 'project (list (type-tag x)))))\n\n; The drop procedure:\n\n(define (drop-down x)\n  (if (projectable? x)\n      (let* ((projection (project x))\n             (reraise (raise projection)))\n        (if (equ? reraise x)\n            (drop-down projection)\n            x))\n      x))\n\n; Again, we do this for Racket scoping rules:\n(define drop drop-down)\n"
  },
  {
    "path": "scheme/sicp/02/86.scm",
    "content": "; SICP exercise 2.86\n;\n; Suppose we want to handle comlex numbers whose real parts, imaginary parts,\n; magnitudes and angles can be either ordinary numbers, rational numbers or\n; other numbers we wish to add to our system. Describe and implement the\n; changes to the system needed to accomodate this. You will have to define\n; operations such as sine and cosine that are generic over ordinary numbers\n; and rational numbers.\n\n; Meh. This is a long one. OK, let's start with our assumptions first.\n;\n; We shall have three number types - integer, rational and real. We shall\n; implement our own. Additionally we will support the scheme-number type by\n; patching the type system functions. We will have all the generic operations\n; working for those two types. Furthermore, we shall support the type tower\n; and have raise, project and drop. We shall have a coercion procedure that\n; attempts to raise its arguments as much as it can, in order to implement\n; sine, cosine and atan on all the numbers we have.\n\n; We shall have five number types - integer, rational, scheme-number, scheme\n; and complex. We will patch the type functions as we did in a previous\n; exercise in order to support scheme-numbers seamlessly. We will implement\n; generic operations on all those types. Our type tower will support raise,\n; project and drop (although we will call it simplify). We will have a\n; coercion procedure that attempts to raise arguments, first to the same type\n; and then as much as possible, in order to implement sine, cosine and\n; arctangent. We shall eschew the install-*-package pattern - the package\n; boundaries are obvious.\n\n; Let's start with the type functions, table and coercion infrastructure:\n\n(define (attach-tag type-tag contents)\n  (if (equal? type-tag 'scheme-number)\n      contents\n      (cons type-tag contents)))\n\n(define (type-tag datum)\n  (cond ((number? datum) 'scheme-number)\n        ((pair? datum) (car datum))\n        (else (error \"Bad tagged datum - TYPE-TAG\" datum))))\n\n(define (contents datum)\n  (cond ((number? datum) datum)\n        ((pair? datum) (cdr datum))\n        (else (error \"Bad tagged datum - CONTENTS\" datum))))\n\n(define table (make-hash))\n(define (put op type item) (hash-set! table (list op type) item))\n(define (get op type) (hash-ref table (list op type) #f))\n\n(define (put-coercion from to op) (put 'coerce (list from to) op))\n(define (get-coercion from to) (get 'coerce (list from to)))\n\n; Here is our type tower, supetype, supertype?, raise and project:\n\n(put 'supertype 'integer 'rational)\n(put 'supertype 'rational 'scheme-number)\n(put 'supertype 'scheme-number 'real)\n(put 'supertype 'real 'complex)\n\n(define (supertype type)\n  (get 'supertype type))\n\n(define (supertype? a b)\n  (let ((super (supertype a)))\n    (cond ((equal? super b) #t)\n          ((not super) #f)\n          (else (supertype? super b)))))\n\n(define (same-type? a b) (equal? (type-tag a) (type-tag b)))\n\n(define (raise a) (apply-generic 'raise a))\n(define (project a) (apply-generic 'project a))\n\n(define (projectable? a) (get 'project (list (type-tag a))))\n(define (raisable? a) (get 'raise (list (type-tag a))))\n\n; Now a simplification procedure. It will be called simplify instead of drop,\n; because drop is already reserved:\n\n(define (simplify x)\n  (cond ((not (projectable? x)) x)\n        ((equ? (raise (project x)) x) (simplify (project x)))\n        (else x)))\n\n; Now the generic arithmemtic procedures. Note how square is defined in terms\n; of a generic operation without using apply-generic.\n\n(define (add x y) (apply-generic 'add x y))\n(define (sub x y) (apply-generic 'sub x y))\n(define (mul x y) (apply-generic 'mul x y))\n(define (div x y) (apply-generic 'div x y))\n(define (equ? x y) (apply-generic 'equ? x y))\n(define (square-root x) (apply-generic 'square-root x))\n(define (sine x) (apply-generic 'sine x))\n(define (cosine x) (apply-generic 'cosine x))\n(define (arctangent x y) (apply-generic 'arctangent x y))\n(define (square x) (mul x x))\n\n; Now some infrastructure for which operations can be simplified. We shall put\n; them in the table under the key simplifiable. If an operation is present\n; there, the result can be simplified. This is very nice, since apply-generic\n; does not need to know which operations should be simplified - instead, when\n; adding a new operation, the writer can decide whether it should simplify its\n; result.\n\n(define (simplifiable? op)\n  (get 'simplifiable op))\n\n(put 'simplifiable 'add #t)\n(put 'simplifiable 'sub #t)\n(put 'simplifiable 'mul #t)\n(put 'simplifiable 'div #t)\n(put 'simplifiable 'square-root #t)\n(put 'simplifiable 'sine #t)\n(put 'simplifiable 'cosine #t)\n(put 'simplifiable 'arctangent #t)\n(put 'simplifiable 'real-part #t)\n(put 'simplifiable 'imag-part #t)\n(put 'simplifiable 'magnitude #t)\n(put 'simplifiable 'angle #t)\n\n; And now - the integers. Note that they are not implementing div, since\n; division of integers will result to a rational. Also note, that if you\n; construct an integer with make-integer, you need to pass in an exact\n; integer, otherwise you get an error.\n\n(let ()\n  (define (tag x) (attach-tag 'integer x))\n  (put 'add '(integer integer) (lambda (x y) (tag (+ x y))))\n  (put 'sub '(integer integer) (lambda (x y) (tag (- x y))))\n  (put 'mul '(integer integer) (lambda (x y) (tag (* x y))))\n  (put 'equ? '(integer integer) =)\n  (put 'raise '(integer) (lambda (n) (make-rational n 1)))\n  (put 'make 'integer\n       (lambda (n) (if (exact-integer? n)\n                       (tag n)\n                       (error \"Attempted to make an integer with a non-integer\" n)))))\n\n(define (make-integer n) ((get 'make 'integer) n))\n\n; The next one is the rational numbers:\n\n(let ()\n  (define (numer x) (car x))\n  (define (denom x) (cdr x))\n  (define (make-rat n d)\n    (if (and (exact-integer? n) (exact-integer? d))\n        (let ((g (gcd n d)))\n          (cons (/ n g) (/ d g)))\n        (error \"Cannot construct a rational with non-exact numbers\" n d)))\n\n  (define (add-rat x y)\n    (make-rat (+ (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (sub-rat x y)\n    (make-rat (- (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (mul-rat x y)\n    (make-rat (* (numer x) (numer y))\n              (* (denom x) (denom y))))\n  (define (div-rat x y)\n    (make-rat (* (numer x) (denom y))\n              (* (denom x) (numer y))))\n  (define (raise-rat r)\n    (make-scheme-number (/ (numer r) (denom r))))\n  (define (project-rat r)\n    (make-integer (truncate (/ (numer r) (denom r)))))\n\n  (define (tag x) (attach-tag 'rational x))\n  (put 'numer '(rational) numer)\n  (put 'denom '(rational) denom)\n  (put 'raise '(rational) raise-rat)\n  (put 'project '(rational) project-rat)\n  (put 'add '(rational rational) (lambda (x y) (tag (add-rat x y))))\n  (put 'sub '(rational rational) (lambda (x y) (tag (sub-rat x y))))\n  (put 'mul '(rational rational) (lambda (x y) (tag (mul-rat x y))))\n  (put 'div '(rational rational) (lambda (x y) (tag (div-rat x y))))\n  (put 'equ? '(rational rational) equal?)\n  (put 'make 'rational (lambda (n d) (tag (make-rat n d)))))\n\n(define (make-rational n d) ((get 'make 'rational) n d))\n(define (numer r) (apply-generic 'numer r))\n(define (denom r) (apply-generic 'denom r))\n\n; And now, the ever-mysterious scheme-numbers. Note that they are inbetween\n; the rationals and the reals. This is somehow uncool, since we'll never get a\n; real as a result form our operations because of simplification. At least it\n; is less writing in the tests.\n\n(let ()\n  (put 'add '(scheme-number scheme-number) +)\n  (put 'sub '(scheme-number scheme-number) -)\n  (put 'mul '(scheme-number scheme-number) *)\n  (put 'div '(scheme-number scheme-number) /)\n  (put 'equ? '(scheme-number scheme-number) =)\n  (put 'sine '(scheme-number) sin)\n  (put 'cosine '(scheme-number) cos)\n  (put 'square-root '(scheme-number scheme-number) sqrt)\n  (put 'arctangent '(scheme-number scheme-number) atan)\n  (put 'project '(scheme-number) (lambda (x) (make-rational (inexact->exact (truncate x)) 1)))\n  (put 'raise '(scheme-number) (lambda (x) (make-real (exact->inexact x)))))\n\n(define (make-scheme-number x) (attach-tag 'scheme-number x))\n\n; Then the real numbers. They are pretty much the same as the integers,\n; although without the exact-integer check.\n\n(let ()\n  (define (tag x) (attach-tag 'real x))\n  (put 'add '(real real) (lambda (x y) (tag (+ x y))))\n  (put 'sub '(real real) (lambda (x y) (tag (- x y))))\n  (put 'mul '(real real) (lambda (x y) (tag (* x y))))\n  (put 'div '(real real) (lambda (x y) (tag (/ x y))))\n  (put 'sine '(real) (lambda (x) (tag (sin x))))\n  (put 'cosine '(real) (lambda (x) (tag (cos x))))\n  (put 'square-root '(real) (lambda (x) (tag (sqrt x))))\n  (put 'arctangent '(real real) (lambda (x y) (tag (atan x y))))\n  (put 'project '(real) (lambda (x) (make-scheme-number x)))\n  (put 'raise '(real) (lambda (x) (make-complex-from-real-imag (tag x) (tag 0.0))))\n  (put 'equ? '(real real) =)\n  (put 'make 'real (lambda (x) (tag x))))\n\n(define (make-real n) ((get 'make 'real) n))\n\n; Now we need the complex numbers. They are trickier. We start with the\n; generic procedures:\n\n(define (real-part z) (apply-generic 'real-part z))\n(define (imag-part z) (apply-generic 'imag-part z))\n(define (magnitude z) (apply-generic 'magnitude z))\n(define (angle z) (apply-generic 'angle z))\n\n(define (make-from-real-imag x y) ((get 'make-from-real-imag 'rectangular) x y))\n(define (make-from-mag-ang r a) ((get 'make-from-mag-ang 'polar) r a))\n\n; They are followed by the rectangular representation. Note that it is\n; implemented in terms of the generic procedures we defined earlier.\n\n(let ()\n  (define (real-part z) (car z))\n  (define (imag-part z) (cdr z))\n  (define (make-from-real-imag x y) (cons x y))\n  (define (magnitude z) (square-root (add (square (real-part z)) (square (imag-part z)))))\n  (define (angle z) (arctangent (imag-part z) (real-part z)))\n  (define (make-from-mag-ang r a) (cons (mul r (cosine a)) (mul r (sine a))))\n\n  (define (tag x) (attach-tag 'rectangular x))\n  (put 'real-part '(rectangular) real-part)\n  (put 'imag-part '(rectangular) imag-part)\n  (put 'angle '(rectangular) angle)\n  (put 'magnitude '(rectangular) magnitude)\n  (put 'make-from-real-imag 'rectangular (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'rectangular (lambda (r a) (tag (make-from-mag-ang r a)))))\n\n; The polar package is similar.\n\n(let ()\n  (define (magnitude z) (car z))\n  (define (angle z) (cdr z))\n  (define (make-from-mag-ang r a) (cons r a))\n  (define (real-part z) (mul (magnitude z) (cosine (angle z))))\n  (define (imag-part z) (mul (magnitude z) (sine (angle z))))\n  (define (make-from-real-imag x y) (cons (square-root (add (square x) (square y)))\n                                          (arctangent y x)))\n\n  (define (tag x) (attach-tag 'polar x))\n  (put 'real-part '(polar) real-part)\n  (put 'imag-part '(polar) imag-part)\n  (put 'magnitude '(polar) magnitude)\n  (put 'angle '(polar) angle)\n  (put 'make-from-real-imag 'polar (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'polar (lambda (r a) (tag (make-from-mag-ang r a)))))\n\n; And finally, the complex package:\n\n(let ()\n  (define (make-from-real-imag x y)\n    ((get 'make-from-real-imag 'rectangular) x y))\n  (define (make-from-mag-ang r a)\n    ((get 'make-from-mag-ang 'polar) r a))\n\n  (define (add-complex z1 z2)\n    (make-from-real-imag (add (real-part z1) (real-part z2))\n                         (add (imag-part z1) (imag-part z2))))\n  (define (sub-complex z1 z2)\n    (make-from-real-imag (sub (real-part z1) (real-part z2))\n                         (sub (imag-part z1) (imag-part z2))))\n  (define (mul-complex z1 z2)\n    (make-from-mag-ang (mul (magnitude z1) (magnitude z2))\n                       (add (angle z1) (angle z2))))\n  (define (div-complex z1 z2)\n    (make-from-mag-ang (div (magnitude z1) (magnitude z2))\n                       (sub (angle z1) (angle z2))))\n  (define (equ?-complex z1 z2)\n    (and (equ? (real-part z1) (real-part z2))\n         (equ? (imag-part z1) (imag-part z2))))\n\n  (define (tag x) (attach-tag 'complex x))\n  (put 'real-part '(complex) real-part)\n  (put 'imag-part '(complex) imag-part)\n  (put 'magnitude '(complex) magnitude)\n  (put 'angle '(complex) angle)\n  (put 'add '(complex complex) (lambda (z1 z2) (tag (add-complex z1 z2))))\n  (put 'sub '(complex complex) (lambda (z1 z2) (tag (sub-complex z1 z2))))\n  (put 'mul '(complex complex) (lambda (z1 z2) (tag (mul-complex z1 z2))))\n  (put 'div '(complex complex) (lambda (z1 z2) (tag (div-complex z1 z2))))\n  (put 'equ? '(complex complex) equ?-complex)\n  (put 'project '(complex) (lambda (z) (real-part z)))\n  (put 'make-from-real-imag 'complex (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'complex (lambda (r a) (tag (make-from-mag-ang r a)))))\n\n(define (make-complex-from-real-imag x y) ((get 'make-from-real-imag 'complex) x y))\n(define (make-complex-from-mag-ang r a) ((get 'make-from-mag-ang 'complex) r a))\n(define make-complex make-complex-from-real-imag)\n\n; The apply-generic procedure is at the end, because it uses procedures that\n; are redefined (such as raise). It is fairly complicated. When it is called\n; with a number of arguments, it looks them up in the table and if a procedure\n; is present, it calls it. Otherwise, it checks if all the arguments passed to\n; it are of the same type and if so, it raises them all and tries again. There\n; is an internal recursion in order to provide a good error message -\n; otherwise the original arguments will get lost and then error will include\n; the raised types.\n\n(define (apply-generic op . args)\n  (define (applicable? args)\n    (get op (map type-tag args)))\n\n  (define (apply-generic-failed)\n    (error \"No method for these types - APPLY-GENERIC\" (list op (map type-tag args))))\n\n  (define (all-of-same-type? args)\n    (define (check rest)\n      (cond ((null? rest) #t)\n            ((same-type? (car args) (car rest)) (check (cdr rest)))\n            (else #f)))\n    (check args))\n\n  (define (of-same-type-and-raisable? args)\n    (and (all-of-same-type? args)\n         (raisable? (car args))))\n\n  (define (coercable-to-same-type? args)\n    (and (= (length args) 2)\n         (let ((type-a (type-tag (car args)))\n               (type-b (type-tag (cadr args))))\n           (or (supertype? type-a type-b)\n               (supertype? type-b type-a)))))\n\n  (define (coerce-to-same-type args)\n    (and (= (length args) 2)\n         (let* ((a (car args))\n                (b (cadr args))\n                (type-a (type-tag a))\n                (type-b (type-tag b)))\n           (cond ((same-type? a b) (list a b))\n                 ((supertype? type-a type-b) (coerce-to-same-type (list (raise a) b)))\n                 ((supertype? type-b type-a) (coerce-to-same-type (list a (raise b))))\n                 (else #f)))))\n\n  (define (attempt-coercion args)\n    (let ((number-of-arguments (length args)))\n      (cond ((of-same-type-and-raisable? args) (try (map raise args)))\n            ((coercable-to-same-type? args) (try (coerce-to-same-type args)))\n            (else (apply-generic-failed)))))\n\n  (define (try args)\n    (if (applicable? args)\n        (let ((result (apply (get op (map type-tag args)) (map contents args))))\n          (if (simplifiable? op)\n              (simplify result)\n              result))\n        (attempt-coercion args)))\n\n  (try args))\n"
  },
  {
    "path": "scheme/sicp/02/87.scm",
    "content": "; SICP exercise 2.87\n;\n; Install =zero? for polynomials in the generic arithmetic package. This will\n; allow adjoin-term to work for polynomials with coefficients that are\n; themselves polynomials.\n\n; OK, let's start with our original arithmetic package. We are going to reuse\n; the code from exercise 2.86, although we will remove scheme-numbers because\n; they complicate things.\n;\n; Apart from introducing =zero? to polynomials, we need to add allow for a\n; polynomial to be addded and multiplied by a number in order to support\n; adding and multiplying polynomials that whose coefficients are themselves\n; polynomial.\n\n; The type functions, table and coercion infrastructure.\n\n(define (attach-tag type-tag contents)\n  (cons type-tag contents))\n\n(define (type-tag datum)\n  (if (pair? datum)\n      (car datum)\n      (error \"Bad tagged datum - TYPE-TAG\" datum)))\n\n(define (contents datum)\n  (if (pair? datum)\n      (cdr datum)\n      (error \"Bad tagged datum - CONTENTS\" datum)))\n\n(define table (make-hash))\n(define (put op type item) (hash-set! table (list op type) item))\n(define (get op type) (hash-ref table (list op type) #f))\n\n(define (put-coercion from to op) (put 'coerce (list from to) op))\n(define (get-coercion from to) (get 'coerce (list from to)))\n\n; The type tower, supetype, supertype?, raise and project:\n\n(put 'supertype 'integer 'rational)\n(put 'supertype 'rational 'scheme-number)\n(put 'supertype 'scheme-number 'real)\n(put 'supertype 'real 'complex)\n\n(define (supertype type)\n  (get 'supertype type))\n\n(define (supertype? a b)\n  (let ((super (supertype a)))\n    (cond ((equal? super b) #t)\n          ((not super) #f)\n          (else (supertype? super b)))))\n\n(define (same-type? a b) (equal? (type-tag a) (type-tag b)))\n\n(define (raise a) (apply-generic 'raise a))\n(define (project a) (apply-generic 'project a))\n\n(define (projectable? a) (get 'project (list (type-tag a))))\n(define (raisable? a) (get 'raise (list (type-tag a))))\n\n; Now a simplification procedure. It will be called simplify instead of drop,\n; because drop is already reserved:\n\n(define (simplify x)\n  (cond ((not (projectable? x)) x)\n        ((equ? (raise (project x)) x) (simplify (project x)))\n        (else x)))\n\n; Now the generic arithmemtic procedures.\n\n(define (add x y) (apply-generic 'add x y))\n(define (sub x y) (apply-generic 'sub x y))\n(define (mul x y) (apply-generic 'mul x y))\n(define (div x y) (apply-generic 'div x y))\n(define (equ? x y) (apply-generic 'equ? x y))\n(define (square-root x) (apply-generic 'square-root x))\n(define (sine x) (apply-generic 'sine x))\n(define (cosine x) (apply-generic 'cosine x))\n(define (arctangent x y) (apply-generic 'arctangent x y))\n(define (=zero? x) (apply-generic '=zero? x))\n(define (square x) (mul x x))\n\n; The simplification table:\n\n(define (simplifiable? op)\n  (get 'simplifiable op))\n\n(put 'simplifiable 'add #t)\n(put 'simplifiable 'sub #t)\n(put 'simplifiable 'mul #t)\n(put 'simplifiable 'div #t)\n(put 'simplifiable 'square-root #t)\n(put 'simplifiable 'sine #t)\n(put 'simplifiable 'cosine #t)\n(put 'simplifiable 'arctangent #t)\n(put 'simplifiable 'real-part #t)\n(put 'simplifiable 'imag-part #t)\n(put 'simplifiable 'magnitude #t)\n(put 'simplifiable 'angle #t)\n\n; Integers:\n\n(let ()\n  (define (tag x) (attach-tag 'integer x))\n  (put 'add '(integer integer) (lambda (x y) (tag (+ x y))))\n  (put 'sub '(integer integer) (lambda (x y) (tag (- x y))))\n  (put 'mul '(integer integer) (lambda (x y) (tag (* x y))))\n  (put 'equ? '(integer integer) =)\n  (put '=zero? '(integer) zero?)\n  (put 'raise '(integer) (lambda (n) (make-rational n 1)))\n  (put 'make 'integer\n       (lambda (n) (if (exact-integer? n)\n                       (tag n)\n                       (error \"Attempted to make an integer with a non-integer\" n)))))\n\n(define (make-integer n) ((get 'make 'integer) n))\n\n; Rational numbers:\n\n(let ()\n  (define (numer x) (car x))\n  (define (denom x) (cdr x))\n  (define (make-rat n d)\n    (if (and (exact-integer? n) (exact-integer? d))\n        (let ((g (gcd n d)))\n          (cons (/ n g) (/ d g)))\n        (error \"Cannot construct a rational with non-exact numbers\" n d)))\n\n  (define (add-rat x y)\n    (make-rat (+ (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (sub-rat x y)\n    (make-rat (- (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (mul-rat x y)\n    (make-rat (* (numer x) (numer y))\n              (* (denom x) (denom y))))\n  (define (div-rat x y)\n    (make-rat (* (numer x) (denom y))\n              (* (denom x) (numer y))))\n  (define (=zero?-rat x)\n    (zero? (numer x)))\n  (define (raise-rat r)\n    (make-real (exact->inexact (/ (numer r) (denom r)))))\n  (define (project-rat r)\n    (make-integer (truncate (/ (numer r) (denom r)))))\n\n  (define (tag x) (attach-tag 'rational x))\n  (put 'numer '(rational) numer)\n  (put 'denom '(rational) denom)\n  (put 'raise '(rational) raise-rat)\n  (put 'project '(rational) project-rat)\n  (put '=zero? '(rational) =zero?-rat)\n  (put 'add '(rational rational) (lambda (x y) (tag (add-rat x y))))\n  (put 'sub '(rational rational) (lambda (x y) (tag (sub-rat x y))))\n  (put 'mul '(rational rational) (lambda (x y) (tag (mul-rat x y))))\n  (put 'div '(rational rational) (lambda (x y) (tag (div-rat x y))))\n  (put 'equ? '(rational rational) equal?)\n  (put 'make 'rational (lambda (n d) (tag (make-rat n d)))))\n\n(define (make-rational n d) ((get 'make 'rational) n d))\n(define (numer r) (apply-generic 'numer r))\n(define (denom r) (apply-generic 'denom r))\n\n; Real numbers:\n\n(let ()\n  (define (tag x) (attach-tag 'real x))\n  (put 'add '(real real) (lambda (x y) (tag (+ x y))))\n  (put 'sub '(real real) (lambda (x y) (tag (- x y))))\n  (put 'mul '(real real) (lambda (x y) (tag (* x y))))\n  (put 'div '(real real) (lambda (x y) (tag (/ x y))))\n  (put 'sine '(real) (lambda (x) (tag (sin x))))\n  (put 'cosine '(real) (lambda (x) (tag (cos x))))\n  (put 'square-root '(real) (lambda (x) (tag (sqrt x))))\n  (put 'arctangent '(real real) (lambda (x y) (tag (atan x y))))\n  (put 'project '(real) (lambda (x) (make-rational (inexact->exact (truncate x)) 1)))\n  (put 'raise '(real) (lambda (x) (make-complex-from-real-imag (tag x) (tag 0.0))))\n  (put 'equ? '(real real) =)\n  (put '=zero? '(real) zero?)\n  (put 'make 'real (lambda (x) (tag x))))\n\n(define (make-real n) ((get 'make 'real) n))\n\n; Generic procedures for complex numbers:\n\n(define (real-part z) (apply-generic 'real-part z))\n(define (imag-part z) (apply-generic 'imag-part z))\n(define (magnitude z) (apply-generic 'magnitude z))\n(define (angle z) (apply-generic 'angle z))\n\n(define (make-from-real-imag x y) ((get 'make-from-real-imag 'rectangular) x y))\n(define (make-from-mag-ang r a) ((get 'make-from-mag-ang 'polar) r a))\n\n; Rectangular representation of complex numbers:\n\n(let ()\n  (define (real-part z) (car z))\n  (define (imag-part z) (cdr z))\n  (define (make-from-real-imag x y) (cons x y))\n  (define (magnitude z) (square-root (add (square (real-part z)) (square (imag-part z)))))\n  (define (angle z) (arctangent (imag-part z) (real-part z)))\n  (define (make-from-mag-ang r a) (cons (mul r (cosine a)) (mul r (sine a))))\n\n  (define (tag x) (attach-tag 'rectangular x))\n  (put 'real-part '(rectangular) real-part)\n  (put 'imag-part '(rectangular) imag-part)\n  (put 'angle '(rectangular) angle)\n  (put 'magnitude '(rectangular) magnitude)\n  (put 'make-from-real-imag 'rectangular (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'rectangular (lambda (r a) (tag (make-from-mag-ang r a)))))\n\n; Polar representation of complex numbers:\n\n(let ()\n  (define (magnitude z) (car z))\n  (define (angle z) (cdr z))\n  (define (make-from-mag-ang r a) (cons r a))\n  (define (real-part z) (mul (magnitude z) (cosine (angle z))))\n  (define (imag-part z) (mul (magnitude z) (sine (angle z))))\n  (define (make-from-real-imag x y) (cons (square-root (add (square x) (square y)))\n                                          (arctangent y x)))\n\n  (define (tag x) (attach-tag 'polar x))\n  (put 'real-part '(polar) real-part)\n  (put 'imag-part '(polar) imag-part)\n  (put 'magnitude '(polar) magnitude)\n  (put 'angle '(polar) angle)\n  (put 'make-from-real-imag 'polar (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'polar (lambda (r a) (tag (make-from-mag-ang r a)))))\n\n; The complex numbers themselves:\n\n(let ()\n  (define (make-from-real-imag x y)\n    ((get 'make-from-real-imag 'rectangular) x y))\n  (define (make-from-mag-ang r a)\n    ((get 'make-from-mag-ang 'polar) r a))\n\n  (define (add-complex z1 z2)\n    (make-from-real-imag (add (real-part z1) (real-part z2))\n                         (add (imag-part z1) (imag-part z2))))\n  (define (sub-complex z1 z2)\n    (make-from-real-imag (sub (real-part z1) (real-part z2))\n                         (sub (imag-part z1) (imag-part z2))))\n  (define (mul-complex z1 z2)\n    (make-from-mag-ang (mul (magnitude z1) (magnitude z2))\n                       (add (angle z1) (angle z2))))\n  (define (div-complex z1 z2)\n    (make-from-mag-ang (div (magnitude z1) (magnitude z2))\n                       (sub (angle z1) (angle z2))))\n  (define (equ?-complex z1 z2)\n    (and (equ? (real-part z1) (real-part z2))\n         (equ? (imag-part z1) (imag-part z2))))\n\n  (define (tag x) (attach-tag 'complex x))\n  (put 'real-part '(complex) real-part)\n  (put 'imag-part '(complex) imag-part)\n  (put 'magnitude '(complex) magnitude)\n  (put 'angle '(complex) angle)\n  (put 'add '(complex complex) (lambda (z1 z2) (tag (add-complex z1 z2))))\n  (put 'sub '(complex complex) (lambda (z1 z2) (tag (sub-complex z1 z2))))\n  (put 'mul '(complex complex) (lambda (z1 z2) (tag (mul-complex z1 z2))))\n  (put 'div '(complex complex) (lambda (z1 z2) (tag (div-complex z1 z2))))\n  (put 'equ? '(complex complex) equ?-complex)\n  (put 'zero? '(complex complex) (lambda (z) (and (=zero? (real-part z))\n                                                  (=zero? (imag-part z)))))\n  (put 'project '(complex) (lambda (z) (real-part z)))\n  (put 'make-from-real-imag 'complex (lambda (x y) (tag (make-from-real-imag x y))))\n  (put 'make-from-mag-ang 'complex (lambda (r a) (tag (make-from-mag-ang r a)))))\n\n(define (make-complex-from-real-imag x y) ((get 'make-from-real-imag 'complex) x y))\n(define (make-complex-from-mag-ang r a) ((get 'make-from-mag-ang 'complex) r a))\n(define make-complex make-complex-from-real-imag)\n\n; Now the new stuff - the polynomial package:\n\n(let ()\n  (define (make-poly variable term-list)\n    (cons variable term-list))\n  (define (variable p) (car p))\n  (define (term-list p) (cdr p))\n\n  (define (same-variable? v1 v2)\n    (and (variable? v1) (variable? v2) (eq? v1 v2)))\n  (define (variable? x) (symbol? x))\n\n  (define (adjoin-term term term-list)\n    (if (=zero? (coeff term))\n        term-list\n        (cons term term-list)))\n\n  (define (the-empty-termlist) '())\n  (define (first-term term-list) (car term-list))\n  (define (rest-terms term-list) (cdr term-list))\n  (define (empty-termlist? term-list) (null? term-list))\n\n  (define (make-term order coeff) (list order coeff))\n  (define (order term) (car term))\n  (define (coeff term) (cadr term))\n\n  (define (add-terms L1 L2)\n    (cond ((empty-termlist? L1) L2)\n          ((empty-termlist? L2) L1)\n          (else\n            (let ((t1 (first-term L1)) (t2 (first-term L2)))\n              (cond ((> (order t1) (order t2))\n                     (adjoin-term t1 (add-terms (rest-terms L1) L2)))\n                    ((< (order t1) (order t2))\n                     (adjoin-term t2 (add-terms L1 (rest-terms L2))))\n                    (else\n                      (adjoin-term\n                        (make-term (order t1) (add (coeff t1) (coeff t2)))\n                        (add-terms (rest-terms L1) (rest-terms L2)))))))))\n  (define (mul-terms L1 L2)\n    (if (empty-termlist? L1)\n        (the-empty-termlist)\n        (add-terms (mul-term-by-all-terms (first-term L1) L2)\n                   (mul-terms (rest-terms L1) L2))))\n  (define (mul-term-by-all-terms t1 L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((t2 (first-term L)))\n          (adjoin-term (make-term (+ (order t1) (order t2)) (mul (coeff t1) (coeff t2)))\n                       (mul-term-by-all-terms t1 (rest-terms L))))))\n\n  (define (add-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (make-poly (variable p1)\n                 (add-terms (term-list p1)\n                            (term-list p2)))\n      (error \"Polynomials not in same var - ADD-POLY\" (list p1 p2))))\n\n  (define (mul-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (make-poly (variable p1)\n                 (mul-terms (term-list p1)\n                            (term-list p2)))\n      (error \"Polynomials not in same var - MUL-POLY\" (list p1 p2))))\n\n  (define (make-const p n)\n    (tag (make-poly (variable p)\n                    (adjoin-term (make-term 0 (make-integer n))\n                                 (the-empty-termlist)))))\n\n  (define (tag p) (attach-tag 'polynomial p))\n  (put 'add '(polynomial polynomial) (lambda (p1 p2) (tag (add-poly p1 p2))))\n  (put 'mul '(polynomial polynomial) (lambda (p1 p2) (tag (mul-poly p1 p2))))\n  (put '=zero? '(polynomial) (lambda (p) (empty-termlist? (term-list p))))\n  \n  (put 'add '(integer polynomial) (lambda (n p) (add (make-const p n) (tag p))))\n  (put 'mul '(integer polynomial) (lambda (n p) (mul (make-const p n) (tag p))))\n  (put 'mul '(polynomial integer) (lambda (p n) (mul (make-integer n) (tag p))))\n\n\n  (put 'make 'polynomial (lambda (var terms) (tag (make-poly var terms)))))\n\n(define (make-polynomial var terms)\n  ((get 'make 'polynomial) var terms))\n\n; apply-generic with some coercion:\n\n(define (apply-generic op . args)\n  (define (applicable? args)\n    (get op (map type-tag args)))\n\n  (define (apply-generic-failed)\n    (error \"No method for these types - APPLY-GENERIC\" (list op (map type-tag args))))\n\n  (define (all-of-same-type? args)\n    (define (check rest)\n      (cond ((null? rest) #t)\n            ((same-type? (car args) (car rest)) (check (cdr rest)))\n            (else #f)))\n    (check args))\n\n  (define (of-same-type-and-raisable? args)\n    (and (all-of-same-type? args)\n         (raisable? (car args))))\n\n  (define (coercable-to-same-type? args)\n    (and (= (length args) 2)\n         (let ((type-a (type-tag (car args)))\n               (type-b (type-tag (cadr args))))\n           (or (supertype? type-a type-b)\n               (supertype? type-b type-a)))))\n\n  (define (coerce-to-same-type args)\n    (and (= (length args) 2)\n         (let* ((a (car args))\n                (b (cadr args))\n                (type-a (type-tag a))\n                (type-b (type-tag b)))\n           (cond ((same-type? a b) (list a b))\n                 ((supertype? type-a type-b) (coerce-to-same-type (list (raise a) b)))\n                 ((supertype? type-b type-a) (coerce-to-same-type (list a (raise b))))\n                 (else #f)))))\n\n  (define (attempt-coercion args)\n    (let ((number-of-arguments (length args)))\n      (cond ((of-same-type-and-raisable? args) (try (map raise args)))\n            ((coercable-to-same-type? args) (try (coerce-to-same-type args)))\n            (else (apply-generic-failed)))))\n\n  (define (try args)\n    (if (applicable? args)\n        (let ((result (apply (get op (map type-tag args)) (map contents args))))\n          (if (simplifiable? op)\n              (simplify result)\n              result))\n        (attempt-coercion args)))\n\n  (try args))\n"
  },
  {
    "path": "scheme/sicp/02/88.scm",
    "content": "; SICP exercise 2.88\n;\n; Extend the polynomial system to include subtraction of polynomials. (Hint:\n; you may find it helpful to define a generic negation operation.)\n\n; Ok, let's do that. We shall take the code from the previous exercise, but\n; for simplicity's sake, let's get rid of the complex numbers. We will\n; introduce a new generic operation, neg and we shall use it to implement\n; subtraction of polynomials. Whenever we subtract b from a (a - b), we shall\n; negate b and add the result to a. Negating b means creating a new polynomial\n; in the same variable, will all the coefficients negated with neg.\n\n; The type functions, table and coercion infrastructure.\n\n(define (attach-tag type-tag contents)\n  (cons type-tag contents))\n\n(define (type-tag datum)\n  (if (pair? datum)\n      (car datum)\n      (error \"Bad tagged datum - TYPE-TAG\" datum)))\n\n(define (contents datum)\n  (if (pair? datum)\n      (cdr datum)\n      (error \"Bad tagged datum - CONTENTS\" datum)))\n\n(define table (make-hash))\n(define (put op type item) (hash-set! table (list op type) item))\n(define (get op type) (hash-ref table (list op type) #f))\n\n(define (put-coercion from to op) (put 'coerce (list from to) op))\n(define (get-coercion from to) (get 'coerce (list from to)))\n\n; The type tower, supetype, supertype?, raise and project:\n\n(put 'supertype 'integer 'rational)\n(put 'supertype 'rational 'scheme-number)\n(put 'supertype 'scheme-number 'real)\n\n(define (supertype type)\n  (get 'supertype type))\n\n(define (supertype? a b)\n  (let ((super (supertype a)))\n    (cond ((equal? super b) #t)\n          ((not super) #f)\n          (else (supertype? super b)))))\n\n(define (same-type? a b) (equal? (type-tag a) (type-tag b)))\n\n(define (raise a) (apply-generic 'raise a))\n(define (project a) (apply-generic 'project a))\n\n(define (projectable? a) (get 'project (list (type-tag a))))\n(define (raisable? a) (get 'raise (list (type-tag a))))\n\n; Now a simplification procedure. It will be called simplify instead of drop,\n; because drop is already reserved:\n\n(define (simplify x)\n  (cond ((not (projectable? x)) x)\n        ((equ? (raise (project x)) x) (simplify (project x)))\n        (else x)))\n\n; Now the generic arithmemtic procedures.\n\n(define (add x y) (apply-generic 'add x y))\n(define (sub x y) (apply-generic 'sub x y))\n(define (mul x y) (apply-generic 'mul x y))\n(define (div x y) (apply-generic 'div x y))\n(define (neg x) (apply-generic 'neg x))\n(define (equ? x y) (apply-generic 'equ? x y))\n(define (square-root x) (apply-generic 'square-root x))\n(define (sine x) (apply-generic 'sine x))\n(define (cosine x) (apply-generic 'cosine x))\n(define (arctangent x y) (apply-generic 'arctangent x y))\n(define (=zero? x) (apply-generic '=zero? x))\n(define (square x) (mul x x))\n\n; The simplification table:\n\n(define (simplifiable? op)\n  (get 'simplifiable op))\n\n(put 'simplifiable 'add #t)\n(put 'simplifiable 'sub #t)\n(put 'simplifiable 'mul #t)\n(put 'simplifiable 'div #t)\n(put 'simplifiable 'neg #t)\n(put 'simplifiable 'square-root #t)\n(put 'simplifiable 'sine #t)\n(put 'simplifiable 'cosine #t)\n(put 'simplifiable 'arctangent #t)\n(put 'simplifiable 'real-part #t)\n(put 'simplifiable 'imag-part #t)\n(put 'simplifiable 'magnitude #t)\n(put 'simplifiable 'angle #t)\n\n; Integers:\n\n(let ()\n  (define (tag x) (attach-tag 'integer x))\n  (put 'add '(integer integer) (lambda (x y) (tag (+ x y))))\n  (put 'sub '(integer integer) (lambda (x y) (tag (- x y))))\n  (put 'mul '(integer integer) (lambda (x y) (tag (* x y))))\n  (put 'neg '(integer) (lambda (x) (tag (- x))))\n  (put 'equ? '(integer integer) =)\n  (put '=zero? '(integer) zero?)\n  (put 'raise '(integer) (lambda (n) (make-rational n 1)))\n  (put 'make 'integer\n       (lambda (n) (if (exact-integer? n)\n                       (tag n)\n                       (error \"Attempted to make an integer with a non-integer\" n)))))\n\n(define (make-integer n) ((get 'make 'integer) n))\n\n; Rational numbers:\n\n(let ()\n  (define (numer x) (car x))\n  (define (denom x) (cdr x))\n  (define (make-rat n d)\n    (if (and (exact-integer? n) (exact-integer? d))\n        (let ((g (gcd n d)))\n          (cons (/ n g) (/ d g)))\n        (error \"Cannot construct a rational with non-exact numbers\" n d)))\n\n  (define (add-rat x y)\n    (make-rat (+ (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (sub-rat x y)\n    (make-rat (- (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (mul-rat x y)\n    (make-rat (* (numer x) (numer y))\n              (* (denom x) (denom y))))\n  (define (div-rat x y)\n    (make-rat (* (numer x) (denom y))\n              (* (denom x) (numer y))))\n  (define (neg-rat x)\n    (make-rat (- (numer x)) (denom x)))\n  (define (=zero?-rat x)\n    (zero? (numer x)))\n  (define (raise-rat r)\n    (make-real (exact->inexact (/ (numer r) (denom r)))))\n  (define (project-rat r)\n    (make-integer (truncate (/ (numer r) (denom r)))))\n\n  (define (tag x) (attach-tag 'rational x))\n  (put 'numer '(rational) numer)\n  (put 'denom '(rational) denom)\n  (put 'raise '(rational) raise-rat)\n  (put 'project '(rational) project-rat)\n  (put '=zero? '(rational) =zero?-rat)\n  (put 'add '(rational rational) (lambda (x y) (tag (add-rat x y))))\n  (put 'sub '(rational rational) (lambda (x y) (tag (sub-rat x y))))\n  (put 'mul '(rational rational) (lambda (x y) (tag (mul-rat x y))))\n  (put 'div '(rational rational) (lambda (x y) (tag (div-rat x y))))\n  (put 'neg '(rational) (lambda (x) (tag (neg-rat x))))\n  (put 'equ? '(rational rational) equal?)\n  (put 'make 'rational (lambda (n d) (tag (make-rat n d)))))\n\n(define (make-rational n d) ((get 'make 'rational) n d))\n(define (numer r) (apply-generic 'numer r))\n(define (denom r) (apply-generic 'denom r))\n\n; Real numbers:\n\n(let ()\n  (define (tag x) (attach-tag 'real x))\n  (put 'add '(real real) (lambda (x y) (tag (+ x y))))\n  (put 'sub '(real real) (lambda (x y) (tag (- x y))))\n  (put 'mul '(real real) (lambda (x y) (tag (* x y))))\n  (put 'div '(real real) (lambda (x y) (tag (/ x y))))\n  (put 'neg '(real) (lambda (x) (tag (- x))))\n  (put 'sine '(real) (lambda (x) (tag (sin x))))\n  (put 'cosine '(real) (lambda (x) (tag (cos x))))\n  (put 'square-root '(real) (lambda (x) (tag (sqrt x))))\n  (put 'arctangent '(real real) (lambda (x y) (tag (atan x y))))\n  (put 'project '(real) (lambda (x) (make-rational (inexact->exact (truncate x)) 1)))\n  (put 'equ? '(real real) =)\n  (put '=zero? '(real) zero?)\n  (put 'make 'real (lambda (x) (tag x))))\n\n(define (make-real n) ((get 'make 'real) n))\n\n; The polynomial package:\n\n(let ()\n  (define (make-poly variable term-list)\n    (cons variable term-list))\n  (define (variable p) (car p))\n  (define (term-list p) (cdr p))\n\n  (define (same-variable? v1 v2)\n    (and (variable? v1) (variable? v2) (eq? v1 v2)))\n  (define (variable? x) (symbol? x))\n\n  (define (adjoin-term term term-list)\n    (if (=zero? (coeff term))\n        term-list\n        (cons term term-list)))\n\n  (define (the-empty-termlist) '())\n  (define (first-term term-list) (car term-list))\n  (define (rest-terms term-list) (cdr term-list))\n  (define (empty-termlist? term-list) (null? term-list))\n\n  (define (make-term order coeff) (list order coeff))\n  (define (order term) (car term))\n  (define (coeff term) (cadr term))\n\n  (define (add-terms L1 L2)\n    (cond ((empty-termlist? L1) L2)\n          ((empty-termlist? L2) L1)\n          (else\n            (let ((t1 (first-term L1)) (t2 (first-term L2)))\n              (cond ((> (order t1) (order t2))\n                     (adjoin-term t1 (add-terms (rest-terms L1) L2)))\n                    ((< (order t1) (order t2))\n                     (adjoin-term t2 (add-terms L1 (rest-terms L2))))\n                    (else\n                      (adjoin-term\n                        (make-term (order t1) (add (coeff t1) (coeff t2)))\n                        (add-terms (rest-terms L1) (rest-terms L2)))))))))\n  (define (mul-terms L1 L2)\n    (if (empty-termlist? L1)\n        (the-empty-termlist)\n        (add-terms (mul-term-by-all-terms (first-term L1) L2)\n                   (mul-terms (rest-terms L1) L2))))\n  (define (mul-term-by-all-terms t1 L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((t2 (first-term L)))\n          (adjoin-term (make-term (+ (order t1) (order t2)) (mul (coeff t1) (coeff t2)))\n                       (mul-term-by-all-terms t1 (rest-terms L))))))\n\n  (define (map-coeffs proc p)\n    (make-poly (variable p)\n               (map (lambda (term) (make-term (order term) (proc (coeff term))))\n                    (term-list p))))\n\n  (define (add-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (make-poly (variable p1)\n                 (add-terms (term-list p1)\n                            (term-list p2)))\n      (error \"Polynomials not in same var - ADD-POLY\" (list p1 p2))))\n  (define (mul-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (make-poly (variable p1)\n                 (mul-terms (term-list p1)\n                            (term-list p2)))\n      (error \"Polynomials not in same var - MUL-POLY\" (list p1 p2))))\n  (define (neg-poly p)\n    (map-coeffs neg p))\n  (define (sub-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (add-poly p1 (neg-poly p2))\n      (error \"Polynomials not in same var - SUB-POLY\" (list p1 p2))))\n\n  (define (make-const p n)\n    (tag (make-poly (variable p)\n                    (adjoin-term (make-term 0 (make-integer n))\n                                 (the-empty-termlist)))))\n\n  (define (tag p) (attach-tag 'polynomial p))\n  (put 'add '(polynomial polynomial) (lambda (p1 p2) (tag (add-poly p1 p2))))\n  (put 'sub '(polynomial polynomial) (lambda (p1 p2) (tag (sub-poly p1 p2))))\n  (put 'mul '(polynomial polynomial) (lambda (p1 p2) (tag (mul-poly p1 p2))))\n  (put '=zero? '(polynomial) (lambda (p) (empty-termlist? (term-list p))))\n  (put 'neg '(polynomial) (lambda (p) (tag (neg-poly p))))\n  \n  (put 'add '(integer polynomial) (lambda (n p) (add (make-const p n) (tag p))))\n  (put 'mul '(integer polynomial) (lambda (n p) (mul (make-const p n) (tag p))))\n  (put 'mul '(polynomial integer) (lambda (p n) (mul (make-integer n) (tag p))))\n\n\n  (put 'make 'polynomial (lambda (var terms) (tag (make-poly var terms)))))\n\n(define (make-polynomial var terms)\n  ((get 'make 'polynomial) var terms))\n\n; apply-generic with some coercion:\n\n(define (apply-generic op . args)\n  (define (applicable? args)\n    (get op (map type-tag args)))\n\n  (define (apply-generic-failed)\n    (error \"No method for these types - APPLY-GENERIC\" (list op (map type-tag args))))\n\n  (define (all-of-same-type? args)\n    (define (check rest)\n      (cond ((null? rest) #t)\n            ((same-type? (car args) (car rest)) (check (cdr rest)))\n            (else #f)))\n    (check args))\n\n  (define (of-same-type-and-raisable? args)\n    (and (all-of-same-type? args)\n         (raisable? (car args))))\n\n  (define (coercable-to-same-type? args)\n    (and (= (length args) 2)\n         (let ((type-a (type-tag (car args)))\n               (type-b (type-tag (cadr args))))\n           (or (supertype? type-a type-b)\n               (supertype? type-b type-a)))))\n\n  (define (coerce-to-same-type args)\n    (and (= (length args) 2)\n         (let* ((a (car args))\n                (b (cadr args))\n                (type-a (type-tag a))\n                (type-b (type-tag b)))\n           (cond ((same-type? a b) (list a b))\n                 ((supertype? type-a type-b) (coerce-to-same-type (list (raise a) b)))\n                 ((supertype? type-b type-a) (coerce-to-same-type (list a (raise b))))\n                 (else #f)))))\n\n  (define (attempt-coercion args)\n    (let ((number-of-arguments (length args)))\n      (cond ((of-same-type-and-raisable? args) (try (map raise args)))\n            ((coercable-to-same-type? args) (try (coerce-to-same-type args)))\n            (else (apply-generic-failed)))))\n\n  (define (try args)\n    (if (applicable? args)\n        (let ((result (apply (get op (map type-tag args)) (map contents args))))\n          (if (simplifiable? op)\n              (simplify result)\n              result))\n        (attempt-coercion args)))\n\n  (try args))\n"
  },
  {
    "path": "scheme/sicp/02/89.scm",
    "content": "; SICP exercise 2.89\n;\n; Define procedures that implement the term-list representation described\n; above as appropriate for dense polynomials.\n\n; First, we need to derefine map-coeffs in terms of adjoin-term so it can be\n; independent of the representation. It is substantially slower, but at least\n; it works with both representations. Second, we shall define first-term to\n; return a list (order coeff) and we shall calculate the order with length.\n; This is an O(n) operation, so it makes everything slower. In the next\n; exercise, we shall look into a better representation abstraction and clearer\n; bounaries.\n\n; The type functions, table and coercion infrastructure.\n\n(define (attach-tag type-tag contents)\n  (cons type-tag contents))\n\n(define (type-tag datum)\n  (if (pair? datum)\n      (car datum)\n      (error \"Bad tagged datum - TYPE-TAG\" datum)))\n\n(define (contents datum)\n  (if (pair? datum)\n      (cdr datum)\n      (error \"Bad tagged datum - CONTENTS\" datum)))\n\n(define table (make-hash))\n(define (put op type item) (hash-set! table (list op type) item))\n(define (get op type) (hash-ref table (list op type) #f))\n\n(define (put-coercion from to op) (put 'coerce (list from to) op))\n(define (get-coercion from to) (get 'coerce (list from to)))\n\n; The type tower, supetype, supertype?, raise and project:\n\n(put 'supertype 'integer 'rational)\n(put 'supertype 'rational 'scheme-number)\n(put 'supertype 'scheme-number 'real)\n\n(define (supertype type)\n  (get 'supertype type))\n\n(define (supertype? a b)\n  (let ((super (supertype a)))\n    (cond ((equal? super b) #t)\n          ((not super) #f)\n          (else (supertype? super b)))))\n\n(define (same-type? a b) (equal? (type-tag a) (type-tag b)))\n\n(define (raise a) (apply-generic 'raise a))\n(define (project a) (apply-generic 'project a))\n\n(define (projectable? a) (get 'project (list (type-tag a))))\n(define (raisable? a) (get 'raise (list (type-tag a))))\n\n; Now a simplification procedure. It will be called simplify instead of drop,\n; because drop is already reserved:\n\n(define (simplify x)\n  (cond ((not (projectable? x)) x)\n        ((equ? (raise (project x)) x) (simplify (project x)))\n        (else x)))\n\n; Now the generic arithmemtic procedures.\n\n(define (add x y) (apply-generic 'add x y))\n(define (sub x y) (apply-generic 'sub x y))\n(define (mul x y) (apply-generic 'mul x y))\n(define (div x y) (apply-generic 'div x y))\n(define (neg x) (apply-generic 'neg x))\n(define (equ? x y) (apply-generic 'equ? x y))\n(define (square-root x) (apply-generic 'square-root x))\n(define (sine x) (apply-generic 'sine x))\n(define (cosine x) (apply-generic 'cosine x))\n(define (arctangent x y) (apply-generic 'arctangent x y))\n(define (=zero? x) (apply-generic '=zero? x))\n(define (square x) (mul x x))\n\n; The simplification table:\n\n(define (simplifiable? op)\n  (get 'simplifiable op))\n\n(put 'simplifiable 'add #t)\n(put 'simplifiable 'sub #t)\n(put 'simplifiable 'mul #t)\n(put 'simplifiable 'div #t)\n(put 'simplifiable 'neg #t)\n(put 'simplifiable 'square-root #t)\n(put 'simplifiable 'sine #t)\n(put 'simplifiable 'cosine #t)\n(put 'simplifiable 'arctangent #t)\n(put 'simplifiable 'real-part #t)\n(put 'simplifiable 'imag-part #t)\n(put 'simplifiable 'magnitude #t)\n(put 'simplifiable 'angle #t)\n\n; Integers:\n\n(let ()\n  (define (tag x) (attach-tag 'integer x))\n  (put 'add '(integer integer) (lambda (x y) (tag (+ x y))))\n  (put 'sub '(integer integer) (lambda (x y) (tag (- x y))))\n  (put 'mul '(integer integer) (lambda (x y) (tag (* x y))))\n  (put 'neg '(integer) (lambda (x) (tag (- x))))\n  (put 'equ? '(integer integer) =)\n  (put '=zero? '(integer) zero?)\n  (put 'raise '(integer) (lambda (n) (make-rational n 1)))\n  (put 'make 'integer\n       (lambda (n) (if (exact-integer? n)\n                       (tag n)\n                       (error \"Attempted to make an integer with a non-integer\" n)))))\n\n(define (make-integer n) ((get 'make 'integer) n))\n\n; Rational numbers:\n\n(let ()\n  (define (numer x) (car x))\n  (define (denom x) (cdr x))\n  (define (make-rat n d)\n    (if (and (exact-integer? n) (exact-integer? d))\n        (let ((g (gcd n d)))\n          (cons (/ n g) (/ d g)))\n        (error \"Cannot construct a rational with non-exact numbers\" n d)))\n\n  (define (add-rat x y)\n    (make-rat (+ (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (sub-rat x y)\n    (make-rat (- (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (mul-rat x y)\n    (make-rat (* (numer x) (numer y))\n              (* (denom x) (denom y))))\n  (define (div-rat x y)\n    (make-rat (* (numer x) (denom y))\n              (* (denom x) (numer y))))\n  (define (neg-rat x)\n    (make-rat (- (numer x)) (denom x)))\n  (define (=zero?-rat x)\n    (zero? (numer x)))\n  (define (raise-rat r)\n    (make-real (exact->inexact (/ (numer r) (denom r)))))\n  (define (project-rat r)\n    (make-integer (truncate (/ (numer r) (denom r)))))\n\n  (define (tag x) (attach-tag 'rational x))\n  (put 'numer '(rational) numer)\n  (put 'denom '(rational) denom)\n  (put 'raise '(rational) raise-rat)\n  (put 'project '(rational) project-rat)\n  (put '=zero? '(rational) =zero?-rat)\n  (put 'add '(rational rational) (lambda (x y) (tag (add-rat x y))))\n  (put 'sub '(rational rational) (lambda (x y) (tag (sub-rat x y))))\n  (put 'mul '(rational rational) (lambda (x y) (tag (mul-rat x y))))\n  (put 'div '(rational rational) (lambda (x y) (tag (div-rat x y))))\n  (put 'neg '(rational) (lambda (x) (tag (neg-rat x))))\n  (put 'equ? '(rational rational) equal?)\n  (put 'make 'rational (lambda (n d) (tag (make-rat n d)))))\n\n(define (make-rational n d) ((get 'make 'rational) n d))\n(define (numer r) (apply-generic 'numer r))\n(define (denom r) (apply-generic 'denom r))\n\n; Real numbers:\n\n(let ()\n  (define (tag x) (attach-tag 'real x))\n  (put 'add '(real real) (lambda (x y) (tag (+ x y))))\n  (put 'sub '(real real) (lambda (x y) (tag (- x y))))\n  (put 'mul '(real real) (lambda (x y) (tag (* x y))))\n  (put 'div '(real real) (lambda (x y) (tag (/ x y))))\n  (put 'neg '(real) (lambda (x) (tag (- x))))\n  (put 'sine '(real) (lambda (x) (tag (sin x))))\n  (put 'cosine '(real) (lambda (x) (tag (cos x))))\n  (put 'square-root '(real) (lambda (x) (tag (sqrt x))))\n  (put 'arctangent '(real real) (lambda (x y) (tag (atan x y))))\n  (put 'project '(real) (lambda (x) (make-rational (inexact->exact (truncate x)) 1)))\n  (put 'equ? '(real real) =)\n  (put '=zero? '(real) zero?)\n  (put 'make 'real (lambda (x) (tag x))))\n\n(define (make-real n) ((get 'make 'real) n))\n\n; The polynomial package:\n\n(let ()\n  (define (make-poly variable term-list)\n    (cons variable term-list))\n  (define (variable p) (car p))\n  (define (term-list p) (cdr p))\n\n  (define (same-variable? v1 v2)\n    (and (variable? v1) (variable? v2) (eq? v1 v2)))\n  (define (variable? x) (symbol? x))\n\n  (define (adjoin-term term term-list)\n    (let ((term-list-order (- (length term-list) 1))\n          (term-order (order term)))\n      (cond ((=zero? (coeff term)) term-list)\n            ((= term-list-order term-order)\n             (cons (add (coeff term) (car term-list))\n                   (cdr term-list)))\n            ((< term-order term-list-order)\n             (cons (car term-list) (adjoin-term term (cdr term-list))))\n            ((> term-order term-list-order)\n             (adjoin-term term (cons (make-integer 0) term-list))))))\n\n  (define (the-empty-termlist) '())\n  (define (first-term term-list) (make-term (- (length term-list) 1) (car term-list)))\n  (define (rest-terms term-list) (cdr term-list))\n  (define (empty-termlist? term-list) (null? term-list))\n\n  (define (make-term order coeff) (list order coeff))\n  (define (order term) (car term))\n  (define (coeff term) (cadr term))\n\n  (define (add-terms L1 L2)\n    (cond ((empty-termlist? L1) L2)\n          ((empty-termlist? L2) L1)\n          (else\n            (let ((t1 (first-term L1)) (t2 (first-term L2)))\n              (cond ((> (order t1) (order t2))\n                     (adjoin-term t1 (add-terms (rest-terms L1) L2)))\n                    ((< (order t1) (order t2))\n                     (adjoin-term t2 (add-terms L1 (rest-terms L2))))\n                    (else\n                      (adjoin-term\n                        (make-term (order t1) (add (coeff t1) (coeff t2)))\n                        (add-terms (rest-terms L1) (rest-terms L2)))))))))\n  (define (mul-terms L1 L2)\n    (if (empty-termlist? L1)\n        (the-empty-termlist)\n        (add-terms (mul-term-by-all-terms (first-term L1) L2)\n                   (mul-terms (rest-terms L1) L2))))\n  (define (mul-term-by-all-terms t1 L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((t2 (first-term L)))\n          (adjoin-term (make-term (+ (order t1) (order t2)) (mul (coeff t1) (coeff t2)))\n                       (mul-term-by-all-terms t1 (rest-terms L))))))\n\n  (define (map-coeffs proc p)\n    (define (map-terms term-list result)\n      (if (empty-termlist? term-list)\n          result\n          (let ((first (first-term term-list))\n                (rest (rest-terms term-list)))\n            (map-terms rest\n                       (adjoin-term (make-term (order first) (proc (coeff first)))\n                                    result)))))\n    (make-poly (variable p)\n               (map-terms (term-list p) (the-empty-termlist))))\n\n  (define (add-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (make-poly (variable p1)\n                 (add-terms (term-list p1)\n                            (term-list p2)))\n      (error \"Polynomials not in same var - ADD-POLY\" (list p1 p2))))\n  (define (mul-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (make-poly (variable p1)\n                 (mul-terms (term-list p1)\n                            (term-list p2)))\n      (error \"Polynomials not in same var - MUL-POLY\" (list p1 p2))))\n  (define (neg-poly p)\n    (map-coeffs neg p))\n  (define (sub-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (add-poly p1 (neg-poly p2))\n      (error \"Polynomials not in same var - SUB-POLY\" (list p1 p2))))\n\n  (define (make-const p n)\n    (tag (make-poly (variable p)\n                    (adjoin-term (make-term 0 (make-integer n))\n                                 (the-empty-termlist)))))\n\n  (define (tag p) (attach-tag 'polynomial p))\n  (put 'add '(polynomial polynomial) (lambda (p1 p2) (tag (add-poly p1 p2))))\n  (put 'sub '(polynomial polynomial) (lambda (p1 p2) (tag (sub-poly p1 p2))))\n  (put 'mul '(polynomial polynomial) (lambda (p1 p2) (tag (mul-poly p1 p2))))\n  (put '=zero? '(polynomial) (lambda (p) (empty-termlist? (term-list p))))\n  (put 'neg '(polynomial) (lambda (p) (tag (neg-poly p))))\n  \n  (put 'add '(integer polynomial) (lambda (n p) (add (make-const p n) (tag p))))\n  (put 'mul '(integer polynomial) (lambda (n p) (mul (make-const p n) (tag p))))\n  (put 'add '(polynomial integer) (lambda (p n) (add (make-integer n) (tag p))))\n  (put 'mul '(polynomial integer) (lambda (p n) (mul (make-integer n) (tag p))))\n\n\n  (put 'make 'polynomial (lambda (var terms) (tag (make-poly var terms)))))\n\n(define (make-polynomial var terms)\n  ((get 'make 'polynomial) var terms))\n\n; apply-generic with some coercion:\n\n(define (apply-generic op . args)\n  (define (applicable? args)\n    (get op (map type-tag args)))\n\n  (define (apply-generic-failed)\n    (error \"No method for these types - APPLY-GENERIC\" (list op (map type-tag args))))\n\n  (define (all-of-same-type? args)\n    (define (check rest)\n      (cond ((null? rest) #t)\n            ((same-type? (car args) (car rest)) (check (cdr rest)))\n            (else #f)))\n    (check args))\n\n  (define (of-same-type-and-raisable? args)\n    (and (all-of-same-type? args)\n         (raisable? (car args))))\n\n  (define (coercable-to-same-type? args)\n    (and (= (length args) 2)\n         (let ((type-a (type-tag (car args)))\n               (type-b (type-tag (cadr args))))\n           (or (supertype? type-a type-b)\n               (supertype? type-b type-a)))))\n\n  (define (coerce-to-same-type args)\n    (and (= (length args) 2)\n         (let* ((a (car args))\n                (b (cadr args))\n                (type-a (type-tag a))\n                (type-b (type-tag b)))\n           (cond ((same-type? a b) (list a b))\n                 ((supertype? type-a type-b) (coerce-to-same-type (list (raise a) b)))\n                 ((supertype? type-b type-a) (coerce-to-same-type (list a (raise b))))\n                 (else #f)))))\n\n  (define (attempt-coercion args)\n    (let ((number-of-arguments (length args)))\n      (cond ((of-same-type-and-raisable? args) (try (map raise args)))\n            ((coercable-to-same-type? args) (try (coerce-to-same-type args)))\n            (else (apply-generic-failed)))))\n\n  (define (try args)\n    (if (applicable? args)\n        (let ((result (apply (get op (map type-tag args)) (map contents args))))\n          (if (simplifiable? op)\n              (simplify result)\n              result))\n        (attempt-coercion args)))\n\n  (try args))\n"
  },
  {
    "path": "scheme/sicp/02/90.scm",
    "content": "; SICP exercise 2.90\n;\n; Suppose we want to have a polynomial system that is efficient for both\n; sparse and dense polynomials. One way to do this is to allow both kinds of\n; term-list representations in our system. The situation is analogous to the\n; complex-number example of section 2.4, where we allowed both rectangular and\n; polar representations. To do this we must distinguish different types of\n; term lists and make the operations on term lists generic. Redesign the\n; polynomial system to implement this generalization. This is a major effort,\n; not a local change.\n\n; Come now, it is not a major effort. It is not uber simple either, but hey,\n; it is not supposed to be either. We base this on the prevoius exercise:\n\n(define (attach-tag type-tag contents)\n  (cons type-tag contents))\n\n(define (type-tag datum)\n  (if (pair? datum)\n      (car datum)\n      (error \"Bad tagged datum - TYPE-TAG\" datum)))\n\n(define (contents datum)\n  (if (pair? datum)\n      (cdr datum)\n      (error \"Bad tagged datum - CONTENTS\" datum)))\n\n(define table (make-hash))\n(define (put op type item) (hash-set! table (list op type) item))\n(define (get op type) (hash-ref table (list op type) #f))\n\n(define (put-coercion from to op) (put 'coerce (list from to) op))\n(define (get-coercion from to) (get 'coerce (list from to)))\n\n; The type tower, supetype, supertype?, raise and project:\n\n(put 'supertype 'integer 'rational)\n(put 'supertype 'rational 'scheme-number)\n(put 'supertype 'scheme-number 'real)\n\n(define (supertype type)\n  (get 'supertype type))\n\n(define (supertype? a b)\n  (let ((super (supertype a)))\n    (cond ((equal? super b) #t)\n          ((not super) #f)\n          (else (supertype? super b)))))\n\n(define (same-type? a b) (equal? (type-tag a) (type-tag b)))\n\n(define (raise a) (apply-generic 'raise a))\n(define (project a) (apply-generic 'project a))\n\n(define (projectable? a) (get 'project (list (type-tag a))))\n(define (raisable? a) (get 'raise (list (type-tag a))))\n\n; Now a simplification procedure. It will be called simplify instead of drop,\n; because drop is already reserved:\n\n(define (simplify x)\n  (cond ((not (projectable? x)) x)\n        ((equ? (raise (project x)) x) (simplify (project x)))\n        (else x)))\n\n; Now the generic arithmemtic procedures.\n\n(define (add x y) (apply-generic 'add x y))\n(define (sub x y) (apply-generic 'sub x y))\n(define (mul x y) (apply-generic 'mul x y))\n(define (div x y) (apply-generic 'div x y))\n(define (neg x) (apply-generic 'neg x))\n(define (equ? x y) (apply-generic 'equ? x y))\n(define (square-root x) (apply-generic 'square-root x))\n(define (sine x) (apply-generic 'sine x))\n(define (cosine x) (apply-generic 'cosine x))\n(define (arctangent x y) (apply-generic 'arctangent x y))\n(define (=zero? x) (apply-generic '=zero? x))\n(define (square x) (mul x x))\n\n; The simplification table:\n\n(define (simplifiable? op)\n  (get 'simplifiable op))\n\n(put 'simplifiable 'add #t)\n(put 'simplifiable 'sub #t)\n(put 'simplifiable 'mul #t)\n(put 'simplifiable 'div #t)\n(put 'simplifiable 'neg #t)\n(put 'simplifiable 'square-root #t)\n(put 'simplifiable 'sine #t)\n(put 'simplifiable 'cosine #t)\n(put 'simplifiable 'arctangent #t)\n(put 'simplifiable 'real-part #t)\n(put 'simplifiable 'imag-part #t)\n(put 'simplifiable 'magnitude #t)\n(put 'simplifiable 'angle #t)\n\n; Integers:\n\n(let ()\n  (define (tag x) (attach-tag 'integer x))\n  (put 'add '(integer integer) (lambda (x y) (tag (+ x y))))\n  (put 'sub '(integer integer) (lambda (x y) (tag (- x y))))\n  (put 'mul '(integer integer) (lambda (x y) (tag (* x y))))\n  (put 'neg '(integer) (lambda (x) (tag (- x))))\n  (put 'equ? '(integer integer) =)\n  (put '=zero? '(integer) zero?)\n  (put 'raise '(integer) (lambda (n) (make-rational n 1)))\n  (put 'make 'integer\n       (lambda (n) (if (exact-integer? n)\n                       (tag n)\n                       (error \"Attempted to make an integer with a non-integer\" n)))))\n\n(define (make-integer n) ((get 'make 'integer) n))\n\n; Rational numbers:\n\n(let ()\n  (define (numer x) (car x))\n  (define (denom x) (cdr x))\n  (define (make-rat n d)\n    (if (and (exact-integer? n) (exact-integer? d))\n        (let ((g (gcd n d)))\n          (cons (/ n g) (/ d g)))\n        (error \"Cannot construct a rational with non-exact numbers\" n d)))\n\n  (define (add-rat x y)\n    (make-rat (+ (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (sub-rat x y)\n    (make-rat (- (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (mul-rat x y)\n    (make-rat (* (numer x) (numer y))\n              (* (denom x) (denom y))))\n  (define (div-rat x y)\n    (make-rat (* (numer x) (denom y))\n              (* (denom x) (numer y))))\n  (define (neg-rat x)\n    (make-rat (- (numer x)) (denom x)))\n  (define (=zero?-rat x)\n    (zero? (numer x)))\n  (define (raise-rat r)\n    (make-real (exact->inexact (/ (numer r) (denom r)))))\n  (define (project-rat r)\n    (make-integer (truncate (/ (numer r) (denom r)))))\n\n  (define (tag x) (attach-tag 'rational x))\n  (put 'numer '(rational) numer)\n  (put 'denom '(rational) denom)\n  (put 'raise '(rational) raise-rat)\n  (put 'project '(rational) project-rat)\n  (put '=zero? '(rational) =zero?-rat)\n  (put 'add '(rational rational) (lambda (x y) (tag (add-rat x y))))\n  (put 'sub '(rational rational) (lambda (x y) (tag (sub-rat x y))))\n  (put 'mul '(rational rational) (lambda (x y) (tag (mul-rat x y))))\n  (put 'div '(rational rational) (lambda (x y) (tag (div-rat x y))))\n  (put 'neg '(rational) (lambda (x) (tag (neg-rat x))))\n  (put 'equ? '(rational rational) equal?)\n  (put 'make 'rational (lambda (n d) (tag (make-rat n d)))))\n\n(define (make-rational n d) ((get 'make 'rational) n d))\n(define (numer r) (apply-generic 'numer r))\n(define (denom r) (apply-generic 'denom r))\n\n; Real numbers:\n\n(let ()\n  (define (tag x) (attach-tag 'real x))\n  (put 'add '(real real) (lambda (x y) (tag (+ x y))))\n  (put 'sub '(real real) (lambda (x y) (tag (- x y))))\n  (put 'mul '(real real) (lambda (x y) (tag (* x y))))\n  (put 'div '(real real) (lambda (x y) (tag (/ x y))))\n  (put 'neg '(real) (lambda (x) (tag (- x))))\n  (put 'sine '(real) (lambda (x) (tag (sin x))))\n  (put 'cosine '(real) (lambda (x) (tag (cos x))))\n  (put 'square-root '(real) (lambda (x) (tag (sqrt x))))\n  (put 'arctangent '(real real) (lambda (x y) (tag (atan x y))))\n  (put 'project '(real) (lambda (x) (make-rational (inexact->exact (truncate x)) 1)))\n  (put 'equ? '(real real) =)\n  (put '=zero? '(real) zero?)\n  (put 'make 'real (lambda (x) (tag x))))\n\n(define (make-real n) ((get 'make 'real) n))\n\n; And now, the polynomial package. First, the generic term-list operations.\n; Note that adjoin-term uses the table, but not apply-generic.\n\n(define (make-term order coeff) (list order coeff))\n(define (order term) (car term))\n(define (coeff term) (cadr term))\n\n(define (empty-termlist? term-list) (apply-generic 'empty-termlist? term-list))\n(define (first-term term-list) (apply-generic 'first-term term-list))\n(define (rest-terms term-list) (apply-generic 'rest-terms term-list))\n\n(define (adjoin-term term term-list)\n  (let ((proc (get 'adjoin-term (type-tag term-list))))\n    (if proc\n        (proc term (contents term-list))\n        (error \"No method for these types - ADJOIN-TERM\" term-list))))\n\n; Sparse representation:\n\n(let ()\n  (define (the-empty-termlist) '())\n  (define (empty-termlist? term-list) (null? term-list))\n  (define (first-term term-list) (car term-list))\n  (define (rest-terms term-list) (cdr term-list))\n  (define (adjoin-term term term-list)\n    (cond ((=zero? (coeff term)) term-list)\n          ((null? term-list) (list term))\n          ((> (order (car term-list)) (order term))\n           (cons (car term-list) (adjoin-term term (cdr term-list))))\n          ((= (order (car term-list)) (order term))\n           (adjoin-term (make-term (order term)\n                                   (add (coeff term) (coeff (car term-list))))\n                        (cdr term-list)))\n          (else (cons term term-list))))\n\n  (define (tag x) (attach-tag 'sparse x))\n  (put 'empty-termlist? '(sparse) empty-termlist?)\n  (put 'first-term '(sparse) first-term)\n  (put 'rest-terms '(sparse) (lambda (l) (tag (rest-terms l))))\n  (put 'adjoin-term 'sparse (lambda (term term-list) (tag (adjoin-term term term-list))))\n  (put 'make 'sparse (lambda () (tag (the-empty-termlist)))))\n\n(define (the-empty-sparse-termlist) ((get 'make 'sparse)))\n\n; Dense representation:\n\n(let ()\n  (define (the-empty-termlist) '())\n  (define (term-list-order term-list) (- (length term-list) 1))\n  (define (empty-termlist? term-list) (null? term-list))\n  (define (first-term term-list) (make-term (term-list-order term-list) (car term-list)))\n  (define (rest-terms term-list) (cdr term-list))\n  (define (adjoin-term term term-list)\n    (let ((term-list-order (term-list-order term-list))\n          (term-order (order term)))\n      (cond ((=zero? (coeff term)) term-list)\n            ((= term-list-order term-order)\n             (cons (add (coeff term) (car term-list))\n                   (cdr term-list)))\n            ((< term-order term-list-order)\n             (cons (car term-list) (adjoin-term term (cdr term-list))))\n            ((> term-order term-list-order)\n             (adjoin-term term (cons (make-integer 0) term-list))))))\n\n  (define (tag x) (attach-tag 'dense x))\n  (put 'first-term '(dense) first-term)\n  (put 'rest-terms '(dense) (lambda (l) (tag (rest-terms l))))\n  (put 'empty-termlist? '(dense) empty-termlist?)\n  (put 'adjoin-term 'dense (lambda (term term-list) (tag (adjoin-term term term-list))))\n  (put 'make 'dense (lambda () (tag (the-empty-termlist)))))\n\n(define (the-empty-dense-termlist) ((get 'make 'dense)))\n\n; The polynomial package. Operations between polynomials with the same\n; representation will preserve the type of representation. Polynomials with\n; operations of mixed representation will choose an arbitrary representation\n; for the result.\n\n(let ()\n  (define (make-poly variable term-list)\n    (cons variable term-list))\n  (define (variable p) (car p))\n  (define (term-list p) (cdr p))\n\n  (define (same-variable? v1 v2)\n    (and (variable? v1) (variable? v2) (eq? v1 v2)))\n  (define (variable? x) (symbol? x))\n\n  (define (empty-termlist-of-type term-list)\n    ((get 'make (type-tag term-list))))\n\n  (define (add-terms L1 L2)\n    (cond ((empty-termlist? L1) L2)\n          ((empty-termlist? L2) L1)\n          (else\n            (let ((t1 (first-term L1)) (t2 (first-term L2)))\n              (cond ((> (order t1) (order t2))\n                     (adjoin-term t1 (add-terms (rest-terms L1) L2)))\n                    ((< (order t1) (order t2))\n                     (adjoin-term t2 (add-terms L1 (rest-terms L2))))\n                    (else\n                      (adjoin-term\n                        (make-term (order t1) (add (coeff t1) (coeff t2)))\n                        (add-terms (rest-terms L1) (rest-terms L2)))))))))\n  (define (mul-terms L1 L2)\n    (if (empty-termlist? L1)\n        (empty-termlist-of-type L1)\n        (add-terms (mul-term-by-all-terms (first-term L1) L2)\n                   (mul-terms (rest-terms L1) L2))))\n  (define (mul-term-by-all-terms t1 L)\n    (if (empty-termlist? L)\n        (empty-termlist-of-type L)\n        (let ((t2 (first-term L)))\n          (adjoin-term (make-term (+ (order t1) (order t2)) (mul (coeff t1) (coeff t2)))\n                       (mul-term-by-all-terms t1 (rest-terms L))))))\n  (define (map-terms proc L)\n    (if (empty-termlist? L)\n        (empty-termlist-of-type L)\n        (let ((first (first-term L))\n              (rest (rest-terms L)))\n          (adjoin-term (make-term (order first) (proc (coeff first)))\n                       (map-terms proc rest)))))\n  (define (neg-terms L)\n    (map-terms neg L))\n\n  (define (add-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (make-poly (variable p1)\n                 (add-terms (term-list p1)\n                            (term-list p2)))\n      (error \"Polynomials not in same var - ADD-POLY\" (list p1 p2))))\n  (define (mul-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (make-poly (variable p1)\n                 (mul-terms (term-list p1)\n                            (term-list p2)))\n      (error \"Polynomials not in same var - MUL-POLY\" (list p1 p2))))\n  (define (sub-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (add-poly p1 (neg-poly p2))\n      (error \"Polynomials not in same var - SUB-POLY\" (list p1 p2))))\n  (define (neg-poly p)\n    (make-poly (variable p)\n               (neg-terms (term-list p))))\n\n  (define (make-const p n)\n    (tag (make-poly (variable p)\n                    (adjoin-term (make-term 0 (make-integer n))\n                                 (empty-termlist-of-type (term-list p))))))\n\n  (define (tag p) (attach-tag 'polynomial p))\n  (put 'add '(polynomial polynomial) (lambda (p1 p2) (tag (add-poly p1 p2))))\n  (put 'sub '(polynomial polynomial) (lambda (p1 p2) (tag (sub-poly p1 p2))))\n  (put 'mul '(polynomial polynomial) (lambda (p1 p2) (tag (mul-poly p1 p2))))\n  (put '=zero? '(polynomial) (lambda (p) (empty-termlist? (term-list p))))\n  (put 'neg '(polynomial) (lambda (p) (tag (neg-poly p))))\n  \n  (put 'add '(integer polynomial) (lambda (n p) (add (make-const p n) (tag p))))\n  (put 'mul '(integer polynomial) (lambda (n p) (mul (make-const p n) (tag p))))\n  (put 'add '(polynomial integer) (lambda (p n) (add (make-integer n) (tag p))))\n  (put 'mul '(polynomial integer) (lambda (p n) (mul (make-integer n) (tag p))))\n\n  (put 'make 'polynomial (lambda (var terms) (tag (make-poly var terms)))))\n\n(define (make-polynomial var terms)\n  ((get 'make 'polynomial) var terms))\n\n; apply-generic with some coercion:\n\n(define (apply-generic op . args)\n  (define (applicable? args)\n    (get op (map type-tag args)))\n\n  (define (apply-generic-failed)\n    (error \"No method for these types - APPLY-GENERIC\" (list op (map type-tag args))))\n\n  (define (all-of-same-type? args)\n    (define (check rest)\n      (cond ((null? rest) #t)\n            ((same-type? (car args) (car rest)) (check (cdr rest)))\n            (else #f)))\n    (check args))\n\n  (define (of-same-type-and-raisable? args)\n    (and (all-of-same-type? args)\n         (raisable? (car args))))\n\n  (define (coercable-to-same-type? args)\n    (and (= (length args) 2)\n         (let ((type-a (type-tag (car args)))\n               (type-b (type-tag (cadr args))))\n           (or (supertype? type-a type-b)\n               (supertype? type-b type-a)))))\n\n  (define (coerce-to-same-type args)\n    (and (= (length args) 2)\n         (let* ((a (car args))\n                (b (cadr args))\n                (type-a (type-tag a))\n                (type-b (type-tag b)))\n           (cond ((same-type? a b) (list a b))\n                 ((supertype? type-a type-b) (coerce-to-same-type (list (raise a) b)))\n                 ((supertype? type-b type-a) (coerce-to-same-type (list a (raise b))))\n                 (else #f)))))\n\n  (define (attempt-coercion args)\n    (let ((number-of-arguments (length args)))\n      (cond ((of-same-type-and-raisable? args) (try (map raise args)))\n            ((coercable-to-same-type? args) (try (coerce-to-same-type args)))\n            (else (apply-generic-failed)))))\n\n  (define (try args)\n    (if (applicable? args)\n        (let ((result (apply (get op (map type-tag args)) (map contents args))))\n          (if (simplifiable? op)\n              (simplify result)\n              result))\n        (attempt-coercion args)))\n\n  (try args))\n"
  },
  {
    "path": "scheme/sicp/02/91.scm",
    "content": "; SICP exercise 2.91\n;\n; A univariate polynomial can be divided by another one to produce a\n; polynomial quotient and a polynomial remainder. For example:\n;\n;   x⁵ - 1\n;   ────── = x³ + x, remainder x - 1\n;   x² - 1\n;\n; Division can be performed via long division. That is, divide the\n; highest-order term of the dividend by the highest-order term of the divisor.\n; The result is the first term of the quotient. Next, multiply the result by\n; the divisor, subtract that from the dividend, and produce the rest of the\n; answer by recursively dividing the difference by the divisor. Stop when the\n; order of the divisor exceeds the order of the dividend and declare the\n; dividend to be the remainder. Also, if the dividend ever becomes zero,\n; return zero as both quotient and remainder.\n;\n; We can design a div-poly procedure on the model of add-poly and mul-poly.\n; The procedure checks to see if two polys have the same variable. If so,\n; div-poly strips off the variable and passes the problem to div-terms, which\n; performs the division operation on term lists. div-poly finally reattaches\n; the variable to the result supplied by div-terms. It is convenient to design\n; div-terms to compute both the quotient and the remainder of a division.\n; div-terms can take two term lists as arguments and return a list of the\n; quotient term list and the remainder term list.\n;\n; Complete the following definition of div-terms by filling in the missing\n; expressions. Use this to implement div-poly, which takes two polys as\n; arguments and returns a list of quotient and remainder polys.\n;\n; (define (div-terms L1 L2)\n;   (if (empty-termlist? L1)\n;       (list (the-empty-termlist) (the-empty-termlist))\n;       (let ((t1 (first-term L1))\n;             (t2 (first-term L2)))\n;         (if (> (order t2) (order t1))\n;             (list (the-empty-termlist) L1)\n;             (let ((new-c (div (coeff t1) (coeff t2)))\n;                   (new-o (- (order t1) (order t2))))\n;               (let ((rest-of-result\n;                 <compute rest of result recursively>\n;                 ))\n;                 <form complete result>\n;                 ))))))\n\n; We base this on the dense representation in exercise 2.89.\n\n; The type functions, table and coercion infrastructure.\n\n(define (attach-tag type-tag contents)\n  (cons type-tag contents))\n\n(define (type-tag datum)\n  (if (pair? datum)\n      (car datum)\n      (error \"Bad tagged datum - TYPE-TAG\" datum)))\n\n(define (contents datum)\n  (if (pair? datum)\n      (cdr datum)\n      (error \"Bad tagged datum - CONTENTS\" datum)))\n\n(define table (make-hash))\n(define (put op type item) (hash-set! table (list op type) item))\n(define (get op type) (hash-ref table (list op type) #f))\n\n(define (put-coercion from to op) (put 'coerce (list from to) op))\n(define (get-coercion from to) (get 'coerce (list from to)))\n\n; The type tower, supetype, supertype?, raise and project:\n\n(put 'supertype 'integer 'rational)\n(put 'supertype 'rational 'scheme-number)\n(put 'supertype 'scheme-number 'real)\n\n(define (supertype type)\n  (get 'supertype type))\n\n(define (supertype? a b)\n  (let ((super (supertype a)))\n    (cond ((equal? super b) #t)\n          ((not super) #f)\n          (else (supertype? super b)))))\n\n(define (same-type? a b) (equal? (type-tag a) (type-tag b)))\n\n(define (raise a) (apply-generic 'raise a))\n(define (project a) (apply-generic 'project a))\n\n(define (projectable? a) (get 'project (list (type-tag a))))\n(define (raisable? a) (get 'raise (list (type-tag a))))\n\n; Now a simplification procedure. It will be called simplify instead of drop,\n; because drop is already reserved:\n\n(define (simplify x)\n  (cond ((not (projectable? x)) x)\n        ((equ? (raise (project x)) x) (simplify (project x)))\n        (else x)))\n\n; Now the generic arithmemtic procedures.\n\n(define (add x y) (apply-generic 'add x y))\n(define (sub x y) (apply-generic 'sub x y))\n(define (mul x y) (apply-generic 'mul x y))\n(define (div x y) (apply-generic 'div x y))\n(define (neg x) (apply-generic 'neg x))\n(define (equ? x y) (apply-generic 'equ? x y))\n(define (square-root x) (apply-generic 'square-root x))\n(define (sine x) (apply-generic 'sine x))\n(define (cosine x) (apply-generic 'cosine x))\n(define (arctangent x y) (apply-generic 'arctangent x y))\n(define (=zero? x) (apply-generic '=zero? x))\n(define (square x) (mul x x))\n\n; The simplification table:\n\n(define (simplifiable? op)\n  (get 'simplifiable op))\n\n(put 'simplifiable 'add #t)\n(put 'simplifiable 'sub #t)\n(put 'simplifiable 'mul #t)\n(put 'simplifiable 'div #t)\n(put 'simplifiable 'neg #t)\n(put 'simplifiable 'square-root #t)\n(put 'simplifiable 'sine #t)\n(put 'simplifiable 'cosine #t)\n(put 'simplifiable 'arctangent #t)\n(put 'simplifiable 'real-part #t)\n(put 'simplifiable 'imag-part #t)\n(put 'simplifiable 'magnitude #t)\n(put 'simplifiable 'angle #t)\n\n; Integers:\n\n(let ()\n  (define (tag x) (attach-tag 'integer x))\n  (put 'add '(integer integer) (lambda (x y) (tag (+ x y))))\n  (put 'sub '(integer integer) (lambda (x y) (tag (- x y))))\n  (put 'mul '(integer integer) (lambda (x y) (tag (* x y))))\n  (put 'neg '(integer) (lambda (x) (tag (- x))))\n  (put 'equ? '(integer integer) =)\n  (put '=zero? '(integer) zero?)\n  (put 'raise '(integer) (lambda (n) (make-rational n 1)))\n  (put 'make 'integer\n       (lambda (n) (if (exact-integer? n)\n                       (tag n)\n                       (error \"Attempted to make an integer with a non-integer\" n)))))\n\n(define (make-integer n) ((get 'make 'integer) n))\n\n; Rational numbers:\n\n(let ()\n  (define (numer x) (car x))\n  (define (denom x) (cdr x))\n  (define (make-rat n d)\n    (if (and (exact-integer? n) (exact-integer? d))\n        (let ((g (gcd n d)))\n          (cons (/ n g) (/ d g)))\n        (error \"Cannot construct a rational with non-exact numbers\" n d)))\n\n  (define (add-rat x y)\n    (make-rat (+ (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (sub-rat x y)\n    (make-rat (- (* (numer x) (denom y))\n                 (* (numer y) (denom x)))\n              (* (denom x) (denom y))))\n  (define (mul-rat x y)\n    (make-rat (* (numer x) (numer y))\n              (* (denom x) (denom y))))\n  (define (div-rat x y)\n    (make-rat (* (numer x) (denom y))\n              (* (denom x) (numer y))))\n  (define (neg-rat x)\n    (make-rat (- (numer x)) (denom x)))\n  (define (=zero?-rat x)\n    (zero? (numer x)))\n  (define (raise-rat r)\n    (make-real (exact->inexact (/ (numer r) (denom r)))))\n  (define (project-rat r)\n    (make-integer (truncate (/ (numer r) (denom r)))))\n\n  (define (tag x) (attach-tag 'rational x))\n  (put 'numer '(rational) numer)\n  (put 'denom '(rational) denom)\n  (put 'raise '(rational) raise-rat)\n  (put 'project '(rational) project-rat)\n  (put '=zero? '(rational) =zero?-rat)\n  (put 'add '(rational rational) (lambda (x y) (tag (add-rat x y))))\n  (put 'sub '(rational rational) (lambda (x y) (tag (sub-rat x y))))\n  (put 'mul '(rational rational) (lambda (x y) (tag (mul-rat x y))))\n  (put 'div '(rational rational) (lambda (x y) (tag (div-rat x y))))\n  (put 'neg '(rational) (lambda (x) (tag (neg-rat x))))\n  (put 'equ? '(rational rational) equal?)\n  (put 'make 'rational (lambda (n d) (tag (make-rat n d)))))\n\n(define (make-rational n d) ((get 'make 'rational) n d))\n(define (numer r) (apply-generic 'numer r))\n(define (denom r) (apply-generic 'denom r))\n\n; Real numbers:\n\n(let ()\n  (define (tag x) (attach-tag 'real x))\n  (put 'add '(real real) (lambda (x y) (tag (+ x y))))\n  (put 'sub '(real real) (lambda (x y) (tag (- x y))))\n  (put 'mul '(real real) (lambda (x y) (tag (* x y))))\n  (put 'div '(real real) (lambda (x y) (tag (/ x y))))\n  (put 'neg '(real) (lambda (x) (tag (- x))))\n  (put 'sine '(real) (lambda (x) (tag (sin x))))\n  (put 'cosine '(real) (lambda (x) (tag (cos x))))\n  (put 'square-root '(real) (lambda (x) (tag (sqrt x))))\n  (put 'arctangent '(real real) (lambda (x y) (tag (atan x y))))\n  (put 'project '(real) (lambda (x) (make-rational (inexact->exact (truncate x)) 1)))\n  (put 'equ? '(real real) =)\n  (put '=zero? '(real) zero?)\n  (put 'make 'real (lambda (x) (tag x))))\n\n(define (make-real n) ((get 'make 'real) n))\n\n; The polynomial package:\n\n(let ()\n  (define (make-poly variable term-list)\n    (cons variable term-list))\n  (define (variable p) (car p))\n  (define (term-list p) (cdr p))\n\n  (define (same-variable? v1 v2)\n    (and (variable? v1) (variable? v2) (eq? v1 v2)))\n  (define (variable? x) (symbol? x))\n\n  (define (adjoin-term term term-list)\n    (let ((term-list-order (- (length term-list) 1))\n          (term-order (order term)))\n      (cond ((=zero? (coeff term)) term-list)\n            ((= term-list-order term-order)\n             (cons (add (coeff term) (car term-list))\n                   (cdr term-list)))\n            ((< term-order term-list-order)\n             (cons (car term-list) (adjoin-term term (cdr term-list))))\n            ((> term-order term-list-order)\n             (adjoin-term term (cons (make-integer 0) term-list))))))\n\n  (define (the-empty-termlist) '())\n  (define (first-term term-list) (make-term (- (length term-list) 1) (car term-list)))\n  (define (rest-terms term-list) (cdr term-list))\n  (define (empty-termlist? term-list) (null? term-list))\n\n  (define (make-term order coeff) (list order coeff))\n  (define (order term) (car term))\n  (define (coeff term) (cadr term))\n\n  (define (add-terms L1 L2)\n    (cond ((empty-termlist? L1) L2)\n          ((empty-termlist? L2) L1)\n          (else\n            (let ((t1 (first-term L1)) (t2 (first-term L2)))\n              (cond ((> (order t1) (order t2))\n                     (adjoin-term t1 (add-terms (rest-terms L1) L2)))\n                    ((< (order t1) (order t2))\n                     (adjoin-term t2 (add-terms L1 (rest-terms L2))))\n                    (else\n                      (adjoin-term\n                        (make-term (order t1) (add (coeff t1) (coeff t2)))\n                        (add-terms (rest-terms L1) (rest-terms L2)))))))))\n  (define (mul-terms L1 L2)\n    (if (empty-termlist? L1)\n        (the-empty-termlist)\n        (add-terms (mul-term-by-all-terms (first-term L1) L2)\n                   (mul-terms (rest-terms L1) L2))))\n  (define (mul-term-by-all-terms t1 L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((t2 (first-term L)))\n          (adjoin-term (make-term (+ (order t1) (order t2)) (mul (coeff t1) (coeff t2)))\n                       (mul-term-by-all-terms t1 (rest-terms L))))))\n  (define (sub-terms L1 L2)\n    (add-terms L1 (neg-terms L2)))\n\n  (define (div-terms L1 L2)\n    (if (empty-termlist? L1)\n        (list (the-empty-termlist) (the-empty-termlist))\n        (let ((t1 (first-term L1))\n              (t2 (first-term L2)))\n          (if (> (order t2) (order t1))\n              (list (the-empty-termlist) L1)\n              (let* ((new-c (div (coeff t1) (coeff t2)))\n                     (new-o (- (order t1) (order t2)))\n                     (term (make-term new-o new-c))\n                     (multiplier (adjoin-term term (the-empty-termlist)))\n                     (rest-of-result (div-terms (sub-terms L1 (mul-terms multiplier L2))\n                                                L2))\n                     (result-quotient (car rest-of-result))\n                     (result-remainder (cadr rest-of-result)))\n                (list (adjoin-term term result-quotient) result-remainder))))))\n  (define (neg-terms L)\n    (map-terms neg L))\n\n  (define (map-terms proc L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((first (first-term L))\n              (rest (rest-terms L)))\n          (adjoin-term (make-term (order first) (proc (coeff first)))\n                       (map-terms proc rest)))))\n\n  (define (add-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (make-poly (variable p1)\n                 (add-terms (term-list p1)\n                            (term-list p2)))\n      (error \"Polynomials not in same var - ADD-POLY\" (list p1 p2))))\n  (define (mul-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (make-poly (variable p1)\n                 (mul-terms (term-list p1)\n                            (term-list p2)))\n      (error \"Polynomials not in same var - MUL-POLY\" (list p1 p2))))\n  (define (div-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (map (lambda (term-list) (make-poly (variable p1) term-list))\n           (div-terms (term-list p1)\n                      (term-list p2)))\n      (error \"Polynomials not in same var - DIV-POLY\" (list p1 p2))))\n  (define (sub-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (make-poly (variable p1)\n                 (sub-terms (term-list p1)\n                            (term-list p2)))\n      (error \"Polynomials not in same var - SUB-POLY\" (list p1 p2))))\n  (define (neg-poly p)\n    (make-poly (variable p)\n               (neg-terms (term-list p))))\n\n  (define (make-const p n)\n    (tag (make-poly (variable p)\n                    (adjoin-term (make-term 0 (make-integer n))\n                                 (the-empty-termlist)))))\n\n  (define (tag p) (attach-tag 'polynomial p))\n  (put 'add '(polynomial polynomial) (lambda (p1 p2) (tag (add-poly p1 p2))))\n  (put 'sub '(polynomial polynomial) (lambda (p1 p2) (tag (sub-poly p1 p2))))\n  (put 'mul '(polynomial polynomial) (lambda (p1 p2) (tag (mul-poly p1 p2))))\n  (put 'div '(polynomial polynomial) (lambda (p1 p2) (map tag (div-poly p1 p2))))\n  (put '=zero? '(polynomial) (lambda (p) (empty-termlist? (term-list p))))\n  (put 'neg '(polynomial) (lambda (p) (tag (neg-poly p))))\n\n  (put 'add '(integer polynomial) (lambda (n p) (add (make-const p n) (tag p))))\n  (put 'mul '(integer polynomial) (lambda (n p) (mul (make-const p n) (tag p))))\n  (put 'add '(polynomial integer) (lambda (p n) (add (make-integer n) (tag p))))\n  (put 'mul '(polynomial integer) (lambda (p n) (mul (make-integer n) (tag p))))\n\n  (put 'make 'polynomial (lambda (var terms) (tag (make-poly var terms)))))\n\n(define (make-polynomial var terms)\n  ((get 'make 'polynomial) var terms))\n\n; apply-generic with some coercion:\n\n(define (apply-generic op . args)\n  (define (applicable? args)\n    (get op (map type-tag args)))\n\n  (define (apply-generic-failed)\n    (error \"No method for these types - APPLY-GENERIC\" (list op (map type-tag args))))\n\n  (define (all-of-same-type? args)\n    (define (check rest)\n      (cond ((null? rest) #t)\n            ((same-type? (car args) (car rest)) (check (cdr rest)))\n            (else #f)))\n    (check args))\n\n  (define (of-same-type-and-raisable? args)\n    (and (all-of-same-type? args)\n         (raisable? (car args))))\n\n  (define (coercable-to-same-type? args)\n    (and (= (length args) 2)\n         (let ((type-a (type-tag (car args)))\n               (type-b (type-tag (cadr args))))\n           (or (supertype? type-a type-b)\n               (supertype? type-b type-a)))))\n\n  (define (coerce-to-same-type args)\n    (and (= (length args) 2)\n         (let* ((a (car args))\n                (b (cadr args))\n                (type-a (type-tag a))\n                (type-b (type-tag b)))\n           (cond ((same-type? a b) (list a b))\n                 ((supertype? type-a type-b) (coerce-to-same-type (list (raise a) b)))\n                 ((supertype? type-b type-a) (coerce-to-same-type (list a (raise b))))\n                 (else #f)))))\n\n  (define (attempt-coercion args)\n    (let ((number-of-arguments (length args)))\n      (cond ((of-same-type-and-raisable? args) (try (map raise args)))\n            ((coercable-to-same-type? args) (try (coerce-to-same-type args)))\n            (else (apply-generic-failed)))))\n\n  (define (try args)\n    (if (applicable? args)\n        (let ((result (apply (get op (map type-tag args)) (map contents args))))\n          (if (simplifiable? op)\n              (simplify result)\n              result))\n        (attempt-coercion args)))\n\n  (try args))\n"
  },
  {
    "path": "scheme/sicp/02/92.scm",
    "content": "; SICP exercise 2.92\n;\n; By imposing an ordering on variables, extend the polynomial package so that\n; addition and multiplication of polynomials works for polynomials in\n; different variables. (This is not easy!)\n\n; That's gonna be fun!\n;\n; Let's use the code from the previous examples. We will choose sparse\n; representation of polynomials. Furthermore, we shall only have one numerical\n; type - scheme-number that we will dub number in order to simplify things.\n\n(define (attach-tag type-tag contents)\n  (if (eq? type-tag 'number)\n      contents\n      (cons type-tag contents)))\n\n(define (type-tag datum)\n  (cond ((number? datum) 'number)\n        ((pair? datum) (car datum))\n        (else (error \"Bad tagged datum - TYPE-TAG\" datum))))\n\n(define (contents datum)\n  (cond ((number? datum) datum)\n        ((pair? datum) (cdr datum))\n        (else (error \"Bad tagged datum - CONTENTS\" datum))))\n\n(define table (make-hash))\n(define (put op type item) (hash-set! table (list op type) item))\n(define (get op type) (hash-ref table (list op type) #f))\n\n(define (put-coercion from to op) (put 'coerce (list from to) op))\n(define (get-coercion from to) (get 'coerce (list from to)))\n\n; The type tower, supetype, supertype?, raise and project:\n\n(define (supertype type)\n  (get 'supertype type))\n\n(define (supertype? a b)\n  (let ((super (supertype a)))\n    (cond ((equal? super b) #t)\n          ((not super) #f)\n          (else (supertype? super b)))))\n\n(define (same-type? a b) (equal? (type-tag a) (type-tag b)))\n\n(define (raise a) (apply-generic 'raise a))\n(define (project a) (apply-generic 'project a))\n\n(define (projectable? a) (get 'project (list (type-tag a))))\n(define (raisable? a) (get 'raise (list (type-tag a))))\n\n; Now the generic arithmemtic procedures.\n\n(define (add x y) (apply-generic 'add x y))\n(define (sub x y) (apply-generic 'sub x y))\n(define (mul x y) (apply-generic 'mul x y))\n(define (div x y) (apply-generic 'div x y))\n(define (neg x) (apply-generic 'neg x))\n(define (equ? x y) (apply-generic 'equ? x y))\n(define (=zero? x) (apply-generic '=zero? x))\n(define (square x) (mul x x))\n\n; Numbers\n\n(let ()\n  (put 'add '(number number) +)\n  (put 'sub '(number number) -)\n  (put 'mul '(number number) *)\n  (put 'div '(number number) /)\n  (put 'neg '(number) -)\n  (put 'equ? '(number number) =)\n  (put '=zero? '(number) zero?))\n\n; A very clever procedure for normalizing terms. It is not nested under\n; polynomials so it can be tested separately.\n\n; The polynomial package:\n\n(define (make-term order coeff) (list order coeff))\n(define (order term) (car term))\n(define (coeff term) (cadr term))\n\n(let ()\n  (define (make-poly variable term-list)\n    (cons variable term-list))\n  (define (variable p) (car p))\n  (define (term-list p) (cdr p))\n\n  (define (same-variable? v1 v2)\n    (and (variable? v1) (variable? v2) (eq? v1 v2)))\n  (define (before? v1 v2)\n    (string<? (symbol->string v1) (symbol->string v2)))\n  (define (variable? x) (symbol? x))\n\n  (define (the-empty-termlist) '())\n  (define (empty-termlist? term-list) (null? term-list))\n  (define (first-term term-list) (car term-list))\n  (define (rest-terms term-list) (cdr term-list))\n  (define (adjoin-term term term-list)\n    (cond ((=zero? (coeff term)) term-list)\n          ((null? term-list) (list term))\n          ((> (order (car term-list)) (order term))\n           (cons (car term-list) (adjoin-term term (cdr term-list))))\n          ((= (order (car term-list)) (order term))\n           (adjoin-term (make-term (order term)\n                                   (add (coeff term) (coeff (car term-list))))\n                        (cdr term-list)))\n          (else (cons term term-list))))\n\n  (define (const var number)\n    (make-poly var (adjoin-term (make-term 0 number) (the-empty-termlist))))\n  (define (poly-const var polynomial)\n    (make-term var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n\n  (define (map-terms proc L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((first (first-term L))\n              (rest (rest-terms L)))\n          (adjoin-term (make-term (order first) (proc (coeff first)))\n                       (map-terms proc rest)))))\n  (define (neg-terms L)\n    (map-terms neg L))\n  (define (add-terms L1 L2)\n    (cond ((empty-termlist? L1) L2)\n          ((empty-termlist? L2) L1)\n          (else\n            (let ((t1 (first-term L1)) (t2 (first-term L2)))\n              (cond ((> (order t1) (order t2))\n                     (adjoin-term t1 (add-terms (rest-terms L1) L2)))\n                    ((< (order t1) (order t2))\n                     (adjoin-term t2 (add-terms L1 (rest-terms L2))))\n                    (else\n                      (adjoin-term\n                        (make-term (order t1) (add (coeff t1) (coeff t2)))\n                        (add-terms (rest-terms L1) (rest-terms L2)))))))))\n  (define (sub-terms L1 L2)\n    (add-terms L1 (neg-terms L2)))\n  (define (mul-terms L1 L2)\n    (if (empty-termlist? L1)\n        (the-empty-termlist)\n        (add-terms (mul-term-by-all-terms (first-term L1) L2)\n                   (mul-terms (rest-terms L1) L2))))\n  (define (mul-term-by-all-terms t1 L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((t2 (first-term L)))\n          (adjoin-term (make-term (+ (order t1) (order t2)) (mul (coeff t1) (coeff t2)))\n                       (mul-term-by-all-terms t1 (rest-terms L))))))\n  (define (div-terms L1 L2)\n    (if (empty-termlist? L1)\n        (list (the-empty-termlist) (the-empty-termlist))\n        (let ((t1 (first-term L1))\n              (t2 (first-term L2)))\n          (if (> (order t2) (order t1))\n              (list (the-empty-termlist) L1)\n              (let* ((new-c (div (coeff t1) (coeff t2)))\n                     (new-o (- (order t1) (order t2)))\n                     (term (make-term new-o new-c))\n                     (multiplier (adjoin-term term (the-empty-termlist)))\n                     (rest-of-result (div-terms (sub-terms L1 (mul-terms multiplier L2))\n                                                L2))\n                     (result-quotient (car rest-of-result))\n                     (result-remainder (cadr rest-of-result)))\n                (list (adjoin-term term result-quotient) result-remainder))))))\n  (define (neg-poly p)\n    (make-poly (variable p)\n               (neg-terms (term-list p))))\n  (define (add-poly p1 p2)\n    (define (const var polynomial)\n      (make-poly var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n    (let ((v1 (variable p1))\n          (v2 (variable p2))\n          (t1 (term-list p1))\n          (t2 (term-list p2)))\n      (cond ((same-variable? v1 v2) (make-poly v1 (add-terms t1 t2)))\n            ((before? v1 v2) (add-poly p1 (const v1 p2)))\n            (else (add-poly (const v2 p1) p2)))))\n  (define (mul-poly p1 p2)\n    (define (const var polynomial)\n      (make-poly var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n    (let ((v1 (variable p1))\n          (v2 (variable p2))\n          (t1 (term-list p1))\n          (t2 (term-list p2)))\n      (cond ((same-variable? v1 v2) (make-poly v1 (mul-terms t1 t2)))\n            ((before? v1 v2) (mul-poly p1 (const v1 p2)))\n            (else (mul-poly (const v2 p1) p2)))))\n  (define (sub-poly p1 p2)\n    (define (const var polynomial)\n      (make-poly var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n    (let ((v1 (variable p1))\n          (v2 (variable p2))\n          (t1 (term-list p1))\n          (t2 (term-list p2)))\n      (cond ((same-variable? v1 v2) (make-poly v1 (sub-terms t1 t2)))\n            ((before? v1 v2) (sub-poly p1 (const v1 p2)))\n            (else (sub-poly (const v2 p1) p2)))))\n  (define (div-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (map (lambda (term-list) (make-poly (variable p1) term-list))\n           (div-terms (term-list p1)\n                      (term-list p2)))\n      (error \"Polynomials not in same var - DIV-POLY\" (list p1 p2))))\n\n  (define (tag p) (attach-tag 'polynomial p))\n  (put 'add '(polynomial polynomial) (lambda (p1 p2) (tag (add-poly p1 p2))))\n  (put 'sub '(polynomial polynomial) (lambda (p1 p2) (tag (sub-poly p1 p2))))\n  (put 'mul '(polynomial polynomial) (lambda (p1 p2) (tag (mul-poly p1 p2))))\n  (put 'div '(polynomial polynomial) (lambda (p1 p2) (map tag (div-poly p1 p2))))\n  (put '=zero? '(polynomial) (lambda (p) (empty-termlist? (term-list p))))\n  (put 'neg '(polynomial) (lambda (p) (tag (neg-poly p))))\n\n  (put 'add '(number polynomial) (lambda (n p) (tag (add-poly (const (variable p) n) p))))\n  (put 'mul '(number polynomial) (lambda (n p) (tag (mul-poly (const (variable p) n) p))))\n  (put 'add '(polynomial number) (lambda (p n) (tag (add-poly p (const (variable p) n)))))\n  (put 'mul '(polynomial number) (lambda (p n) (tag (mul-poly p (const (variable p) n)))))\n\n  (put 'make 'polynomial (lambda (var terms) (tag (make-poly var terms)))))\n\n(define (make-polynomial var terms)\n  ((get 'make 'polynomial) var terms))\n\n; apply-generic with some coercion:\n\n(define (apply-generic op . args)\n  (define (applicable? args)\n    (get op (map type-tag args)))\n\n  (define (apply-generic-failed)\n    (error \"No method for these types - APPLY-GENERIC\" (list op (map type-tag args))))\n\n  (define (all-of-same-type? args)\n    (define (check rest)\n      (cond ((null? rest) #t)\n            ((same-type? (car args) (car rest)) (check (cdr rest)))\n            (else #f)))\n    (check args))\n\n  (define (of-same-type-and-raisable? args)\n    (and (all-of-same-type? args)\n         (raisable? (car args))))\n\n  (define (coercable-to-same-type? args)\n    (and (= (length args) 2)\n         (let ((type-a (type-tag (car args)))\n               (type-b (type-tag (cadr args))))\n           (or (supertype? type-a type-b)\n               (supertype? type-b type-a)))))\n\n  (define (coerce-to-same-type args)\n    (and (= (length args) 2)\n         (let* ((a (car args))\n                (b (cadr args))\n                (type-a (type-tag a))\n                (type-b (type-tag b)))\n           (cond ((same-type? a b) (list a b))\n                 ((supertype? type-a type-b) (coerce-to-same-type (list (raise a) b)))\n                 ((supertype? type-b type-a) (coerce-to-same-type (list a (raise b))))\n                 (else #f)))))\n\n  (define (attempt-coercion args)\n    (let ((number-of-arguments (length args)))\n      (cond ((of-same-type-and-raisable? args) (try (map raise args)))\n            ((coercable-to-same-type? args) (try (coerce-to-same-type args)))\n            (else (apply-generic-failed)))))\n\n  (define (try args)\n    (if (applicable? args)\n        (apply (get op (map type-tag args)) (map contents args))\n        (attempt-coercion args)))\n\n  (try args))\n"
  },
  {
    "path": "scheme/sicp/02/93.scm",
    "content": "; SICP exercise 2.93\n;\n; Modify the rational-artihmetic package to use generic operations, but change\n; make-rat so that it does not attempt to reduce fractions to lowest terms.\n; Test your system by calling make-rational on two polynomials to produce a\n; rational function\n;\n;   (define p1 (make-polynomial 'x '((2 1) (0 1))))\n;   (define p2 (make-polynomial 'x '((3 1) (0 1))))\n;   (define rf (make-rational p2 p1))\n;\n; Now add rf to itself, using add. You will observe that this addition\n; procedure does not reduce fractions to lowest terms.\n\n(define (attach-tag type-tag contents)\n  (if (eq? type-tag 'number)\n      contents\n      (cons type-tag contents)))\n\n(define (type-tag datum)\n  (cond ((number? datum) 'number)\n        ((pair? datum) (car datum))\n        (else (error \"Bad tagged datum - TYPE-TAG\" datum))))\n\n(define (contents datum)\n  (cond ((number? datum) datum)\n        ((pair? datum) (cdr datum))\n        (else (error \"Bad tagged datum - CONTENTS\" datum))))\n\n(define table (make-hash))\n(define (put op type item) (hash-set! table (list op type) item))\n(define (get op type) (hash-ref table (list op type) #f))\n\n; Now the generic arithmemtic procedures.\n\n(define (add x y) (apply-generic 'add x y))\n(define (sub x y) (apply-generic 'sub x y))\n(define (mul x y) (apply-generic 'mul x y))\n(define (div x y) (apply-generic 'div x y))\n(define (neg x) (apply-generic 'neg x))\n(define (equ? x y) (apply-generic 'equ? x y))\n(define (=zero? x) (apply-generic '=zero? x))\n(define (square x) (mul x x))\n\n; Numbers\n\n(let ()\n  (put 'add '(number number) +)\n  (put 'sub '(number number) -)\n  (put 'mul '(number number) *)\n  (put 'div '(number number) /)\n  (put 'neg '(number) -)\n  (put 'equ? '(number number) =)\n  (put '=zero? '(number) zero?))\n\n; Rationals:\n\n(let ()\n  (define (make-rat n d) (cons n d))\n  (define (numer x) (car x))\n  (define (denom x) (cdr x))\n\n  (define (add-rat x y)\n    (make-rat (add (mul (numer x) (denom y))\n                   (mul (numer y) (denom x)))\n              (mul (denom x) (denom y))))\n  (define (sub-rat x y)\n    (make-rat (sub (mul (numer x) (denom y))\n                   (mul (numer y) (denom x)))\n              (mul (denom x) (denom y))))\n  (define (mul-rat x y)\n    (make-rat (mul (numer x) (numer y))\n              (mul (denom x) (denom y))))\n  (define (div-rat x y)\n    (make-rat (mul (numer x) (denom y))\n              (mul (denom x) (numer y))))\n  (define (=zero?-rat x)\n    (zero? (numer x)))\n\n  (define (tag x) (attach-tag 'rational x))\n  (put 'numer '(rational) numer)\n  (put 'denom '(rational) denom)\n  (put '=zero? '(rational) =zero?-rat)\n  (put 'add '(rational rational) (lambda (x y) (tag (add-rat x y))))\n  (put 'sub '(rational rational) (lambda (x y) (tag (sub-rat x y))))\n  (put 'mul '(rational rational) (lambda (x y) (tag (mul-rat x y))))\n  (put 'div '(rational rational) (lambda (x y) (tag (div-rat x y))))\n  (put 'equ? '(rational rational) equal?)\n  (put 'make 'rational (lambda (n d) (tag (make-rat n d)))))\n\n(define (make-rational n d) ((get 'make 'rational) n d))\n(define (numer r) (apply-generic 'numer r))\n(define (denom r) (apply-generic 'denom r))\n\n; A very clever procedure for normalizing terms. It is not nested under\n; polynomials so it can be tested separately.\n\n; The polynomial package:\n\n(define (make-term order coeff) (list order coeff))\n(define (order term) (car term))\n(define (coeff term) (cadr term))\n\n(let ()\n  (define (make-poly variable term-list)\n    (cons variable term-list))\n  (define (variable p) (car p))\n  (define (term-list p) (cdr p))\n\n  (define (same-variable? v1 v2)\n    (and (variable? v1) (variable? v2) (eq? v1 v2)))\n  (define (before? v1 v2)\n    (string<? (symbol->string v1) (symbol->string v2)))\n  (define (variable? x) (symbol? x))\n\n  (define (the-empty-termlist) '())\n  (define (empty-termlist? term-list) (null? term-list))\n  (define (first-term term-list) (car term-list))\n  (define (rest-terms term-list) (cdr term-list))\n  (define (adjoin-term term term-list)\n    (cond ((=zero? (coeff term)) term-list)\n          ((null? term-list) (list term))\n          ((> (order (car term-list)) (order term))\n           (cons (car term-list) (adjoin-term term (cdr term-list))))\n          ((= (order (car term-list)) (order term))\n           (adjoin-term (make-term (order term)\n                                   (add (coeff term) (coeff (car term-list))))\n                        (cdr term-list)))\n          (else (cons term term-list))))\n\n  (define (const var number)\n    (make-poly var (adjoin-term (make-term 0 number) (the-empty-termlist))))\n  (define (poly-const var polynomial)\n    (make-term var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n\n  (define (map-terms proc L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((first (first-term L))\n              (rest (rest-terms L)))\n          (adjoin-term (make-term (order first) (proc (coeff first)))\n                       (map-terms proc rest)))))\n  (define (neg-terms L)\n    (map-terms neg L))\n  (define (add-terms L1 L2)\n    (cond ((empty-termlist? L1) L2)\n          ((empty-termlist? L2) L1)\n          (else\n            (let ((t1 (first-term L1)) (t2 (first-term L2)))\n              (cond ((> (order t1) (order t2))\n                     (adjoin-term t1 (add-terms (rest-terms L1) L2)))\n                    ((< (order t1) (order t2))\n                     (adjoin-term t2 (add-terms L1 (rest-terms L2))))\n                    (else\n                      (adjoin-term\n                        (make-term (order t1) (add (coeff t1) (coeff t2)))\n                        (add-terms (rest-terms L1) (rest-terms L2)))))))))\n  (define (sub-terms L1 L2)\n    (add-terms L1 (neg-terms L2)))\n  (define (mul-terms L1 L2)\n    (if (empty-termlist? L1)\n        (the-empty-termlist)\n        (add-terms (mul-term-by-all-terms (first-term L1) L2)\n                   (mul-terms (rest-terms L1) L2))))\n  (define (mul-term-by-all-terms t1 L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((t2 (first-term L)))\n          (adjoin-term (make-term (+ (order t1) (order t2)) (mul (coeff t1) (coeff t2)))\n                       (mul-term-by-all-terms t1 (rest-terms L))))))\n  (define (div-terms L1 L2)\n    (if (empty-termlist? L1)\n        (list (the-empty-termlist) (the-empty-termlist))\n        (let ((t1 (first-term L1))\n              (t2 (first-term L2)))\n          (if (> (order t2) (order t1))\n              (list (the-empty-termlist) L1)\n              (let* ((new-c (div (coeff t1) (coeff t2)))\n                     (new-o (- (order t1) (order t2)))\n                     (term (make-term new-o new-c))\n                     (multiplier (adjoin-term term (the-empty-termlist)))\n                     (rest-of-result (div-terms (sub-terms L1 (mul-terms multiplier L2))\n                                                L2))\n                     (result-quotient (car rest-of-result))\n                     (result-remainder (cadr rest-of-result)))\n                (list (adjoin-term term result-quotient) result-remainder))))))\n\n  (define (neg-poly p)\n    (make-poly (variable p)\n               (neg-terms (term-list p))))\n  (define (add-poly p1 p2)\n    (define (const var polynomial)\n      (make-poly var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n    (let ((v1 (variable p1))\n          (v2 (variable p2))\n          (t1 (term-list p1))\n          (t2 (term-list p2)))\n      (cond ((same-variable? v1 v2) (make-poly v1 (add-terms t1 t2)))\n            ((before? v1 v2) (add-poly p1 (const v1 p2)))\n            (else (add-poly (const v2 p1) p2)))))\n  (define (mul-poly p1 p2)\n    (define (const var polynomial)\n      (make-poly var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n    (let ((v1 (variable p1))\n          (v2 (variable p2))\n          (t1 (term-list p1))\n          (t2 (term-list p2)))\n      (cond ((same-variable? v1 v2) (make-poly v1 (mul-terms t1 t2)))\n            ((before? v1 v2) (mul-poly p1 (const v1 p2)))\n            (else (mul-poly (const v2 p1) p2)))))\n  (define (sub-poly p1 p2)\n    (define (const var polynomial)\n      (make-poly var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n    (let ((v1 (variable p1))\n          (v2 (variable p2))\n          (t1 (term-list p1))\n          (t2 (term-list p2)))\n      (cond ((same-variable? v1 v2) (make-poly v1 (sub-terms t1 t2)))\n            ((before? v1 v2) (sub-poly p1 (const v1 p2)))\n            (else (sub-poly (const v2 p1) p2)))))\n  (define (div-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (map (lambda (term-list) (make-poly (variable p1) term-list))\n           (div-terms (term-list p1)\n                      (term-list p2)))\n      (error \"Polynomials not in same var - DIV-POLY\" (list p1 p2))))\n\n  (define (tag p) (attach-tag 'polynomial p))\n  (put 'add '(polynomial polynomial) (lambda (p1 p2) (tag (add-poly p1 p2))))\n  (put 'sub '(polynomial polynomial) (lambda (p1 p2) (tag (sub-poly p1 p2))))\n  (put 'mul '(polynomial polynomial) (lambda (p1 p2) (tag (mul-poly p1 p2))))\n  (put 'div '(polynomial polynomial) (lambda (p1 p2) (map tag (div-poly p1 p2))))\n  (put '=zero? '(polynomial) (lambda (p) (empty-termlist? (term-list p))))\n  (put 'neg '(polynomial) (lambda (p) (tag (neg-poly p))))\n\n  (put 'add '(number polynomial) (lambda (n p) (tag (add-poly (const (variable p) n) p))))\n  (put 'mul '(number polynomial) (lambda (n p) (tag (mul-poly (const (variable p) n) p))))\n  (put 'add '(polynomial number) (lambda (p n) (tag (add-poly p (const (variable p) n)))))\n  (put 'mul '(polynomial number) (lambda (p n) (tag (mul-poly p (const (variable p) n)))))\n\n  (put 'make 'polynomial (lambda (var terms) (tag (make-poly var terms)))))\n\n(define (make-polynomial var terms)\n  ((get 'make 'polynomial) var terms))\n\n; apply-generic without any coercion:\n\n(define (apply-generic op . args)\n  (let ((type-tags (map type-tag args)))\n    (let ((proc (get op type-tags)))\n      (if proc\n          (apply proc (map contents args))\n          (error \"No method for these types - APPLY-GENERIC\" (list op type-tags))))))\n"
  },
  {
    "path": "scheme/sicp/02/94.scm",
    "content": "; SICP exercise 2.94\n;\n; Using div-terms, implement the procedure remainder-terms and use this to\n; define gcd-terms as above. Now write a procedure gcd-poly that computes the\n; polynomial GCD of two polys. (The procedure should signal an error if the\n; two polys are not in the same variable.) Install in the system a generic\n; operation greated-common-divisor that reduces to gcd-poly for polynomials\n; and to ordinary gcd for ordinary numbers. As a test, try:\n;\n;   (define (p1 (make-polynomial 'x '((4 1) (3 -1) (2 -2) (1 2)))))\n;   (define (p2 (make-polynomial 'x '((3 1) (1 -1)))))\n;   (greated-common-divisor p1 p2)\n;\n; and check your result by hand.\n\n(define (attach-tag type-tag contents)\n  (if (eq? type-tag 'number)\n      contents\n      (cons type-tag contents)))\n\n(define (type-tag datum)\n  (cond ((number? datum) 'number)\n        ((pair? datum) (car datum))\n        (else (error \"Bad tagged datum - TYPE-TAG\" datum))))\n\n(define (contents datum)\n  (cond ((number? datum) datum)\n        ((pair? datum) (cdr datum))\n        (else (error \"Bad tagged datum - CONTENTS\" datum))))\n\n(define table (make-hash))\n(define (put op type item) (hash-set! table (list op type) item))\n(define (get op type) (hash-ref table (list op type) #f))\n\n; Now the generic arithmemtic procedures.\n\n(define (add x y) (apply-generic 'add x y))\n(define (sub x y) (apply-generic 'sub x y))\n(define (mul x y) (apply-generic 'mul x y))\n(define (div x y) (apply-generic 'div x y))\n(define (neg x) (apply-generic 'neg x))\n(define (equ? x y) (apply-generic 'equ? x y))\n(define (=zero? x) (apply-generic '=zero? x))\n(define (greatest-common-divisor x y) (apply-generic 'greatest-common-divisor x y))\n(define (square x) (mul x x))\n\n; Numbers\n\n(let ()\n  (put 'add '(number number) +)\n  (put 'sub '(number number) -)\n  (put 'mul '(number number) *)\n  (put 'div '(number number) /)\n  (put 'neg '(number) -)\n  (put 'greatest-common-divisor '(number number) gcd)\n  (put 'equ? '(number number) =)\n  (put '=zero? '(number) zero?))\n\n; Rationals:\n\n(let ()\n  (define (make-rat n d) (cons n d))\n  (define (numer x) (car x))\n  (define (denom x) (cdr x))\n\n  (define (add-rat x y)\n    (make-rat (add (mul (numer x) (denom y))\n                   (mul (numer y) (denom x)))\n              (mul (denom x) (denom y))))\n  (define (sub-rat x y)\n    (make-rat (sub (mul (numer x) (denom y))\n                   (mul (numer y) (denom x)))\n              (mul (denom x) (denom y))))\n  (define (mul-rat x y)\n    (make-rat (mul (numer x) (numer y))\n              (mul (denom x) (denom y))))\n  (define (div-rat x y)\n    (make-rat (mul (numer x) (denom y))\n              (mul (denom x) (numer y))))\n  (define (=zero?-rat x)\n    (zero? (numer x)))\n\n  (define (tag x) (attach-tag 'rational x))\n  (put 'numer '(rational) numer)\n  (put 'denom '(rational) denom)\n  (put '=zero? '(rational) =zero?-rat)\n  (put 'add '(rational rational) (lambda (x y) (tag (add-rat x y))))\n  (put 'sub '(rational rational) (lambda (x y) (tag (sub-rat x y))))\n  (put 'mul '(rational rational) (lambda (x y) (tag (mul-rat x y))))\n  (put 'div '(rational rational) (lambda (x y) (tag (div-rat x y))))\n  (put 'equ? '(rational rational) equal?)\n  (put 'make 'rational (lambda (n d) (tag (make-rat n d)))))\n\n(define (make-rational n d) ((get 'make 'rational) n d))\n(define (numer r) (apply-generic 'numer r))\n(define (denom r) (apply-generic 'denom r))\n\n; A very clever procedure for normalizing terms. It is not nested under\n; polynomials so it can be tested separately.\n\n; The polynomial package:\n\n(define (make-term order coeff) (list order coeff))\n(define (order term) (car term))\n(define (coeff term) (cadr term))\n\n(let ()\n  (define (make-poly variable term-list)\n    (cons variable term-list))\n  (define (variable p) (car p))\n  (define (term-list p) (cdr p))\n\n  (define (same-variable? v1 v2)\n    (and (variable? v1) (variable? v2) (eq? v1 v2)))\n  (define (before? v1 v2)\n    (string<? (symbol->string v1) (symbol->string v2)))\n  (define (variable? x) (symbol? x))\n\n  (define (the-empty-termlist) '())\n  (define (empty-termlist? term-list) (null? term-list))\n  (define (first-term term-list) (car term-list))\n  (define (rest-terms term-list) (cdr term-list))\n  (define (adjoin-term term term-list)\n    (cond ((=zero? (coeff term)) term-list)\n          ((null? term-list) (list term))\n          ((> (order (car term-list)) (order term))\n           (cons (car term-list) (adjoin-term term (cdr term-list))))\n          ((= (order (car term-list)) (order term))\n           (adjoin-term (make-term (order term)\n                                   (add (coeff term) (coeff (car term-list))))\n                        (cdr term-list)))\n          (else (cons term term-list))))\n\n  (define (const var number)\n    (make-poly var (adjoin-term (make-term 0 number) (the-empty-termlist))))\n  (define (poly-const var polynomial)\n    (make-term var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n\n  (define (map-terms proc L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((first (first-term L))\n              (rest (rest-terms L)))\n          (adjoin-term (make-term (order first) (proc (coeff first)))\n                       (map-terms proc rest)))))\n  (define (neg-terms L)\n    (map-terms neg L))\n  (define (add-terms L1 L2)\n    (cond ((empty-termlist? L1) L2)\n          ((empty-termlist? L2) L1)\n          (else\n            (let ((t1 (first-term L1)) (t2 (first-term L2)))\n              (cond ((> (order t1) (order t2))\n                     (adjoin-term t1 (add-terms (rest-terms L1) L2)))\n                    ((< (order t1) (order t2))\n                     (adjoin-term t2 (add-terms L1 (rest-terms L2))))\n                    (else\n                      (adjoin-term\n                        (make-term (order t1) (add (coeff t1) (coeff t2)))\n                        (add-terms (rest-terms L1) (rest-terms L2)))))))))\n  (define (sub-terms L1 L2)\n    (add-terms L1 (neg-terms L2)))\n  (define (mul-terms L1 L2)\n    (if (empty-termlist? L1)\n        (the-empty-termlist)\n        (add-terms (mul-term-by-all-terms (first-term L1) L2)\n                   (mul-terms (rest-terms L1) L2))))\n  (define (mul-term-by-all-terms t1 L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((t2 (first-term L)))\n          (adjoin-term (make-term (+ (order t1) (order t2)) (mul (coeff t1) (coeff t2)))\n                       (mul-term-by-all-terms t1 (rest-terms L))))))\n  (define (div-terms L1 L2)\n    (if (empty-termlist? L1)\n        (list (the-empty-termlist) (the-empty-termlist))\n        (let ((t1 (first-term L1))\n              (t2 (first-term L2)))\n          (if (> (order t2) (order t1))\n              (list (the-empty-termlist) L1)\n              (let ((new-c (div (coeff t1) (coeff t2)))\n                    (new-o (- (order t1) (order t2))))\n                (let ((rest-of-result\n                        (div-terms\n                          (add-terms L1\n                                     (neg-terms (mul-term-by-all-terms (make-term new-o new-c)\n                                                                       L2)))\n                          L2)))\n                  (cons (adjoin-term (make-term new-o new-c)\n                                     (car rest-of-result))\n                        (cdr rest-of-result))))))))\n  (define (remainder-terms a b)\n    (cadr (div-terms a b)))\n  (define (gcd-terms a b)\n    (if (empty-termlist? b)\n        a\n        (gcd-terms b (remainder-terms a b))))\n\n  (define (neg-poly p)\n    (make-poly (variable p)\n               (neg-terms (term-list p))))\n  (define (add-poly p1 p2)\n    (define (const var polynomial)\n      (make-poly var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n    (let ((v1 (variable p1))\n          (v2 (variable p2))\n          (t1 (term-list p1))\n          (t2 (term-list p2)))\n      (cond ((same-variable? v1 v2) (make-poly v1 (add-terms t1 t2)))\n            ((before? v1 v2) (add-poly p1 (const v1 p2)))\n            (else (add-poly (const v2 p1) p2)))))\n  (define (mul-poly p1 p2)\n    (define (const var polynomial)\n      (make-poly var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n    (let ((v1 (variable p1))\n          (v2 (variable p2))\n          (t1 (term-list p1))\n          (t2 (term-list p2)))\n      (cond ((same-variable? v1 v2) (make-poly v1 (mul-terms t1 t2)))\n            ((before? v1 v2) (mul-poly p1 (const v1 p2)))\n            (else (mul-poly (const v2 p1) p2)))))\n  (define (sub-poly p1 p2)\n    (define (const var polynomial)\n      (make-poly var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n    (let ((v1 (variable p1))\n          (v2 (variable p2))\n          (t1 (term-list p1))\n          (t2 (term-list p2)))\n      (cond ((same-variable? v1 v2) (make-poly v1 (sub-terms t1 t2)))\n            ((before? v1 v2) (sub-poly p1 (const v1 p2)))\n            (else (sub-poly (const v2 p1) p2)))))\n  (define (div-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n        (map (lambda (term-list) (make-poly (variable p1) term-list))\n             (div-terms (term-list p1)\n                        (term-list p2)))\n        (error \"Polynomials not in same var - DIV-POLY\" (list p1 p2))))\n  (define (gcd-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n        (make-poly (variable p1) (gcd-terms (term-list p1) (term-list p2)))\n        (error \"Polynomials not in same var - GCD-POLY\" (list p1 p2))))\n\n  (define (tag p) (attach-tag 'polynomial p))\n  (put 'add '(polynomial polynomial) (lambda (p1 p2) (tag (add-poly p1 p2))))\n  (put 'sub '(polynomial polynomial) (lambda (p1 p2) (tag (sub-poly p1 p2))))\n  (put 'mul '(polynomial polynomial) (lambda (p1 p2) (tag (mul-poly p1 p2))))\n  (put 'div '(polynomial polynomial) (lambda (p1 p2) (map tag (div-poly p1 p2))))\n  (put '=zero? '(polynomial) (lambda (p) (empty-termlist? (term-list p))))\n  (put 'greatest-common-divisor '(polynomial polynomial) (lambda (p1 p2) (tag (gcd-poly p1 p2))))\n  (put 'neg '(polynomial) (lambda (p) (tag (neg-poly p))))\n  (put 'add '(number polynomial) (lambda (n p) (tag (add-poly (const (variable p) n) p))))\n  (put 'mul '(number polynomial) (lambda (n p) (tag (mul-poly (const (variable p) n) p))))\n  (put 'add '(polynomial number) (lambda (p n) (tag (add-poly p (const (variable p) n)))))\n  (put 'mul '(polynomial number) (lambda (p n) (tag (mul-poly p (const (variable p) n)))))\n\n  (put 'make 'polynomial (lambda (var terms) (tag (make-poly var terms)))))\n\n(define (make-polynomial var terms)\n  ((get 'make 'polynomial) var terms))\n\n; apply-generic without any coercion:\n\n(define (apply-generic op . args)\n  (let ((type-tags (map type-tag args)))\n    (let ((proc (get op type-tags)))\n      (if proc\n          (apply proc (map contents args))\n          (error \"No method for these types - APPLY-GENERIC\" (list op type-tags))))))\n"
  },
  {
    "path": "scheme/sicp/02/95.scm",
    "content": "; SICP exercise 2.95\n;\n; ₁₂₃\n; Define P₁, P₂, and P₃ to be the polynomials:\n;\n;     P₁: x² - 2x + 1\n;     P₂: 11x² + 7\n;     P₃: 13x + 5\n;\n; Now define Q₁ to be the product of P₁ and P₂ and Q₂ to be the product of P₁\n; and P₃, and use greated-common-divisor (exercise 2.94) to compute the GCD of\n; Q₁ and Q₂. Note that the answer is not the same as P₁. This example\n; introduces noninteger operations into the computation, causing difficulties\n; with the GCD algorithms. To understand what is happening, try tracing\n; gcd-terms while computing the GCD or try performing the division by hand.\n\n; I'll avoid doing it by hand, since the numbers are not too nice. Here is\n; each step from gcd-terms:\n;\n; +------------------------------------+------------------------------------+\n; | quotient                           | remainder                          |\n; +------------------------------------+------------------------------------+\n; | 11x⁴ + -22x³ + 18x² + -14x + 7     | 13x³ + -21x² + 3x + 5              |\n; | 13x³ + -21x² + 3x + 5              | 1458/169x² + -2916/169x + 1458/169 |\n; | 1458/169x² + -2916/169x + 1458/169 | 0                                  |\n; +------------------------------------+------------------------------------+\n;\n; As you can see, it goes into divison of non-integers. Since Racket supports\n; rational numbers, this is actually a GCD of Q₁ and Q₂, although with\n; rational coefficients (as the footnote indicates). It can easily produce\n; rounding errors in case of floating-point precision.\n"
  },
  {
    "path": "scheme/sicp/02/96.scm",
    "content": "; SICP exercise 2.96\n;\n; a. Implement the procedure pseudoremainder-terms, which is just like\n; remainder-terms except that it multiplies the dividend by the integerizing\n; factor described above before calling div-terms. Modify gcd-terms to use\n; pseudoremainder-terms and verify that greatest-common-divisor now produces\n; an answer with integer coefficients on the example in exercise 2.95.\n;\n; b. The GCD now has integer coefficients, but they are larger than those of\n; P₁. Modify gcd-terms so that it removes common factors from the coefficients\n; of the answer by dividing all the coefficients by their (integer) greated\n; common divisor.\n\n; Here it goes:\n\n; The type system:\n\n(define (attach-tag type-tag contents)\n  (if (eq? type-tag 'number)\n      contents\n      (cons type-tag contents)))\n\n(define (type-tag datum)\n  (cond ((number? datum) 'number)\n        ((pair? datum) (car datum))\n        (else (error \"Bad tagged datum - TYPE-TAG\" datum))))\n\n(define (contents datum)\n  (cond ((number? datum) datum)\n        ((pair? datum) (cdr datum))\n        (else (error \"Bad tagged datum - CONTENTS\" datum))))\n\n(define table (make-hash))\n(define (put op type item) (hash-set! table (list op type) item))\n(define (get op type) (hash-ref table (list op type) #f))\n\n; Now the generic arithmemtic procedures.\n\n(define (add x y) (apply-generic 'add x y))\n(define (sub x y) (apply-generic 'sub x y))\n(define (mul x y) (apply-generic 'mul x y))\n(define (div x y) (apply-generic 'div x y))\n(define (neg x) (apply-generic 'neg x))\n(define (equ? x y) (apply-generic 'equ? x y))\n(define (=zero? x) (apply-generic '=zero? x))\n(define (greatest-common-divisor x y) (apply-generic 'greatest-common-divisor x y))\n(define (square x) (mul x x))\n\n; Numbers\n\n(let ()\n  (put 'add '(number number) +)\n  (put 'sub '(number number) -)\n  (put 'mul '(number number) *)\n  (put 'div '(number number) /)\n  (put 'neg '(number) -)\n  (put 'greatest-common-divisor '(number number) gcd)\n  (put 'equ? '(number number) =)\n  (put '=zero? '(number) zero?))\n\n; Rationals:\n\n(let ()\n  (define (make-rat n d) (cons n d))\n  (define (numer x) (car x))\n  (define (denom x) (cdr x))\n\n  (define (add-rat x y)\n    (make-rat (add (mul (numer x) (denom y))\n                   (mul (numer y) (denom x)))\n              (mul (denom x) (denom y))))\n  (define (sub-rat x y)\n    (make-rat (sub (mul (numer x) (denom y))\n                   (mul (numer y) (denom x)))\n              (mul (denom x) (denom y))))\n  (define (mul-rat x y)\n    (make-rat (mul (numer x) (numer y))\n              (mul (denom x) (denom y))))\n  (define (div-rat x y)\n    (make-rat (mul (numer x) (denom y))\n              (mul (denom x) (numer y))))\n  (define (=zero?-rat x)\n    (zero? (numer x)))\n\n  (define (tag x) (attach-tag 'rational x))\n  (put 'numer '(rational) numer)\n  (put 'denom '(rational) denom)\n  (put '=zero? '(rational) =zero?-rat)\n  (put 'add '(rational rational) (lambda (x y) (tag (add-rat x y))))\n  (put 'sub '(rational rational) (lambda (x y) (tag (sub-rat x y))))\n  (put 'mul '(rational rational) (lambda (x y) (tag (mul-rat x y))))\n  (put 'div '(rational rational) (lambda (x y) (tag (div-rat x y))))\n  (put 'equ? '(rational rational) equal?)\n  (put 'make 'rational (lambda (n d) (tag (make-rat n d)))))\n\n(define (make-rational n d) ((get 'make 'rational) n d))\n(define (numer r) (apply-generic 'numer r))\n(define (denom r) (apply-generic 'denom r))\n\n; A very clever procedure for normalizing terms. It is not nested under\n; polynomials so it can be tested separately.\n\n; The polynomial package:\n\n(define (make-term order coeff) (list order coeff))\n(define (order term) (car term))\n(define (coeff term) (cadr term))\n\n(let ()\n  (define (make-poly variable term-list)\n    (cons variable term-list))\n  (define (variable p) (car p))\n  (define (term-list p) (cdr p))\n\n  (define (same-variable? v1 v2)\n    (and (variable? v1) (variable? v2) (eq? v1 v2)))\n  (define (before? v1 v2)\n    (string<? (symbol->string v1) (symbol->string v2)))\n  (define (variable? x) (symbol? x))\n\n  (define (the-empty-termlist) '())\n  (define (empty-termlist? term-list) (null? term-list))\n  (define (first-term term-list) (car term-list))\n  (define (rest-terms term-list) (cdr term-list))\n  (define (adjoin-term term term-list)\n    (cond ((=zero? (coeff term)) term-list)\n          ((null? term-list) (list term))\n          ((> (order (car term-list)) (order term))\n           (cons (car term-list) (adjoin-term term (cdr term-list))))\n          ((= (order (car term-list)) (order term))\n           (adjoin-term (make-term (order term)\n                                   (add (coeff term) (coeff (car term-list))))\n                        (cdr term-list)))\n          (else (cons term term-list))))\n\n  (define (const var number)\n    (make-poly var (adjoin-term (make-term 0 number) (the-empty-termlist))))\n  (define (poly-const var polynomial)\n    (make-term var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n\n  (define (map-terms proc L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((first (first-term L))\n              (rest (rest-terms L)))\n          (adjoin-term (make-term (order first) (proc (coeff first)))\n                       (map-terms proc rest)))))\n  (define (neg-terms L)\n    (map-terms neg L))\n  (define (add-terms L1 L2)\n    (cond ((empty-termlist? L1) L2)\n          ((empty-termlist? L2) L1)\n          (else\n            (let ((t1 (first-term L1)) (t2 (first-term L2)))\n              (cond ((> (order t1) (order t2))\n                     (adjoin-term t1 (add-terms (rest-terms L1) L2)))\n                    ((< (order t1) (order t2))\n                     (adjoin-term t2 (add-terms L1 (rest-terms L2))))\n                    (else\n                      (adjoin-term\n                        (make-term (order t1) (add (coeff t1) (coeff t2)))\n                        (add-terms (rest-terms L1) (rest-terms L2)))))))))\n  (define (sub-terms L1 L2)\n    (add-terms L1 (neg-terms L2)))\n  (define (mul-terms L1 L2)\n    (if (empty-termlist? L1)\n        (the-empty-termlist)\n        (add-terms (mul-term-by-all-terms (first-term L1) L2)\n                   (mul-terms (rest-terms L1) L2))))\n  (define (mul-term-by-all-terms t1 L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((t2 (first-term L)))\n          (adjoin-term (make-term (+ (order t1) (order t2)) (mul (coeff t1) (coeff t2)))\n                       (mul-term-by-all-terms t1 (rest-terms L))))))\n  (define (div-terms L1 L2)\n    (if (empty-termlist? L1)\n        (list (the-empty-termlist) (the-empty-termlist))\n        (let ((t1 (first-term L1))\n              (t2 (first-term L2)))\n          (if (> (order t2) (order t1))\n              (list (the-empty-termlist) L1)\n              (let ((new-c (div (coeff t1) (coeff t2)))\n                    (new-o (- (order t1) (order t2))))\n                (let ((rest-of-result\n                        (div-terms\n                          (add-terms L1\n                                     (neg-terms (mul-term-by-all-terms (make-term new-o new-c)\n                                                                       L2)))\n                          L2)))\n                  (cons (adjoin-term (make-term new-o new-c)\n                                     (car rest-of-result))\n                        (cdr rest-of-result))))))))\n  (define (pseudoremainder-terms a b)\n    (let ((factor (expt (coeff (car b))\n                       (+ 1\n                          (order (car a))\n                          (- (order (car b)))))))\n      (cadr (div-terms (mul-term-by-all-terms (make-term 0 factor) a) b))))\n  (define (gcd-terms a b)\n    (if (empty-termlist? b)\n        (let ((divisor (apply gcd (map coeff a))))\n          (map-terms (lambda (c) (/ c divisor)) a))\n        (gcd-terms b (pseudoremainder-terms a b))))\n\n  (define (neg-poly p)\n    (make-poly (variable p)\n               (neg-terms (term-list p))))\n  (define (add-poly p1 p2)\n    (define (const var polynomial)\n      (make-poly var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n    (let ((v1 (variable p1))\n          (v2 (variable p2))\n          (t1 (term-list p1))\n          (t2 (term-list p2)))\n      (cond ((same-variable? v1 v2) (make-poly v1 (add-terms t1 t2)))\n            ((before? v1 v2) (add-poly p1 (const v1 p2)))\n            (else (add-poly (const v2 p1) p2)))))\n  (define (mul-poly p1 p2)\n    (define (const var polynomial)\n      (make-poly var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n    (let ((v1 (variable p1))\n          (v2 (variable p2))\n          (t1 (term-list p1))\n          (t2 (term-list p2)))\n      (cond ((same-variable? v1 v2) (make-poly v1 (mul-terms t1 t2)))\n            ((before? v1 v2) (mul-poly p1 (const v1 p2)))\n            (else (mul-poly (const v2 p1) p2)))))\n  (define (sub-poly p1 p2)\n    (define (const var polynomial)\n      (make-poly var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n    (let ((v1 (variable p1))\n          (v2 (variable p2))\n          (t1 (term-list p1))\n          (t2 (term-list p2)))\n      (cond ((same-variable? v1 v2) (make-poly v1 (sub-terms t1 t2)))\n            ((before? v1 v2) (sub-poly p1 (const v1 p2)))\n            (else (sub-poly (const v2 p1) p2)))))\n  (define (div-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n        (map (lambda (term-list) (make-poly (variable p1) term-list))\n             (div-terms (term-list p1)\n                        (term-list p2)))\n        (error \"Polynomials not in same var - DIV-POLY\" (list p1 p2))))\n  (define (gcd-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n        (make-poly (variable p1) (gcd-terms (term-list p1) (term-list p2)))\n        (error \"Polynomials not in same var - GCD-POLY\" (list p1 p2))))\n\n  (define (tag p) (attach-tag 'polynomial p))\n  (put 'add '(polynomial polynomial) (lambda (p1 p2) (tag (add-poly p1 p2))))\n  (put 'sub '(polynomial polynomial) (lambda (p1 p2) (tag (sub-poly p1 p2))))\n  (put 'mul '(polynomial polynomial) (lambda (p1 p2) (tag (mul-poly p1 p2))))\n  (put 'div '(polynomial polynomial) (lambda (p1 p2) (map tag (div-poly p1 p2))))\n  (put '=zero? '(polynomial) (lambda (p) (empty-termlist? (term-list p))))\n  (put 'greatest-common-divisor '(polynomial polynomial) (lambda (p1 p2) (tag (gcd-poly p1 p2))))\n  (put 'neg '(polynomial) (lambda (p) (tag (neg-poly p))))\n  (put 'add '(number polynomial) (lambda (n p) (tag (add-poly (const (variable p) n) p))))\n  (put 'mul '(number polynomial) (lambda (n p) (tag (mul-poly (const (variable p) n) p))))\n  (put 'add '(polynomial number) (lambda (p n) (tag (add-poly p (const (variable p) n)))))\n  (put 'mul '(polynomial number) (lambda (p n) (tag (mul-poly p (const (variable p) n)))))\n\n  (put 'make 'polynomial (lambda (var terms) (tag (make-poly var terms)))))\n\n(define (make-polynomial var terms)\n  ((get 'make 'polynomial) var terms))\n\n; apply-generic without any coercion:\n\n(define (apply-generic op . args)\n  (let ((type-tags (map type-tag args)))\n    (let ((proc (get op type-tags)))\n      (if proc\n          (apply proc (map contents args))\n          (error \"No method for these types - APPLY-GENERIC\" (list op type-tags))))))\n"
  },
  {
    "path": "scheme/sicp/02/97.scm",
    "content": "; SICP exercise 2.97\n;\n; a. Implement this algorithm as a procedure reduce-terms that takes two term\n; lists n and d as arguments and returns a list nn, dd, which are n and d\n; reduced to lowest terms via the algorithm given above. Also write a\n; procedure reduce-poly, analogous to add-poly, that checks to see if the two\n; polys have the same variable. If so, reduce-poly strips off the variable and\n; passes the problem to reduce-terms, then reattaches the variable to the two\n; term lists supplied by reduce-terms.\n;\n; b. Define a procedure analogous to reduce-terms that does what the original\n; make-rat did for integers:\n;\n;   (define (reduce-integers n d)\n;     (let ((g (gcd n d)))\n;       (list (/ n g) (/ d g))))\n;\n; and define reduce as a generic operation that calls apply-generic to\n; dispatch either reduce-poly (for polynomial arguments) or reduce-integers\n; (for scheme-number arguments). You can now easily make the\n; rational-arithmetic package reduce fractions to lowest terms by having\n; make-rat call reduce before combining the given numberator and denominator\n; to form a rational number. The system now handles rational expressions in\n; either integers or polynomials.\n;\n; To test your program, try the example at the beginning of this extended\n; exercise:\n;\n;   (define p1 (make-polynomial 'x '((1 1) (0 1))))\n;   (define p2 (make-polynomial 'x '((3 1) (0 -1)))\n;   (define p3 (make-polynomial 'x '((1 1))))\n;   (define p4 (make-polynomial 'x '((2 1) (0 -1))))\n;\n;   (define rf1 (make-rational p1 p2))\n;   (define rf2 (make-rational p3 p4))\n;\n;   (add rf1 rf2)\n;\n; See if you get the correct answer, correctly reduced to lowest terms.\n\n; Our type system:\n\n(define (attach-tag type-tag contents)\n  (if (eq? type-tag 'number)\n      contents\n      (cons type-tag contents)))\n\n(define (type-tag datum)\n  (cond ((number? datum) 'number)\n        ((pair? datum) (car datum))\n        (else (error \"Bad tagged datum - TYPE-TAG\" datum))))\n\n(define (contents datum)\n  (cond ((number? datum) datum)\n        ((pair? datum) (cdr datum))\n        (else (error \"Bad tagged datum - CONTENTS\" datum))))\n\n(define table (make-hash))\n(define (put op type item) (hash-set! table (list op type) item))\n(define (get op type) (hash-ref table (list op type) #f))\n\n; Now the generic arithmemtic procedures.\n\n(define (add x y) (apply-generic 'add x y))\n(define (sub x y) (apply-generic 'sub x y))\n(define (mul x y) (apply-generic 'mul x y))\n(define (div x y) (apply-generic 'div x y))\n(define (reduce x y) (apply-generic 'reduce x y))\n(define (neg x) (apply-generic 'neg x))\n(define (equ? x y) (apply-generic 'equ? x y))\n(define (=zero? x) (apply-generic '=zero? x))\n(define (greatest-common-divisor x y) (apply-generic 'greatest-common-divisor x y))\n(define (square x) (mul x x))\n\n; Numbers\n\n(let ()\n  (define (reduce-integers n d)\n    (let ((g (gcd n d)))\n      (list (/ n g) (/ d g))))\n\n  (put 'add '(number number) +)\n  (put 'sub '(number number) -)\n  (put 'reduce '(number number) reduce-integers)\n  (put 'mul '(number number) *)\n  (put 'div '(number number) /)\n  (put 'neg '(number) -)\n  (put 'greatest-common-divisor '(number number) gcd)\n  (put 'equ? '(number number) =)\n  (put '=zero? '(number) zero?))\n\n; Rationals:\n\n(let ()\n  (define (make-rat n d)\n    (let ((terms (reduce n d)))\n      (cons (car terms) (cadr terms))))\n  (define (numer x) (car x))\n  (define (denom x) (cdr x))\n\n  (define (add-rat x y)\n    (make-rat (add (mul (numer x) (denom y))\n                   (mul (numer y) (denom x)))\n              (mul (denom x) (denom y))))\n  (define (sub-rat x y)\n    (make-rat (sub (mul (numer x) (denom y))\n                   (mul (numer y) (denom x)))\n              (mul (denom x) (denom y))))\n  (define (mul-rat x y)\n    (make-rat (mul (numer x) (numer y))\n              (mul (denom x) (denom y))))\n  (define (div-rat x y)\n    (make-rat (mul (numer x) (denom y))\n              (mul (denom x) (numer y))))\n  (define (=zero?-rat x)\n    (zero? (numer x)))\n\n  (define (tag x) (attach-tag 'rational x))\n  (put 'numer '(rational) numer)\n  (put 'denom '(rational) denom)\n  (put '=zero? '(rational) =zero?-rat)\n  (put 'add '(rational rational) (lambda (x y) (tag (add-rat x y))))\n  (put 'sub '(rational rational) (lambda (x y) (tag (sub-rat x y))))\n  (put 'mul '(rational rational) (lambda (x y) (tag (mul-rat x y))))\n  (put 'div '(rational rational) (lambda (x y) (tag (div-rat x y))))\n  (put 'equ? '(rational rational) equal?)\n  (put 'make 'rational (lambda (n d) (tag (make-rat n d)))))\n\n(define (make-rational n d) ((get 'make 'rational) n d))\n(define (numer r) (apply-generic 'numer r))\n(define (denom r) (apply-generic 'denom r))\n\n; A very clever procedure for normalizing terms. It is not nested under\n; polynomials so it can be tested separately.\n\n; The polynomial package:\n\n(define (make-term order coeff) (list order coeff))\n(define (order term) (car term))\n(define (coeff term) (cadr term))\n\n(let ()\n  (define (make-poly variable term-list)\n    (cons variable term-list))\n  (define (variable p) (car p))\n  (define (term-list p) (cdr p))\n\n  (define (same-variable? v1 v2)\n    (and (variable? v1) (variable? v2) (eq? v1 v2)))\n  (define (before? v1 v2)\n    (string<? (symbol->string v1) (symbol->string v2)))\n  (define (variable? x) (symbol? x))\n\n  (define (the-empty-termlist) '())\n  (define (empty-termlist? term-list) (null? term-list))\n  (define (first-term term-list) (car term-list))\n  (define (rest-terms term-list) (cdr term-list))\n  (define (adjoin-term term term-list)\n    (cond ((=zero? (coeff term)) term-list)\n          ((null? term-list) (list term))\n          ((> (order (car term-list)) (order term))\n           (cons (car term-list) (adjoin-term term (cdr term-list))))\n          ((= (order (car term-list)) (order term))\n           (adjoin-term (make-term (order term)\n                                   (add (coeff term) (coeff (car term-list))))\n                        (cdr term-list)))\n          (else (cons term term-list))))\n\n  (define (const var number)\n    (make-poly var (adjoin-term (make-term 0 number) (the-empty-termlist))))\n  (define (poly-const var polynomial)\n    (make-term var (adjoin-term (make-term 0 (tag polynomial)) (the-empty-termlist))))\n\n  (define (map-terms proc L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((first (first-term L))\n              (rest (rest-terms L)))\n          (adjoin-term (make-term (order first) (proc (coeff first)))\n                       (map-terms proc rest)))))\n  (define (neg-terms L)\n    (map-terms neg L))\n  (define (add-terms L1 L2)\n    (cond ((empty-termlist? L1) L2)\n          ((empty-termlist? L2) L1)\n          (else\n            (let ((t1 (first-term L1)) (t2 (first-term L2)))\n              (cond ((> (order t1) (order t2))\n                     (adjoin-term t1 (add-terms (rest-terms L1) L2)))\n                    ((< (order t1) (order t2))\n                     (adjoin-term t2 (add-terms L1 (rest-terms L2))))\n                    (else\n                      (adjoin-term\n                        (make-term (order t1) (add (coeff t1) (coeff t2)))\n                        (add-terms (rest-terms L1) (rest-terms L2)))))))))\n  (define (sub-terms L1 L2)\n    (add-terms L1 (neg-terms L2)))\n  (define (mul-terms L1 L2)\n    (if (empty-termlist? L1)\n        (the-empty-termlist)\n        (add-terms (mul-term-by-all-terms (first-term L1) L2)\n                   (mul-terms (rest-terms L1) L2))))\n  (define (mul-term-by-all-terms t1 L)\n    (if (empty-termlist? L)\n        (the-empty-termlist)\n        (let ((t2 (first-term L)))\n          (adjoin-term (make-term (+ (order t1) (order t2)) (mul (coeff t1) (coeff t2)))\n                       (mul-term-by-all-terms t1 (rest-terms L))))))\n  (define (div-terms L1 L2)\n    (if (empty-termlist? L1)\n        (list (the-empty-termlist) (the-empty-termlist))\n        (let ((t1 (first-term L1))\n              (t2 (first-term L2)))\n          (if (> (order t2) (order t1))\n              (list (the-empty-termlist) L1)\n              (let ((new-c (div (coeff t1) (coeff t2)))\n                    (new-o (- (order t1) (order t2))))\n                (let ((rest-of-result\n                        (div-terms\n                          (add-terms L1\n                                     (neg-terms (mul-term-by-all-terms (make-term new-o new-c)\n                                                                       L2)))\n                          L2)))\n                  (cons (adjoin-term (make-term new-o new-c)\n                                     (car rest-of-result))\n                        (cdr rest-of-result))))))))\n  (define (pseudoremainder-terms a b)\n    (let ((factor (expt (coeff (car b))\n                       (+ 1\n                          (order (car a))\n                          (- (order (car b)))))))\n      (cadr (div-terms (mul-term-by-all-terms (make-term 0 factor) a) b))))\n  (define (gcd-terms a b)\n    (if (empty-termlist? b)\n        (let ((divisor (apply gcd (map coeff a))))\n          (map-terms (lambda (c) (/ c divisor)) a))\n        (gcd-terms b (pseudoremainder-terms a b))))\n  (define (reduce-terms n d)\n    (let ((g (gcd-terms n d)))\n      (list (car (div-terms n g))\n            (car (div-terms d g)))))\n\n  (define (neg-poly p)\n    (make-poly (variable p)\n               (neg-terms (term-list p))))\n  (define (reduce-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (map (lambda (terms) (make-poly (variable p1) terms))\n           (reduce-terms (term-list p1) (term-list p2)))\n      (error \"Polynomials not in same var - REDUCE-POLY\" (list p1 p2))))\n  (define (add-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (make-poly (variable p1)\n                 (add-terms (term-list p1)\n                            (term-list p2)))\n      (error \"Polynomials not in same var - ADD-POLY\" (list p1 p2))))\n  (define (mul-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (make-poly (variable p1)\n                 (mul-terms (term-list p1)\n                            (term-list p2)))\n      (error \"Polynomials not in same var - MUL-POLY\" (list p1 p2))))\n  (define (sub-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n      (make-poly (variable p1)\n                 (sub-terms (term-list p1)\n                            (term-list p2)))\n      (error \"Polynomials not in same var - SUB-POLY\" (list p1 p2))))\n  (define (div-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n        (map (lambda (term-list) (make-poly (variable p1) term-list))\n             (div-terms (term-list p1)\n                        (term-list p2)))\n        (error \"Polynomials not in same var - DIV-POLY\" (list p1 p2))))\n  (define (gcd-poly p1 p2)\n    (if (same-variable? (variable p1) (variable p2))\n        (make-poly (variable p1) (gcd-terms (term-list p1) (term-list p2)))\n        (error \"Polynomials not in same var - GCD-POLY\" (list p1 p2))))\n\n  (define (tag p) (attach-tag 'polynomial p))\n  (put 'add '(polynomial polynomial) (lambda (p1 p2) (tag (add-poly p1 p2))))\n  (put 'sub '(polynomial polynomial) (lambda (p1 p2) (tag (sub-poly p1 p2))))\n  (put 'mul '(polynomial polynomial) (lambda (p1 p2) (tag (mul-poly p1 p2))))\n  (put 'div '(polynomial polynomial) (lambda (p1 p2) (map tag (div-poly p1 p2))))\n  (put 'reduce '(polynomial polynomial) (lambda (p1 p2) (map tag (reduce-poly p1 p2))))\n  (put '=zero? '(polynomial) (lambda (p) (empty-termlist? (term-list p))))\n  (put 'greatest-common-divisor '(polynomial polynomial) (lambda (p1 p2) (tag (gcd-poly p1 p2))))\n  (put 'neg '(polynomial) (lambda (p) (tag (neg-poly p))))\n  (put 'add '(number polynomial) (lambda (n p) (tag (add-poly (const (variable p) n) p))))\n  (put 'mul '(number polynomial) (lambda (n p) (tag (mul-poly (const (variable p) n) p))))\n  (put 'add '(polynomial number) (lambda (p n) (tag (add-poly p (const (variable p) n)))))\n  (put 'mul '(polynomial number) (lambda (p n) (tag (mul-poly p (const (variable p) n)))))\n\n  (put 'make 'polynomial (lambda (var terms) (tag (make-poly var terms)))))\n\n(define (make-polynomial var terms)\n  ((get 'make 'polynomial) var terms))\n\n; apply-generic without any coercion:\n\n(define (apply-generic op . args)\n  (let ((type-tags (map type-tag args)))\n    (let ((proc (get op type-tags)))\n      (if proc\n          (apply proc (map contents args))\n          (error \"No method for these types - APPLY-GENERIC\" (list op type-tags))))))\n"
  },
  {
    "path": "scheme/sicp/02/showcase/picturelang/main.scm",
    "content": "(require racket/gui/base)\n(require racket/draw)\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; Vectors\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n(define (make-vect x y)\n  (list x y))\n\n(define (xcor-vect vect)\n  (car vect))\n\n(define (ycor-vect vect)\n  (cadr vect))\n\n(define (add-vect v1 v2)\n  (make-vect (+ (xcor-vect v1)\n                (xcor-vect v2))\n             (+ (ycor-vect v1)\n                (ycor-vect v2))))\n\n(define (sub-vect v1 v2)\n  (make-vect (- (xcor-vect v1)\n                (xcor-vect v2))\n             (- (ycor-vect v1)\n                (ycor-vect v2))))\n\n(define (scale-vect s v)\n  (make-vect (* s (xcor-vect v))\n             (* s (ycor-vect v))))\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; Segments\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n(define (make-segment start end)\n  (list start end))\n\n(define (start-segment segment)\n  (car segment))\n\n(define (end-segment segment)\n  (cadr segment))\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; Frames\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n(define (make-frame origin edge1 edge2)\n  (list origin edge1 edge2))\n\n(define (origin-frame frame)\n  (car frame))\n\n(define (edge1-frame frame)\n  (cadr frame))\n\n(define (edge2-frame frame)\n  (caddr frame))\n\n(define (frame-coord-map frame)\n  (lambda (v)\n    (add-vect\n      (origin-frame frame)\n      (add-vect (scale-vect (xcor-vect v)\n                            (edge1-frame frame))\n                (scale-vect (ycor-vect v)\n                            (edge2-frame frame))))))\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; Transforming painters\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n(define (transform-painter painter origin corner1 corner2)\n  (lambda (frame)\n    (let ((m (frame-coord-map frame)))\n      (let ((new-origin (m origin)))\n        (painter\n          (make-frame new-origin\n                      (sub-vect (m corner1) new-origin)\n                      (sub-vect (m corner2) new-origin)))))))\n\n(define (identity painter)\n  painter)\n\n(define (flip-vert painter)\n  (transform-painter painter\n                     (make-vect 0.0 1.0)\n                     (make-vect 1.0 1.0)\n                     (make-vect 0.0 0.0)))\n\n(define (flip-horiz painter)\n  (transform-painter painter\n                     (make-vect 1.0 0.0)\n                     (make-vect 0.0 0.0)\n                     (make-vect 1.0 1.0)))\n\n(define (rotate90 painter)\n  (transform-painter painter\n                     (make-vect 1.0 0.0)\n                     (make-vect 1.0 1.0)\n                     (make-vect 0.0 0.0)))\n\n(define (rotate180 painter)\n  (transform-painter painter\n                     (make-vect 1.0 1.0)\n                     (make-vect 0.0 1.0)\n                     (make-vect 1.0 0.0)))\n\n(define (rotate270 painter)\n  (transform-painter painter\n                     (make-vect 0.0 1.0)\n                     (make-vect 0.0 0.0)\n                     (make-vect 1.0 1.0)))\n\n(define (squash-inwards painter)\n  (transform-painter painter\n                     (make-vect 0.0 0.0)\n                     (make-vect 0.65 0.35)\n                     (make-vect 0.35 0.65)))\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; Composing painters\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n(define (beside painter1 painter2)\n  (let ((split-point (make-vect 0.5 0.0)))\n    (let ((paint-left\n            (transform-painter painter1\n                               (make-vect 0.0 0.0)\n                               split-point\n                               (make-vect 0.0 1.0)))\n          (paint-right\n            (transform-painter painter2\n                               split-point\n                               (make-vect 1.0 0.0)\n                               (make-vect 0.5 1.0))))\n\n      (lambda (frame)\n        (paint-left frame)\n        (paint-right frame)))))\n\n(define (below painter1 painter2)\n  (let ((split-point (make-vect 0.0 0.5)))\n    (let ((paint-bottom\n            (transform-painter painter1\n                               (make-vect 0.0 0.0)\n                               (make-vect 1.0 0.0)\n                               split-point))\n          (paint-top\n            (transform-painter painter2\n                               split-point\n                               (make-vect 1.0 0.5)\n                               (make-vect 0.0 1.0))))\n      (lambda (frame)\n        (paint-bottom frame)\n        (paint-top frame)))))\n\n(define (square-of-four tl tr bl br)\n  (lambda (painter)\n    (let ((top (beside (tl painter) (tr painter)))\n          (bottom (beside (bl painter) (br painter))))\n      (below bottom top))))\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; Line-drawing painters\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n(define (segments->painter segment-list)\n  (lambda (frame)\n    (for-each\n      (lambda (segment)\n        (draw-line\n          ((frame-coord-map frame) (start-segment segment))\n          ((frame-coord-map frame) (end-segment segment))))\n      segment-list)))\n\n(define outline\n  (segments->painter\n    (list (make-segment (make-vect 0.0 0.0) (make-vect 0.0 1.0))\n          (make-segment (make-vect 0.0 1.0) (make-vect 1.0 1.0))\n          (make-segment (make-vect 1.0 1.0) (make-vect 1.0 0.0))\n          (make-segment (make-vect 1.0 0.0) (make-vect 0.0 0.0)))))\n\n(define diamond\n  (segments->painter\n    (list (make-segment (make-vect 0.5 0.0) (make-vect 1.0 0.5))\n          (make-segment (make-vect 1.0 0.5) (make-vect 0.5 1.0))\n          (make-segment (make-vect 0.5 1.0) (make-vect 0.0 0.5))\n          (make-segment (make-vect 0.0 0.5) (make-vect 0.5 0.0))\n          )))\n\n(define cross\n  (segments->painter\n    (list (make-segment (make-vect 0.0 0.0) (make-vect 1.0 1.0))\n          (make-segment (make-vect 1.0 0.0) (make-vect 0.0 1.0)))))\n\n(define wave\n  (segments->painter\n    (list (make-segment (make-vect 0.00 0.70) (make-vect 0.16 0.57))\n          (make-segment (make-vect 0.16 0.57) (make-vect 0.30 0.67))\n          (make-segment (make-vect 0.30 0.67) (make-vect 0.37 0.67))\n          (make-segment (make-vect 0.37 0.67) (make-vect 0.40 0.64))\n          (make-segment (make-vect 0.40 0.64) (make-vect 0.42 0.68))\n          (make-segment (make-vect 0.42 0.68) (make-vect 0.32 0.80))\n          (make-segment (make-vect 0.32 0.80) (make-vect 0.33 0.85))\n          (make-segment (make-vect 0.33 0.85) (make-vect 0.36 1.00))\n\n          (make-segment (make-vect 0.60 1.00) (make-vect 0.62 0.84))\n          (make-segment (make-vect 0.62 0.84) (make-vect 0.62 0.78))\n          (make-segment (make-vect 0.62 0.78) (make-vect 0.53 0.70))\n          (make-segment (make-vect 0.53 0.70) (make-vect 0.57 0.64))\n          (make-segment (make-vect 0.57 0.64) (make-vect 0.63 0.67))\n          (make-segment (make-vect 0.63 0.67) (make-vect 0.68 0.66))\n          (make-segment (make-vect 0.68 0.66) (make-vect 0.87 0.51))\n          (make-segment (make-vect 0.87 0.51) (make-vect 1.00 0.40))\n\n          (make-segment (make-vect 1.00 0.30) (make-vect 0.73 0.52))\n          (make-segment (make-vect 0.73 0.52) (make-vect 0.61 0.53))\n          (make-segment (make-vect 0.61 0.53) (make-vect 0.67 0.25))\n          (make-segment (make-vect 0.67 0.25) (make-vect 0.71 0.00))\n\n          (make-segment (make-vect 0.60 0.00) (make-vect 0.56 0.23))\n          (make-segment (make-vect 0.56 0.23) (make-vect 0.51 0.28))\n          (make-segment (make-vect 0.51 0.28) (make-vect 0.46 0.28))\n          (make-segment (make-vect 0.46 0.28) (make-vect 0.40 0.12))\n          (make-segment (make-vect 0.40 0.12) (make-vect 0.36 0.00))\n\n          (make-segment (make-vect 0.23 0.00) (make-vect 0.34 0.30))\n          (make-segment (make-vect 0.34 0.30) (make-vect 0.36 0.52))\n          (make-segment (make-vect 0.36 0.52) (make-vect 0.32 0.55))\n          (make-segment (make-vect 0.32 0.55) (make-vect 0.28 0.55))\n          (make-segment (make-vect 0.28 0.55) (make-vect 0.17 0.45))\n          (make-segment (make-vect 0.17 0.45) (make-vect 0.00 0.60)))))\n\n(define smiling-wave\n  (segments->painter\n    (list (make-segment (make-vect 0.00 0.70) (make-vect 0.16 0.57))\n          (make-segment (make-vect 0.16 0.57) (make-vect 0.30 0.67))\n          (make-segment (make-vect 0.30 0.67) (make-vect 0.37 0.67))\n          (make-segment (make-vect 0.37 0.67) (make-vect 0.40 0.64))\n          (make-segment (make-vect 0.40 0.64) (make-vect 0.42 0.68))\n          (make-segment (make-vect 0.42 0.68) (make-vect 0.32 0.80))\n          (make-segment (make-vect 0.32 0.80) (make-vect 0.33 0.85))\n          (make-segment (make-vect 0.33 0.85) (make-vect 0.36 1.00))\n\n          (make-segment (make-vect 0.60 1.00) (make-vect 0.62 0.84))\n          (make-segment (make-vect 0.62 0.84) (make-vect 0.62 0.78))\n          (make-segment (make-vect 0.62 0.78) (make-vect 0.53 0.70))\n          (make-segment (make-vect 0.53 0.70) (make-vect 0.57 0.64))\n          (make-segment (make-vect 0.57 0.64) (make-vect 0.63 0.67))\n          (make-segment (make-vect 0.63 0.67) (make-vect 0.68 0.66))\n          (make-segment (make-vect 0.68 0.66) (make-vect 0.87 0.51))\n          (make-segment (make-vect 0.87 0.51) (make-vect 1.00 0.40))\n\n          (make-segment (make-vect 1.00 0.30) (make-vect 0.73 0.52))\n          (make-segment (make-vect 0.73 0.52) (make-vect 0.61 0.53))\n          (make-segment (make-vect 0.61 0.53) (make-vect 0.67 0.25))\n          (make-segment (make-vect 0.67 0.25) (make-vect 0.71 0.00))\n\n          (make-segment (make-vect 0.60 0.00) (make-vect 0.56 0.23))\n          (make-segment (make-vect 0.56 0.23) (make-vect 0.51 0.28))\n          (make-segment (make-vect 0.51 0.28) (make-vect 0.46 0.28))\n          (make-segment (make-vect 0.46 0.28) (make-vect 0.40 0.12))\n          (make-segment (make-vect 0.40 0.12) (make-vect 0.36 0.00))\n\n          (make-segment (make-vect 0.23 0.00) (make-vect 0.34 0.30))\n          (make-segment (make-vect 0.34 0.30) (make-vect 0.36 0.52))\n          (make-segment (make-vect 0.36 0.52) (make-vect 0.32 0.55))\n          (make-segment (make-vect 0.32 0.55) (make-vect 0.28 0.55))\n          (make-segment (make-vect 0.28 0.55) (make-vect 0.17 0.45))\n          (make-segment (make-vect 0.17 0.45) (make-vect 0.00 0.60))\n\n          (make-segment (make-vect 0.41 0.78) (make-vect 0.54 0.78))\n          (make-segment (make-vect 0.54 0.78) (make-vect 0.52 0.76))\n          (make-segment (make-vect 0.52 0.76) (make-vect 0.43 0.76))\n          (make-segment (make-vect 0.43 0.76) (make-vect 0.41 0.78)))))\n\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; Splitting painters\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n(define (right-split painter n)\n  (if (= n 0)\n      painter\n      (let ((smaller (right-split painter (- n 1))))\n        (beside painter (below smaller smaller)))))\n\n(define (up-split painter n)\n  (if (= n 0)\n      painter\n      (let ((smaller (up-split painter (- n 1))))\n        (below painter (beside smaller smaller)))))\n\n(define (corner-split painter n)\n  (if (= n 0)\n      painter\n      (let ((up (up-split painter (- n 1)))\n            (right (right-split painter (- n 1))))\n        (let ((top-left (beside up up))\n              (bottom-right (below right right))\n              (corner (corner-split painter (- n 1))))\n          (beside (below painter top-left)\n                  (below bottom-right corner))))))\n\n(define (simpler-corner-split painter n)\n  (if (= n 0)\n      painter\n      (let ((up (up-split painter (- n 1)))\n            (right (right-split painter (- n 1))))\n        (beside (below painter up)\n                (below right (corner-split painter (- n 1)))))))\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; Square of four painters\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n(define (square-limit painter n)\n  (let ((quarter (corner-split painter n)))\n    (let ((half (beside (flip-horiz quarter) quarter)))\n      (below (flip-vert half) half))))\n\n(define flipped-pairs\n  (square-of-four identity flip-vert identity flip-vert))\n\n(define (simpler-square-limit painter n)\n  (let ((combine4 (square-of-four flip-horiz identity\n                                  rotate180 flip-vert)))\n    (combine4 (simpler-corner-split painter n))))\n\n(define (inverted-square-limit painter n)\n  (let ((combine4 (square-of-four flip-vert rotate180\n                                  identity flip-horiz)))\n    (combine4 (corner-split painter n))))\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; Canvas-drawing functions\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n(define (draw-line a b)\n  (let ((original-pen (send dc get-pen)))\n    (send dc set-pen \"black\" 1 'solid)\n\n    (send dc draw-line (xcor-vect a) (ycor-vect a)\n                       (xcor-vect b) (ycor-vect b))\n\n    (send dc set-pen original-pen)))\n\n(define rogers-size 150)\n(define rogers-bitmap (make-object bitmap% rogers-size rogers-size))\n(send rogers-bitmap load-file \"rogers.jpg\")\n\n(define (rogers frame)\n  (let ((original-transformation (send dc get-transformation))\n        (origin (origin-frame frame))\n        (x-axis (edge1-frame frame))\n        (y-axis (edge2-frame frame))\n        (factor (/ 1.0 (- rogers-size 2))))\n    (send dc transform (vector (xcor-vect x-axis)\n                               (xcor-vect y-axis)\n                               (ycor-vect x-axis)\n                               (ycor-vect y-axis)\n                               (xcor-vect origin)\n                               (ycor-vect origin)))\n    (send dc scale factor factor)\n\n    (send dc draw-bitmap rogers-bitmap 0 0)\n\n    (send dc set-transformation original-transformation)))\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; Drawing pictures list\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n(define pictures-in-a-row 6)\n(define pictures-in-a-column 4)\n(define picture-size 190)\n(define picture-margin 20)\n\n(define (draw-pictures-list pictures pos)\n  (define (draw-text text x y)\n    (let ((original-transformation (send dc get-transformation)))\n      (send dc scale 1 -1)\n      (send dc translate 0 (- 0 picture-size picture-margin))\n\n      (send dc draw-text text x (+ (- y) 4))\n\n      (send dc set-transformation original-transformation)))\n  (if (null? pictures)\n      #t\n      (let ((x (+ (* (+ picture-margin picture-size)\n                     (remainder pos pictures-in-a-row))\n                  picture-margin))\n            (y (+ (* (+ picture-margin picture-size)\n                     (- pictures-in-a-column (quotient pos pictures-in-a-row) 1))\n                  picture-margin))\n            (label (car pictures))\n            (picture (cadr pictures))\n            (remaining (cddr pictures)))\n        (draw-text label x y)\n        (picture (make-frame (make-vect x y)\n                             (make-vect picture-size 0.0)\n                             (make-vect 0.0 picture-size)))\n        (draw-pictures-list remaining (+ pos 1)))))\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; Setting up a canvas\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n(define width\n  (+ (* pictures-in-a-row picture-size)\n     (* pictures-in-a-row picture-margin)\n     picture-margin))\n\n(define height\n  (+ (* pictures-in-a-column picture-size)\n     (* pictures-in-a-column picture-margin)\n     picture-margin))\n\n(define target (make-bitmap width height))\n(define dc (new bitmap-dc% [bitmap target]))\n\n(send dc translate 0 height)\n(send dc scale 1 -1)\n(send dc set-smoothing 'smoothed)\n(send dc set-font (make-object font% 12 'system 'normal 'bold))\n(send dc set-text-foreground \"dim gray\")\n\n(define frame (new frame%\n                   [label \"Example\"]\n                   [width width]\n                   [height (+ height 10)]))\n\n(define canvas\n  (new canvas% [parent frame]\n               [paint-callback\n                 (lambda (canvas dc)\n                   (send dc draw-bitmap target 0 0))]))\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; Drawing things\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n(draw-pictures-list\n  (list\n    \"outline (2.49a)\"\n    outline\n\n    \"cross (2.49b)\"\n    cross\n\n    \"diamond (2.49c)\"\n    diamond\n\n    \"beside\"\n    (beside diamond outline)\n\n    \"below (2.51)\"\n    (below outline cross)\n\n    \"beside, below\"\n    (below (beside cross outline)\n           (beside diamond cross))\n\n    \"wave (2.49d)\"\n    wave\n\n    \"flip-horiz (2.50)\"\n    (flip-horiz wave)\n\n    \"rotate180 (2.50)\"\n    (rotate180 wave)\n\n    \"rotate270 (2.50)\"\n    (rotate270 wave)\n\n    \"smiling-wave (2.52a)\"\n    smiling-wave\n\n    \"flipped-pairs\"\n    (flipped-pairs wave)\n\n    \"right-split\"\n    (right-split outline 4)\n\n    \"up-split (2.44)\"\n    (up-split outline 4)\n\n    \"corner-split\"\n    (corner-split outline 4)\n\n    \"simpler-corner-split (2.52b)\"\n    (simpler-corner-split outline 4)\n\n    \"square-limit\"\n    (square-limit wave 4)\n\n    \"inverted-square-limit (2.52c)\"\n    (inverted-square-limit wave 4)\n\n    \"rogers\"\n    rogers\n\n    \"simpler-square-limit, rogers\"\n    (simpler-square-limit rogers 4)\n\n    \"square-limit, rogers\"\n    (square-limit rogers 4)\n\n    \"inverted-square-limit, rogers\"\n    (inverted-square-limit (flip-vert rogers) 4)\n\n    \"squash-inwards\"\n    (squash-inwards rogers)\n\n    \"square-limit, squash-inwards\"\n    (square-limit (squash-inwards rogers) 4))\n  0)\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; Render the frame\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n(send frame show #t)\n"
  },
  {
    "path": "scheme/sicp/02/tests/01-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../01.scm\")\n\n(define sicp-2.01-tests\n  (test-suite\n    \"Tests for SICP exercise 2.01\"\n\n    (check-equal? (numer (make-rat 1 2)) 1)\n    (check-equal? (denom (make-rat 1 2)) 2)\n\n    (check-equal? (numer (make-rat -1 2)) -1)\n    (check-equal? (denom (make-rat -1 2)) 2)\n\n    (check-equal? (numer (make-rat 1 -2)) -1)\n    (check-equal? (denom (make-rat 1 -2)) 2)\n\n    (check-equal? (numer (make-rat -1 -2)) 1)\n    (check-equal? (denom (make-rat -1 -2)) 2)\n\n    (check-equal? (numer (make-rat -2 -4)) 1)\n    (check-equal? (denom (make-rat -2 -4)) 2)\n\n    (check-equal? (numer (make-rat 2 4)) 1)\n    (check-equal? (denom (make-rat 2 4)) 2)\n))\n\n(run-tests sicp-2.01-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/02-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../02.scm\")\n\n(define sicp-2.02-tests\n  (test-suite\n    \"Tests for SICP exercise 2.02\"\n\n    (check-equal? (x-point (make-point 1 2)) 1)\n    (check-equal? (y-point (make-point 1 2)) 2)\n\n    (check-equal? (start-segment (make-segment (make-point 1 2) (make-point 3 4)))\n                  (make-point 1 2))\n    (check-equal? (end-segment (make-segment (make-point 1 2) (make-point 3 4)))\n                  (make-point 3 4))\n\n    (check-equal? (midpoint-segment (make-segment (make-point 0 10) (make-point 10 0)))\n                  (make-point 5 5))\n    (check-equal? (midpoint-segment (make-segment (make-point 0 0) (make-point 0 10)))\n                  (make-point 0 5))\n    (check-equal? (midpoint-segment (make-segment (make-point 10 0) (make-point 0 0)))\n                  (make-point 5 0))\n))\n\n(run-tests sicp-2.02-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/03-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../03.scm\")\n\n(define sicp-2.03-tests\n  (test-suite\n    \"Tests for SICP exercise 2.03\"\n\n    (check-equal? (perimeter (make-rectangle (make-point 1 1)\n                                             (make-point 2 2)))\n                  4)\n    (check-equal? (perimeter (make-rectangle (make-point 0 0)\n                                             (make-point 3 4)))\n                  14)\n\n    (check-equal? (area (make-rectangle (make-point 1 1)\n                                        (make-point 2 2)))\n                  1)\n    (check-equal? (area (make-rectangle (make-point 0 0)\n                                        (make-point 3 4)))\n                  12)\n))\n\n(run-tests sicp-2.03-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/05-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../05.scm\")\n\n(define sicp-2.05-tests\n  (test-suite\n    \"Tests for SICP exercise 2.05\"\n\n    (check-equal? (car (cons 5 7)) 5)\n    (check-equal? (cdr (cons 5 7)) 7)\n\n    (check-equal? (car (cons 0 7)) 0)\n    (check-equal? (cdr (cons 5 0)) 0)\n))\n\n(run-tests sicp-2.05-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/06-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../06.scm\")\n\n(define (double x)\n  (+ x x))\n\n(define sicp-2.06-tests\n  (test-suite\n    \"Tests for SICP exercise 2.06\"\n\n    (check-equal? ((one double) 2) 4)\n    (check-equal? ((two double) 2) 8)\n\n    (check-equal? (((add one two) double) 2) 16)\n))\n\n(run-tests sicp-2.06-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/07-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../07.scm\")\n\n(define sicp-2.07-tests\n  (test-suite\n    \"Tests for SICP exercise 2.07\"\n\n    (check-equal? (lower-bound (make-interval 4 5)) 4)\n    (check-equal? (upper-bound (make-interval 4 5)) 5)\n))\n\n(run-tests sicp-2.07-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/08-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../08.scm\")\n\n(define sicp-2.08-tests\n  (test-suite\n    \"Tests for SICP exercise 2.08\"\n\n    (check-equal? (sub-interval (make-interval 20 25)\n                                (make-interval 1 2))\n                  (make-interval 18 24))\n\n    (check-equal? (sub-interval (make-interval 10 12)\n                                (make-interval -3 -1))\n                  (make-interval 11 15))\n))\n\n(run-tests sicp-2.08-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/10-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../10.scm\")\n\n(define sicp-2.10-tests\n  (test-suite\n    \"Tests for SICP exercise 2.10\"\n\n    (check-equal? (div-interval (make-interval 10.0 20.0)\n                                (make-interval 2.0 5.0))\n                  (make-interval 2.0 10.0))\n\n    (check-exn exn? (lambda () (div-interval (make-interval 10 20)\n                                             (make-interval -1 1))))\n))\n\n(run-tests sicp-2.10-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/11-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../11.scm\")\n\n(define sicp-2.11-tests\n  (test-suite\n    \"Tests for SICP exercise 2.11\"\n\n    (check-equal? (mul-interval (make-interval 1 2)\n                                (make-interval 3 4))\n                  (make-interval 3 8))\n\n    (check-equal? (mul-interval (make-interval 1 2)\n                                (make-interval -3 4))\n                  (make-interval -6 8))\n\n    (check-equal? (mul-interval (make-interval 1 2)\n                                (make-interval -4 -3))\n                  (make-interval -8 -3))\n\n    (check-equal? (mul-interval (make-interval -1 2)\n                                (make-interval 3 4))\n                  (make-interval -4 8))\n\n    (check-equal? (mul-interval (make-interval -1 2)\n                                (make-interval -3 4))\n                  (make-interval -6 8))\n    (check-equal? (mul-interval (make-interval -4 2)\n                                (make-interval -3 4))\n                  (make-interval -16 12))\n    (check-equal? (mul-interval (make-interval -2 2)\n                                (make-interval -3 2))\n                  (make-interval -6 6))\n    (check-equal? (mul-interval (make-interval -2 2)\n                                (make-interval -2 3))\n                  (make-interval -6 6))\n\n    (check-equal? (mul-interval (make-interval -1 2)\n                                (make-interval -4 -3))\n                  (make-interval -8 4))\n\n    (check-equal? (mul-interval (make-interval -2 -1)\n                                (make-interval 3 4))\n                  (make-interval -8 -3))\n\n    (check-equal? (mul-interval (make-interval -2 -1)\n                                (make-interval -3 4))\n                  (make-interval -8 6))\n\n    (check-equal? (mul-interval (make-interval -2 -1)\n                                (make-interval -4 -3))\n                  (make-interval 3 8))\n))\n\n(run-tests sicp-2.11-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/12-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../12.scm\")\n\n(define sicp-2.12-tests\n  (test-suite\n    \"Tests for SICP exercise 2.12\"\n\n    (check-equal? (percent (make-interval 95 105)) 5)\n    (check-equal? (make-center-percent 100 5) (make-interval 95 105))\n    (check-equal? (percent (make-center-percent 100 5)) 5)\n))\n\n(run-tests sicp-2.12-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/17-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../17.scm\")\n\n(define sicp-2.17-tests\n  (test-suite\n    \"Tests for SICP exercise 2.17\"\n\n    (check-equal? (last-pair (list 23 72 149 34)) (list 34))\n    (check-equal? (last-pair (list 34)) (list 34))\n))\n\n(run-tests sicp-2.17-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/18-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../18.scm\")\n\n(define sicp-2.18-tests\n  (test-suite\n    \"Tests for SICP exercise 2.18\"\n\n    (check-equal? (reverse (list 1 4 9 16 25)) (list 25 16 9 4 1))\n    (check-equal? (reverse (list 1)) (list 1))\n    (check-equal? (reverse '()) '())\n))\n\n(run-tests sicp-2.18-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/19-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../19.scm\")\n\n(define sicp-2.19-tests\n  (test-suite\n    \"Tests for SICP exercise 2.19\"\n\n    (check-equal? (cc 100 '(50 25 10 5 1)) 292)\n    (check-equal? (cc 11 '(10 5 1)) 4)\n))\n\n(run-tests sicp-2.19-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/20-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../20.scm\")\n\n(define sicp-2.20-tests\n  (test-suite\n    \"Tests for SICP exercise 2.20\"\n\n    (check-equal? (same-parity 1 2 3 4 5 6 7) (list 1 3 5 7))\n    (check-equal? (same-parity 2 3 4 5 6 7) (list 2 4 6))\n))\n\n(run-tests sicp-2.20-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/21-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../21.scm\")\n\n(define sicp-2.21-tests\n  (test-suite\n    \"Tests for SICP exercise 2.21\"\n\n    (check-equal? (square-list-1 (list 1 2 3 4)) (list 1 4 9 16))\n    (check-equal? (square-list-2 (list 1 2 3 4)) (list 1 4 9 16))\n))\n\n(run-tests sicp-2.21-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/25-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../25.scm\")\n\n(define sicp-2.25-tests\n  (test-suite\n    \"Tests for SICP exercise 2.25\"\n\n    (check-equal? \n      (car (cdr (car (cdr (cdr '(1 3 (5 7) 9))))))\n      7)\n    (check-equal?\n      (car (car '((7))))\n      7)\n    (check-equal? \n      (car (cdr (car (cdr (car (cdr (car (cdr (car (cdr (car (cdr '(1 (2 (3 (4 (5 (6 7))))))))))))))))))\n      7)\n))\n\n(run-tests sicp-2.25-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/27-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../27.scm\")\n\n(define sicp-2.27-tests\n  (test-suite\n    \"Tests for SICP exercise 2.27\"\n\n    (check-equal? (deep-reverse '((1 2) (3 4))) '((4 3) (2 1)))\n))\n\n(run-tests sicp-2.27-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/28-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../28.scm\")\n\n(define sicp-2.28-tests\n  (test-suite\n    \"Tests for SICP exercise 2.28\"\n\n    (check-equal? (fringe '((1 2) (3 4))) '(1 2 3 4))\n    (check-equal? (fringe '(((1 2) (3 4)) ((1 2) (3 4)))) '(1 2 3 4 1 2 3 4))\n    (check-equal? (fringe '(((1 2) 3 4) 5)) '(1 2 3 4 5))\n    (check-equal? (fringe '(1 (2 (3 4) 5 (6)) 7)) '(1 2 3 4 5 6 7))\n))\n\n(run-tests sicp-2.28-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/29-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../29.scm\")\n\n(define sicp-2.29-tests\n  (test-suite\n    \"Tests for SICP exercise 2.29\"\n\n    (check-equal? (left-branch (make-mobile (make-branch 1 2)\n                                            (make-branch 3 4)))\n                  (make-branch 1 2))\n\n    (check-equal? (right-branch (make-mobile (make-branch 1 2)\n                                             (make-branch 3 4)))\n                  (make-branch 3 4))\n\n    (check-equal? (branch-length (make-branch 1 2))\n                  1)\n\n    (check-equal? (branch-structure (make-branch 1 2))\n                  2)\n\n    (check-equal?\n      (total-weight (make-mobile (make-branch 1 (make-mobile (make-branch 2 3)\n                                                             (make-branch 4 5)))\n                                 (make-branch 6 7)))\n      15)\n\n    (check-true\n      (balanced? (make-mobile (make-branch 3 4)\n                              (make-branch 6 2))))\n\n    (check-false\n      (balanced? (make-mobile (make-branch 3 3)\n                              (make-branch 6 2))))\n\n    (check-true\n      (balanced? (make-mobile (make-branch 3 (make-mobile (make-branch 2 4)\n                                                          (make-branch 8 1)))\n                              (make-branch 5 3))))\n\n    (check-false\n      (balanced? (make-mobile (make-branch 3 (make-mobile (make-branch 2 4)\n                                                          (make-branch 7 1)))\n                              (make-branch 5 3))))\n\n    (check-false\n      (balanced? (make-mobile (make-branch 3 (make-mobile (make-branch 2 4)\n                                                          (make-branch 8 1)))\n                              (make-branch 4 3))))\n))\n\n(run-tests sicp-2.29-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/30-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../30.scm\")\n\n(define sicp-2.30-tests\n  (test-suite\n    \"Tests for SICP exercise 2.30\"\n\n    (check-equal?\n      (square-tree (list 1\n                         (list 2 (list 3 4) 5)\n                         (list 6 7)))\n      '(1 (4 (9 16) 25) (36 49)))\n))\n\n(run-tests sicp-2.30-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/31-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../31.scm\")\n\n(define sicp-2.31-tests\n  (test-suite\n    \"Tests for SICP exercise 2.31\"\n\n    (check-equal? (square-tree '(1 (2 (3 4) 5) (6 7)))\n                  '(1 (4 (9 16) 25) (36 49)))\n\n    (check-equal? (tree-map (lambda (x) (+ x 1))\n                            '(1 (2 (3 4) 5) (6 7)))\n                  '(2 (3 (4 5) 6) (7 8)))\n))\n\n(run-tests sicp-2.31-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/32-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../32.scm\")\n\n(define sicp-2.32-tests\n  (test-suite\n    \"Tests for SICP exercise 2.32\"\n\n    (check-equal? (subsets '())\n                  '(()))\n    (check-equal? (subsets '(1))\n                  '(() (1)))\n    (check-equal? (subsets '(1 2))\n                  '(() (2) (1) (1 2)))\n    (check-equal? (subsets '(1 2 3))\n                  '(() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3)))\n))\n\n(run-tests sicp-2.32-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/33-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../33.scm\")\n\n(define sicp-2.33-tests\n  (test-suite\n    \"Tests for SICP exercise 2.33\"\n\n    (check-equal? (map (lambda (x) (* x x)) '(1 2 3 4)) '(1 4 9 16))\n    (check-equal? (append '(1 2 3) '(4 5 6)) '(1 2 3 4 5 6))\n    (check-equal? (length '(1 2 3)) 3)\n))\n\n(run-tests sicp-2.33-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/34-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../34.scm\")\n\n(define sicp-2.34-tests\n  (test-suite\n    \"Tests for SICP exercise 2.34\"\n\n    (check-equal? (horner-eval 2 (list 1 3 0 5 0 1)) 79)\n))\n\n(run-tests sicp-2.34-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/35-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../35.scm\")\n\n(define sicp-2.35-tests\n  (test-suite\n    \"Tests for SICP exercise 2.35\"\n\n    (check-equal? (count-leaves '()) 0)\n    (check-equal? (count-leaves '(1 2 3 4)) 4)\n    (check-equal? (count-leaves '(1 2 (3 4 (5 6) 7) 8 (9))) 9)\n))\n\n(run-tests sicp-2.35-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/36-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../36.scm\")\n\n(define sicp-2.36-tests\n  (test-suite\n    \"Tests for SICP exercise 2.36\"\n\n    (check-equal? (accumulate-n + 0 '((1 2 3) (4 5 6) (7 8 9) (10 11 12))) '(22 26 30))\n))\n\n(run-tests sicp-2.36-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/37-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../37.scm\")\n\n(define sicp-2.37-tests\n  (test-suite\n    \"Tests for SICP exercise 2.37\"\n\n    (check-equal?\n      (matrix-*-vector '((1 2)\n                         (3 4))\n                       '(5 6))\n      '(17 39))\n\n    (check-equal?\n      (transpose '((1 2 3)\n                   (4 5 6)\n                   (7 8 9)))\n      '((1 4 7)\n        (2 5 8)\n        (3 6 9)))\n\n    (check-equal?\n      (matrix-*-matrix '((1 2)\n                         (3 4))\n                       '((5 6)\n                         (7 8)))\n      '((19 22)\n        (43 50)))\n))\n\n(run-tests sicp-2.37-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/39-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../39.scm\")\n\n(define sicp-2.39-tests\n  (test-suite\n    \"Tests for SICP exercise 2.39\"\n\n    (check-equal? (reverse-r '(1 2 3 4 5)) '(5 4 3 2 1))\n    (check-equal? (reverse-l '(1 2 3 4 5)) '(5 4 3 2 1))\n))\n\n(run-tests sicp-2.39-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/40-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../40.scm\")\n\n(define sicp-2.40-tests\n  (test-suite\n    \"Tests for SICP exercise 2.40\"\n\n    (check-equal? (enumerate-interval 1 5) '(1 2 3 4 5))\n\n    (check-equal? (unique-pairs 2) '((1 2)))\n    (check-equal? (unique-pairs 3) '((1 2) (1 3) (2 3)))\n    (check-equal? (unique-pairs 4) '((1 2) (1 3) (1 4) (2 3) (2 4) (3 4)))\n\n    (check-equal? (prime-sum-pairs 6) '((1 2) (1 4) (1 6) (2 3) (2 5) (3 4) (5 6)))\n))\n\n(run-tests sicp-2.40-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/41-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../41.scm\")\n\n(define sicp-2.41-tests\n  (test-suite\n    \"Tests for SICP exercise 2.41\"\n\n    (check-equal? (triples-sum 5 9) '((1 3 5) (2 3 4)))\n    (check-equal? (triples-sum 5 10) '((1 4 5) (2 3 5)))\n))\n\n(run-tests sicp-2.41-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/42-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../42.scm\")\n\n(define sicp-2.42-tests\n  (test-suite\n    \"Tests for SICP exercise 2.42\"\n\n    (check-true (safe? 2 '((1 1) (3 2))))\n    (check-false (safe? 2 '((1 1) (1 2))))\n\n    (check-true (safe? 2 '((3 1) (1 2))))\n    (check-false (safe? 2 '((3 1) (2 2))))\n    (check-false (safe? 2 '((1 1) (2 2))))\n\n    (check-true (all? zero? '(0 0 0)))\n    (check-false (all? zero? '(0 1 0)))\n    (check-true (all? zero? '()))\n\n    (check-equal? 92 (length (queens 8)))\n))\n\n(run-tests sicp-2.42-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/44-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../44.scm\")\n\n(define (below a b) (list 'below a b))\n(define (beside a b) (list 'beside a b))\n\n(define sicp-2.44-tests\n  (test-suite\n    \"Tests for SICP exercise 2.44\"\n\n    (check-equal? (up-split 'a 1)\n                  '(below a (beside a a)))\n\n    (check-equal? (up-split 'a 2)\n                  '(below a\n                          (beside (below a\n                                         (beside a a))\n                                  (below a\n                                         (beside a a)))))\n\n\n))\n\n(run-tests sicp-2.44-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/45-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n\n(define (below a b) (list 'below a b))\n(define (beside a b) (list 'beside a b))\n\n(load \"../45.scm\")\n\n(define sicp-2.45-tests\n  (test-suite\n    \"Tests for SICP exercise 2.45\"\n\n    (check-equal? (up-split 'a 1)\n                  '(below a (beside a a)))\n\n    (check-equal? (up-split 'a 2)\n                  '(below a\n                          (beside (below a\n                                         (beside a a))\n                                  (below a\n                                         (beside a a)))))\n\n    (check-equal? (right-split 'a 1)\n                  '(beside a (below a a)))\n\n    (check-equal? (right-split 'a 2)\n                  '(beside a \n                           (below (beside a\n                                          (below a a))\n                                  (beside a\n                                          (below a a)))))\n))\n\n(run-tests sicp-2.45-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/46-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../46.scm\")\n\n(define sicp-2.46-tests\n  (test-suite\n    \"Tests for SICP exercise 2.46\"\n\n    (check-equal? 1.0\n                  (xcor-vect (make-vect 1.0 2.0)))\n\n    (check-equal? 2.0\n                  (ycor-vect (make-vect 1.0 2.0)))\n\n    (check-equal? (make-vect 4.0 6.0)\n                  (add-vect (make-vect 1.0 2.0)\n                            (make-vect 3.0 4.0)))\n\n    (check-equal? (make-vect 3.0 1.0)\n                  (sub-vect (make-vect 4.0 3.0)\n                            (make-vect 1.0 2.0)))\n\n    (check-equal? (make-vect 3.0 6.0)\n                  (scale-vect 3.0\n                              (make-vect 1.0 2.0)))\n))\n\n(run-tests sicp-2.46-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/47-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../47.scm\")\n\n(define sicp-2.47-tests\n  (test-suite\n    \"Tests for SICP exercise 2.47\"\n\n    (check-equal? (origin-frame1 (make-frame1 1 2 3))\n                  1)\n    (check-equal? (edge1-frame1 (make-frame1 1 2 3))\n                  2)\n    (check-equal? (edge2-frame1 (make-frame1 1 2 3))\n                  3)\n\n    (check-equal? (origin-frame2 (make-frame2 1 2 3))\n                  1)\n    (check-equal? (edge1-frame2 (make-frame2 1 2 3))\n                  2)\n    (check-equal? (edge2-frame2 (make-frame2 1 2 3))\n                  3)\n))\n\n(run-tests sicp-2.47-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/48-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../48.scm\")\n\n(define sicp-2.48-tests\n  (test-suite\n    \"Tests for SICP exercise 2.48\"\n\n    (check-equal? (start-segment (make-segment (make-vect 1.0 2.0)\n                                               (make-vect 3.0 4.0)))\n                  (make-vect 1.0 2.0))\n\n    (check-equal? (end-segment (make-segment (make-vect 1.0 2.0)\n                                             (make-vect 3.0 4.0)))\n                  (make-vect 3.0 4.0))\n))\n\n(run-tests sicp-2.48-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/54-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../54.scm\")\n\n(define sicp-2.54-tests\n  (test-suite\n    \"Tests for SICP exercise 2.54\"\n\n    (check-true (equal2? 'a 'a))\n    (check-true (equal2? '(a b) '(a b)))\n    (check-true (equal2? '(a (b c) d) '(a (b c) d)))\n    (check-true (equal2? '(a (b c) d (e f)) '(a (b c) d (e f))))\n))\n\n(run-tests sicp-2.54-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/56-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../56.scm\")\n\n(define sicp-2.56-tests\n  (test-suite\n    \"Tests for SICP exercise 2.56\"\n\n    (check-equal? (deriv '(+ x 3) 'x)\n                  1)\n\n    (check-equal? (deriv '(* x y) 'x)\n                  'y)\n\n    (check-equal? (deriv '(* (* x y) (+ x 3)) 'x)\n                  '(+ (* x y) (* y (+ x 3))))\n\n\n\n    (check-equal? (deriv '(** x 3) 'x)\n                  '(* 3 (** x 2)))\n\n    (check-equal? (deriv '(** x 2) 'x)\n                  '(* 2 x))\n\n    (check-equal? (deriv '(** x 1) 'x)\n                  1)\n))\n\n(run-tests sicp-2.56-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/57-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../57.scm\")\n\n(define sicp-2.57-tests\n  (test-suite\n    \"Tests for SICP exercise 2.57\"\n\n    (check-equal? (multiplier '(* x y z)) 'x)\n    (check-equal? (multiplicand '(* x y z)) '(* y z))\n\n    (check-equal? (addend '(+ x y z)) 'x)\n    (check-equal? (augend '(+ x y z)) '(+ y z))\n\n    (check-equal? (deriv '(* x y (+ x 3)) 'x)\n                  '(+ (* x y) (* y (+ x 3))))\n\n    (check-equal? (deriv '(+ 0 y x) 'x)\n                  1)\n))\n\n(run-tests sicp-2.57-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/58-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../58.scm\")\n\n(define sicp-2.58-tests\n  (test-suite\n    \"Tests for SICP exercise 2.58\"\n\n    (check-equal? (deriv '(x * x) 'x)\n                         '(x + x))\n\n    (check-equal? (deriv '(x + (3 * (x + (y + 2)))) 'x)\n                  4)\n))\n\n(run-tests sicp-2.58-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/59-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../59.scm\")\n\n(define sicp-2.59-tests\n  (test-suite\n    \"Tests for SICP exercise 2.59\"\n\n    (check-equal? (union-set '(1 2) '(3 4))\n                  '(1 2 3 4))\n\n    (check-equal? (union-set '(1 2 3) '(2 4))\n                  '(1 3 2 4))\n))\n\n(run-tests sicp-2.59-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/60-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../60.scm\")\n\n(define sicp-2.60-tests\n  (test-suite\n    \"Tests for SICP exercise 2.60\"\n\n    (check-true (element-of-set? 1 '(2 3 2 1 3 2 2)))\n    (check-true (element-of-set? 2 '(2 3 2 1 3 2 2)))\n    (check-true (element-of-set? 3 '(2 3 2 1 3 2 2)))\n    (check-false (element-of-set? 4 '(2 3 2 1 3 2 2)))\n\n    (check-equal? (adjoin-set '1 '()) '(1))\n    (check-equal? (adjoin-set '1 '(2 3)) '(1 2 3))\n    (check-equal? (adjoin-set '2 '(3 2 1)) '(2 3 2 1))\n\n    (check-equal? (union-set '(1 2) '(3 4)) '(1 2 3 4))\n    (check-equal? (union-set '(1 2) '(1 3)) '(1 2 1 3))\n\n    (check-equal? (intersection-set '(1 2 3) '(2 3 4)) '(2 3))\n    (check-equal? (intersection-set '(1 2 2 3 3) '(2 3 3 4 4 4)) '(2 2 3 3))\n    (check-equal? (intersection-set '(1 2 3) '(2 2 2 3 3 4 4 4)) '(2 3))\n))\n\n(run-tests sicp-2.60-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/61-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../61.scm\")\n\n(define sicp-2.61-tests\n  (test-suite\n    \"Tests for SICP exercise 2.61\"\n\n    (check-equal? (adjoin-set 0 '()) '(0))\n\n    (check-equal? (adjoin-set 0 '(1 3 5)) '(0 1 3 5))\n    (check-equal? (adjoin-set 1 '(1 3 5)) '(1 3 5))\n    (check-equal? (adjoin-set 2 '(1 3 5)) '(1 2 3 5))\n    (check-equal? (adjoin-set 3 '(1 3 5)) '(1 3 5))\n    (check-equal? (adjoin-set 4 '(1 3 5)) '(1 3 4 5))\n    (check-equal? (adjoin-set 5 '(1 3 5)) '(1 3 5))\n    (check-equal? (adjoin-set 6 '(1 3 5)) '(1 3 5 6))\n    (check-equal? (adjoin-set 7 '(1 3 5)) '(1 3 5 7))\n))\n\n(run-tests sicp-2.61-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/62-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../62.scm\")\n\n(define sicp-2.62-tests\n  (test-suite\n    \"Tests for SICP exercise 2.62\"\n\n    (check-equal? (union-set '() '()) '())\n    (check-equal? (union-set '(1) '()) '(1))\n    (check-equal? (union-set '() '(1)) '(1))\n\n    (check-equal? (union-set '(1) '(2)) '(1 2))\n    (check-equal? (union-set '(2) '(1)) '(1 2))\n\n    (check-equal? (union-set '(1 3) '(2)) '(1 2 3))\n    (check-equal? (union-set '(1) '(2 3)) '(1 2 3))\n    (check-equal? (union-set '(2) '(1 3)) '(1 2 3))\n    (check-equal? (union-set '(1 2) '(3)) '(1 2 3))\n\n    (check-equal? (union-set '(1 2) '(1 3)) '(1 2 3))\n    (check-equal? (union-set '(1 2 3) '(1 2)) '(1 2 3))\n    (check-equal? (union-set '(1 2) '(1 2 3)) '(1 2 3))\n\n    (check-equal? (union-set '(1 3 5 7 9) '(2 4 6 8 10)) '(1 2 3 4 5 6 7 8 9 10))\n))\n\n(run-tests sicp-2.62-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/65-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../65.scm\")\n\n(define sicp-2.65-tests\n  (test-suite\n    \"Tests for SICP exercise 2.65\"\n\n    (check-equal?\n      (tree->list (intersection-set (list->tree '(1 3 5 7 9 11))\n                                    (list->tree '(2 3 5 9 10))))\n      '(3 5 9))\n\n    (check-equal?\n      (tree->list (union-set (list->tree '(1 3 5 7 9 11))\n                             (list->tree '(2 3 5 9 10))))\n      '(1 2 3 5 7 9 10 11))\n))\n\n(run-tests sicp-2.65-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/66-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../66.scm\")\n\n(define a-tree\n  '((99 a) ((50 b) ((25 c) ((12 d) () ())\n                           ((42 e) ((30 f) () ())\n                                   ()))\n                   ((75 g) () ()))\n           ()))\n\n(define (name-for number)\n  (let ((record (lookup number a-tree)))\n    (if record\n        (name record)\n        #f)))\n\n(define sicp-2.66-tests\n  (test-suite\n    \"Tests for SICP exercise 2.66\"\n\n    (check-equal? (name-for 99) 'a)\n    (check-equal? (name-for 50) 'b)\n    (check-equal? (name-for 25) 'c)\n    (check-equal? (name-for 12) 'd)\n    (check-equal? (name-for 42) 'e)\n    (check-equal? (name-for 30) 'f)\n    (check-equal? (name-for 75) 'g)\n\n    (check-equal? (name-for 20) #f)\n))\n\n(run-tests sicp-2.66-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/67-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../67.scm\")\n\n(define sicp-2.67-tests\n  (test-suite\n    \"Tests for SICP exercise 2.67\"\n\n    (check-equal? (decode sample-message sample-tree)\n                  '(A D A B B C A))\n))\n\n(run-tests sicp-2.67-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/68-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../68.scm\")\n\n(define sample-tree\n  (make-code-tree (make-leaf 'A 4)\n                  (make-code-tree\n                    (make-leaf 'B 2)\n                    (make-code-tree (make-leaf 'D 1)\n                                    (make-leaf 'C 1)))))\n\n(define sample-message '(0 1 1 0 0 1 0 1 0 1 1 1 0))\n\n(define sicp-2.68-tests\n  (test-suite\n    \"Tests for SICP exercise 2.68\"\n\n    (check-equal? (encode '(A D A B B C A) sample-tree)\n                  '(0 1 1 0 0 1 0 1 0 1 1 1 0))\n\n    (check-exn exn? (lambda () (encode '(E) sample-tree)))\n))\n\n(run-tests sicp-2.68-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/69-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../69.scm\")\n\n(define sicp-2.69-tests\n  (test-suite\n    \"Tests for SICP exercise 2.69\"\n\n    (check-equal?\n      (generate-huffman-tree '((A 4) (B 2) (C 1) (D 1)))\n      (make-code-tree (make-leaf 'A 4)\n                      (make-code-tree\n                        (make-leaf 'B 2)\n                        (make-code-tree (make-leaf 'D 1)\n                                        (make-leaf 'C 1)))))\n))\n\n(run-tests sicp-2.69-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/73-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../73.scm\")\n\n(define sicp-2.73-tests\n  (test-suite\n    \"Tests for SICP exercise 2.73\"\n\n    (check-equal? (deriv '(+ x 3) 'x)\n                  1)\n\n    (check-equal? (deriv '(* x y) 'x)\n                  'y)\n\n    (check-equal? (deriv '(* (* x y) (+ x 3)) 'x)\n                  '(+ (* x y) (* y (+ x 3))))\n\n\n\n    (check-equal? (deriv '(** x 3) 'x)\n                  '(* 3 (** x 2)))\n\n    (check-equal? (deriv '(** x 2) 'x)\n                  '(* 2 x))\n\n    (check-equal? (deriv '(** x 1) 'x)\n                  1)\n))\n\n(run-tests sicp-2.73-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/74-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../74.scm\")\n\n(define paul\n  '((salary 2000)\n   (address \"Arrakeen Palace\")))\n(define leto\n  '((salary 2500)\n    (address \"The Caladan planet\")))\n(define atreides\n  (attach-tag 'atreides-file\n    (list\n      (list \"Paul Atreides\" paul)\n      (list \"Duke Leto\" leto))))\n\n(define stilgar\n  '((income . 1000)\n    (location . \"Sietch Tabr\")))\n(define chani\n  '((income . 800)\n    (location . \"Whenever Paul is\")))\n(define fremen\n  (attach-tag 'fremen-file\n    (list\n      (cons \"Stilgar\" stilgar)\n      (cons \"Chani\" chani))))\n\n(define sicp-2.74-tests\n  (test-suite\n    \"Tests for SICP exercise 2.74\"\n\n    (test-suite \"Data structures\"\n      (check-equal? (a-list-get '((\"a\" 1) (\"b\" 2)) \"b\")\n                    2)\n      (check-equal? (a-list-get '() 'a) '())\n\n      (check-equal? (p-list-get '((a . 1) (b . 2)) 'b) 2)\n      (check-equal? (p-list-get '() 'a) '())\n    )\n\n    (test-suite \"Tags\"\n      (check-equal? (attach-tag 'number 1) '(number . 1))\n      (check-equal? (type-tag (attach-tag 'number 1)) 'number)\n      (check-exn exn? (lambda () (type-tag 1)))\n      (check-equal? (contents (attach-tag 'number 1)) 1)\n      (check-exn exn? (lambda () (contents 1)))\n    )\n\n    (test-suite \"get-record\"\n      (check-equal? (get-record \"Paul Atreides\" atreides) (attach-tag 'atreides paul))\n      (check-equal? (get-record \"Duke Leto\" atreides) (attach-tag 'atreides leto))\n      (check-equal? (get-record \"Stilgar\" fremen) (attach-tag 'fremen stilgar))\n      (check-equal? (get-record \"Chani\" fremen) (attach-tag 'fremen chani))\n      (check-equal? (get-record \"Vladimir Harkonnen\" atreides) '())\n      (check-equal? (get-record \"Feyd-Rautha Harkonnen\" fremen) '())\n    )\n\n    (test-suite \"get-salary\"\n      (check-equal? (get-salary (get-record \"Paul Atreides\" atreides)) 2000)\n      (check-equal? (get-salary (get-record \"Duke Leto\" atreides)) 2500)\n      (check-equal? (get-salary (get-record \"Stilgar\" fremen)) 1000)\n      (check-equal? (get-salary (get-record \"Chani\" fremen)) 800)\n    )\n\n    (test-suite \"find-employee-record\"\n      (check-equal? (find-employee-record \"Paul Atreides\" (list atreides fremen)) (attach-tag 'atreides paul))\n      (check-equal? (find-employee-record \"Duke Leto\" (list atreides fremen)) (attach-tag 'atreides leto))\n      (check-equal? (find-employee-record \"Stilgar\" (list atreides fremen)) (attach-tag 'fremen stilgar))\n      (check-equal? (find-employee-record \"Chani\" (list atreides fremen)) (attach-tag 'fremen chani))\n      (check-equal? (find-employee-record \"Vladimir Harkonnen\" (list atreides fremen)) '())\n    )\n))\n\n(run-tests sicp-2.74-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/75-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../75.scm\")\n\n(define sicp-2.75-tests\n  (test-suite\n    \"Tests for SICP exercise 2.75\"\n\n    (check-equal? (magnitute (make-from-mag-ang 3 4)) 3)\n    (check-equal? (angle (make-from-mag-ang 3 4)) 4)\n    (check-= (real-part (make-from-mag-ang 2 (acos 1))) 2 0.001)\n    (check-= (imag-part (make-from-mag-ang 2 (asin 1))) 2 0.001)\n))\n\n(run-tests sicp-2.75-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/78-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../78.scm\")\n\n(define sicp-2.78-tests\n  (test-suite\n    \"Tests for SICP exercise 2.78\"\n\n    (test-suite \"scheme-number package\"\n      (check-equal? (add (make-scheme-number 8) (make-scheme-number 2)) (make-scheme-number 10))\n      (check-equal? (sub (make-scheme-number 8) (make-scheme-number 2)) (make-scheme-number 6))\n      (check-equal? (mul (make-scheme-number 8) (make-scheme-number 2)) (make-scheme-number 16))\n      (check-equal? (div (make-scheme-number 8) (make-scheme-number 2)) (make-scheme-number 4))\n    )\n\n    (test-suite \"rational package\"\n      (check-equal? (add (make-rational 3 4) (make-rational 1 2)) (make-rational 5 4))\n      (check-equal? (sub (make-rational 3 4) (make-rational 1 2)) (make-rational 1 4))\n      (check-equal? (mul (make-rational 3 4) (make-rational 1 2)) (make-rational 3 8))\n      (check-equal? (div (make-rational 3 4) (make-rational 1 2)) (make-rational 6 4))\n    )\n\n    (test-suite \"rational package\"\n      (check-equal? (real-part (make-from-real-imag 3 4)) 3)\n      (check-equal? (imag-part (make-from-real-imag 3 4)) 4)\n      (check-equal? (magnitude (make-from-real-imag 3 4)) 5)\n      (check-equal? (angle (make-from-real-imag 3 4)) (atan 4 3))\n\n      (check-= (real-part ((get 'make-from-mag-ang 'rectangular) 5 (atan 4 3))) 3 0.0001)\n      (check-= (imag-part ((get 'make-from-mag-ang 'rectangular) 5 (atan 4 3))) 4 0.0001)\n    )\n\n    (test-suite \"polar package\"\n      (check-= (real-part (make-from-mag-ang 5 (atan 4 3))) 3 0.0001)\n      (check-= (imag-part (make-from-mag-ang 5 (atan 4 3))) 4 0.0001)\n      (check-equal? (magnitude (make-from-mag-ang 3 4)) 3)\n      (check-equal? (angle (make-from-mag-ang 3 4)) 4)\n\n      (check-= (magnitude ((get 'make-from-real-imag 'polar) 3 4)) 5 0.0001)\n      (check-= (angle ((get 'make-from-real-imag 'polar) 3 4)) (atan 4 3) 0.0001)\n    )\n\n    (test-suite \"complex package\"\n      (check-equal?\n        (add (make-complex-from-real-imag 1 2) (make-complex-from-real-imag 3 4))\n        (make-complex-from-real-imag 4 6))\n      (check-equal?\n        (sub (make-complex-from-real-imag 6 7) (make-complex-from-real-imag 1 3))\n        (make-complex-from-real-imag 5 4))\n      (check-equal?\n        (mul (make-complex-from-mag-ang 2 4) (make-complex-from-mag-ang 3 5))\n        (make-complex-from-mag-ang 6 9))\n      (check-equal?\n        (div (make-complex-from-mag-ang 6 5) (make-complex-from-mag-ang 3 4))\n        (make-complex-from-mag-ang 2 1))\n\n      (check-equal? (real-part (make-complex-from-real-imag 3 4)) 3)\n      (check-equal? (imag-part (make-complex-from-real-imag 3 4)) 4)\n      (check-equal? (magnitude (make-complex-from-mag-ang 1 2)) 1)\n      (check-equal? (angle (make-complex-from-mag-ang 1 2)) 2)\n\n      (check-=\n        (real-part\n          (mul (make-complex-from-mag-ang 5 (atan 4 3))\n               (make-complex-from-real-imag 1 0)))\n        3\n        0.0001)\n\n      (check-=\n        (imag-part\n          (mul (make-complex-from-mag-ang 5 (atan 4 3))\n               (make-complex-from-real-imag 1 0)))\n        4\n        0.0001)\n    )\n))\n\n(run-tests sicp-2.78-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/79-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../79.scm\")\n\n(define sicp-2.79-tests\n  (test-suite\n    \"Tests for SICP exercise 2.79\"\n\n    (check-true (equ? (make-scheme-number 1) (make-scheme-number 1)))\n    (check-false (equ? (make-scheme-number 1) (make-scheme-number 2)))\n\n    (check-true (equ? (make-rational 1 2) (make-rational 1 2)))\n    (check-true (equ? (make-rational 1 2) (make-rational 2 4)))\n    (check-false (equ? (make-rational 1 2) (make-rational 2 2)))\n    (check-false (equ? (make-rational 1 2) (make-rational 1 1)))\n\n    (check-true (equ? (make-complex-from-real-imag 1 2) (make-complex-from-real-imag 1 2)))\n    (check-true (equ? (make-complex-from-mag-ang 1 2) (make-complex-from-mag-ang 1 2)))\n    (check-false (equ? (make-complex-from-real-imag 1 2) (make-complex-from-real-imag 1 1)))\n    (check-false (equ? (make-complex-from-real-imag 1 2) (make-complex-from-real-imag 2 2)))\n    (check-false (equ? (make-complex-from-mag-ang 1 2) (make-complex-from-mag-ang 1 1)))\n    (check-false (equ? (make-complex-from-mag-ang 1 2) (make-complex-from-mag-ang 2 2)))\n))\n\n(run-tests sicp-2.79-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/80-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../80.scm\")\n\n(define sicp-2.80-tests\n  (test-suite\n    \"Tests for SICP exercise 2.80\"\n\n    (check-true (=zero? (make-scheme-number 0)))\n    (check-false (=zero? (make-scheme-number 1)))\n\n    (check-true (=zero? (make-rational 0 1)))\n    (check-true (=zero? (make-rational 0 2)))\n    (check-false (=zero? (make-rational 1 2)))\n\n    (check-true (=zero? (make-complex-from-real-imag 0 0)))\n    (check-false (=zero? (make-complex-from-real-imag 0 1)))\n\n    (check-true (=zero? (make-complex-from-mag-ang 0 1)))\n    (check-false (=zero? (make-complex-from-mag-ang 1 0)))\n))\n\n(run-tests sicp-2.80-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/82-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../82.scm\")\n\n(define sicp-2.82-tests\n  (test-suite\n    \"Tests for SICP exercise 2.82\"\n\n    (check-equal? (foo (make-a) (make-a)) '(foo-a-a a a))\n    (check-equal? (foo (make-a) (make-b)) '(foo-b-b a->b b))\n    (check-equal? (foo (make-b) (make-a)) '(foo-b-b b a->b))\n\n    (check-equal? (bar (make-a) (make-a) (make-a)) '(bar-a-a-a a a a))\n    (check-equal? (bar (make-a) (make-b) (make-b)) '(bar-b-b-b a->b b b))\n    (check-equal? (bar (make-b) (make-a) (make-b)) '(bar-b-b-b b a->b b))\n    (check-equal? (bar (make-b) (make-b) (make-a)) '(bar-b-b-b b b a->b))\n    (check-equal? (bar (make-a) (make-a) (make-b)) '(bar-b-b-b a->b a->b b))\n    (check-equal? (bar (make-a) (make-b) (make-a)) '(bar-b-b-b a->b b a->b))\n    (check-equal? (bar (make-b) (make-a) (make-a)) '(bar-b-b-b b a->b a->b))\n\n    (check-equal? (baz (make-a) (make-a) (make-a) (make-a)) '(baz-a-a-a-a a a a a))\n    (check-equal? (baz (make-a) (make-b) (make-b) (make-b)) '(baz-b-b-b-b a->b b b b))\n    (check-equal? (baz (make-b) (make-a) (make-b) (make-b)) '(baz-b-b-b-b b a->b b b))\n    (check-equal? (baz (make-b) (make-b) (make-a) (make-b)) '(baz-b-b-b-b b b a->b b))\n    (check-equal? (baz (make-b) (make-b) (make-b) (make-a)) '(baz-b-b-b-b b b b a->b))\n\n    (check-exn exn? (lambda () (foo (make-a) (make-c))))\n))\n\n(run-tests sicp-2.82-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/83-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../83.scm\")\n\n(define sicp-2.83-tests\n  (test-suite\n    \"Tests for SICP exercise 2.83\"\n\n    (check-equal? (raise (make-integer 4)) (make-rational 4 1))\n    (check-equal? (raise (make-rational 5 2)) (make-real 2.5))\n    (check-equal? (raise (make-real 2.0)) (make-complex 2.0 0))\n\n))\n\n(run-tests sicp-2.83-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/84-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../84.scm\")\n\n(define sicp-2.84-tests\n  (test-suite\n    \"Tests for SICP exercise 2.84\"\n\n    (check-equal? (supertype 'integer) 'rational)\n    (check-equal? (supertype 'rational) 'real)\n    (check-equal? (supertype 'real) 'complex)\n    (check-equal? (supertype 'complex) #f)\n\n    (check-true (supertype? 'rational 'integer))\n    (check-true (supertype? 'real 'integer))\n    (check-true (supertype? 'complex 'integer))\n    (check-true (supertype? 'real 'rational))\n    (check-true (supertype? 'complex 'rational))\n    (check-true (supertype? 'complex 'real))\n    (check-false (supertype? 'integer 'rational))\n    (check-false (supertype? 'integer 'real))\n    (check-false (supertype? 'integer 'complex))\n    (check-false (supertype? 'rational 'real))\n    (check-false (supertype? 'rational 'complex))\n    (check-false (supertype? 'real 'complex))\n\n    (check-equal? (foo (make-integer 1) (make-integer 1)) 'foo-integer)\n    (check-equal? (foo (make-rational 1 2) (make-integer 1)) 'foo-rational)\n    (check-equal? (foo (make-integer 1) (make-rational 1 2)) 'foo-rational)\n    (check-equal? (foo (make-integer 1) (make-real 1.0)) 'foo-real)\n    (check-equal? (foo (make-rational 1 2) (make-real 1.0)) 'foo-real)\n    (check-equal? (foo (make-real 1.0) (make-integer 1)) 'foo-real)\n    (check-equal? (foo (make-real 1.0) (make-rational 1 2)) 'foo-real)\n    (check-equal? (foo (make-integer 1) (make-complex 1 2)) 'foo-complex)\n    (check-equal? (foo (make-rational 1 2) (make-complex 1 2)) 'foo-complex)\n    (check-equal? (foo (make-real 1.0) (make-complex 1 2)) 'foo-complex)\n    (check-equal? (foo (make-complex 1 2) (make-integer 1)) 'foo-complex)\n    (check-equal? (foo (make-complex 1 2) (make-rational 1 2)) 'foo-complex)\n    (check-equal? (foo (make-complex 1 2) (make-real 1.0)) 'foo-complex)\n))\n\n(run-tests sicp-2.84-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/85-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../85.scm\")\n\n(define sicp-2.85-tests\n  (test-suite\n    \"Tests for SICP exercise 2.85\"\n\n    (check-true (equ? (make-integer 1) (make-integer 1)))\n    (check-true (equ? (make-rational 1 2) (make-rational 2 4)))\n    (check-true (equ? (make-real 1.5) (make-real 1.5)))\n    (check-true (equ? (make-complex 1 2) (make-complex 1 2)))\n\n    (check-false (equ? (make-integer 1) (make-integer 2)))\n    (check-false (equ? (make-rational 1 2) (make-rational 1 3)))\n    (check-false (equ? (make-rational 1 2) (make-rational 2 2)))\n    (check-false (equ? (make-real 1.5) (make-real 2.5)))\n    (check-false (equ? (make-complex 1 2) (make-complex 1 3)))\n    (check-false (equ? (make-complex 1 2) (make-complex 2 2)))\n\n    (check-equal? (project (make-complex 1.0 2.0)) (make-real 1.0))\n    (check-equal? (project (make-real 2.5)) (make-rational 25 10))\n    (check-equal? (project (make-rational 5 2)) (make-integer 2))\n\n    (check-equal? (drop (make-complex 1 2)) (make-complex 1 2))\n    (check-equal? (drop (make-complex 2.5 0)) (make-rational 5 2))\n    (check-equal? (drop (make-complex 1 0)) (make-integer 1))\n    (check-equal? (drop (make-real 2.5)) (make-rational 5 2))\n    (check-equal? (drop (make-real 1.0)) (make-integer 1))\n    (check-equal? (drop (make-rational 1 2)) (make-rational 1 2))\n    (check-equal? (drop (make-rational 1 1)) (make-integer 1))\n    (check-equal? (drop (make-integer 1)) (make-integer 1))\n\n    (check-equal? (add (make-complex 1 2) (make-complex 3 4)) (make-complex 4 6))\n    (check-equal? (add (make-complex 1 1) (make-complex 2 -1)) (make-integer 3))\n    (check-equal? (add (make-real 1.5) (make-real 2.5)) (make-integer 4))\n))\n\n(run-tests sicp-2.85-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/86-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../86.scm\")\n\n(define sicp-2.86-tests\n  (test-suite\n    \"Tests for SICP exercise 2.86\"\n\n    (test-suite \"type tower\"\n      (check-true (supertype? 'integer 'rational))\n      (check-true (supertype? 'integer 'real))\n      (check-true (supertype? 'integer 'complex))\n      (check-true (supertype? 'rational 'real))\n      (check-true (supertype? 'rational 'complex))\n      (check-true (supertype? 'real 'complex))\n    )\n\n    (test-suite \"integers\"\n      (check-exn exn? (lambda () (make-integer 1.5)))\n      (check-equal? (add (make-integer 1) (make-integer 2)) (make-integer 3))\n      (check-equal? (sub (make-integer 3) (make-integer 2)) (make-integer 1))\n      (check-equal? (mul (make-integer 2) (make-integer 4)) (make-integer 8))\n      (check-true (equ? (make-integer 1) (make-integer 1)))\n      (check-false (equ? (make-integer 1) (make-integer 2)))\n      (check-equal? (raise (make-integer 2)) (make-rational 2 1))\n    )\n\n    (test-suite \"rationals\"\n      (check-exn exn? (lambda () (make-rational 1.5 1)))\n      (check-exn exn? (lambda () (make-rational 1 1.5)))\n      (check-equal? (add (make-rational 1 2) (make-rational 3 4)) (make-rational 5 4))\n      (check-equal? (sub (make-rational 3 4) (make-rational 1 2)) (make-rational 1 4))\n      (check-equal? (mul (make-rational 2 3) (make-rational 3 6)) (make-rational 1 3))\n      (check-equal? (div (make-rational 5 4) (make-rational 1 2)) (make-rational 5 2))\n      (check-equal? (raise (make-rational 5 2)) (/ 5 2))\n      (check-true (equ? (make-rational 1 2) (make-rational 2 4)))\n      (check-false (equ? (make-rational 1 2) (make-rational 1 3)))\n      (check-equal? (project (make-rational 5 2)) (make-integer 2))\n    )\n\n    (test-suite \"scheme numbers\"\n      (check-equal? (type-tag 1) 'scheme-number)\n      (check-equal? (contents 1) 1)\n      (check-equal? (attach-tag 'scheme-number 1) 1)\n      (check-equal? (add 1 2) (make-integer 3))\n      (check-equal? (sub 3 2) (make-integer 1))\n      (check-equal? (mul 2 4) (make-integer 8))\n      (check-equal? (div 8 4) (make-integer 2))\n      (check-equal? (sine 1) (sin 1))\n      (check-equal? (cosine 1) (cos 1))\n      (check-equal? (arctangent 3 4) (atan 3 4))\n      (check-equal? (project 4.5) (make-rational 4 1))\n      (check-equal? (raise 4.5) (make-real 4.5))\n      (check-true (equ? 1 1))\n      (check-false (equ? 2 3))\n    )\n\n    (test-suite \"reals\"\n      (check-equal? (add (make-real 1.5) (make-real 2.0)) 3.5)\n      (check-equal? (sub (make-real 3.5) (make-real 2.0)) 1.5)\n      (check-equal? (mul (make-real 1.25) (make-real 2.0)) 2.5)\n      (check-equal? (div (make-real 5.0) (make-real 2.0)) 2.5)\n      (check-equal? (sine (make-real 1.0)) (sin 1.0))\n      (check-equal? (cosine (make-real 1.0)) (cos 1.0))\n      (check-equal? (square-root (make-real 2.0)) (sqrt 2.0))\n      (check-equal? (arctangent (make-real 3.0) (make-real 4.0)) (atan 3.0 4.0))\n      (check-true (equ? (make-real 2.5) (make-real 2.5)))\n      (check-false (equ? (make-real 2.0) (make-real 2.5)))\n      (check-equal? (project (make-real 2.5)) 2.5)\n    )\n\n    (test-suite \"coercions among numbers\"\n      (check-equal? (div (make-integer 1) (make-integer 2)) (make-rational 1 2))\n      (check-equal? (add (make-integer 1) (make-rational 1 2)) (make-rational 3 2))\n      (check-equal? (add (make-integer 1) (make-real 2.5)) 3.5)\n      (check-equal? (sine (make-integer 1)) (sin 1.0))\n      (check-equal? (sine (make-rational 2 2)) (sin 1.0))\n      (check-equal? (arctangent (make-integer 3) (make-integer 4)) (atan 3.0 4.0))\n    )\n\n    (test-suite \"simplification\"\n      (check-equal? (simplify (make-rational 2 1)) (make-integer 2))\n      (check-equal? (simplify (/ 2 1)) (make-integer 2))\n      (check-equal? (simplify (make-real 4.0)) (make-integer 4))\n      (check-equal? (simplify 2.5) 2.5)\n      (check-equal? (simplify (make-real 2.5)) 2.5)\n    )\n\n    (test-suite \"complex numbers with various coercions and simplifications\"\n      (check-equal? (add (make-complex (make-real 1.0) (make-real 2.0))\n                         (make-complex (make-real 3.0) (make-real 4.0)))\n                    (make-complex (make-integer 4) (make-integer 6)))\n      (check-equal? (sub (make-complex (make-real 3.0) (make-real 5.0))\n                         (make-complex (make-real 1.0) (make-real 2.0)))\n                    (make-complex (make-integer 2) (make-integer 3)))\n      (check-equal? (mul (make-complex (make-real 3.0) (make-real 4.0))\n                         (make-complex (make-real 6.0) (make-real 8.0)))\n                    (make-complex-from-mag-ang (make-integer 50)\n                                               (+ (atan 4.0 3.0)\n                                                  (atan 8.0 6.0))))\n      (check-equal? (div (make-complex (make-real 6.0) (make-real 8.0))\n                         (make-complex (make-real 3.0) (make-real 4.0)))\n                    (make-integer 2))\n      (check-true (equ? (make-complex (make-real 1.0) (make-real 2.0))\n                        (make-complex (make-real 1.0) (make-real 2.0))))\n      (check-true (equ? (make-complex (make-real 1.0) (make-real 2.0))\n                        (make-complex (make-integer 1) (make-integer 2))))\n      (check-equal? (mul (make-complex-from-mag-ang (make-integer 2) (make-rational 2 1))\n                         (make-complex-from-mag-ang (make-real 3) (make-real 4)))\n                    (make-complex-from-mag-ang (make-integer 6) (make-integer 6)))\n\n      (check-equal? (real-part (make-complex-from-mag-ang (make-real 5)\n                                                          (make-real (atan 4 3))))\n                    (* 5 (cos (atan 4 3))))\n      (check-equal? (imag-part (make-complex-from-mag-ang (make-real 5)\n                                                          (make-real (atan 4 3))))\n                    (* 5 (sin (atan 4 3))))\n      (check-equal? (mul (make-complex-from-mag-ang (make-integer 2) (make-rational 2 1))\n                         (make-complex-from-mag-ang 3 (make-real 4)))\n                    (make-complex-from-mag-ang (make-integer 6) (make-integer 6)))\n    )\n))\n\n(run-tests sicp-2.86-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/87-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../87.scm\")\n\n(define (poly var . coeffs)\n  (define (value coeff)\n    (cond ((and (number? coeff) (integer? coeff)) (make-integer coeff))\n          ((number? coeff) (make-real coeff))\n          (else coeff)))\n  (define (to-term-list coeffs)\n    (cond ((null? coeffs) '())\n          ((=zero? (value (car coeffs))) (to-term-list (cdr coeffs)))\n          (else (cons (list (- (length coeffs) 1) (value (car coeffs)))\n                      (to-term-list (cdr coeffs))))))\n\n  (make-polynomial var (to-term-list coeffs)))\n\n(define sicp-2.87-tests\n  (test-suite\n    \"Tests for SICP exercise 2.87\"\n\n    (test-suite \"polynomials\"\n      (check-equal? (add (poly 'x 1 2 3) (poly 'x 4 5 6))\n                    (poly 'x 5 7 9))\n      (check-equal? (mul (poly 'x 1 1) (poly 'x 1 -1))\n                    (poly 'x 1 0 -1))\n      (check-equal? (mul (poly 'x 1 (poly 'y 1 0))\n                         (poly 'x 1 (poly 'y 1 0)))\n                    (poly 'x 1 (poly 'y 2 0) (poly 'y 1 0 0)))\n    )\n\n    (test-suite \"type tower\"\n      (check-true (supertype? 'integer 'rational))\n      (check-true (supertype? 'integer 'real))\n      (check-true (supertype? 'integer 'complex))\n      (check-true (supertype? 'rational 'real))\n      (check-true (supertype? 'rational 'complex))\n      (check-true (supertype? 'real 'complex))\n    )\n\n    (test-suite \"integers\"\n      (check-exn exn? (lambda () (make-integer 1.5)))\n      (check-equal? (add (make-integer 1) (make-integer 2)) (make-integer 3))\n      (check-equal? (sub (make-integer 3) (make-integer 2)) (make-integer 1))\n      (check-equal? (mul (make-integer 2) (make-integer 4)) (make-integer 8))\n      (check-true (equ? (make-integer 1) (make-integer 1)))\n      (check-false (equ? (make-integer 1) (make-integer 2)))\n      (check-equal? (raise (make-integer 2)) (make-rational 2 1))\n      (check-true (=zero? (make-integer 0)))\n    )\n\n    (test-suite \"rationals\"\n      (check-exn exn? (lambda () (make-rational 1.5 1)))\n      (check-exn exn? (lambda () (make-rational 1 1.5)))\n      (check-equal? (add (make-rational 1 2) (make-rational 3 4)) (make-rational 5 4))\n      (check-equal? (sub (make-rational 3 4) (make-rational 1 2)) (make-rational 1 4))\n      (check-equal? (mul (make-rational 2 3) (make-rational 3 6)) (make-rational 1 3))\n      (check-equal? (div (make-rational 5 4) (make-rational 1 2)) (make-rational 5 2))\n      (check-equal? (raise (make-rational 5 2)) (make-real 2.5))\n      (check-true (equ? (make-rational 1 2) (make-rational 2 4)))\n      (check-false (equ? (make-rational 1 2) (make-rational 1 3)))\n      (check-equal? (project (make-rational 5 2)) (make-integer 2))\n      (check-true (=zero? (make-rational 0 1)))\n    )\n\n    (test-suite \"reals\"\n      (check-equal? (add (make-real 1.5) (make-real 2.0)) (make-real 3.5))\n      (check-equal? (sub (make-real 3.5) (make-real 2.0)) (make-real 1.5))\n      (check-equal? (mul (make-real 1.25) (make-real 2.0)) (make-real 2.5))\n      (check-equal? (div (make-real 5.0) (make-real 2.0)) (make-real 2.5))\n      (check-equal? (sine (make-real 1.0)) (make-real (sin 1.0)))\n      (check-equal? (cosine (make-real 1.0)) (make-real (cos 1.0)))\n      (check-equal? (square-root (make-real 2.0)) (make-real (sqrt 2.0)))\n      (check-equal? (arctangent (make-real 3.0) (make-real 4.0)) (make-real (atan 3.0 4.0)))\n      (check-true (equ? (make-real 2.5) (make-real 2.5)))\n      (check-false (equ? (make-real 2.0) (make-real 2.5)))\n      (check-equal? (project (make-real 2.5)) (make-rational 2 1))\n      (check-true (=zero? (make-real 0.0)))\n    )\n\n    (test-suite \"coercions among numbers\"\n      (check-equal? (div (make-integer 1) (make-integer 2)) (make-rational 1 2))\n      (check-equal? (add (make-integer 1) (make-rational 1 2)) (make-rational 3 2))\n      (check-equal? (add (make-integer 1) (make-real 2.5)) (make-real 3.5))\n      (check-equal? (sine (make-integer 1)) (make-real (sin 1.0)))\n      (check-equal? (sine (make-rational 2 2)) (make-real (sin 1.0)))\n      (check-equal? (arctangent (make-integer 3) (make-integer 4)) (make-real (atan 3.0 4.0)))\n    )\n\n    (test-suite \"simplification\"\n      (check-equal? (simplify (make-rational 2 1)) (make-integer 2))\n      (check-equal? (simplify (make-real 4.0)) (make-integer 4))\n      (check-equal? (simplify (make-real 2.5)) (make-real 2.5))\n    )\n))\n\n(run-tests sicp-2.87-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/88-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../88.scm\")\n\n(define (poly var . coeffs)\n  (define (value coeff)\n    (cond ((and (number? coeff) (integer? coeff)) (make-integer coeff))\n          ((number? coeff) (make-real coeff))\n          (else coeff)))\n  (define (to-term-list coeffs)\n    (cond ((null? coeffs) '())\n          ((=zero? (value (car coeffs))) (to-term-list (cdr coeffs)))\n          (else (cons (list (- (length coeffs) 1) (value (car coeffs)))\n                      (to-term-list (cdr coeffs))))))\n\n  (make-polynomial var (to-term-list coeffs)))\n\n(define sicp-2.88-tests\n  (test-suite\n    \"Tests for SICP exercise 2.88\"\n\n    (test-suite \"polynomials\"\n      (check-equal? (add (poly 'x 1 2 3) (poly 'x 4 5 6))\n                    (poly 'x 5 7 9))\n      (check-equal? (mul (poly 'x 1 1) (poly 'x 1 -1))\n                    (poly 'x 1 0 -1))\n      (check-equal? (mul (poly 'x 1 (poly 'y 1 0))\n                         (poly 'x 1 (poly 'y 1 0)))\n                    (poly 'x 1 (poly 'y 2 0) (poly 'y 1 0 0)))\n\n      (check-equal? (neg (poly 'x 1 -2 3))\n                    (poly 'x -1 2 -3))\n      (check-equal? (sub (poly 'x 4 4 4)\n                         (poly 'x 3 2 1))\n                    (poly 'x 1 2 3))\n    )\n\n    (test-suite \"type tower\"\n      (check-true (supertype? 'integer 'rational))\n      (check-true (supertype? 'integer 'real))\n      (check-true (supertype? 'rational 'real))\n    )\n\n    (test-suite \"integers\"\n      (check-exn exn? (lambda () (make-integer 1.5)))\n      (check-equal? (add (make-integer 1) (make-integer 2)) (make-integer 3))\n      (check-equal? (sub (make-integer 3) (make-integer 2)) (make-integer 1))\n      (check-equal? (mul (make-integer 2) (make-integer 4)) (make-integer 8))\n      (check-equal? (neg (make-integer 1)) (make-integer -1))\n      (check-true (equ? (make-integer 1) (make-integer 1)))\n      (check-false (equ? (make-integer 1) (make-integer 2)))\n      (check-equal? (raise (make-integer 2)) (make-rational 2 1))\n      (check-true (=zero? (make-integer 0)))\n    )\n\n    (test-suite \"rationals\"\n      (check-exn exn? (lambda () (make-rational 1.5 1)))\n      (check-exn exn? (lambda () (make-rational 1 1.5)))\n      (check-equal? (add (make-rational 1 2) (make-rational 3 4)) (make-rational 5 4))\n      (check-equal? (sub (make-rational 3 4) (make-rational 1 2)) (make-rational 1 4))\n      (check-equal? (mul (make-rational 2 3) (make-rational 3 6)) (make-rational 1 3))\n      (check-equal? (div (make-rational 5 4) (make-rational 1 2)) (make-rational 5 2))\n      (check-equal? (neg (make-rational 1 2)) (make-rational -1 2))\n      (check-equal? (raise (make-rational 5 2)) (make-real 2.5))\n      (check-true (equ? (make-rational 1 2) (make-rational 2 4)))\n      (check-false (equ? (make-rational 1 2) (make-rational 1 3)))\n      (check-equal? (project (make-rational 5 2)) (make-integer 2))\n      (check-true (=zero? (make-rational 0 1)))\n    )\n\n    (test-suite \"reals\"\n      (check-equal? (add (make-real 1.5) (make-real 2.0)) (make-real 3.5))\n      (check-equal? (sub (make-real 3.5) (make-real 2.0)) (make-real 1.5))\n      (check-equal? (mul (make-real 1.25) (make-real 2.0)) (make-real 2.5))\n      (check-equal? (div (make-real 5.0) (make-real 2.0)) (make-real 2.5))\n      (check-equal? (neg (make-real 2.5)) (make-real -2.5))\n      (check-equal? (sine (make-real 1.0)) (make-real (sin 1.0)))\n      (check-equal? (cosine (make-real 1.0)) (make-real (cos 1.0)))\n      (check-equal? (square-root (make-real 2.0)) (make-real (sqrt 2.0)))\n      (check-equal? (arctangent (make-real 3.0) (make-real 4.0)) (make-real (atan 3.0 4.0)))\n      (check-true (equ? (make-real 2.5) (make-real 2.5)))\n      (check-false (equ? (make-real 2.0) (make-real 2.5)))\n      (check-equal? (project (make-real 2.5)) (make-rational 2 1))\n      (check-true (=zero? (make-real 0.0)))\n    )\n\n    (test-suite \"coercions among numbers\"\n      (check-equal? (div (make-integer 1) (make-integer 2)) (make-rational 1 2))\n      (check-equal? (add (make-integer 1) (make-rational 1 2)) (make-rational 3 2))\n      (check-equal? (add (make-integer 1) (make-real 2.5)) (make-real 3.5))\n      (check-equal? (sine (make-integer 1)) (make-real (sin 1.0)))\n      (check-equal? (sine (make-rational 2 2)) (make-real (sin 1.0)))\n      (check-equal? (arctangent (make-integer 3) (make-integer 4)) (make-real (atan 3.0 4.0)))\n    )\n\n    (test-suite \"simplification\"\n      (check-equal? (simplify (make-rational 2 1)) (make-integer 2))\n      (check-equal? (simplify (make-real 4.0)) (make-integer 4))\n      (check-equal? (simplify (make-real 2.5)) (make-real 2.5))\n    )\n))\n\n(run-tests sicp-2.88-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/89-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../89.scm\")\n\n(define (poly var . coeffs)\n  (define (value coeff)\n    (cond ((and (number? coeff) (integer? coeff)) (make-integer coeff))\n          ((number? coeff) (make-real coeff))\n          (else coeff)))\n\n  (make-polynomial var (map value coeffs)))\n\n(define sicp-2.89-tests\n  (test-suite\n    \"Tests for SICP exercise 2.89\"\n\n    (test-suite \"polynomials\"\n      (check-equal? (add (poly 'x 1 2 3) (poly 'x 4 5 6))\n                    (poly 'x 5 7 9))\n      (check-equal? (mul (poly 'x 1 1) (poly 'x 1 -1))\n                    (poly 'x 1 0 -1))\n      (check-equal? (mul (poly 'x 1 (poly 'y 1 0))\n                         (poly 'x 1 (poly 'y 1 0)))\n                    (poly 'x 1 (poly 'y 2 0) (poly 'y 1 0 0)))\n\n      (check-equal? (neg (poly 'x 1 -2 3))\n                    (poly 'x -1 2 -3))\n      (check-equal? (sub (poly 'x 4 4 4)\n                         (poly 'x 3 2 1))\n                    (poly 'x 1 2 3))\n      (check-equal? (sub (poly 'x 3 3 3)\n                         (poly 'x 3 2 1))\n                    (poly 'x 1 2))\n    )\n))\n\n(run-tests sicp-2.89-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/90-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../90.scm\")\n\n(define (t order n)\n  (list order (make-integer n)))\n\n(define (sparse . terms)\n  (cons 'sparse terms))\n\n(define (dense . coeffs)\n  (cons 'dense (map make-integer coeffs)))\n\n(define (poly var term-list)\n  (make-polynomial var term-list))\n\n(define sicp-2.90-tests\n  (test-suite\n    \"Tests for SICP exercise 2.90\"\n\n    (test-suite \"sparse representation\"\n      (check-true (empty-termlist? (the-empty-sparse-termlist)))\n      (check-equal? (first-term (sparse (t 2 1))) (t 2 1))\n      (check-equal? (rest-terms (sparse (t 2 1) (t 1 2)))\n                    (sparse (t 1 2)))\n      (check-equal? (adjoin-term (t 2 2) (sparse (t 1 1)))\n                    (sparse (t 2 2) (t 1 1)))\n      (check-equal? (adjoin-term (t 2 0) (sparse (t 1 1)))\n                    (sparse (t 1 1)))\n      (check-equal? (adjoin-term (t 1 -1) (sparse (t 2 1) (t 1 1) (t 0 1)))\n                    (sparse (t 2 1) (t 0 1)))\n    )\n\n    (test-suite \"dense representation\"\n      (check-true (empty-termlist? (the-empty-dense-termlist)))\n      (check-equal? (first-term (dense 10 20 30)) (t 2 10))\n      (check-equal? (rest-terms (dense 10 20 30)) (dense 20 30))\n      (check-equal? (adjoin-term (t 2 1) (dense 1))\n                    (dense 1 0 1))\n      (check-equal? (adjoin-term (t 0 1) (dense 1 1))\n                    (dense 1 2))\n      (check-equal? (adjoin-term (t 0 1) (dense 1 0 0))\n                    (dense 1 0 1))\n      (check-equal? (adjoin-term (t 2 0) (dense 1))\n                    (dense 1))\n    )\n\n    (test-suite \"polynomial operations\"\n      (check-equal? (add (poly 'x (sparse (t 2 1)))\n                         (poly 'x (sparse (t 1 0))))\n                    (poly 'x (sparse (t 2 1) (t 1 0))))\n      (check-equal? (mul (poly 'x (sparse (t 1 1) (t 0 1)))\n                         (poly 'x (sparse (t 1 1) (t 0 -1))))\n                    (poly 'x (sparse (t 2 1) (t 0 -1))))\n      (check-equal? (sub (poly 'x (sparse (t 2 3) (t 1 3) (t 0 3)))\n                         (poly 'x (sparse (t 2 3) (t 1 2) (t 0 1))))\n                    (poly 'x (sparse (t 1 1) (t 0 2))))\n\n      (check-equal? (add (poly 'x (dense 2 0))\n                         (poly 'x (dense 1)))\n                    (poly 'x (dense 2 1)))\n      (check-equal? (mul (poly 'x (dense 1 1))\n                         (poly 'x (dense 1 -1)))\n                    (poly 'x (dense 1 0 -1)))\n    )\n))\n\n(run-tests sicp-2.90-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/91-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../91.scm\")\n\n(define (poly var . coeffs)\n  (define (value coeff)\n    (cond ((and (number? coeff) (integer? coeff)) (make-integer coeff))\n          ((number? coeff) (make-real coeff))\n          (else coeff)))\n\n  (make-polynomial var (map value coeffs)))\n\n(define sicp-2.91-tests\n  (test-suite\n    \"Tests for SICP exercise 2.91\"\n\n    (check-equal? (add (poly 'x 1 2 3) (poly 'x 4 5 6))\n                  (poly 'x 5 7 9))\n    (check-equal? (mul (poly 'x 1 1) (poly 'x 1 -1))\n                  (poly 'x 1 0 -1))\n    (check-equal? (mul (poly 'x 1 (poly 'y 1 0))\n                       (poly 'x 1 (poly 'y 1 0)))\n                  (poly 'x 1 (poly 'y 2 0) (poly 'y 1 0 0)))\n\n    (check-equal? (neg (poly 'x 1 -2 3))\n                  (poly 'x -1 2 -3))\n    (check-equal? (sub (poly 'x 4 4 4)\n                       (poly 'x 3 2 1))\n                  (poly 'x 1 2 3))\n    (check-equal? (sub (poly 'x 3 3 3)\n                       (poly 'x 3 2 1))\n                  (poly 'x 1 2))\n\n    (check-equal? (div (poly 'x 1 0 0 0 0 -1)\n                       (poly 'x 1 0 -1))\n                  (list (poly 'x 1 0 1 0)\n                        (poly 'x 1 -1)))\n))\n\n(run-tests sicp-2.91-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/92-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../92.scm\")\n\n(define (poly var . coeffs)\n  (define (to-term-list coeffs)\n    (cond ((null? coeffs) '())\n          ((=zero? (car coeffs)) (to-term-list (cdr coeffs)))\n          (else (cons (list (- (length coeffs) 1) (car coeffs))\n                      (to-term-list (cdr coeffs))))))\n\n  (make-polynomial var (to-term-list coeffs)))\n\n(define sicp-2.92-tests\n  (test-suite\n    \"Tests for SICP exercise 2.92\"\n\n    (check-equal? (add (poly 'x 1 0) (poly 'y 1 0))\n                  (poly 'x 1 (poly 'y 1 0)))\n    (check-equal? (add (poly 'y 1 0) (poly 'x 1 0))\n                  (poly 'x 1 (poly 'y 1 0)))\n\n    (check-equal? (mul (poly 'x 1 2 0) (poly 'y 1 0))\n                  (poly 'x (poly 'y 1 0) (poly 'y 2 0) 0))\n    (check-equal? (mul (poly 'y 1 0) (poly 'x 1 2 0))\n                  (poly 'x (poly 'y 1 0) (poly 'y 2 0) 0))\n\n    (check-equal? (sub (poly 'x 1 0) (poly 'y 1 0))\n                  (poly 'x 1 (poly 'y -1 0)))\n    (check-equal? (sub (poly 'y 1 0) (poly 'x 1 0))\n                  (poly 'x -1 (poly 'y 1 0)))\n))\n\n(run-tests sicp-2.92-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/93-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../93.scm\")\n\n(define (poly var . coeffs)\n  (define (to-term-list coeffs)\n    (cond ((null? coeffs) '())\n          ((=zero? (car coeffs)) (to-term-list (cdr coeffs)))\n          (else (cons (list (- (length coeffs) 1) (car coeffs))\n                      (to-term-list (cdr coeffs))))))\n\n  (make-polynomial var (to-term-list coeffs)))\n\n(define sicp-2.93-tests\n  (test-suite\n    \"Tests for SICP exercise 2.93\"\n\n    (test-suite \"rationals\"\n      (check-equal? (add (make-rational 1 2) (make-rational 3 4)) (make-rational 10 8))\n      (check-equal? (sub (make-rational 3 4) (make-rational 1 2)) (make-rational 2 8))\n      (check-equal? (mul (make-rational 2 3) (make-rational 4 5)) (make-rational 8 15))\n      (check-equal? (div (make-rational 2 3) (make-rational 4 5)) (make-rational 10 12))\n    )\n\n    (test-suite \"rational functions\"\n      (check-equal? (add (make-rational (poly 'x 1 0 1)\n                                        (poly 'x 1 0 0 1))\n                         (make-rational (poly 'x 1 0 1)\n                                        (poly 'x 1 0 0 1)))\n                    (make-rational (poly 'x 2 0 2 2 0 2)\n                                   (poly 'x 1 0 0 2 0 0 1)))\n    )\n))\n\n(run-tests sicp-2.93-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/94-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../94.scm\")\n\n(define (poly var . coeffs)\n  (define (to-term-list coeffs)\n    (cond ((null? coeffs) '())\n          ((=zero? (car coeffs)) (to-term-list (cdr coeffs)))\n          (else (cons (list (- (length coeffs) 1) (car coeffs))\n                      (to-term-list (cdr coeffs))))))\n\n  (make-polynomial var (to-term-list coeffs)))\n\n(define sicp-2.94-tests\n  (test-suite\n    \"Tests for SICP exercise 2.94\"\n\n    (check-equal? (greatest-common-divisor 10 6) 2)\n    (check-equal? (greatest-common-divisor (poly 'x 1 -1 -2 2)\n                                           (poly 'x 1 0 -1))\n                  (poly 'x -1 1))\n    (check-equal? (greatest-common-divisor (poly 'x 1 0 -1)\n                                           (poly 'x 1 -1 -2 2))\n                  (poly 'x -1 1))\n))\n\n(run-tests sicp-2.94-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/96-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../96.scm\")\n\n(define (poly var . coeffs)\n  (define (to-term-list coeffs)\n    (cond ((null? coeffs) '())\n          ((=zero? (car coeffs)) (to-term-list (cdr coeffs)))\n          (else (cons (list (- (length coeffs) 1) (car coeffs))\n                      (to-term-list (cdr coeffs))))))\n\n  (make-polynomial var (to-term-list coeffs)))\n\n(define p1 (poly 'x 1 -2 1))\n(define p2 (poly 'x 11 0 7))\n(define p3 (poly 'x 13 5))\n(define q1 (mul p1 p2))\n(define q2 (mul p1 p3))\n\n(define sicp-2.96-tests\n  (test-suite\n    \"Tests for SICP exercise 2.96\"\n\n    (check-equal? (greatest-common-divisor q1 q2) p1)\n))\n\n(run-tests sicp-2.96-tests)\n"
  },
  {
    "path": "scheme/sicp/02/tests/97-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../97.scm\")\n\n(define (poly var . coeffs)\n  (define (to-term-list coeffs)\n    (cond ((null? coeffs) '())\n          ((=zero? (car coeffs)) (to-term-list (cdr coeffs)))\n          (else (cons (list (- (length coeffs) 1) (car coeffs))\n                      (to-term-list (cdr coeffs))))))\n\n  (make-polynomial var (to-term-list coeffs)))\n\n(define sicp-2.97-tests\n  (test-suite\n    \"Tests for SICP exercise 2.97\"\n\n    (check-equal? (make-rational 8 10) (make-rational 4 5))\n    (check-equal? (reduce (poly 'x 1 2 1) (poly 'x 1 0 -1))\n                  (list (poly 'x 1 1) (poly 'x 1 -1)))\n    (check-equal? (add (make-rational (poly 'x 1 1)\n                                      (poly 'x 1 0 0 -1))\n                       (make-rational (poly 'x 1 0)\n                                      (poly 'x 1 0 -1)))\n                  (make-rational (poly 'x -1 -2 -3 -1)\n                                 (poly 'x -1 -1 0 1 1)))\n))\n\n(run-tests sicp-2.97-tests)\n"
  },
  {
    "path": "scheme/sicp/03/01.scm",
    "content": "; SICP exercise 3.01\n;\n; An accumulator is a procedure that is called repeatedly with a single\n; numeric argument and accumulates its arguments into a sum. Each time it is\n; called, it returns the currently accumulated sum. Write a procedure\n; make-acumulator that generates accumulators, each maintaining an independent\n; sum. The input to make-accumulator should specify the initial value of the\n; sum; for example\n;\n;   (define A (make-accumulator 5))\n;\n;   (A 10)\n;   15\n;\n;   (A 10)\n;   25\n\n(define (make-accumulator amount)\n  (lambda (value)\n    (set! amount (+ amount value))\n    amount))\n"
  },
  {
    "path": "scheme/sicp/03/02.scm",
    "content": "; SICP exercise 3.02\n;\n; In software-testing applications, it is useful to be able to count the\n; number of times a given procedure is caled during the course of a\n; computation. Write a procedure make-monitored that takes as input a\n; procedure, f, that itself takes one input.The result returned by\n; make-monitored is a third procedure, say mf, that keeps track of the number\n; of times is has been called by a maintaining an internal counter. If the\n; input to mf is the special symbol how-many-calls?, then mf returns the value\n; of the counter. If the input is the special symbol reset-count, then mf\n; resets the counter to zero. For any other input, mf returns the result of\n; calling f on that input and increments the counter. For instance, we sould\n; make a monitored version of the sqrt procedure:\n;\n; (define s (make-monitored sqrt))\n;\n; (s 100)\n; 10\n;\n; (s 'how-many-calls?)\n; 1\n\n(define (make-monitored function)\n  (let ((count 0))\n    (lambda (arg)\n      (cond ((eq? arg 'how-many-calls?) count)\n            ((eq? arg 'reset-count) (set! count 0))\n            (else (set! count (+ count 1))\n                  (function arg))))))\n"
  },
  {
    "path": "scheme/sicp/03/03.scm",
    "content": "; SICP exercise 3.03\n;\n; Modify the make-account procedure so that is creates password-protected\n; accounts. That is, make-account should take a sumbol as an additional\n; argument, as in:\n;\n;   (define acc (make-account 100 'secret-password))\n;\n; The resulting account object should process a request only if it is\n; accompanied by the password with which the account was created, and should\n; otherwise return a complaint:\n;\n;   ((acc 'secret-password 'withdraw) 40)\n;   60\n;\n;   ((acc 'some-other-password 'deposit) 50)\n;   \"Incorect password\"\n\n(define (make-account balance account-password)\n  (define (withdraw amount)\n    (if (>= balance amount)\n        (begin (set! balance (- balance amount))\n               balance)\n        \"Insufficient funds\"))\n  (define (deposit amount)\n    (set! balance (+ balance amount))\n    balance)\n  (define (unauthorized amount)\n    \"Incorrect password\")\n  (define (dispatch message password)\n    (cond ((not (eq? account-password password)) unauthorized)\n          ((eq? message 'withdraw) withdraw)\n          ((eq? message 'deposit) deposit)\n          (else (error \"Unknown request - MAKE-ACCOUNT\" m))))\n  dispatch)\n"
  },
  {
    "path": "scheme/sicp/03/04.scm",
    "content": "; SICP exercise 3.04\n;\n; Modify the make-account procedure of exercise 3.3 by adding another local\n; state variable so that, if an account is accessed more than seven\n; consecutive times with an incorrect password, it invokes the procedure\n; call-the-cops.\n\n(define (make-account balance account-password)\n  (define consecuitive-failed-attempts 0)\n  (define (withdraw amount)\n    (set! consecuitive-failed-attempts 0)\n    (if (>= balance amount)\n        (begin (set! balance (- balance amount))\n               balance)\n        \"Insufficient funds\"))\n  (define (deposit amount)\n    (set! consecuitive-failed-attempts 0)\n    (set! balance (+ balance amount))\n    balance)\n  (define (unauthorized amount)\n    (set! consecuitive-failed-attempts (+ consecuitive-failed-attempts 1))\n    (if (>= consecuitive-failed-attempts 7)\n        (call-the-cops)\n        #f)\n    \"Incorrect password\")\n  (define (dispatch message password)\n    (cond ((not (eq? account-password password)) unauthorized)\n          ((eq? message 'withdraw) withdraw)\n          ((eq? message 'deposit) deposit)\n          (else (error \"Unknown request - MAKE-ACCOUNT\" m))))\n  dispatch)\n"
  },
  {
    "path": "scheme/sicp/03/05.scm",
    "content": "; SICP exercise 3.05\n;\n; Monte Carlo integration is a method of estimating definite integrals by\n; means of Monte Carlo simulation. Consider computing the area of a region of\n; space described by a predicate P(x,y) that is true for points (x,y) in the\n; region and false for points not in the region. For example, the region\n; contained within a circle of radius 3 centered at (5,7) is described by the\n; predicate that tests whether (x - 5)² + (y - 7)² ≤ 3². To estimate the area\n; of the region described by such a predicate, begin by choosing a rectangle\n; that contins the region. For example, a rectangle with diagonally opposite\n; corners at (2,4) and (8,10) contains the circle above. The desired integral\n; is the area of that portion of the rectangle that lies in the region. We can\n; estimate the integral by picking, at random, points (x,y) that lie in the\n; rectangle, and testing P(x,y) for each point to determine whether the point\n; lies in the region. If we try this with many points, then the fraction of\n; points that fall in the region should give an estimate of the proportion of\n; the rectangle that lies in the region. Hence, multiplying this fraction by\n; the area of the entire rectangle should produce an estimate of the integral.\n;\n; Implement Monte Carlo integration as a procedure estimate-integral that\n; takes as arguments a predicate P, upper and lower bounds x1, x2, y1 and y2\n; for the rectangle, and the number of trials to perform in order to produce\n; the estimate. Your procedure should use the same monte-carlo procedure that\n; was used above to estimate π. Use your estimate-integral to produce an\n; estimate of π by measuring the area of a unit circle.\n;\n; You will find it useful to have a procedure that returns a number chosen at\n; random for a given range. The following random-in-range procedure implements\n; this in terms of the random procedure used in section 1.2.6, which returns a\n; nonnegative number less than its input.\n;\n;   (define (random-in-range low high)\n;     (let ((range (- high low)))\n;       (+ low (random range))))\n\n(define (monte-carlo trials experiment)\n  (define (iter trials-remaining trials-passed)\n    (cond ((= trials-remaining 0)\n           (/ trials-passed trials))\n          ((experiment)\n           (iter (- trials-remaining 1)\n                 (+ trials-passed 1)))\n          (else\n           (iter (- trials-remaining 1)\n                 trials-passed))))\n  (iter trials 0))\n\n(define (estimate-integral predicate x1 x2 y1 y2 trials)\n  (monte-carlo trials\n               (lambda () (predicate (random-in-range x1 x2)\n                                     (random-in-range y1 y2)))))\n\n(define (random-in-range low high)\n  (+ (* (random) (- high low))\n     low))\n\n(define (estimate-pi)\n  (define (circle x y)\n    (<= (+ (* x x) (* y y)) 1))\n  (* (estimate-integral circle -1 1 -1 1 1000000)\n     4.0))\n"
  },
  {
    "path": "scheme/sicp/03/06.scm",
    "content": "; SICP exercise 3.06\n;\n; It is useful to be able to reset a random-number generator to produce a\n; sequence starting from a given value. Design a new rand procedure that is\n; called with an argument that is either the symbol generate or the symbol\n; reset and behaves as follows: (rand 'generate) produces a new random number;\n; ((rand 'reset) <new-value>) resets the internal state variable to the\n; designated <new-value>. Thus, by resetting the state, one can generate\n; repeateble sequences. These are very handy to have when testing and\n; debugging programs that use random numbers.\n\n(define seed (current-milliseconds))\n\n(define (rand-update number)\n  (let ((modulus 4294967296)\n        (multiplier 1664525)\n        (increment 1013904223))\n    (modulo (+ (* multiplier number) increment) modulus)))\n\n(define rand\n  (let ((x seed))\n    (lambda (message)\n      (cond ((eq? message 'generate)\n             (set! x (rand-update x))\n             x)\n            ((eq? message 'reset)\n             (lambda (new-value) (set! x new-value)))\n            (else (error \"Unknown request - RAND\" message))))))\n"
  },
  {
    "path": "scheme/sicp/03/07.scm",
    "content": "; SICP exercise 3.07\n;\n; Consider the bank account objects created by make-account, with the password\n; modification described in exercise 3.3. Suppose that our banking system\n; requires the ability to make joint accounts. Define a procedure make-joint\n; that accomplishes this. make-joint should take three arguments. The first is\n; a password-protected account. The second argument must match the password\n; with which the account was defined in order for the make-joint operation to\n; proceed. The third argument is a new password. make-joint is to create an\n; additional access to the original account using the new password. For\n; example, if peter-acc is a bank account with password open-sesame, then\n;\n; (define paul-acc\n;   (make-joint peter-acc 'open-sesame 'rosebud))\n;\n; will allow one to make transaction on peter-acc using the name paul-acc and\n; the password rosebud. You may wish to modify your solution to exercise 3.3\n; to accommodate for this new feature.\n\n(define (make-account balance account-password)\n  (define (withdraw amount)\n    (if (>= balance amount)\n        (begin (set! balance (- balance amount))\n               balance)\n        \"Insufficient funds\"))\n  (define (deposit amount)\n    (set! balance (+ balance amount))\n    balance)\n  (define (unauthorized amount)\n    \"Incorrect password\")\n  (define (dispatch message password)\n    (cond ((not (eq? account-password password)) unauthorized)\n          ((eq? message 'withdraw) withdraw)\n          ((eq? message 'deposit) deposit)\n          (else (error \"Unknown request - MAKE-ACCOUNT\" m))))\n  dispatch)\n\n(define (make-joint account original-password new-password)\n  (lambda (message password)\n    (if (eq? password new-password)\n        (account message original-password)\n        (lambda (amount) \"Incorrect password\"))))\n"
  },
  {
    "path": "scheme/sicp/03/08.scm",
    "content": "; SICP exercise 3.08\n;\n; When we defined the evaluation model in section 1.1.3, we said that the\n; first step in evaluating an expression is to evaluate its subexpressions.\n; But we never specified the order in which the subexpressions should be\n; evaluated (e.g., left to right or right to left). When we introduce\n; assignment, the order in which the arguments to a procedure are evaluated\n; can make a difference to the result. Define a simple procedure f such that\n; evaluating\n;\n;   (+ (f 0) (f 1))\n;\n; will return 0 if the arguments to + are evaluted from left to right but will\n; return 1 if the arguments are evaluated from right to left.\n\n(define f\n  (let ((current 0))\n    (lambda (number)\n      (let ((existing current))\n        (set! current number)\n        existing))))\n"
  },
  {
    "path": "scheme/sicp/03/09.scm",
    "content": "; SICP exercise 3.09\n;\n; In section 1.2.1 we used the substitution model to analyze two procedures\n; for computing factorials, a recursive version\n;\n;   (define (factorial n)\n;     (if (= n 1)\n;         1\n;         (* n (factorial (- n 1)))))\n;\n; and an iterative version\n;\n;   (define (factorial n)\n;     (fact-iter 1 1 n))\n;\n;   (define (fact-iter product counter max-count)\n;     (if (> counter max-count)\n;         product\n;         (fact-iter (* counter product)\n;                    (+ counter 1)\n;                    max-count)))\n;\n; Show the environment structures created by evaluating (factorial 6) using\n; each version of the factorial procedure.\n\n; With the first version, we have the following environments on each call:\n;\n;   +------+   +------+   +------+   +------+   +------+   +------+\n;   | n: 6 |   | n: 5 |   | n: 4 |   | n: 3 |   | n: 2 |   | n: 1 |\n;   +------+   +------+   +------+   +------+   +------+   +------+\n;\n; With the second version, we have the following environments:\n;\n;   +---------------------------------------------------------------------+\n;   | factorial: <function>                                               |\n;   | fact-iter: <function>                                               |\n;   +---------------------------------------------------------------------+\n;           ^                  ^                    ^           ^     ^\n;           |                  |                    |           |     |\n;   +--------------+   +---------------+   +----------------+   |     |\n;   |   product: 1 |   |   product:  1 |   |   product:   2 |   |   +------+\n;   |   counter: 1 |   |   counter:  2 |   |   counter:   3 |   |   | n: 6 |\n;   | max-count: 6 |   | max-count:  6 |   | max-count:   6 |   |   +------+\n;   +--------------+   +---------------+   +----------------+   |   (factorial)\n;                                                               |\n;           +------------------+--------------------+-----------+--------+\n;           |                  |                    |                    |\n;   +--------------+   +---------------+   +----------------+   +----------------+\n;   |   product: 6 |   |   product: 24 |   |   product: 120 |   |   product: 720 |\n;   |   counter: 4 |   |   counter:  5 |   |   counter:   6 |   |   counter:   7 |\n;   | max-count: 6 |   | max-count:  6 |   | max-count:   6 |   | max-count:   6 |\n;   +--------------+   +---------------+   +----------------+   +----------------+\n"
  },
  {
    "path": "scheme/sicp/03/10.scm",
    "content": "; SICP exercise 3.10\n;\n; In the make-withdraw procedure, the local variable balance is created as a\n; parameter of make-withdraw. We could also create the local state variable\n; explicitly, using let, as follows:\n;\n;   (define (make-withdraw initial-amount)\n;     (let ((balance initial-amount))\n;       (lambda (amount)\n;         (>= balance amount)\n;         (being (set! balance (- balance amount))\n;                (balance)\n;         \"Insufficient funds\"))))\n;\n; Recall from section 1.3.2 that let is simply syntactic sugar for a procedure\n; call:\n;\n;   (let ((<var> <exp>)) <body)\n;\n; is interpreted as an alternate syntax for:\n;\n;   ((lambda (<var>) <body>) <exp)\n;\n; Use the environment model to analyze this alternate version of\n; make-withdraw, drawing figures like the ones above to illustrate the\n; interactions\n;\n;   (define W1 (make-withdraw 100))\n;\n;   (W1 50)\n;\n;   (define W2 (make-withdraw 100))\n;\n; Show that the two versions of make-withdraw create objects with the same\n; behavior. How do environment structures differ in the two versions?\n\n; Alright, here's the diagram before (W1 50)\n;\n; global-env: +-----------------------------------------------------------------------+\n;             | W1                                                                    |\n;             +-|---------------------------------------------------------------------+\n;               |  +---------------------+\n;               |  | initial-amount: 100 |\n;               |  +---------------------+\n;               |            ^\n;               |            |\n;               |  +---------------------+\n;               |  | amount: 100         |\n;               |  +---------------------+\n;               |            ^\n;               |            |\n;             +--------+     |\n;             | lambda |-----+\n;             +--------+\n;               |\n;               parameters: amount\n;               body: (if (>= balance amount)\n;                         (begin (set! balance (- balance amount))\n;                                balance)\n;                         \"Insufficient funds\"))\n;\n; After the withdraw, we get the following:\n;\n; global-env: +-----------------------------------------------------------------------+\n;             | W1                             W2                                     |\n;             +-|------------------------------|--------------------------------------+\n;               |  +---------------------+     |  +---------------------+\n;               |  | initial-amount: 100 |     |  | initial-amount: 100 |\n;               |  +---------------------+     |  +---------------------+\n;               |            ^                 |            ^\n;               |            |                 |            |\n;               |  +---------------------+     |  +---------------------+\n;               |  | amount: 50          |     |  | amount: 100         |\n;               |  +---------------------+     |  +---------------------+\n;               |            ^                 |            ^\n;               |            |                 |            |\n;             +--------+     |               +--------+     |\n;             | lambda |-----+               | lambda |-----+\n;             +--------+                     +--------+\n;               |                              |\n;               parameters: amount             parameters: amount\n;               body: ...                      body: ...\n;\n; The difference is that this version creates one additional frame that holds\n; the amount. That way the initial amount is still available, although not\n; used in the code we currently have. Since the initial-amount is not used, we\n; can safely ignore it. Since this version is only modifying the second frame\n; in a manner, similar to the previous version, the behavior of the two\n; version is the same.\n"
  },
  {
    "path": "scheme/sicp/03/11.scm",
    "content": "; SICP exercise 3.11\n;\n; In section 3.2.3 we saw how the environment model described the behavior of\n; procedures with local state. Now we have seen how internal definitions work.\n; A typical message-passing procedure contains both of these aspects. Consider\n; the bank account procedure of section 3.1.1:\n;\n; (define (make-account balance)\n;   (define (withdraw amount)\n;     (if (>= balance amount)\n;         (begin (set! balance (- balance amount))\n;                balance)\n;         \"Insufficient funds\"))\n;   (define (deposit amount)\n;     (set! balance (+ balance amount))\n;     balance)\n;   (define (dispatch m)\n;     (cond ((eq? m 'withdraw) withdraw)\n;           ((eq? m 'deposit) deposit)\n;           (else (error \"Unknown request - MAKE-ACCOUNT\" m))))\n;   dispatch)\n;\n; Show the environment structure generated by the sequence of interactions\n;\n;   (define (acc (make-account 50)))\n;\n;   ((acc 'deposit) 40)\n;   90\n;\n;   ((acc 'withdraw) 60)\n;   30\n;\n; Where is the local state for acc kept? Suppose we define another account\n;\n;   (define acc2 (make-account 100))\n;\n; How are the local states for the two accounts kept distinct? Which parts of\n; the environment structure are shared between acc and acc2?\n\n; Here's the environment structure:\n;\n; globals:\n; +--------------------------------------------------------------+\n; | make-account: <procedure>                                    |\n; | acc: <procedure>                                             |\n; +--|-----------------------------------------------------------+\n;    |               ^\n;    |               |    +------------------------------+\n;    |    acc:       |    |                              |\n;    |    +-----------------------+                      |\n;    |    | balance: 30           |      +-----------+   |\n;    |    | withdraw: <procedure>--------| procedure ----+\n;    |    | deposit: <procedure>-----+   +-----------+\n;    |    | dispatch: <procedure> |  |   parameters: amount\n;    |    +-|---------------------+  |   body: (if (>= balance amount)\n;    |      |    ^         ^         |             (being (set! balance (- balance amount))\n;    |      |    |         |         |                    balance)\n;    |      |    |         |         |             \"Insufficient funds\")\n;    |      |    |         |         |\n;    |      |    |         |   +-----------+\n;    |      |    |         +---- procedure |\n;    |      |    |             +-----------+\n;    |      |    |             parameters: amount\n;    |      |    |             body: (set! balance (+ balance amount))\n;    |      |    |                   balance\n; +-----------+  |\n; | procedure ---+\n; +-----------+\n; parameters: m\n; code: (cond ((eq? m 'withdraw) withdraw)\n;             ((eq? m 'deposit) deposit)\n;             ((else error \"Unknown require - MAKE-ACCOUNT\" m)))\n;\n; The local state of acc is kept within the frame created by calling\n; make-account. If we define acc2, the whole structure (apart form globals)\n; would be replicated and there would be a similar procedure with a similar\n; frame that stores the ammount of acc2 and all the procedures that manipulate\n; it. The only part of the environment that is shared is the globals.\n"
  },
  {
    "path": "scheme/sicp/03/12.scm",
    "content": "; SICP exercise 3.12\n;\n; The following procedure for appending lists was introduced in section 2.2.1:\n\n;   (define (append x y)\n;     (if (null? x)\n;         y\n;         (cons (car x) (append (cdr x) y))))\n;\n; append forms a new list by succesively consing the elements of x onto y. The\n; procedure append! is similar to append, but it is a mutator rather than a\n; constructor. It appends the lists by splicing them together, modifying the\n; final pair of x so that its cdr is not y. (It is an error to call append!\n; with an empty x.)\n;\n;   (define (append! x y)\n;     (set-cdr! (last-pair x) y)\n;     x)\n;\n; Here last-pair is a procedure that returns the last pair in its argument:\n;\n;   (define (last-pair x)\n;     (if (null? (cdr x))\n;         x\n;         (last-pair (cdr x))))\n;\n; Consider the interaction\n;\n;   (define x (list 'a 'b))\n;   (define y (list 'c d))\n;   (define z (append x y))\n;\n;   z\n;   (a b c d)\n;\n;   (cdr x)\n;   <response>\n;\n;   (define w (append! x y))\n;\n;   w\n;   (a b c d)\n;\n;   (cdr x)\n;   <response>\n;\n; What are the missing <response>s? Draw box-and-pointer diagrams to explain\n; your answer.\n\n; The first missing response is: (b)\n; The second missing response is: (b c d)\n;\n; Here's how everything looks before calling append!:\n;\n;          +---+---+     +---+---+\n;    x --> | . | . ------| . | / |\n;          +-|-+---+     +-|-+---+\n;            |             |\n;          +---+         +---+\n;          | a |         | b |\n;          +---+         +---+\n;\n;          +---+---+     +---+---+    y --> +---+---+     +---+---+\n;    z --> | . | . ------| . | . -----------| . | . ------| . | / |\n;          +-|-+---+     +-|-+---+          +-|-+---+     +-|-+---+\n;            |             |                  |             |\n;          +---+         +---+              +---+         +---+\n;          | a |         | b |              | c |         | d |\n;          +---+         +---+              +---+         +---+\n;\n; When we call append!, the pairs look like this:\n;\n;    w --> +---+---+     +---+---+\n;    x --> | . | . ------| . | . -------------+\n;          +-|-+---+     +-|-+---+            |\n;            |             |                  |\n;          +---+         +---+                |\n;          | a |         | b |                |\n;          +---+         +---+                |\n;                                             |\n;          +---+---+     +---+---+    y --> +---+---+     +---+---+\n;    z --> | . | . ------| . | . -----------| . | . ------| . | / |\n;          +-|-+---+     +-|-+---+          +-|-+---+     +-|-+---+\n;            |             |                  |             |\n;          +---+         +---+              +---+         +---+\n;          | a |         | b |              | c |         | d |\n;          +---+         +---+              +---+         +---+\n"
  },
  {
    "path": "scheme/sicp/03/13.scm",
    "content": "; SICP exercise 3.13\n;\n; Consider the following make-cycle procedure, which uses the last-pair\n; procedure defined in exercise 3.12:\n;\n;   (define (make-cycle x)\n;     (set-cdr! (last-pair x) x)\n;     x)\n;\n; Draw a box-and-pointer diagram that shows the structure z created by\n;\n;   (define z (make-cycle (list 'a 'b 'c)))\n;\n; What happens if we try to compute (last-pair z)?\n\n; Here's the diagram:\n;\n;         +----------------------------------+\n;         |                                  |\n;       +---+---+    +---+---+    +---+---+  |\n; z --> | . | . -----| . | . -----| . | . ---+\n;       +-|-+---+    +-|-+---+    +-|-+---+\n;         |            |            |\n;       +---+        +---+        +---+\n;       | a |        | b |        | c |\n;       +---+        +---+        +---+\n;\n; If we try to compute (last-pair z), it will end up in an infinite recursion,\n; because there is no pair with a cdr that is null.\n"
  },
  {
    "path": "scheme/sicp/03/14.scm",
    "content": "; SICP exercise 3.14\n;\n; The following procedure is quite useful, although obscure:\n;\n;   (define (mystery x)\n;     (define (loop x y)\n;       (if (null? x)\n;           y\n;           (let ((temp (cdr x)))\n;             (set-cdr! x y)\n;             (loop temp x))))\n;     (loop 'x ()))\n;\n; loop uses the \"temporary variable temp to hold the old value of the cdr of\n; x, since the set-cdr! on the next line destroys the cdr. Explain what\n; mystery does in general. Suppose v is defined by\n;\n;   (define v (list 'a 'b 'c 'd))\n;\n; Draw the box-and-pointer diagram that represents the list to which v is\n; bound. Suppose that we now evaluate (define w (mystery v)). Draw\n; box-and-pointer diagrams that show the structures v and w after evaluating\n; this expression. What would be printed as the values of v and w?\n\n; Here's the box and pointer diagram for v:\n;\n;        +---+---+    +---+---+    +---+---+    +---+---+\n; v ---> | . | . -----| . | . -----| . | . -----| . | / |\n;        +-|-+---+    +-|-+---+    +-|-+---+    +-|-+---+\n;          |            |            |            |\n;        +---+        +---+        +---+        +---+\n;        | a |        | b |        | c |        | d |\n;        +---+        +---+        +---+        +---+\n;\n; This is what happens after we call mystery:\n;\n;          +---------------+ +----------+ +----------------+\n;          |               | |          | |                |\n;        +---+---+    +---+|--+    +---+|--+         +---+-|-+\n; v ---> | . | / |    | . | . |    | . | . |  w ---> | . | . |\n;        +-|-+---+    +-|-+---+    +-|-+---+         +-|-+---+\n;          |            |            |                 |\n;        +---+        +---+        +---+             +---+\n;        | a |        | b |        | c |             | d |\n;        +---+        +---+        +---+             +---+\n;\n; In general, mystery reverses the list in space. It sets the cdr of the\n; second element to the first, then the cdr of the third element to the second\n; and so on. When it runs out of elements, it returns the last.\n;\n; In the end, the values are:\n;\n;   w: (d c b a)\n;   v: (a)\n"
  },
  {
    "path": "scheme/sicp/03/15.scm",
    "content": "; SICP exercise 3.15\n;\n; Draw box-and-pointer diagrams to explain the effect of set-to-wow! on the\n; structures z1 and z2 above.\n\n; Here is how the structures look before calling set-to-wow!:\n;\n;         +---+---+                      +---+---+    +---+---+    +---+---+\n; z1 ---> | . | . |              z2 ---> | . | . -----| . | . -----| . | / |\n;         +-|-+-|-+                      +-|-+---+    +-|-+---+    +-|-+---+\n;           |   |                          |            |            |\n;         +---+---+    +---+---+           |          +---+        +---+\n;  x ---> | . | . -----| . | / |           |          | a |        | b |\n;         +-|-+---+    +-|-+---+           |          +---+        +---+\n;           |            |                 |            |            |\n;         +---+        +---+               |          +-|-+---+    +-|-+---+\n;         | a |        | b |               +----------| . | . -----| . | / |\n;         +---+        +---+                          +---+---+    +---+---+\n;\n; Here's what happens after the two calls to set-to-wow!:\n;\n;         +---+---+                      +---+---+    +---+---+    +---+---+\n; z1 ---> | . | . |              z2 ---> | . | . -----| . | . -----| . | / |\n;         +-|-+-|-+                      +-|-+---+    +-|-+---+    +-|-+---+\n;           |   |                          |            |            |\n;         +---+---+    +---+---+           |          +---+        +---+\n;  x ---> | . | . -----| . | / |           |          | a |        | b |\n;         +-|-+---+    +-|-+---+           |          +---+        +---+\n;           |            |                 |                         |\n;        +-----+       +---+               |          +---+---+    +-|-+---+\n;        | wow |       | b |               +----------| . | . -----| . | / |\n;        +-----+       +---+                          +-|-+---+    +---+---+\n;                                                       |\n;                                                    +-----+\n;                                                    | wow |\n;                                                    +-----+\n"
  },
  {
    "path": "scheme/sicp/03/16.scm",
    "content": "; SICP exercise 3.16\n;\n; Ben Bitdiddle decides to write a procedure to count the number of pairs in\n; any list structure. \"It's easy,\" he reasons. \"The number of pairs in any\n; structure is the number in the car plus the number in the cdr plus one more\n; to count the current pair.\" So Ben writes the following procedure:\n;\n;   (define (count-pairs x)\n;     (if (not (pair? x))\n;         0\n;         (+ (count-pairs (car x))\n;            (count-pairs (cdr x))\n;            1)))\n;\n; Show that this procedure is not correct. In particular, draw box-and-pointer\n; diagrams representing list structures made up of exactly three pairs for\n; which Ben's procedure would return 3; return 4; never return at all.\n\n; Here are the diagrams:\n;\n; 3: +---+---+    +---+---+    +---+---+\n;    | . | . -----| . | . -----| . | / |\n;    +---+---+    +---+---+    +---+---+\n;\n; 4: +---+---+    +---+---+\n;    | . | . -----| . | / |\n;    +-|-+---+    +---+---+\n;      |            |\n;    +---+---+      |\n;    | . | . -------+\n;    +---+---+\n;\n; 7: +---+---+\n;    | . | . |\n;    +-|-+-|-+\n;      |   |\n;    +---+---+\n;    | . | . |\n;    +-|-+-|-+\n;      |   |\n;    +---+---+\n;    | . | / |\n;    +---+---+\n;\n; infinite:\n;    +---+---+    +---+---+    +---+---+\n;    | . | . -----| . | . -----| . | . |\n;    +---+---+    +---+---+    +---+-|-+\n;      |                             |\n;      +-----------------------------+\n\n(define (count-pairs x)\n  (if (not (pair? x))\n      0\n      (+ (count-pairs (car x))\n         (count-pairs (cdr x))\n         1)))\n\n(define a '(a))\n(define b (cons 'b a))\n(define c (cons a a))\n\n(define three '(a b c))\n(define four (cons b a))\n(define seven (cons c c))\n"
  },
  {
    "path": "scheme/sicp/03/17.scm",
    "content": "; SICP exercise 3.17\n;\n; Devise a correct version of count-pairs procedure of exercise 3.16 that\n; retuns the number of distinct pairs in any structure. (Hint: traverse the\n; structure, maintaining an auxiliary data structure that is used to keep\n; track of which pairs have already been counted.)\n\n(define (count-pairs x)\n  (let ((counted '()))\n    (define (count x)\n      (cond ((not (pair? x)) 0)\n            ((null? x) 0)\n            ((memq x counted) 0)\n            (else\n              (set! counted (cons x counted))\n              (+ 1\n                 (count (car x))\n                 (count (cdr x))))))\n    (count x)))\n"
  },
  {
    "path": "scheme/sicp/03/18.scm",
    "content": "; SICP exercise 3.18\n;\n; Write a procedure that examines a list and determines whether it contains a\n; cycle, that is, whether a program that tried to find the end of the list by\n; taking successive cdrs would go into an infinite loop. Exercise 3.13\n; constructed such lists.\n\n(require r5rs/init)\n\n(define (has-cycle? x)\n  (let ((counted '()))\n    (define (cycle? x)\n      (cond ((null? x) #f)\n            ((memq x counted) #t)\n            (else\n              (set! counted (cons x counted))\n              (cycle? (cdr x)))))\n    (cycle? x)))\n\n(define (lastpair x)\n  (if (null? (cdr x))\n      x\n      (lastpair (cdr x))))\n\n(define (make-cycle x)\n  (set-cdr! (lastpair x) x)\n  x)\n"
  },
  {
    "path": "scheme/sicp/03/19.scm",
    "content": "; SICP exercise 3.19\n;\n; Redo exercise 3.18 using an algorithm that takes only a constant amount of\n; space. (This requires a very clever idea.)\n\n(require r5rs/init)\n\n(define (has-cycle? x)\n  (if (null? x)\n      #f\n      (let ((p1 x)\n            (p2 (cdr x)))\n        (define (loop)\n          (cond ((null? p2) #f)\n                ((null? (cdr p2)) #f)\n                ((eq? p1 p2) #t)\n                (else\n                  (set! p1 (cdr p1))\n                  (set! p2 (cddr p2))\n                  (loop))))\n        (loop))))\n\n(define (lastpair x)\n  (if (null? (cdr x))\n      x\n      (lastpair (cdr x))))\n\n(define (make-cycle x)\n  (set-cdr! (lastpair x) x)\n  x)\n"
  },
  {
    "path": "scheme/sicp/03/20.scm",
    "content": "; SICP exercise 3.20\n;\n; Draw environment diagrams to illustrate the evaluation of the sequence of\n; expressions\n;\n;   (define x (cons 1 2))\n;   (define z (cons x x))\n;   (set-car! (cdr z) 17)\n;   (car x)\n;\n; using the procedural representation of pairs given above. (Compare exercise\n; 3.11.)\n\n; This is the environment after the two defines:\n;\n; global: +-----------------------------------------------------------------+\n;         | cons: <procedure>                                               |\n;         | car: <procedure>                                                |\n;         | cdr: <procedure>                                                |\n;         | set-car!: <procedure>                                           |\n;         | set-cdr!: <procedure>                                           |\n;         +-----------------------------------------------------------------+\n;             ^\n;             |\n;         +-----------------------+            +-----------------------+\n;         | x: 1                  |  +---------- x: <procedure>        |\n;         | y: 2                  |  |    +----- y: <procedure>        |\n;         | set-x!: <procedure>   |  |    |    | set-x!: <procedure>   |\n;         | set-y!: <procedure>   |  +----+    | set-y!: <procedure>   |\n;         | dispatch: <procedure> |  |         | dispatch: <procedure> |\n;         +---|-------------------+  |         +---|-------------------+\n;             |    ^                 |             |    ^\n;             |    |                 |             |    |\n;         +-----------+              |         +-----------+\n;  x ---> | procedure |--------------+  z ---> | procedure |\n;         +-----------+                        +-----------+\n;         parameters: m                        params: m\n;         body: (cond ((eq? m 'car) x)         body: ...\n;                     ((eq? m 'cdr) y)\n;                     ((eq? m 'set-car!) set-x!)\n;                     ((eq? m 'set-cdr!) set-y!)\n;                     (else (error \"Undefined operation - CONS\" m)))\n;\n; This is what happens after we call (set-car! (cdr z) 17)\n;\n; global: +-----------------------------------------------------------------+\n;         | cons: <procedure>                                               |\n;         | car: <procedure>                                                |\n;         | cdr: <procedure>                                                |\n;         | set-car!: <procedure>                                           |\n;         | set-cdr!: <procedure>                                           |\n;         +-----------------------------------------------------------------+\n;             ^\n;             |\n;         +-----------------------+            +-----------------------+\n;         | x: 17                 |  +---------- x: <procedure>        |\n;         | y: 2                  |  |    +----- y: <procedure>        |\n;         | set-x!: <procedure>   |  |    |    | set-x!: <procedure>   |\n;         | set-y!: <procedure>   |  +----+    | set-y!: <procedure>   |\n;         | dispatch: <procedure> |  |         | dispatch: <procedure> |\n;         +---|-------------------+  |         +---|-------------------+\n;             |    ^                 |             |    ^\n;             |    |                 |             |    |\n;         +-----------+              |         +-----------+\n;  x ---> | procedure |--------------+  z ---> | procedure |\n;         +-----------+                        +-----------+\n;         parameters: m                        params: m\n;         body: (cond ((eq? m 'car) x)         body: ...\n;                     ((eq? m 'cdr) y)\n;                     ((eq? m 'set-car!) set-x!)\n;                     ((eq? m 'set-cdr!) set-y!)\n;                     (else (error \"Undefined operation - CONS\" m)))\n;\n; Essentially, nothing drastic happens. The only difference is where the\n; variable x in the frame of the procedure named pointed by x changes from 1\n; to 17.\n"
  },
  {
    "path": "scheme/sicp/03/21.scm",
    "content": "; SICP exercise 3.21\n;\n; Ben Bitdiddle decides to test the queue implementation described above. He\n; types in the procedures to the List interpreter and proceeds to try them\n; out:\n;\n;   (define q1 (make-queue))\n;\n;   (insert-queue! q1 'a)\n;   ((a) a)\n;\n;   (insert-queue! q1 'b)\n;   ((a b) b)\n;\n;   (delete-queue! q1)\n;   ((b) b)\n;\n;   (delete-queue! q1)\n;   (() b)\n;\n; \"It's all wrong!\" he complains. \"The interpreter's response shows that the\n; last item is inserted into the queue twice. And when I delete both items,\n; the second b is still there, so the queue isn't empty, even though it's\n; supposed to be.\" Eva Lu Ator suggests that Ben has misunderstood what is\n; happening. \"It's not that the items are going into the queue twice,\" she\n; explains. \"It's just that the standard Lisp printer doesn't know how to make\n; sense of the queue representation. If you want to see the queue printed\n; correctly, you'll have to define your own print procedure for queues.\"\n; Explain what Eva Lu is talking about. In particular, show why Ben's examples\n; produce the printed results that they do. Define a procedure print-queue\n; that takes a queue as input and prints the sequence of items in the queue.\n\n; It's quite simple. The queue is a pair whose car is a list of the queue\n; elements and whose cdr is the last pair of that list. Removing an element\n; from the queue does not update the cdr of that pair - when the last element\n; is removed, the queue still holds a reference to a pair whose car is that\n; element. That's why b is printed after an empty list.\n;\n; You can find print-queue in the end of this file.\n\n(require r5rs/init)\n\n(define (front-ptr queue) (car queue))\n(define (rear-ptr queue) (cdr queue))\n(define (set-front-ptr! queue item) (set-car! queue item))\n(define (set-rear-ptr! queue item) (set-cdr! queue item))\n\n(define (empty-queue? queue) (null? (front-ptr queue)))\n(define (make-queue) (cons '() '()))\n(define (front-queue queue)\n  (if (empty-queue? queue)\n      (error \"FRONT called with an empty queue\" queue)\n      (car (front-ptr queue))))\n(define (insert-queue! queue item)\n  (let ((new-pair (cons item '())))\n    (cond ((empty-queue? queue)\n           (set-front-ptr! queue new-pair)\n           (set-rear-ptr! queue new-pair)\n           queue)\n          (else\n            (set-cdr! (rear-ptr queue) new-pair)\n            (set-rear-ptr! queue new-pair)\n            queue))))\n(define (delete-queue! queue)\n  (cond ((empty-queue? queue)\n         (error \"DELETE! called with an empty queue\" queue))\n        (else\n          (set-front-ptr! queue (cdr (front-ptr queue)))\n          queue)))\n\n(define (print-queue queue)\n  (display \"#<queue:\")\n  (display (front-ptr queue))\n  (display \">\")\n  (newline))\n"
  },
  {
    "path": "scheme/sicp/03/22.scm",
    "content": "; SICP exercise 3.22\n;\n; Instead of representing the queue as a pair of pointes, we can build a queue\n; as a procedure with local state. The local state will consist of pointers to\n; the beginning and the end of an ordinary list. Thus, the make-queue\n; procedure will have the form\n;\n; (define (make-queue)\n;   (let ((front-ptr ...)\n;         (rear-ptr ...))\n;     <definitions of internal procedures>\n;     (define (dispatch m) ...)\n;     dispatch))\n;\n; Complete the definition of make-queue and provide implementations of the\n; queue operations using this representation.\n\n(require r5rs/init)\n\n(define (empty-queue? queue) ((queue 'empty?)))\n(define (front-queue queue) ((queue 'front)))\n(define (insert-queue! queue item) ((queue 'insert) item))\n(define (delete-queue! queue) ((queue 'delete)))\n\n(define (make-queue)\n  (let ((front-ptr '())\n        (rear-ptr '()))\n    (define (empty?)\n      (null? front-ptr))\n    (define (front)\n      (if (empty?)\n          (error \"FRONT called with an empty queue\")\n          (car front-ptr)))\n    (define (insert item)\n      (let ((new-pair (cons item '())))\n        (cond ((empty?)\n               (set! front-ptr new-pair)\n               (set! rear-ptr new-pair))\n              (else\n               (set-cdr! rear-ptr new-pair)\n               (set! rear-ptr new-pair)))\n        dispatch))\n    (define (delete)\n      (cond ((empty?)\n             (error \"DELETE called with an empty queue\"))\n            (else\n              (set! front-ptr (cdr front-ptr))\n              dispatch)))\n\n    (define (dispatch m)\n      (cond ((eq? m 'empty?) empty?)\n            ((eq? m 'front) front)\n            ((eq? m 'insert) insert)\n            ((eq? m 'delete) delete)\n            (else (error \"Undefined operation - QUEUE\" m))))\n    dispatch))\n"
  },
  {
    "path": "scheme/sicp/03/23.scm",
    "content": "; SICP exercise 3.23\n;\n; A deque (\"double-ended queue\") is a sequence in which items can be\n; inserted and deleted at either the front or the rear. Operations on deques\n; are the constructor make-deque, the predicate empty-deque?, selectors\n; front-deque and rear-deque and mutators front-insert-deque!,\n; rear-insert-deque!, front-delete-deque! and rear-delete-deque!. Show how to\n; represent deques using pairs, and give implementation of the operations. All\n; operations should be accomplished in Θ(1) steps.\n\n; Oooh, nice! This requires implementing a doubly-linked list. The segments of\n; the lists will be created with make-segment and each will contain an item\n; and a pointer to the previous and the next segment in the queue.\n\n(require r5rs/init)\n\n(define (front-ptr deque) (car deque))\n(define (rear-ptr deque) (cdr deque))\n(define (set-front-ptr! deque item) (set-car! deque item))\n(define (set-rear-ptr! deque item) (set-cdr! deque item))\n\n(define (make-segment item previous next) (cons item (cons previous next)))\n(define (item segment) (car segment))\n(define (previous segment) (cadr segment))\n(define (next segment) (cddr segment))\n(define (set-previous! segment previous) (set-car! (cdr segment) previous))\n(define (set-next! segment next) (set-cdr! (cdr segment) next))\n\n(define (make-deque) (cons '() '()))\n(define (empty-deque? deque) (null? (front-ptr deque)))\n(define (front-deque deque)\n  (if (empty-deque? deque)\n      (error \"FRONT called with an empty deque\" deque)\n      (item (front-ptr deque))))\n(define (rear-deque deque)\n  (if (empty-deque? deque)\n      (error \"REAR called with an empty deque\" deque)\n      (item (rear-ptr deque))))\n(define (front-insert-deque! deque item)\n  (let* ((front (front-ptr deque))\n         (new-segment (make-segment item '() front)))\n    (cond ((empty-deque? deque)\n           (set-front-ptr! deque new-segment)\n           (set-rear-ptr! deque new-segment))\n          (else\n           (set-previous! front new-segment)\n           (set-front-ptr! deque new-segment)))\n    deque))\n(define (rear-insert-deque! deque item)\n  (let* ((rear (rear-ptr deque))\n         (new-segment (make-segment item rear '())))\n    (cond ((empty-deque? deque)\n           (set-front-ptr! deque new-segment)\n           (set-rear-ptr! deque new-segment))\n          (else\n           (set-next! rear new-segment)\n           (set-rear-ptr! deque new-segment)))\n    deque))\n(define (front-delete-deque! deque)\n  (cond ((empty-deque? deque)\n         (error \"FRONT-DELETE called with an empty deque\" deque))\n        ((null? (next (front-ptr deque)))\n         (set-front-ptr! deque '())\n         (set-rear-ptr! deque '()))\n        (else\n         (set-front-ptr! deque (next (front-ptr deque)))\n         (set-previous! (front-ptr deque) '())))\n  deque)\n(define (rear-delete-deque! deque)\n  (cond ((empty-deque? deque)\n         (error \"REAR-DELETE called with an empty deque\" deque))\n        ((null? (previous (rear-ptr deque)))\n         (set-front-ptr! deque '())\n         (set-rear-ptr! deque '()))\n        (else\n         (set-rear-ptr! deque (previous (rear-ptr deque)))\n         (set-next! (rear-ptr deque) '())))\n  deque)\n"
  },
  {
    "path": "scheme/sicp/03/24.scm",
    "content": "; SICP exercise 3.24\n;\n; In the table implementations above, the keys are tested for equality using\n; equal? (called by assoc). This is not always the appropriate test. For\n; instance, we might have a table with numeric keys in which we don't need an\n; exact match to the number we're looking up, but only a number within some\n; tolerance of it. Design a table constructor make-table that takes as an\n; argument a same-key? procedure that will be used to test \"equality\" of keys.\n; make-table should return a dispatch procedure that can be used to access\n; appropriate lookup and insert! procedures for a local table.\n\n(require r5rs/init)\n\n(define (make-table same-key?)\n  (let ((table '(*table*)))\n    (define (find-pair key)\n      (define (search remaining)\n        (cond ((null? remaining) #f)\n              ((same-key? key (caar remaining)) (car remaining))\n              (else (search (cdr remaining)))))\n\n      (search (cdr table)))\n\n    (define (lookup key)\n      (let ((pair (find-pair key)))\n        (if pair\n            (cdr pair)\n            false)))\n\n    (define (insert key value)\n      (let ((pair (find-pair key)))\n        (cond (pair (set-cdr! pair value))\n              (else (set-cdr! table (cons (cons key value)\n                                          (cdr table)))))\n        dispatch))\n\n    (define (dispatch m)\n      (cond ((eq? m 'lookup) lookup)\n            ((eq? m 'insert) insert)\n            (else (error \"Unrecognized message - TABLE\" m))))\n    dispatch))\n\n(define (lookup key table) ((table 'lookup) key))\n(define (insert! key value table) ((table 'insert) key value))\n"
  },
  {
    "path": "scheme/sicp/03/25.scm",
    "content": "; SICP exercise 3.25\n;\n; Generalizing one- and two- dimensional tables, show how to implement a table\n; in which values are stored under an arbitrary number of keys and different\n; values may be stored under different numbers of keys. The lookup and insert!\n; procedures should take as input a list of keys used to access the table.\n\n; I fairly uncertain why we're not using list as key. In good spirit, however,\n; I'm going to let that pass and implement nested tables.\n;\n(require r5rs/init)\n\n(define (make-keyed-table key)\n  (list key))\n\n(define (make-table)\n  (make-keyed-table '*table))\n\n(define (find-pair key table)\n  (define (search records)\n    (cond ((null? records) false)\n          ((equal? key (caar records)) (car records))\n          (else (search (cdr records)))))\n  (search (cdr table)))\n\n(define (lookup keys table)\n  (let* ((first-key (car keys))\n         (rest-keys (cdr keys))\n         (record (find-pair first-key table)))\n    (cond ((not record) #f)\n          ((null? rest-keys) (cdr record))\n          (else (lookup rest-keys record)))))\n\n(define (insert! keys value table)\n  (define (prepend-pair! pair)\n    (set-cdr! table (cons pair (cdr table))))\n  (let* ((first-key (car keys))\n         (rest-keys (cdr keys))\n         (pair (find-pair first-key table)))\n    (cond ((and pair (null? rest-keys))\n           (set-cdr! pair value))\n          (pair\n           (insert! rest-keys value pair))\n          ((null? rest-keys)\n           (prepend-pair! (cons first-key value)))\n          (else\n           (let ((new-table (make-keyed-table first-key)))\n             (prepend-pair! new-table)\n             (insert! rest-keys value new-table))))\n    table))\n"
  },
  {
    "path": "scheme/sicp/03/26.scm",
    "content": "; SICP exercise 3.26\n;\n; To search a table as implemented above, one needs to scan the list of\n; records. This is basically the unordered list representation of Section\n; 2.3.3. For large tables, it may be more efficient to structure the table in\n; a different manner. Describe a table implementation where the (key, value)\n; records are organized using a binary tree, assuming that keys can be ordered\n; in some way (e.g. numerically or alphabetically.) (Compare exercise 2.66 of\n; Chapter 2.)\n\n; I am so happy you said \"describe\".\n;\n; Anyway, it is fairly simple - we just organize the table in a binary tree\n; instead of a list. Whenever we're looking up a key, we're doing a binary\n; tree search for the car of the entry of each one and if we find such a node,\n; we return the cdr of its entry. This performs in O(log(n)) time, which is\n; nice.\n;\n; The hairy side is insert!. On one hand, we can recreate the tree on every\n; insert!. This would keep it balanced and it would perform in O(log(n)), but\n; the insertion cost will be huge. On the other hand, modifying the tree is\n; not straightforward - if we just find a branch where to add a new element,\n; the performance will degrade to O(n), since the tree will not be balanced.\n; And if we want to keep it balanced, we need to learn about AVL-trees,\n; red-black trees and various other balanced binary trees.\n;\n; It's not for the weak of heart.\n"
  },
  {
    "path": "scheme/sicp/03/27.scm",
    "content": "; SICP exercise 3.27\n;\n; Memoization (also called tabulation) is a technique that enables a procedure\n; to record, in a local table, values that have previously been computed. This\n; technique can make a vast difference in the performance of a program. A\n; memoized procedure matintains a table in which values of previous calls are\n; stored using as keys the arguments that produced the values. When the\n; memoized procedure is asked to compute a value, it first checks the table to\n; see if the value is already there and, if so, just returns that value.\n; Otherwise, it compute sthe new value in the ordinary way and stores this in\n; the table. As an example of memoization, recall from section 1.2.2 the\n; exponential process for computing Fibonacci numbers:\n;\n;   (define (fib n)\n;     (cond ((=n 0) 0)\n;           ((=n 1) 1)\n;           (else (+ (fib (- n 1))\n;                    (fib (- n 2))))))\n;\n; The memoized version of the same procedure is\n;\n;   (define memo-fib\n;     (memoize (lambda (n)\n;                (cond ((= n 0) 0)\n;                      ((= n 1) 1)\n;                      (else (+ (memo-fib (- n 1))\n;                               (memo-fib (- n 2))))))))\n;\n; where the memoizer is defined as\n;\n;   (define (memoize f)\n;     (let ((table (make-table)))\n;       (lambda (x)\n;         (let ((previously-computed-result (lookup x table)))\n;           (or previously-computed-result\n;               (let ((result (f x)))\n;                 (insert! x result table)\n;                 result))))))\n;\n; Draw an environment diagram to analyze the computation (memo-fib 3). Explain\n; why memo-fib computes the nth Fibonacci number in a number of steps\n; proportional to n. Would the scheme still work if we had simply defined\n; memo-fib to be (memoize fib)?\n\n; God, I hate environment diagrams. Here's how the environment looks before\n; computing (memo-fib 3).\n;\n; globals:\n; +-------------------------------------------------------------------------+\n; | memoize: <procedure>                                                    |\n; | memo-fib: <procedure>                                                   |\n; +--|----------------------------------------------------------------------+\n;    |            ^\n;    |            |\n;    |   +----------------+\n;    |   | f: <procedure> --------> <lambda>\n;    |   +----------------+         params: n\n;    |            ^                 body: (cond ((= n 0) 0)\n;    |            |                             ...\n;    |   +----------------+\n;    |   | table: <table> --------> (*table)\n;    |   +----------------+\n;    |            ^\n;    |            |\n;    +------> <lambda>\n;             parameters: x\n;             body: (let ((...\n;\n; When we call (memo-fib 3) it does a table lookup, fails and then goes to\n; calculate [1] (+ (memo-fib 2) (memo-fib 1)). Let's assume left-to-right\n; evaluation. It procedures to evaluate (memo-fib 2) which fails the table\n; lookup and then results to [2] (+ (memo-fib 1) (memo-fib 0)). Both fail the\n; lookup, but at least they return immediatelly and the results are written in\n; the table. This is how the environment looks when [2] completes:\n;\n; globals:\n; +-------------------------------------------------------------------------+\n; | memoize: <procedure>                                                    |\n; | memo-fib: <procedure>                                                   |\n; +--|----------------------------------------------------------------------+\n;    |            ^\n;    |            |\n;    |   +----------------+\n;    |   | f: <procedure> --------> <lambda>\n;    |   +----------------+         params: n\n;    |            ^                 body: (cond ((= n 0) 0)\n;    |            |                             ...\n;    |   +----------------+\n;    |   | table: <table> --------> (*table (1 . 1)\n;    |   +----------------+                 (0 . 0))\n;    |    ^       ^\n;    |    |       |\n;    +----|-> <lambda>\n;         |   parameters: x\n;         |   body: (let ((...\n;         |\n;         +------------------------------------+\n;     [1] |                                [2] |\n;     +--------------------------------+   +--------------------------------+\n;     | x: 3                           |   | x: 2                           |\n;     | previously-computed-result: #f |   | previously-computed-result: #f |\n;     +--------------------------------+   +--------------------------------+\n;\n; When (f x) completes, the result is written in the table and the function\n; returns it. This is how the environment looks after (make-fib 2) has\n; returned:\n;\n; globals:\n; +-------------------------------------------------------------------------+\n; | memoize: <procedure>                                                    |\n; | memo-fib: <procedure>                                                   |\n; +--|----------------------------------------------------------------------+\n;    |            ^\n;    |            |\n;    |   +----------------+\n;    |   | f: <procedure> --------> <lambda>\n;    |   +----------------+         params: n\n;    |            ^                 body: (cond ((= n 0) 0)\n;    |            |                             ...\n;    |   +----------------+\n;    |   | table: <table> --------> (*table (2 . 2)\n;    |   +----------------+                 (1 . 1)\n;    |    ^       ^                         (0 . 0))\n;    |    |       |\n;    +----|-> <lambda>\n;         |   parameters: x\n;         |   body: (let ((...\n;     [1] |\n;     +--------------------------------+\n;     | x: 3                           |\n;     | previously-computed-result: #f |\n;     +--------------------------------+\n;\n; Now the second part of [1] computes, which is (memo-fib 1). This time it is\n; found in the table and instead of calling f, the lookup just returns 1. The\n; addition is carried out and the final result, 3, is written in the table and\n; then returned. In the end, we have the following environment:\n;\n; globals:\n; +-------------------------------------------------------------------------+\n; | memoize: <procedure>                                                    |\n; | memo-fib: <procedure>                                                   |\n; +--|----------------------------------------------------------------------+\n;    |            ^\n;    |            |\n;    |   +----------------+\n;    |   | f: <procedure> --------> <lambda>\n;    |   +----------------+         params: n\n;    |            ^                 body: (cond ((= n 0) 0)\n;    |            |                             ...\n;    |   +----------------+\n;    |   | table: <table> --------> (*table (3 . 3)\n;    |   +----------------+                 (2 . 2)\n;    |            ^                         (1 . 1)\n;    |            |                         (0 . 0))\n;    +------> <lambda>\n;             parameters: x\n;             body: (let ((...\n;\n; You can note, that (memo-fib 1) invoked f only once. Even if it had to be\n; calculated once in [1] and once in [2]. Furthermore, note that if we call\n; (memo-fib 3) now, f would not get invoked at all. That's why the steps are\n; proportional to n.\n;\n; This scheme would not work if we did:\n;\n;   (define memo-fib (memoize fib))\n;\n; Or more accuratelly, it would work half-way. The problem is that fib calls\n; recursively itself, instead of memo-fib. Thus, intermediate values are not\n; calculated and the time is still exponential. The only benefit is that if we\n; call memo-fib with the same argument twice, it will reuse the result from\n; the first calculation.\n"
  },
  {
    "path": "scheme/sicp/03/28.scm",
    "content": "; SICP exercise 3.28\n;\n; Define an or-gate as a primitive function box. Your or-gate constructor\n; should be similar to and-gate.\n\n; Sure. Let's grab all the code we've written so far first. The solution is\n; somewhere in there.\n\n; Half-adder & adder:\n\n(require r5rs/init)\n\n(define (half-adder a b s c)\n  (let ((d (make-wire)) (e (make-wire)))\n    (or-gate a b d)\n    (and-gate a b c)\n    (inverter c e)\n    (and-gate d e s)\n    'ok))\n\n(define (full-adder a b c-in sum c-out)\n  (let ((s (make-wire))\n        (c1 (make-wire))\n        (c2 (make-wire)))\n    (half-adder b c-in s c1)\n    (half-adder a s sum c2)\n    (or-gate c1 c2 c-out)\n    'ok))\n\n; Primitive function boxes\n\n(define (inverter input output)\n  (define (invert-input)\n    (let ((new-value (logical-not (get-signal input))))\n      (after-delay inverter-delay\n                   (lambda () (set-signal! output new-value)))))\n  (add-action! input invert-input)\n  'ok)\n\n(define (and-gate a1 a2 output)\n  (define (and-action-procedure)\n    (let ((new-value (logical-and (get-signal a1) (get-signal a2))))\n      (after-delay and-gate-delay (lambda () (set-signal! output new-value)))))\n  (add-action! a1 and-action-procedure)\n  (add-action! a2 and-action-procedure)\n  'ok)\n\n(define (or-gate o1 o2 output)\n  (define (or-action-procedure)\n    (let ((new-value (logical-or (get-signal o1) (get-signal o2))))\n      (after-delay or-gate-delay (lambda () (set-signal! output new-value)))))\n  (add-action! o1 or-action-procedure)\n  (add-action! o2 or-action-procedure)\n  'ok)\n\n; Logical functions\n\n(define (logical-not s)\n  (cond ((= s 0) 1)\n        ((= s 1) 0)\n        (else (error \"Invalid signal\" s))))\n\n(define (logical-and a b)\n  (cond ((and (= a 0) (= b 0)) 0)\n        ((and (= a 0) (= b 1)) 0)\n        ((and (= a 1) (= b 0)) 0)\n        ((and (= a 1) (= b 1)) 1)\n        (else (error \"Invalid signals\" a b))))\n\n(define (logical-or a b)\n  (cond ((and (= a 0) (= b 0)) 0)\n        ((and (= a 0) (= b 1)) 1)\n        ((and (= a 1) (= b 0)) 1)\n        ((and (= a 1) (= b 1)) 1)\n        (else (error \"Invalid signals\" a b))))\n\n; Wires\n\n(define (make-wire)\n  (let ((signal-value 0) (action-procedures '()))\n    (define (set-my-signal! new-value)\n      (if (not (= signal-value new-value))\n          (begin (set! signal-value new-value)\n                 (call-each action-procedures))\n          'done))\n    (define (accept-action-procedure! proc)\n      (set! action-procedures (cons proc action-procedures))\n      (proc))\n    (define (dispatch m)\n      (cond ((eq? m 'get-signal) signal-value)\n            ((eq? m 'set-signal!) set-my-signal!)\n            ((eq? m 'add-action!) accept-action-procedure!)\n            (else (error \"Unknown operation -- WIRE\" m))))\n    dispatch))\n\n(define (call-each procedures)\n  (if (null? procedures)\n      'done\n      (begin\n        ((car procedures))\n        (call-each (cdr procedures)))))\n\n(define (get-signal wire) (wire 'get-signal))\n(define (set-signal! wire new-value) ((wire 'set-signal!) new-value))\n(define (add-action! wire action-procedure) ((wire 'add-action!) action-procedure))\n\n; Queues\n\n(define (front-ptr queue) (car queue))\n(define (rear-ptr queue) (cdr queue))\n(define (set-front-ptr! queue item) (set-car! queue item))\n(define (set-rear-ptr! queue item) (set-cdr! queue item))\n\n(define (make-queue) (cons '() '()))\n(define (empty-queue? queue) (null? (front-ptr queue)))\n(define (front-queue queue)\n  (if (empty-queue? queue)\n      (error \"FRONT called with an empty queue\" queue)\n      (car (front-ptr queue))))\n\n(define (insert-queue! queue item)\n  (let ((new-pair (cons item '())))\n    (cond ((empty-queue? queue)\n           (set-front-ptr! queue new-pair)\n           (set-rear-ptr! queue new-pair))\n          (else\n           (set-cdr! (rear-ptr queue) new-pair)\n           (set-rear-ptr! queue new-pair)))\n    queue))\n\n(define (delete-queue! queue)\n  (cond ((empty-queue? queue)\n         (error \"DELETE! called with an empty queue\" queue))\n        (else\n         (set-front-ptr! queue (cdr (front-ptr queue)))\n         queue)))\n\n; The agenda\n\n(define (make-time-segment time queue) (cons time queue))\n(define (segment-time s) (car s))\n(define (segment-queue s) (cdr s))\n\n(define (make-agenda) (list 0))\n(define (current-time agenda) (car agenda))\n(define (set-current-time! agenda time) (set-car! agenda time))\n(define (segments agenda) (cdr agenda))\n(define (set-segments! agenda segments) (set-cdr! agenda segments))\n(define (first-segment agenda) (car (segments agenda)))\n(define (rest-segments agenda) (cdr (segments agenda)))\n(define (empty-agenda? agenda) (null? (segments agenda)))\n\n(define (add-to-agenda! time action agenda)\n  (define (belongs-before? segments)\n    (or (null? segments)\n        (< time (segment-time (car segments)))))\n  (define (make-new-time-segment time action)\n    (let ((q (make-queue)))\n      (insert-queue! q action)\n      (make-time-segment time q)))\n  (define (add-to-segments! segments)\n    (if (= (segment-time (car segments)) time)\n        (insert-queue! (segment-queue (car segments))\n                       action)\n        (let ((rest (cdr segments)))\n          (if (belongs-before? rest)\n              (set-cdr! segments (cons (make-new-time-segment time action) rest))\n              (add-to-segments! rest)))))\n  (let ((segments (segments agenda)))\n    (if (belongs-before? segments)\n        (set-segments! agenda (cons (make-new-time-segment time action) segments))\n        (add-to-segments! segments))))\n\n(define (remove-first-agenda-item! agenda)\n  (let ((q (segment-queue (first-segment agenda))))\n    (delete-queue! q)\n    (if (empty-queue? q)\n        (set-segments! agenda (rest-segments agenda))\n        'done)))\n\n(define (first-agenda-item agenda)\n  (if (empty-agenda? agenda)\n      (error \"Agenda is empty -- FIRST-AGENDA-ITEM\")\n      (let ((first-seg (first-segment agenda)))\n        (set-current-time! agenda (segment-time first-seg))\n        (front-queue (segment-queue first-seg)))))\n\n; Delays\n\n(define inverter-delay 2)\n(define and-gate-delay 3)\n(define or-gate-delay 5)\n\n; Simulation infrastructure\n\n(define the-agenda (make-agenda))\n(define (after-delay delay action)\n  (add-to-agenda! (+ delay (current-time the-agenda))\n                  action\n                  the-agenda))\n\n(define (propagate)\n  (if (empty-agenda? the-agenda)\n      'done\n      (let ((first-item (first-agenda-item the-agenda)))\n        (first-item)\n        (remove-first-agenda-item! the-agenda)\n        (propagate))))\n\n(define (probe name wire)\n  (add-action! wire\n               (lambda ()\n                 (display name)\n                 (display \" \")\n                 (display (current-time the-agenda))\n                 (display \"  New-value = \")\n                 (display (get-signal wire))\n                 (newline))))\n"
  },
  {
    "path": "scheme/sicp/03/29.scm",
    "content": "; SICP exercise 3.29\n;\n; Another way to construct an or-gate is as a compound digital device, built\n; from and-gates and inverters. Define a procedure or-gate that accomplishes\n; this. What is the delay of the or-gate in terms of and-gate-delay and\n; inverter-delay?\n\n; If we apply De Morgan's law, we get that a || b = !(!a && !b). Here's how\n; the diagram looks:\n;             _\n; a ---|>o---| \\\n;            | |---|>o--- r\n; b ---|>o---|_/\n;\n; The signal travels through an inverted, then an AND gate, then another\n; inverter, so it is (+ (2 inverter-delay) and-gate-delay).\n\n(require r5rs/init)\n\n(define (half-adder a b s c)\n  (let ((d (make-wire)) (e (make-wire)))\n    (or-gate a b d)\n    (and-gate a b c)\n    (inverter c e)\n    (and-gate d e s)\n    'ok))\n\n(define (full-adder a b c-in sum c-out)\n  (let ((s (make-wire))\n        (c1 (make-wire))\n        (c2 (make-wire)))\n    (half-adder b c-in s c1)\n    (half-adder a s sum c2)\n    (or-gate c1 c2 c-out)\n    'ok))\n\n; Primitive function boxes\n\n(define (inverter input output)\n  (define (invert-input)\n    (let ((new-value (logical-not (get-signal input))))\n      (after-delay inverter-delay\n                   (lambda () (set-signal! output new-value)))))\n  (add-action! input invert-input)\n  'ok)\n\n(define (and-gate a1 a2 output)\n  (define (and-action-procedure)\n    (let ((new-value (logical-and (get-signal a1) (get-signal a2))))\n      (after-delay and-gate-delay (lambda () (set-signal! output new-value)))))\n  (add-action! a1 and-action-procedure)\n  (add-action! a2 and-action-procedure)\n  'ok)\n\n(define (or-gate o1 o2 output)\n  (let ((a (make-wire))\n        (b (make-wire))\n        (c (make-wire)))\n    (inverter o1 a)\n    (inverter o2 b)\n    (and-gate a b c)\n    (inverter c output)\n    'ok))\n\n; Logical functions\n\n(define (logical-not s)\n  (cond ((= s 0) 1)\n        ((= s 1) 0)\n        (else (error \"Invalid signal\" s))))\n\n(define (logical-and a b)\n  (cond ((and (= a 0) (= b 0)) 0)\n        ((and (= a 0) (= b 1)) 0)\n        ((and (= a 1) (= b 0)) 0)\n        ((and (= a 1) (= b 1)) 1)\n        (else (error \"Invalid signals\" a b))))\n\n; Wires\n\n(define (make-wire)\n  (let ((signal-value 0) (action-procedures '()))\n    (define (set-my-signal! new-value)\n      (if (not (= signal-value new-value))\n          (begin (set! signal-value new-value)\n                 (call-each action-procedures))\n          'done))\n    (define (accept-action-procedure! proc)\n      (set! action-procedures (cons proc action-procedures))\n      (proc))\n    (define (dispatch m)\n      (cond ((eq? m 'get-signal) signal-value)\n            ((eq? m 'set-signal!) set-my-signal!)\n            ((eq? m 'add-action!) accept-action-procedure!)\n            (else (error \"Unknown operation -- WIRE\" m))))\n    dispatch))\n\n(define (call-each procedures)\n  (if (null? procedures)\n      'done\n      (begin\n        ((car procedures))\n        (call-each (cdr procedures)))))\n\n(define (get-signal wire) (wire 'get-signal))\n(define (set-signal! wire new-value) ((wire 'set-signal!) new-value))\n(define (add-action! wire action-procedure) ((wire 'add-action!) action-procedure))\n\n; Queues\n\n(define (front-ptr queue) (car queue))\n(define (rear-ptr queue) (cdr queue))\n(define (set-front-ptr! queue item) (set-car! queue item))\n(define (set-rear-ptr! queue item) (set-cdr! queue item))\n\n(define (make-queue) (cons '() '()))\n(define (empty-queue? queue) (null? (front-ptr queue)))\n(define (front-queue queue)\n  (if (empty-queue? queue)\n      (error \"FRONT called with an empty queue\" queue)\n      (car (front-ptr queue))))\n\n(define (insert-queue! queue item)\n  (let ((new-pair (cons item '())))\n    (cond ((empty-queue? queue)\n           (set-front-ptr! queue new-pair)\n           (set-rear-ptr! queue new-pair))\n          (else\n           (set-cdr! (rear-ptr queue) new-pair)\n           (set-rear-ptr! queue new-pair)))\n    queue))\n\n(define (delete-queue! queue)\n  (cond ((empty-queue? queue)\n         (error \"DELETE! called with an empty queue\" queue))\n        (else\n         (set-front-ptr! queue (cdr (front-ptr queue)))\n         queue)))\n\n; The agenda\n\n(define (make-time-segment time queue) (cons time queue))\n(define (segment-time s) (car s))\n(define (segment-queue s) (cdr s))\n\n(define (make-agenda) (list 0))\n(define (current-time agenda) (car agenda))\n(define (set-current-time! agenda time) (set-car! agenda time))\n(define (segments agenda) (cdr agenda))\n(define (set-segments! agenda segments) (set-cdr! agenda segments))\n(define (first-segment agenda) (car (segments agenda)))\n(define (rest-segments agenda) (cdr (segments agenda)))\n(define (empty-agenda? agenda) (null? (segments agenda)))\n\n(define (add-to-agenda! time action agenda)\n  (define (belongs-before? segments)\n    (or (null? segments)\n        (< time (segment-time (car segments)))))\n  (define (make-new-time-segment time action)\n    (let ((q (make-queue)))\n      (insert-queue! q action)\n      (make-time-segment time q)))\n  (define (add-to-segments! segments)\n    (if (= (segment-time (car segments)) time)\n        (insert-queue! (segment-queue (car segments))\n                       action)\n        (let ((rest (cdr segments)))\n          (if (belongs-before? rest)\n              (set-cdr! segments (cons (make-new-time-segment time action) rest))\n              (add-to-segments! rest)))))\n  (let ((segments (segments agenda)))\n    (if (belongs-before? segments)\n        (set-segments! agenda (cons (make-new-time-segment time action) segments))\n        (add-to-segments! segments))))\n\n(define (remove-first-agenda-item! agenda)\n  (let ((q (segment-queue (first-segment agenda))))\n    (delete-queue! q)\n    (if (empty-queue? q)\n        (set-segments! agenda (rest-segments agenda))\n        'done)))\n\n(define (first-agenda-item agenda)\n  (if (empty-agenda? agenda)\n      (error \"Agenda is empty -- FIRST-AGENDA-ITEM\")\n      (let ((first-seg (first-segment agenda)))\n        (set-current-time! agenda (segment-time first-seg))\n        (front-queue (segment-queue first-seg)))))\n\n; Delays\n\n(define inverter-delay 2)\n(define and-gate-delay 3)\n\n; Simulation infrastructure\n\n(define the-agenda (make-agenda))\n(define (after-delay delay action)\n  (add-to-agenda! (+ delay (current-time the-agenda))\n                  action\n                  the-agenda))\n\n(define (propagate)\n  (if (empty-agenda? the-agenda)\n      'done\n      (let ((first-item (first-agenda-item the-agenda)))\n        (first-item)\n        (remove-first-agenda-item! the-agenda)\n        (propagate))))\n\n(define (probe name wire)\n  (add-action! wire\n               (lambda ()\n                 (display name)\n                 (display \" \")\n                 (display (current-time the-agenda))\n                 (display \"  New-value = \")\n                 (display (get-signal wire))\n                 (newline))))\n"
  },
  {
    "path": "scheme/sicp/03/30.scm",
    "content": "; SICP exercise 3.30\n;\n; Figure 3.27 shows a ripple-carry adder formed by stringing together n\n; full-adders. This is the simplest form of parallel adder for adding two\n; n-bit binary numbers. The inputs A₁, A₂, A₃, ..., Aᵢ and B₁, B₂, B₃, ..., Bᵢ\n; are the two binary numbers to be added (each Aᵣ and Bᵣ is a 0 or a 1). The\n; circuit generates S₁, S₂, S₃, ..., Sᵢ, the i bits of the sum, and C , the\n; carry from the addition. Write a procedure ripple-carry-adder that generates\n; that circuit. The procedure should take as arguments three lists of i wires\n; each - the Aᵣ, the Bᵣ and the Sᵣ - and also another wire C. The major\n; drawback of the ripple-carry adder is the need to wait for the signals to\n; propagate. What is the delay needed to obtain the complete output from an\n; i-bit ripple-carry adder, expressed in terms of the delays of and-gates,\n; or-gates, and inverters?\n\n; The ripple-carry-adder procedure is defined below.\n;\n; As for the delay:\n;\n; The half-adder has the following delays for each output:\n;\n;   s: and + not + and | or + and (whichever is slower)\n;   c: and\n;\n; The full-adder has the following delays:\n;\n;   sum: and + not + and | or + and\n;   c-out: (and + not + and | or + and) + and + or\n;\n; Finally, the delay of C an n-bit ripple adder is:\n;\n;   n-ripple: n((and + not + and | or + and) + and + or)\n;\n; With the delays we have defined, this is either:\n;\n;   n(3and + or + not)\n;\n; or\n;\n;   n(2or + 2and)\n;\n; whichever is slower. However, we need wait for the last SUM too. We can\n; subtract (and + or) from the time (since this is the time that takes the\n; signal to travel through the carry from the second half-adder in the last\n; adder and then through the and gate) and then we can add the s time for\n; another half-adder, which makes the total time:\n;\n;   n(3and + or + not) + and + not - or\n;\n; or, again:\n;\n;   n(2or + 2and)\n\n(require r5rs/init)\n\n; Ripple-carry adder\n\n(define (ripple-carry-adder a b c-in s c-out)\n  (define (ripple a b s c)\n    (cond ((null? (cdr a))\n           (full-adder (car a) (car b) c-in (car s) c))\n          (else\n           (let ((w (make-wire)))\n             (full-adder (car a) (car b) w (car s) c)\n             (ripple (cdr a) (cdr b) (cdr s) w)))))\n\n  (ripple (reverse a) (reverse b) (reverse s) c-out))\n\n; Half-adder & adder\n\n(define (half-adder a b s c)\n  (let ((d (make-wire)) (e (make-wire)))\n    (or-gate a b d)\n    (and-gate a b c)\n    (inverter c e)\n    (and-gate d e s)\n    'ok))\n\n(define (full-adder a b c-in sum c-out)\n  (let ((s (make-wire))\n        (c1 (make-wire))\n        (c2 (make-wire)))\n    (half-adder b c-in s c1)\n    (half-adder a s sum c2)\n    (or-gate c1 c2 c-out)\n    'ok))\n\n; Primitive function boxes\n\n(define (inverter input output)\n  (define (invert-input)\n    (let ((new-value (logical-not (get-signal input))))\n      (after-delay inverter-delay\n                   (lambda () (set-signal! output new-value)))))\n  (add-action! input invert-input)\n  'ok)\n\n(define (and-gate a1 a2 output)\n  (define (and-action-procedure)\n    (let ((new-value (logical-and (get-signal a1) (get-signal a2))))\n      (after-delay and-gate-delay (lambda () (set-signal! output new-value)))))\n  (add-action! a1 and-action-procedure)\n  (add-action! a2 and-action-procedure)\n  'ok)\n\n(define (or-gate o1 o2 output)\n  (define (or-action-procedure)\n    (let ((new-value (logical-or (get-signal o1) (get-signal o2))))\n      (after-delay or-gate-delay (lambda () (set-signal! output new-value)))))\n  (add-action! o1 or-action-procedure)\n  (add-action! o2 or-action-procedure)\n  'ok)\n\n; Logical functions\n\n(define (logical-not s)\n  (cond ((= s 0) 1)\n        ((= s 1) 0)\n        (else (error \"Invalid signal\" s))))\n\n(define (logical-and a b)\n  (cond ((and (= a 0) (= b 0)) 0)\n        ((and (= a 0) (= b 1)) 0)\n        ((and (= a 1) (= b 0)) 0)\n        ((and (= a 1) (= b 1)) 1)\n        (else (error \"Invalid signals\" a b))))\n\n(define (logical-or a b)\n  (cond ((and (= a 0) (= b 0)) 0)\n        ((and (= a 0) (= b 1)) 1)\n        ((and (= a 1) (= b 0)) 1)\n        ((and (= a 1) (= b 1)) 1)\n        (else (error \"Invalid signals\" a b))))\n\n; Wires\n\n(define (make-wire)\n  (let ((signal-value 0) (action-procedures '()))\n    (define (set-my-signal! new-value)\n      (if (not (= signal-value new-value))\n          (begin (set! signal-value new-value)\n                 (call-each action-procedures))\n          'done))\n    (define (accept-action-procedure! proc)\n      (set! action-procedures (cons proc action-procedures))\n      (proc))\n    (define (dispatch m)\n      (cond ((eq? m 'get-signal) signal-value)\n            ((eq? m 'set-signal!) set-my-signal!)\n            ((eq? m 'add-action!) accept-action-procedure!)\n            (else (error \"Unknown operation -- WIRE\" m))))\n    dispatch))\n\n(define (call-each procedures)\n  (if (null? procedures)\n      'done\n      (begin\n        ((car procedures))\n        (call-each (cdr procedures)))))\n\n(define (get-signal wire) (wire 'get-signal))\n(define (set-signal! wire new-value) ((wire 'set-signal!) new-value))\n(define (add-action! wire action-procedure) ((wire 'add-action!) action-procedure))\n\n; Queues\n\n(define (front-ptr queue) (car queue))\n(define (rear-ptr queue) (cdr queue))\n(define (set-front-ptr! queue item) (set-car! queue item))\n(define (set-rear-ptr! queue item) (set-cdr! queue item))\n\n(define (make-queue) (cons '() '()))\n(define (empty-queue? queue) (null? (front-ptr queue)))\n(define (front-queue queue)\n  (if (empty-queue? queue)\n      (error \"FRONT called with an empty queue\" queue)\n      (car (front-ptr queue))))\n\n(define (insert-queue! queue item)\n  (let ((new-pair (cons item '())))\n    (cond ((empty-queue? queue)\n           (set-front-ptr! queue new-pair)\n           (set-rear-ptr! queue new-pair))\n          (else\n           (set-cdr! (rear-ptr queue) new-pair)\n           (set-rear-ptr! queue new-pair)))\n    queue))\n\n(define (delete-queue! queue)\n  (cond ((empty-queue? queue)\n         (error \"DELETE! called with an empty queue\" queue))\n        (else\n         (set-front-ptr! queue (cdr (front-ptr queue)))\n         queue)))\n\n; The agenda\n\n(define (make-time-segment time queue) (cons time queue))\n(define (segment-time s) (car s))\n(define (segment-queue s) (cdr s))\n\n(define (make-agenda) (list 0))\n(define (current-time agenda) (car agenda))\n(define (set-current-time! agenda time) (set-car! agenda time))\n(define (segments agenda) (cdr agenda))\n(define (set-segments! agenda segments) (set-cdr! agenda segments))\n(define (first-segment agenda) (car (segments agenda)))\n(define (rest-segments agenda) (cdr (segments agenda)))\n(define (empty-agenda? agenda) (null? (segments agenda)))\n\n(define (add-to-agenda! time action agenda)\n  (define (belongs-before? segments)\n    (or (null? segments)\n        (< time (segment-time (car segments)))))\n  (define (make-new-time-segment time action)\n    (let ((q (make-queue)))\n      (insert-queue! q action)\n      (make-time-segment time q)))\n  (define (add-to-segments! segments)\n    (if (= (segment-time (car segments)) time)\n        (insert-queue! (segment-queue (car segments))\n                       action)\n        (let ((rest (cdr segments)))\n          (if (belongs-before? rest)\n              (set-cdr! segments (cons (make-new-time-segment time action) rest))\n              (add-to-segments! rest)))))\n  (let ((segments (segments agenda)))\n    (if (belongs-before? segments)\n        (set-segments! agenda (cons (make-new-time-segment time action) segments))\n        (add-to-segments! segments))))\n\n(define (remove-first-agenda-item! agenda)\n  (let ((q (segment-queue (first-segment agenda))))\n    (delete-queue! q)\n    (if (empty-queue? q)\n        (set-segments! agenda (rest-segments agenda))\n        'done)))\n\n(define (first-agenda-item agenda)\n  (if (empty-agenda? agenda)\n      (error \"Agenda is empty -- FIRST-AGENDA-ITEM\")\n      (let ((first-seg (first-segment agenda)))\n        (set-current-time! agenda (segment-time first-seg))\n        (front-queue (segment-queue first-seg)))))\n\n; Delays\n\n(define inverter-delay 2)\n(define and-gate-delay 3)\n(define or-gate-delay 5)\n\n; Simulation infrastructure\n\n(define the-agenda (make-agenda))\n(define (after-delay delay action)\n  (add-to-agenda! (+ delay (current-time the-agenda))\n                  action\n                  the-agenda))\n\n(define (propagate)\n  (if (empty-agenda? the-agenda)\n      'done\n      (let ((first-item (first-agenda-item the-agenda)))\n        (first-item)\n        (remove-first-agenda-item! the-agenda)\n        (propagate))))\n\n(define (probe name wire)\n  (add-action! wire\n               (lambda ()\n                 (display name)\n                 (display \" \")\n                 (display (current-time the-agenda))\n                 (display \"  New-value = \")\n                 (display (get-signal wire))\n                 (newline))))\n"
  },
  {
    "path": "scheme/sicp/03/31.scm",
    "content": "; SICP exercise 3.31\n;\n; The internal procedure accept-action-procedure! defined in make-wire\n; specifies that when a new action procedure is added to a wire, the procedure\n; is immediately run. Explain why this initialization is necessary. In\n; particular, trace through the half-adder example in the paragraph above and\n; say how the system's response would differ if we had defined\n; accept-action-procedure! as\n;\n;   (define (accept-action-procedure! proc)\n;     (set! action-procedures (cons proc action-procedures)))\n\n; If we define the procedure like that, the output of the inverter will be 0\n; even if its input is also 0. This is wrong. In the example above, when we\n; set the signal of input-1 to 1, the sum would remain 1 because the inputs of\n; the and-gate that leads to sum will be 1 and 0. Thus, sum will remain 0,\n; even if that is wrong.\n;\n; You can run this file to verify.\n\n(require r5rs/init)\n\n; Half-adder & adder:\n\n(define (half-adder a b s c)\n  (let ((d (make-wire)) (e (make-wire)))\n    (or-gate a b d)\n    (and-gate a b c)\n    (inverter c e)\n    (and-gate d e s)\n    'ok))\n\n(define (full-adder a b c-in sum c-out)\n  (let ((s (make-wire))\n        (c1 (make-wire))\n        (c2 (make-wire)))\n    (half-adder b c-in s c1)\n    (half-adder a s sum c2)\n    (or-gate c1 c2 c-out)\n    'ok))\n\n; Primitive function boxes\n\n(define (inverter input output)\n  (define (invert-input)\n    (let ((new-value (logical-not (get-signal input))))\n      (after-delay inverter-delay\n                   (lambda () (set-signal! output new-value)))))\n  (add-action! input invert-input)\n  'ok)\n\n(define (and-gate a1 a2 output)\n  (define (and-action-procedure)\n    (let ((new-value (logical-and (get-signal a1) (get-signal a2))))\n      (after-delay and-gate-delay (lambda () (set-signal! output new-value)))))\n  (add-action! a1 and-action-procedure)\n  (add-action! a2 and-action-procedure)\n  'ok)\n\n(define (or-gate o1 o2 output)\n  (define (or-action-procedure)\n    (let ((new-value (logical-or (get-signal o1) (get-signal o2))))\n      (after-delay or-gate-delay (lambda () (set-signal! output new-value)))))\n  (add-action! o1 or-action-procedure)\n  (add-action! o2 or-action-procedure)\n  'ok)\n\n; Logical functions\n\n(define (logical-not s)\n  (cond ((= s 0) 1)\n        ((= s 1) 0)\n        (else (error \"Invalid signal\" s))))\n\n(define (logical-and a b)\n  (cond ((and (= a 0) (= b 0)) 0)\n        ((and (= a 0) (= b 1)) 0)\n        ((and (= a 1) (= b 0)) 0)\n        ((and (= a 1) (= b 1)) 1)\n        (else (error \"Invalid signals\" a b))))\n\n(define (logical-or a b)\n  (cond ((and (= a 0) (= b 0)) 0)\n        ((and (= a 0) (= b 1)) 1)\n        ((and (= a 1) (= b 0)) 1)\n        ((and (= a 1) (= b 1)) 1)\n        (else (error \"Invalid signals\" a b))))\n\n; Wires\n\n(define (make-wire)\n  (let ((signal-value 0) (action-procedures '()))\n    (define (set-my-signal! new-value)\n      (if (not (= signal-value new-value))\n          (begin (set! signal-value new-value)\n                 (call-each action-procedures))\n          'done))\n    (define (accept-action-procedure! proc)\n      (set! action-procedures (cons proc action-procedures)))\n    (define (dispatch m)\n      (cond ((eq? m 'get-signal) signal-value)\n            ((eq? m 'set-signal!) set-my-signal!)\n            ((eq? m 'add-action!) accept-action-procedure!)\n            (else (error \"Unknown operation -- WIRE\" m))))\n    dispatch))\n\n(define (call-each procedures)\n  (if (null? procedures)\n      'done\n      (begin\n        ((car procedures))\n        (call-each (cdr procedures)))))\n\n(define (get-signal wire) (wire 'get-signal))\n(define (set-signal! wire new-value) ((wire 'set-signal!) new-value))\n(define (add-action! wire action-procedure) ((wire 'add-action!) action-procedure))\n\n; Queues\n\n(define (front-ptr queue) (car queue))\n(define (rear-ptr queue) (cdr queue))\n(define (set-front-ptr! queue item) (set-car! queue item))\n(define (set-rear-ptr! queue item) (set-cdr! queue item))\n\n(define (make-queue) (cons '() '()))\n(define (empty-queue? queue) (null? (front-ptr queue)))\n(define (front-queue queue)\n  (if (empty-queue? queue)\n      (error \"FRONT called with an empty queue\" queue)\n      (car (front-ptr queue))))\n\n(define (insert-queue! queue item)\n  (let ((new-pair (cons item '())))\n    (cond ((empty-queue? queue)\n           (set-front-ptr! queue new-pair)\n           (set-rear-ptr! queue new-pair))\n          (else\n           (set-cdr! (rear-ptr queue) new-pair)\n           (set-rear-ptr! queue new-pair)))\n    queue))\n\n(define (delete-queue! queue)\n  (cond ((empty-queue? queue)\n         (error \"DELETE! called with an empty queue\" queue))\n        (else\n         (set-front-ptr! queue (cdr (front-ptr queue)))\n         queue)))\n\n; The agenda\n\n(define (make-time-segment time queue) (cons time queue))\n(define (segment-time s) (car s))\n(define (segment-queue s) (cdr s))\n\n(define (make-agenda) (list 0))\n(define (current-time agenda) (car agenda))\n(define (set-current-time! agenda time) (set-car! agenda time))\n(define (segments agenda) (cdr agenda))\n(define (set-segments! agenda segments) (set-cdr! agenda segments))\n(define (first-segment agenda) (car (segments agenda)))\n(define (rest-segments agenda) (cdr (segments agenda)))\n(define (empty-agenda? agenda) (null? (segments agenda)))\n\n(define (add-to-agenda! time action agenda)\n  (define (belongs-before? segments)\n    (or (null? segments)\n        (< time (segment-time (car segments)))))\n  (define (make-new-time-segment time action)\n    (let ((q (make-queue)))\n      (insert-queue! q action)\n      (make-time-segment time q)))\n  (define (add-to-segments! segments)\n    (if (= (segment-time (car segments)) time)\n        (insert-queue! (segment-queue (car segments))\n                       action)\n        (let ((rest (cdr segments)))\n          (if (belongs-before? rest)\n              (set-cdr! segments (cons (make-new-time-segment time action) rest))\n              (add-to-segments! rest)))))\n  (let ((segments (segments agenda)))\n    (if (belongs-before? segments)\n        (set-segments! agenda (cons (make-new-time-segment time action) segments))\n        (add-to-segments! segments))))\n\n(define (remove-first-agenda-item! agenda)\n  (let ((q (segment-queue (first-segment agenda))))\n    (delete-queue! q)\n    (if (empty-queue? q)\n        (set-segments! agenda (rest-segments agenda))\n        'done)))\n\n(define (first-agenda-item agenda)\n  (if (empty-agenda? agenda)\n      (error \"Agenda is empty -- FIRST-AGENDA-ITEM\")\n      (let ((first-seg (first-segment agenda)))\n        (set-current-time! agenda (segment-time first-seg))\n        (front-queue (segment-queue first-seg)))))\n\n; Delays\n\n(define inverter-delay 2)\n(define and-gate-delay 3)\n(define or-gate-delay 5)\n\n; Simulation infrastructure\n\n(define the-agenda (make-agenda))\n(define (after-delay delay action)\n  (add-to-agenda! (+ delay (current-time the-agenda))\n                  action\n                  the-agenda))\n\n(define (propagate)\n  (if (empty-agenda? the-agenda)\n      'done\n      (let ((first-item (first-agenda-item the-agenda)))\n        (first-item)\n        (remove-first-agenda-item! the-agenda)\n        (propagate))))\n\n(define (probe name wire)\n  (add-action! wire\n               (lambda ()\n                 (display name)\n                 (display \" \")\n                 (display (current-time the-agenda))\n                 (display \"  New-value = \")\n                 (display (get-signal wire))\n                 (newline))))\n\n(define input-1 (make-wire))\n(define input-2 (make-wire))\n(define sum (make-wire))\n(define carry (make-wire))\n\n(probe 'sum sum)\n(probe 'carry carry)\n\n(half-adder input-1 input-2 sum carry)\n\n(set-signal! input-1 1)\n(propagate)\n\n(set-signal! input-2 1)\n(propagate)\n"
  },
  {
    "path": "scheme/sicp/03/32.scm",
    "content": "; SICP exercise 3.32\n;\n; The procedures to be run during each time segment of the agenda are kept in\n; a queue. Thus, the procedures for each segment are called in the order in\n; which they were added to the agenda (first-in, first-out). Explain why this\n; order must be used. In particular, trace the behavior of an and-gate whose\n; inputs change from 0, 1 to 1, 0 in the same segment and say how the behavior\n; would differ if we stored a segment's procedures in an ordinary list, adding\n; and removing procedures only at the front (last in, first out).\n\n; Each action calculates the new result to be set before it is added to the\n; queue. If we change 0, 1 to 1, 0, we will add two actions to the queue:\n;\n;   a1: set output to 1\n;   a2: set output to 0\n;\n; The reason that we set those outputs is because the gate reads the wire\n; signals before it puts the action after a specific delay. When we change\n; from (0, 1) to (1, 1) it will determine that the output should be 1. We\n; immediatelly change (1, 1) to (1, 0) and the action will set the output to\n; 0.\n;\n; That is, assuming, we use a queue. If we use a stack (last in, first out),\n; those actions will get executed in reverse order. That is, a2 will set the\n; output to 0, after which a1 will set it to 1. In the end, the and gate will\n; output erroneous result.\n;\n; You can run this file to verify.\n\n(require r5rs/init)\n\n; Primitive function boxes\n\n(define (and-gate a1 a2 output)\n  (define (and-action-procedure)\n    (let ((new-value (logical-and (get-signal a1) (get-signal a2))))\n      (after-delay and-gate-delay (lambda () (set-signal! output new-value)))))\n  (add-action! a1 and-action-procedure)\n  (add-action! a2 and-action-procedure)\n  'ok)\n\n; Logical functions\n\n(define (logical-and a b)\n  (cond ((and (= a 0) (= b 0)) 0)\n        ((and (= a 0) (= b 1)) 0)\n        ((and (= a 1) (= b 0)) 0)\n        ((and (= a 1) (= b 1)) 1)\n        (else (error \"Invalid signals\" a b))))\n\n; Wires\n\n(define (make-wire)\n  (let ((signal-value 0) (action-procedures '()))\n    (define (set-my-signal! new-value)\n      (if (not (= signal-value new-value))\n          (begin (set! signal-value new-value)\n                 (call-each action-procedures))\n          'done))\n    (define (accept-action-procedure! proc)\n      (set! action-procedures (cons proc action-procedures)))\n    (define (dispatch m)\n      (cond ((eq? m 'get-signal) signal-value)\n            ((eq? m 'set-signal!) set-my-signal!)\n            ((eq? m 'add-action!) accept-action-procedure!)\n            (else (error \"Unknown operation -- WIRE\" m))))\n    dispatch))\n\n(define (call-each procedures)\n  (if (null? procedures)\n      'done\n      (begin\n        ((car procedures))\n        (call-each (cdr procedures)))))\n\n(define (get-signal wire) (wire 'get-signal))\n(define (set-signal! wire new-value) ((wire 'set-signal!) new-value))\n(define (add-action! wire action-procedure) ((wire 'add-action!) action-procedure))\n\n; The agenda\n\n(define (make-time-segment time actions) (cons time actions))\n(define (segment-time s) (car s))\n(define (segment-actions s) (cdr s))\n(define (set-segment-actions! s actions) (set-cdr! s actions))\n\n(define (make-agenda) (list 0))\n(define (current-time agenda) (car agenda))\n(define (set-current-time! agenda time) (set-car! agenda time))\n(define (segments agenda) (cdr agenda))\n(define (set-segments! agenda segments) (set-cdr! agenda segments))\n(define (first-segment agenda) (car (segments agenda)))\n(define (rest-segments agenda) (cdr (segments agenda)))\n(define (empty-agenda? agenda) (null? (segments agenda)))\n\n(define (add-to-agenda! time action agenda)\n  (define (belongs-before? segments)\n    (or (null? segments)\n        (< time (segment-time (car segments)))))\n  (define (make-new-time-segment time action)\n    (make-time-segment time (list action)))\n  (define (add-to-segments! segments)\n    (if (= (segment-time (car segments)) time)\n        (set-segment-actions! (car segments)\n                              (cons action (segment-actions (car segments))))\n        (let ((rest (cdr segments)))\n          (if (belongs-before? rest)\n              (set-cdr! segments (cons (make-new-time-segment time action) rest))\n              (add-to-segments! rest)))))\n  (let ((segments (segments agenda)))\n    (if (belongs-before? segments)\n        (set-segments! agenda (cons (make-new-time-segment time action) segments))\n        (add-to-segments! segments))))\n\n(define (remove-first-agenda-item! agenda)\n  (set-segment-actions! (first-segment agenda)\n                        (cdr (segment-actions (first-segment agenda))))\n  (if (null? (segment-actions (first-segment agenda)))\n      (set-segments! agenda (rest-segments agenda))\n      'done))\n\n(define (first-agenda-item agenda)\n  (if (empty-agenda? agenda)\n      (error \"Agenda is empty -- FIRST-AGENDA-ITEM\")\n      (let ((first-seg (first-segment agenda)))\n        (set-current-time! agenda (segment-time first-seg))\n        (car (segment-actions first-seg)))))\n\n; Delays\n\n(define inverter-delay 2)\n(define and-gate-delay 3)\n(define or-gate-delay 5)\n\n; Simulation infrastructure\n\n(define the-agenda (make-agenda))\n(define (after-delay delay action)\n  (add-to-agenda! (+ delay (current-time the-agenda))\n                  action\n                  the-agenda))\n\n(define (propagate)\n  (if (empty-agenda? the-agenda)\n      'done\n      (let ((first-item (first-agenda-item the-agenda)))\n        (first-item)\n        (remove-first-agenda-item! the-agenda)\n        (propagate))))\n\n(define (probe name wire)\n  (add-action! wire\n               (lambda ()\n                 (display name)\n                 (display \" \")\n                 (display (current-time the-agenda))\n                 (display \"  New-value = \")\n                 (display (get-signal wire))\n                 (newline))))\n\n(define input-1 (make-wire))\n(define input-2 (make-wire))\n(define output (make-wire))\n(define carry (make-wire))\n\n(probe 'output output)\n\n(and-gate input-1 input-2 output)\n\n(set-signal! input-1 0)\n(set-signal! input-2 1)\n(propagate)\n\n(set-signal! input-1 1)\n(set-signal! input-2 0)\n(propagate)\n"
  },
  {
    "path": "scheme/sicp/03/33.scm",
    "content": "; SICP exercise 3.33\n;\n; Using primitive multiplier, adder, and constant constraints, define a\n; procedure averager that takes three connectors a, b and c as inputs and\n; establishes the constraint that the value of c is average of the values of a\n; and b.\n\n; Averager\n; c = (a + b)/2\n;\n; 2c = a + b\n\n(define (averager a b c)\n  (let ((x (make-connector))\n        (y (make-connector)))\n\n    (adder a b x)\n    (multiplier c y x)\n    (constant 2 y)\n    'ok))\n\n; Celsius to Fahrenheit converter\n\n(define (celsius-fahrenheit-converter c f)\n  (let ((u (make-connector))\n        (v (make-connector))\n        (w (make-connector))\n        (x (make-connector))\n        (y (make-connector)))\n\n    (multiplier c w u)\n    (multiplier v x u)\n    (adder v y f)\n    (constant 9 w)\n    (constant 5 x)\n    (constant 32 y)\n    'ok))\n\n; Constraints\n\n(define (adder a1 a2 sum)\n  (define (process-new-value)\n    (cond ((and (has-value? a1) (has-value? a2))\n           (set-value! sum\n                       (+ (get-value a1) (get-value a2))\n                       me))\n          ((and (has-value? a1) (has-value? sum))\n           (set-value! a2\n                       (- (get-value sum) (get-value a1))\n                       me))\n          ((and (has-value? a2) (has-value? sum))\n           (set-value! a1\n                       (- (get-value sum) (get-value a2))\n                       me))))\n  (define (process-forget-value)\n    (forget-value! sum me)\n    (forget-value! a1 me)\n    (forget-value! a2 me)\n    (process-new-value))\n  (define (me request)\n    (cond ((eq? request 'i-have-a-value)\n           (process-new-value))\n          ((eq? request 'i-lost-my-value)\n           (process-forget-value))\n          (else\n           (error \"Unknown request - ADDER\" request))))\n  (connect a1 me)\n  (connect a2 me)\n  (connect sum me)\n  me)\n\n(define (multiplier m1 m2 product)\n  (define (process-new-value)\n    (cond ((or (and (has-value? m1) (= (get-value m1) 0))\n               (and (has-value? m2) (= (get-value m2) 0)))\n           (set-value! product 0 me))\n          ((and (has-value? m1) (has-value? m2))\n           (set-value! product\n                       (* (get-value m1) (get-value m2))\n                       me))\n          ((and (has-value? product) (has-value? m1))\n           (set-value! m2\n                       (/ (get-value product)\n                          (get-value m1))\n                       me))\n          ((and (has-value? product) (has-value? m2))\n           (set-value! m1\n                       (/ (get-value product)\n                          (get-value m2))\n                       me))))\n  (define (process-forget-value)\n    (forget-value! product me)\n    (forget-value! m1 me)\n    (forget-value! m2 me)\n    (process-new-value))\n  (define (me request)\n    (cond ((eq? request 'i-have-a-value)\n           (process-new-value))\n          ((eq? request 'i-lost-my-value)\n           (process-forget-value))\n          (else\n           (error \"Unknown request - MULTIPLIER\" request))))\n  (connect m1 me)\n  (connect m2 me)\n  (connect product me)\n  me)\n\n(define (constant value connector)\n  (define (me request)\n    (error \"Unknown request - CONSTANT\" request))\n  (connect connector me)\n  (set-value! connector value me)\n  me)\n\n(define (inform-about-value constraint) (constraint 'i-have-a-value))\n(define (inform-about-no-value constraint) (constraint 'i-lost-my-value))\n\n; Connectors\n\n(define (make-connector)\n  (let ((value false) (informant false) (constraints '()))\n    (define (set-my-value newval setter)\n      (cond ((not (has-value? me))\n             (set! value newval)\n             (set! informant setter)\n             (for-each-except setter\n                              inform-about-value\n                              constraints))\n            ((not (= value newval))\n             (error \"Contradiction\" (list value newval)))\n            (else 'ignored)))\n    (define (forget-my-value retractor)\n      (if (eq? retractor informant)\n          (begin (set! informant false)\n                 (for-each-except retractor\n                                  inform-about-no-value\n                                  constraints))\n          'ignored))\n    (define (connect new-constraint)\n      (if (not (memq new-constraint constraints))\n          (set! constraints\n                (cons new-constraint constraints))\n          #t)\n      (if (has-value? me)\n          (inform-about-value new-constraint)\n          #t)\n      'done)\n    (define (me request)\n      (cond ((eq? request 'has-value?)\n             (if informant true false))\n            ((eq? request 'value) value)\n            ((eq? request 'set-value!) set-my-value)\n            ((eq? request 'forget) forget-my-value)\n            ((eq? request 'connect) connect)\n            (else (error \"Unknown operator - CONNECTOR\" request))))\n    me))\n\n(define (for-each-except exception procedure list)\n  (define (loop items)\n    (cond ((null? items) 'done)\n          ((eq? (car items) exception) (loop (cdr items)))\n          (else (procedure (car items))\n                (loop (cdr items)))))\n  (loop list))\n\n(define (has-value? connector) (connector 'has-value?))\n(define (get-value connector) (connector 'value))\n(define (set-value! connector new-value informant) ((connector 'set-value!) new-value informant))\n(define (forget-value! connector retractor) ((connector 'forget) retractor))\n(define (connect connector new-constraint) ((connector 'connect) new-constraint))\n\n; Probe\n\n(define (probe name connector)\n  (define (print-probe value)\n    (newline)\n    (display \"Probe: \")\n    (display name)\n    (display \" = \")\n    (display value))\n  (define (process-new-value)\n    (print-probe (get-value connector)))\n  (define (process-forget-value)\n    (print-probe \"?\"))\n  (define (me request)\n    (cond ((eq? request 'i-have-a-value)\n           (process-new-value))\n          ((eq? request 'i-lost-my-value)\n           (process-forget-value))\n          (else\n           (error \"Unknown request - PROBE\" request))))\n  (connect connector me)\n  me)\n"
  },
  {
    "path": "scheme/sicp/03/34.scm",
    "content": "; SICP exercise 3.34\n;\n; Louis Reasoner wants to build a squarer, a constraint device with two\n; terminals such that the value of connector b on the second terminal will\n; always be the square of the value a on the first terminal. He proposes the\n; following simple device made from a multiplier:\n;\n;   (define (squarer a b)\n;     (multiplier a a b))\n;\n; There is a serious flaw in this idea. Explain.\n\n; This will work alright when a is known and b is unknown. In the reverse\n; case, however, we have a multiplier with a known product and two unknown\n; multiplicands. There is no way to calculate what they are. Thus, it will\n; simply not work when a is unknown.\n"
  },
  {
    "path": "scheme/sicp/03/35.scm",
    "content": "; SICP exercise 3.35\n;\n; Ben Bitdiddle tells Louis that one way to avoid the trouble in exercise 3.34\n; is to define a squarer as a new primitive constraint. Fill in the missing\n; portions in Ben's outline for a procedure to implement such a constraint:\n;\n;   (define (squarer a b)\n;     (define (process-new-value)\n;       (if (has-value? b)\n;           (if (< (get-value b) 0)\n;               (error \"square less than 0 - SQUARER\" (get-value b))\n;               <alternative1>)\n;           <alternative2>))\n;     (define (process-forget-value) <body1>)\n;     (define (me request) <body2>)\n;     <rest-of-definition>>\n;     me)\n\n; I think a cond would have been nicer, but whatever. Here it is:\n\n(define (squarer a b)\n  (define (process-new-value)\n    (if (has-value? b)\n        (if (< (get-value b) 0)\n            (error \"square less than 0 - SQUARER\" (get-value b))\n            (set-value! a (sqrt (get-value b)) me))\n        (if (has-value? a)\n            (if (< (get-value a) 0)\n                (error \"does not work with negative numbers - SQUARER\" (get-value a))\n                (set-value! b (square (get-value a)) me))\n            'ignored)))\n  (define (process-forget-value)\n    (forget-value! a me)\n    (forget-value! b me)\n    (process-new-value))\n  (define (me request)\n    (cond ((eq? request 'i-have-a-value)\n           (process-new-value))\n          ((eq? request 'i-lost-my-value)\n           (process-forget-value))\n          (else\n           (error \"Unknown request - SQUARER\" request))))\n  (connect a me)\n  (connect b me)\n  me)\n\n(define (square x)\n  (* x x))\n\n(define (inform-about-value constraint) (constraint 'i-have-a-value))\n(define (inform-about-no-value constraint) (constraint 'i-lost-my-value))\n\n; Connectors\n\n(define (make-connector)\n  (let ((value false) (informant false) (constraints '()))\n    (define (set-my-value newval setter)\n      (cond ((not (has-value? me))\n             (set! value newval)\n             (set! informant setter)\n             (for-each-except setter\n                              inform-about-value\n                              constraints))\n            ((not (= value newval))\n             (error \"Contradiction\" (list value newval)))\n            (else 'ignored)))\n    (define (forget-my-value retractor)\n      (if (eq? retractor informant)\n          (begin (set! informant false)\n                 (for-each-except retractor\n                                  inform-about-no-value\n                                  constraints))\n          'ignored))\n    (define (connect new-constraint)\n      (if (not (memq new-constraint constraints))\n          (set! constraints\n                (cons new-constraint constraints))\n          #t)\n      (if (has-value? me)\n          (inform-about-value new-constraint)\n          #t)\n      'done)\n    (define (me request)\n      (cond ((eq? request 'has-value?)\n             (if informant true false))\n            ((eq? request 'value) value)\n            ((eq? request 'set-value!) set-my-value)\n            ((eq? request 'forget) forget-my-value)\n            ((eq? request 'connect) connect)\n            (else (error \"Unknown operator - CONNECTOR\" request))))\n    me))\n\n(define (for-each-except exception procedure list)\n  (define (loop items)\n    (cond ((null? items) 'done)\n          ((eq? (car items) exception) (loop (cdr items)))\n          (else (procedure (car items))\n                (loop (cdr items)))))\n  (loop list))\n\n(define (has-value? connector) (connector 'has-value?))\n(define (get-value connector) (connector 'value))\n(define (set-value! connector new-value informant) ((connector 'set-value!) new-value informant))\n(define (forget-value! connector retractor) ((connector 'forget) retractor))\n(define (connect connector new-constraint) ((connector 'connect) new-constraint))\n\n; Probe\n\n(define (probe name connector)\n  (define (print-probe value)\n    (newline)\n    (display \"Probe: \")\n    (display name)\n    (display \" = \")\n    (display value))\n  (define (process-new-value)\n    (print-probe (get-value connector)))\n  (define (process-forget-value)\n    (print-probe \"?\"))\n  (define (me request)\n    (cond ((eq? request 'i-have-a-value)\n           (process-new-value))\n          ((eq? request 'i-lost-my-value)\n           (process-forget-value))\n          (else\n           (error \"Unknown request - PROBE\" request))))\n  (connect connector me)\n  me)\n"
  },
  {
    "path": "scheme/sicp/03/36.scm",
    "content": "; SICP exercise 3.36\n;\n; Suppose we evaluate the following sequence of expressions in the global\n; environment:\n;\n;   (define a (make-connector))\n;   (define b (make-connector))\n;   (set-value! a 10 'user)\n;\n; At some time during evaluation of the set-value!, the following expression\n; from the connector's local procedure is evaluated:\n;\n;   (for-each-except\n;     setter inform-about-value constraints)\n;\n; Draw an environment diagram showing the environment in which the above\n; expression is evaluated\n\n; globals:\n; +-------------------------------------------------------------------------+\n; | a: <procedure>                                                          |\n; | b: <procedure>                                                          |\n; | make-connector: <procedure>                                             |\n; | inform-about-value: <procedure>                                         |\n; | ...                                                                     |\n; +-------------------------------------------------------------------------+\n;                ^\n;                |\n; +------------------------------+\n; | set-my-value: <procedure>    |\n; | forget-my-value: <procedure> |\n; | connect: <procedure>         |\n; | me: <procedure>              |\n; +------------------------------+\n;                ^\n;                |\n; +------------------------------+\n; | value: false                 |\n; | informant: false             |\n; | constraints: ()              |\n; +------------------------------+\n;                ^\n;                |\n; +------------------------------+\n; | newval: 10                   |\n; | setter: 'user                |\n; +------------------------------+\n"
  },
  {
    "path": "scheme/sicp/03/37.scm",
    "content": "; SICP exercise 3.37\n;\n; The celsius-fahrenheit-converter procedure is cumbersome when compared with\n; a more expression-oriented style of definition, such as\n;\n;   (define (celsius-fahrenheit-converter x)\n;     (c+ (c* (c/ (cv 9) (cv 5))\n;             x)\n;         (cv 32)))\n;\n;   (define C (make-connector))\n;   (define F (celsius-fahrenheit-converter C))\n;\n; Here c+, c*, etc. are the \"constraint\" versions of the arithmetic\n; operations. For example, c+ takes two connectors as arguments and returns a\n; connector that is related to these by an adder constraint:\n;\n;   (define (c+ x y)\n;     (let ((z (make-connector)))\n;       (adder x y z)\n;       z))\n;\n; Define analogous procedures c-, c*, c/ and cv (constant value) that enable\n; us to define compound constraints as in the converter example above.\n\n; Celsius to Fahrenheit converter\n\n(define (celsius-fahrenheit-converter x)\n  (c+ (c* (c/ (cv 9) (cv 5))\n          x)\n      (cv 32)))\n\n; Domain-specific language\n\n(define (c+ x y)\n  (let ((z (make-connector)))\n    (adder x y z)\n    z))\n\n(define (c* x y)\n  (let ((z (make-connector)))\n    (multiplier x y z)\n    z))\n\n(define (c/ x y)\n  (let ((z (make-connector)))\n    (multiplier y z x)\n    z))\n\n(define (cv c)\n  (let ((z (make-connector)))\n    (constant c z)\n    z))\n\n; Constraints\n\n(define (adder a1 a2 sum)\n  (define (process-new-value)\n    (cond ((and (has-value? a1) (has-value? a2))\n           (set-value! sum\n                       (+ (get-value a1) (get-value a2))\n                       me))\n          ((and (has-value? a1) (has-value? sum))\n           (set-value! a2\n                       (- (get-value sum) (get-value a1))\n                       me))\n          ((and (has-value? a2) (has-value? sum))\n           (set-value! a1\n                       (- (get-value sum) (get-value a2))\n                       me))))\n  (define (process-forget-value)\n    (forget-value! sum me)\n    (forget-value! a1 me)\n    (forget-value! a2 me)\n    (process-new-value))\n  (define (me request)\n    (cond ((eq? request 'i-have-a-value)\n           (process-new-value))\n          ((eq? request 'i-lost-my-value)\n           (process-forget-value))\n          (else\n           (error \"Unknown request - ADDER\" request))))\n  (connect a1 me)\n  (connect a2 me)\n  (connect sum me)\n  me)\n\n(define (multiplier m1 m2 product)\n  (define (process-new-value)\n    (cond ((or (and (has-value? m1) (= (get-value m1) 0))\n               (and (has-value? m2) (= (get-value m2) 0)))\n           (set-value! product 0 me))\n          ((and (has-value? m1) (has-value? m2))\n           (set-value! product\n                       (* (get-value m1) (get-value m2))\n                       me))\n          ((and (has-value? product) (has-value? m1))\n           (set-value! m2\n                       (/ (get-value product)\n                          (get-value m1))\n                       me))\n          ((and (has-value? product) (has-value? m2))\n           (set-value! m1\n                       (/ (get-value product)\n                          (get-value m2))\n                       me))))\n  (define (process-forget-value)\n    (forget-value! product me)\n    (forget-value! m1 me)\n    (forget-value! m2 me)\n    (process-new-value))\n  (define (me request)\n    (cond ((eq? request 'i-have-a-value)\n           (process-new-value))\n          ((eq? request 'i-lost-my-value)\n           (process-forget-value))\n          (else\n           (error \"Unknown request - MULTIPLIER\" request))))\n  (connect m1 me)\n  (connect m2 me)\n  (connect product me)\n  me)\n\n(define (constant value connector)\n  (define (me request)\n    (error \"Unknown request - CONSTANT\" request))\n  (connect connector me)\n  (set-value! connector value me)\n  me)\n\n(define (inform-about-value constraint) (constraint 'i-have-a-value))\n(define (inform-about-no-value constraint) (constraint 'i-lost-my-value))\n\n; Connectors\n\n(define (make-connector)\n  (let ((value false) (informant false) (constraints '()))\n    (define (set-my-value newval setter)\n      (cond ((not (has-value? me))\n             (set! value newval)\n             (set! informant setter)\n             (for-each-except setter\n                              inform-about-value\n                              constraints))\n            ((not (= value newval))\n             (error \"Contradiction\" (list value newval)))\n            (else 'ignored)))\n    (define (forget-my-value retractor)\n      (if (eq? retractor informant)\n          (begin (set! informant false)\n                 (for-each-except retractor\n                                  inform-about-no-value\n                                  constraints))\n          'ignored))\n    (define (connect new-constraint)\n      (if (not (memq new-constraint constraints))\n          (set! constraints\n                (cons new-constraint constraints))\n          #t)\n      (if (has-value? me)\n          (inform-about-value new-constraint)\n          #t)\n      'done)\n    (define (me request)\n      (cond ((eq? request 'has-value?)\n             (if informant true false))\n            ((eq? request 'value) value)\n            ((eq? request 'set-value!) set-my-value)\n            ((eq? request 'forget) forget-my-value)\n            ((eq? request 'connect) connect)\n            (else (error \"Unknown operator - CONNECTOR\" request))))\n    me))\n\n(define (for-each-except exception procedure list)\n  (define (loop items)\n    (cond ((null? items) 'done)\n          ((eq? (car items) exception) (loop (cdr items)))\n          (else (procedure (car items))\n                (loop (cdr items)))))\n  (loop list))\n\n(define (has-value? connector) (connector 'has-value?))\n(define (get-value connector) (connector 'value))\n(define (set-value! connector new-value informant) ((connector 'set-value!) new-value informant))\n(define (forget-value! connector retractor) ((connector 'forget) retractor))\n(define (connect connector new-constraint) ((connector 'connect) new-constraint))\n\n; Probe\n\n(define (probe name connector)\n  (define (print-probe value)\n    (newline)\n    (display \"Probe: \")\n    (display name)\n    (display \" = \")\n    (display value))\n  (define (process-new-value)\n    (print-probe (get-value connector)))\n  (define (process-forget-value)\n    (print-probe \"?\"))\n  (define (me request)\n    (cond ((eq? request 'i-have-a-value)\n           (process-new-value))\n          ((eq? request 'i-lost-my-value)\n           (process-forget-value))\n          (else\n           (error \"Unknown request - PROBE\" request))))\n  (connect connector me)\n  me)\n"
  },
  {
    "path": "scheme/sicp/03/38.scm",
    "content": "; SICP exercise 3.38\n;\n; Suppose that Peter, Paul and Mary share a joint back account that initially\n; contains $100. Concurrently, Peter deposits $10, Paul withdraws $20, and\n; Mary withdraws half the money in the account, by executing the following\n; commands:\n;\n;   Peter: (set! balance (+ balance 10))\n;   Paul:  (set! balance (- balance 20))\n;   Mary:  (set! balance (- balance (/ balance 2)))\n;\n; a. List all the different possible values for balance after these three\n; transactions have been completed, assuming that the banking system forces\n; the three processes to run sequentially in some order.\n;\n; b. What are some other values that could be produced if the system allows\n; the processes to be interleaved? Draw timing diagrams like the one in figure\n; 3.29 to explain how these values can occur.\n\n; a. The possible values are 35, 40, 45 and 50. To illustrate them, we will\n; abbreviate the operations to +10, -20 and /2. Here are the options:\n;\n;   45: +10, -20, /2\n;   35: +10, /2, -20\n;   45: -20, +10, /2\n;   50: -20, /2, +10\n;   40: /2, +10, -20\n;   40: /2, -20, +10\n;\n; b. I hate plurals. One possible value is 30.\n;\n;   Peter                   Paul                    Marry\n;   ----------------------- ----------------------- -----------------------\n;                                                   access balance: 100\n;                                                   new value: 50\n;                                                   set balance: 50\n;                           access balance: 50\n;   access balance: 50\n;   new value: 70\n;   set balance: 70\n;                           new value: 30\n;                           set balance: 30\n;\n; Another possible value is 55:\n;\n;   Peter                   Paul                    Marry\n;   ----------------------- ----------------------- -----------------------\n;   access balance: 100\n;                           access balance: 100\n;   new value: 110\n;                           new value: 80\n;                           set balance: 80\n;   set balance: 110\n;                                                   access balance: 110\n;                                                   new value: 55\n;                                                   set balance: 55\n"
  },
  {
    "path": "scheme/sicp/03/39.scm",
    "content": "; SICP exercise 3.39\n;\n; Which of the five possibilities in the parallel execution shown above remain\n; if we instead serialize exection as follows:\n;\n;   (define x 10)\n;\n;   (define s (make-serializer))\n;\n;   (parallel-execute\n;     (lambda () (set! x ((s (lambda () (* x x))))))\n;     (s (lambda () (set! x (+ x 1)))))\n\n; If we assume that the lambdas are P1 and P2, then the possible values are:\n;\n;   101: P1 sets x to 100 and then P2 increments x to x.\n;   121: P2 increments x to 11 and then P2 sets x to x.\n;   100: P1 accesses x, then P2 sets X to 11, then P1 sets x.\n"
  },
  {
    "path": "scheme/sicp/03/40.scm",
    "content": "; SICP exercise 3.40\n;\n; Give all possible values of x that can result from executing\n;\n;   (define x 10)\n;\n;   (parallel-execute (lambda () (set! x (* x x)))\n;                     (lambda () (set! x (* x x x))))\n;\n; Which of these possibilities remain if we instead use serialized procedures:\n;\n;   (define x 10)\n;\n;   (define s (make-serializer))\n;\n;   (parallel-execute (s (lambda () (set! x (* x x))))\n;                     (s (lambda () (set! x (* x x x)))))\n\n; Assuming that (* x x) and (* x x x) is atomic and reads the same x all\n; times and that the lambdas are P1 and P2:\n;\n;   1000000: P1 reads (10) and sets (100), P2 reads (100) and sets (1000000)\n;   1000000: P2 reads (10) and sets (1000), P1 reads (1000) and sets (1000000)\n;      1000: P1-read (10), P2-read (10), P1-set (100), P2-set (1000)\n;       100: P1-read (10), P2-read (10), P2-set (1000), P1-set (100)\n;      1000: P2-read (10), P1-read (10), P1-set (100), P2-set (1000)\n;       100: P2-read (10), P1-read (10), P2-set (1000), P1-set (100)\n;\n; If we use the serializer, only the first two option remain.\n"
  },
  {
    "path": "scheme/sicp/03/41.scm",
    "content": "; SICP exercise 3.41\n;\n; Ben Bitdiddle worries that it would be better to implement the bank account\n; as follows (where the commented line has been changed):\n;\n;   (define (make-account balance)\n;     (define (withdraw amount)\n;       (if (>= balance amount)\n;           (begin (set! balance (- balance amount))\n;                  balance)\n;           \"Insufficient funds\"))\n;     (define (deposit amount)\n;       (set! balance (+ balance amount))\n;       balance)\n;     (let ((protected (make-serializer)))\n;       (define (dispatch m)\n;         (cond ((eq? m 'withdraw) (protected withdraw))\n;               ((eq? m 'deposit) (protected deposit))\n;               ((eq? m 'balance) (protected (lambda () balance)))\n;               (else (error \"Unknown request - MAKE-ACCOUNT\" m))))\n;       dispatch))\n;\n; because allowing unserialized access to the bank balance can result in\n; anomalous behavior. Do you agree? Is there any scenario that demonstrats\n; Ben's concern?\n\n; In general - no. It works perfectly fine without serializing the access.\n;\n; In case we're working with some ancient technology where writes to the\n; memory are not atomic, balance might be read while withdraw or deposit are\n; in the middle of updating in, thus we can get a jumble of bits that is not\n; the real balance. Finding a machine where that could happen in the present\n; year, though, might be very expensive.\n"
  },
  {
    "path": "scheme/sicp/03/42.scm",
    "content": "; SICP exercise 3.42\n;\n; Ben Bitdiddle suggests that it's a waste of time to create a new serialized\n; procedure in response to every withdraw and deposit message. He says that\n; make-account could be changed so that the calls to protected are done\n; outside the dispatch procedure. That is, an account would return the same\n; serialized procedure (which was created at the same time as the account)\n; each time it is asked for a withdrawal procedure.\n;\n;   (define (make-account balance)\n;     (define (withdraw amount)\n;       (if (>= balance amount)\n;           (begin (set! balance (- balance amount))\n;                  balance)\n;           \"Insufficient funds\"))\n;     (define (deposit amount)\n;       (set! balance (+ balance amount))\n;       balance)\n;     (let ((protected (make-serializer)))\n;       (let ((protected-withdraw (protected withdraw))\n;             (protected-deposit (protected deposit)))\n;         (define (dispatch m)\n;           (cond ((eq? m 'withdraw) protected-withdraw)\n;                 ((eq? m 'deposit) protected-deposit)\n;                 ((eq? m 'balance) balance)\n;                 (else (error \"Unknown request - MAKE-ACCOUNT\" m))))\n;         dispatch)))\n;\n; Is this a safe change to make? In particular, is there any difference in\n; what concurrency is allowed by these two versions of make-account?\n\n; It actually depends on how make-serializer is implemented. In the original\n; version, two withdrawals are two separate procedures that are serialized. In\n; Ben's approach, we have one serialized procedure that can be called twice at\n; the same time. The question is if the serializer executes those concurrently\n; or sequentially.\n;\n; If execution is sequential (as it should be, if we're using the serializer\n; implementation later in the chapter), then the change is not a problem. On\n; the other hand, if it is a weird serializer that allows the function to be\n; executed twice concurrently, then it is a problem. But I don't think it's\n; likely for a serializer to be like that.\n"
  },
  {
    "path": "scheme/sicp/03/43.scm",
    "content": "; SICP exercise 3.43\n;\n; Suppose that the balances in three accounts start out as $10, $20, and $30,\n; and that multiple processes run, exchanging the balances of the accounts.\n; Argue that if the processes are run sequentially, after any number of\n; concurrent exchanges, the account balances should be $10, $20 and $30 in\n; some order. Draw a timing diagram like the one in figure 3.29 to show how\n; this condition can be violated if the exchanges are implemented using the\n; first version of the account-exchange program in this section. On the other\n; hand, argue that even with this exchange program, the sum of the balances in\n; the accounts will be preserved. Draw a timing diagram to show how even this\n; condition would be violated if we did not serialize the transactions on\n; individual accounts.\n\n; Well, exchanging x and y in (x, y, z) will result to (y, x, z). It is the\n; same for any other pair. The numbers are preserved, even if the order is\n; changed.\n;\n; (x, y, z) = (10, 20, 30) ; 60 total\n;\n; (exchange y z)                  (exchange z x)\n; ------------------------------- -------------------------------\n; read y: 20\n; read x: 10\n; difference: 10\n;\n;                                 read z: 30\n;                                 read x: 10\n;                                 difference: 20\n; withdraw y 10: 10\n;                                 withdraw z 20: 10\n; deposit x 10: 20\n;                                 deposit x 20: 40\n;\n; When the exchanges complete, the account balances will be (40, 10, 10) that\n; ammounts to 60 total. In general, once the difference is calculated, when it\n; is removed to one account it will be added to another. There is no loss of\n; money, even if the balances end up randomly.\n;\n; If we use the non-serialized access to the accounts, we can easily get this\n; situation:\n;\n; (exchange y z)                  (exchange z x)\n; ------------------------------- -------------------------------\n; read y: 20\n; read x: 10\n; difference: 10\n;\n;                                 read z: 30\n;                                 read x: 10\n;                                 difference: 20\n; withdraw y 10\n;   read y: 20\n;   set y: 10\n;                                 withdraw z 20\n;                                   read z: 30\n;                                   set z: 10\n; deposit x 10\n;   read x: 10\n;                                 deposit x 20\n;                                   read x: 10\n;                                   set x: 30\n;   set x: 20\n;\n; In the end, we get (20, 10, 10) which is a loss of money. Not using a\n; serializer just costed the bank 20 bucks.\n"
  },
  {
    "path": "scheme/sicp/03/44.scm",
    "content": "; SICP exercise 3.44\n;\n; Consider the problem of transferring an amount from one account to another.\n; Ben Bitdiddle claims that this can be accomplished with the following\n; procedure, even if there are multiple people concurrently transferring money\n; among multiple accounts, using any account mechanism that serializes deposit\n; and withdrawal transactions, for example, the version of make-account in the\n; text above.\n;\n;   (define (transfer from-account to-account amount)\n;     ((from-account 'withdraw) amount)\n;     ((to-account 'deposit) amount))\n;\n; Louis Reasoner clains that there is a problem here, and that we need to use\n; a more sophisticated method, such as the one required for dealing with the\n; exchange problem. Is Louis right? If not, what is the essential difference\n; between the transfer problem and the exchange problem? (You should assume\n; that the balance in from-account is at least amount.)\n\n; Louis is wrong.\n;\n; The essential difference is that exchanges performs reads prior to writing\n; and that what is written depends on what is read. In this example we only\n; perform writes and the amount is known in advance (and save, since we know\n; that from-account has enough money.)\n"
  },
  {
    "path": "scheme/sicp/03/45.scm",
    "content": "; SICP exercise 3.45\n;\n; Louis Reasoner thinks our bank-account system is unnecessarily complex and\n; error-prone now that deposits and withdrawals aren't automatically\n; serialized. He suggests and make-account-and-serializer should have exported\n; the serializer (for use by such procedures as serialized-exchange) in\n; addition to (rather than instead of) using it to serialize accounts and\n; deposists as make-account did. He proposes to redefine accounts as follows:\n;\n;   (define (make-account-and-serializer balance)\n;     (define (withdraw amount)\n;       (if (>= balance amount)\n;           (begin (set! balance (- balance amount))\n;                  balance)\n;           \"Insufficient funds\"))\n;     (define (deposit amount)\n;       (set! balance (+ balance amount))\n;       balance)\n;     (let ((balance-serialzier (make-serializer)))\n;       (define (dispatch m)\n;         (cond ((eq? m 'withdraw) (balance-serialzier withdraw))\n;               ((eq? m 'deposit) (balance-serialzier deposit))\n;               ((eq? m 'balance) balance)\n;               ((eq? m 'serializer) balance-serialzier)\n;               (else (error \"Unknown request - MAKE-ACCOUNT\" m))))\n;       dispatch))\n;\n; Then deposits are handled as with the original make-account:\n;\n;   (define (deposit account amount)\n;     ((acount 'deposit) amount))\n;\n; Explain what is wrong with Louis' reasoning. In particular, consider whan\n; happens when serialized-exchange is called.\n\n; The system will deadlock.\n;\n; When se called serialized-exchange, it will use the serializer of an account\n; to execute the exchange procedure. However, exchange will eventually call\n; withdraw, which in turn uses the same serializer to modify the amount.\n; However, it cannot proceed until exchange is finished - and exchange cannot\n; finish until (at least) the withdrawal completes.\n"
  },
  {
    "path": "scheme/sicp/03/46.scm",
    "content": "; SICP exercise 3.46\n;\n; Suppose that we implement test-and-set! using an ordinary procedure as shown\n; in the text, without attempting to make the operation attomic. Draw a timing\n; diagram like the one in figure 3.29 to demonstrate how the mutex\n; implementation can fail by allowing two processes to acquire the mutex at\n; the same time.\n\n; Eh.\n;\n; (the-mutex 'acquire)                  (the-mutex 'acquire)\n; ------------------------------------- -------------------------------------\n; test-and-set! cell\n;                                       test-and-set! cell\n;   (if (car cell)\n;                                       (if (car cell)\n;   (begin (set-car! cell true)\n;          false)\n;\n;                                       (begin (set-car! cell true)\n;                                              false)\n;     (set-car! cell true)\n;     false\n;                                         (set-car! cell true)\n;                                         false\n;\n; Both calls set the variable to false and then return immediatelly. Now the\n; mutex has been acquired by two separate processes.\n"
  },
  {
    "path": "scheme/sicp/03/47.scm",
    "content": "; SICP exercise 3.47\n;\n; A semaphore (of size n) is a generalization of a mutex. Like a mutex, a\n; semaphore supports acquire and release operations, but it is more general in\n; that up to n processes can acquire it concurrently. Additional processes\n; that attempt to acquire the semaphore must wait for release operations. Give\n; implementations of semaphores\n;\n; a. in terms of mutexes\n; b. in terms of atomic test-and-set! operations.\n\n; a.\n\n(define (make-semaphore n)\n  (let ((lock (make-mutex)))\n    (define (the-semaphore m)\n      (cond ((eq? m 'acquire)\n             (lock 'acquire)\n             (cond ((> n 0)\n                    (set! n (- n 1))\n                    (lock 'release))\n                   (else\n                    (lock 'release)\n                    (the-semaphore 'acquire))))\n            ((eq? m 'release)\n             (lock 'acquire)\n             (set! n (+ n 1))\n             (lock 'release))))\n    the-semaphore))\n\n; b. This sucks. Oh well.\n\n(define (make-semaphore n)\n  (let ((lock (list false)))\n    (define (the-semaphore m)\n      (cond ((eq? m 'acquire)\n             (if (or (= n 0) (test-and-set! lock))\n                 (the-semaphore 'acquire)\n                 (begin (set! n (- n 1))\n                        (clear! lock))))\n            ((eq? m 'release)\n             (if (test-and-set! lock)\n                 (the-semaphore 'release)\n                 (begin (set! n (+ n 1))\n                        (clear! lock))))))\n    the-semaphore))\n"
  },
  {
    "path": "scheme/sicp/03/48.scm",
    "content": "; SICP exercise 3.48\n;\n; Explain in detail why the deadlock-avoidance method described above, (i.e.\n; accounts are numbered, and each process attempts to acquire the\n; smaller-numbered account first) avoids deadlock in the exchange problem.\n; Rewrite serialzied-exchange to incorporate this idea. (You will also need to\n; modify make-account so that each account is created with a number, which can\n; be accessed by sending an appropriate message.)\n\n; In order to have a deadlock, we need two processes and are attempting to\n; require locks on two resources (x and y). The situation can occur if one\n; tries to acquire the locks in order (x, y) and the other in order (y, x). If\n; both manage to acquire the first lock before they attempt to require the\n; second, a deadlock occurs.\n;\n; If we order the accounts and acquire locks only in ascending order, this\n; situation cannot arise, because both will attempt to acquire the locks in\n; order (x, y).\n;\n; Here's some untested code:\n\n; First, we need a way to generate account numbers. We need to have a lock for\n; this, otherwise we might end up with two accounts sharing the same number.\n\n(define last-account-number 0)\n(define account-number-lock (make-mutex))\n(define (generate-account-number)\n  (account-number-lock 'acquire)\n  (let ((number last-account-number))\n    (set! last-account-number (+ last-account-number 1))\n    (account-number-lock 'release)\n    number))\n\n; This is how we make accounts with a number:\n\n(define (make-account-and-serializer balance)\n  (let ((number (generate-account-number))\n        (serializer (make-serializer)))\n    (define (withdraw amount)\n      (if (>= balance amount)\n          (begin (set! balance (- balance amount))\n                 balance)\n          \"Insufficient funds\"))\n    (define (deposit amount)\n      (set! balance (+ balance amount))\n      balance)\n    (define (dispatch m)\n      (cond ((eq? m 'withdraw) withdraw)\n            ((eq? m 'deposit) deposit)\n            ((eq? m 'balance) balance)\n            ((eq? m 'serializer) serializer)\n            ((eq? m 'number) number)\n            (else (error \"Unknown request - MAKE-ACCOUNT\" m))))\n      dispatch))\n\n; This is how our serialized-exchange looks like:\n\n(define (serialized-exchange account1 account2)\n  (let ((serializer1 (account1 'serializer))\n        (serializer2 (account2 'serializer)))\n    ((serialize-both exchange acount1 acount2) account1 account2)))\n\n; And this is or auxiliary function. The outer serializer gets invoked first.\n; Note, that it doesn't matter whether we lock accounts in ascending or\n; descending order, as long as we always lock in the same order.\n\n(define (serialize-both proc account1 account2)\n  (if (< (number account1) (number account2))\n      ((account1 (account2 proc)))\n      ((account2 (account1 proc)))))\n"
  },
  {
    "path": "scheme/sicp/03/49.scm",
    "content": "; SICP exercise 3.49\n;\n; Give a scenario where the deadlock-avoidance mechanism described above does\n; not work. (Hint: In the exchange problem, each process knows in advance\n; which accounts it will neet to get access to. Consider a situation where a\n; process must get access to some shared resource before it can know which\n; additional shared resources it will require.)\n\n; The question pretty much answers itself. Let's say that we need to acquire\n; two locks. We need to acquire the first lock in order to determine what\n; second lock we need to acquire later. Let's say we need to acquire a in\n; order to determine that we need to acquire b second. If the reverse case is\n; possible (we acquire b and then we determine that we need to acquire a\n; second), there is a possibility of a deadlock.\n;\n; We can solve this problem by having a third lock we acquire before acquiring\n; the first one.\n"
  },
  {
    "path": "scheme/sicp/03/50.scm",
    "content": "; SICP exercise 3.50\n;\n; Complete the following definition, which generalizes stream-map to allow\n; procedures that take multiple arguments analogous to map in section 2.2.1,\n; footnote 12.\n;\n;   (define (stream-map proc . argstreams)\n;     (if (<??> (car argstreams))\n;         the-empty-stream\n;         (<??>\n;          (apply proc (map <??> argstreams))\n;          (apply stream-map\n;                 (cons proc (map <??> argstreams))))))\n\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n"
  },
  {
    "path": "scheme/sicp/03/51.scm",
    "content": "; SICP exercise 3.51\n;\n; In order to take a closer look at delayed evaluation, we will use the\n; following procedure, which simply returns its argument after printing it:\n;\n;   (define (show x)\n;     (display-line x)\n;     x)\n;\n; What does the interpreter print in response to evaluating each expression in\n; the following sequence?\n;\n;   (define x (stream-map\n;               show\n;               (stream-enumerate-interval 0 10)))\n;\n;   (stream-ref x 5)\n;   (stream-ref x 7)\n\n; This is the output in the streams we've defined so far:\n;\n; (define x ..)\n; 0\n;\n; (stream-ref x 5) ; 5\n; 1\n; 2\n; 3\n; 4\n; 5\n;\n; (stream-ref x 7) ; 7\n; 6\n; 7\n;\n; Note, that if you run this in Racket, it will print only 5 and 7. That's\n; because the cars of the streams are also lazy.\n"
  },
  {
    "path": "scheme/sicp/03/52.scm",
    "content": "; SICP exercise 3.52\n;\n; Consider the sequence of expressions\n;\n;   (define sum 0)\n;   (define (accum x)\n;     (set! sum (+ x sum))\n;     sum)\n;\n;   (define seq\n;     (stream-map accum\n;                 (stream-enumerate-interval 1 20)))\n;\n;   (define y (stream-filter even? seq))\n;   (define z (stream-filter\n;               (lambda (x) (= (remainder x 5) 0)) seq))\n;\n;   (stream-ref y 7)\n;   (display-stream z)\n;\n; What is the value of sum after each of the above expressions is evaluated?\n; What is the printed response to evaluating the stream-ref and display-stream\n; expressions? Would these responses differ if we had implemented (delay\n; <exp>) simply as (lambda () <exp>) without using the optimization provided\n; by memo-proc? Explain.\n\n; Fully evaluated, seq is:\n;\n; (1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 153 171 190 210)\n;\n; However, it gets evaluated in parts. Here is how it goes:\n;\n; (define seq\n;   (stream-map accum\n;               (stream-enumerate-interval 1 20)))\n; sum = 1\n;\n; (define y (stream-filter even? seq))\n; sum = 6\n;\n; (define z (stream-filter\n;             (lambda (x) (= (remainder x 5) 0)) seq))\n; sum = 10\n;\n; (stream-ref y 7)\n; sum = 136\n; result = 136\n;\n; (display-stream z)\n; sum = 210\n; output is:\n;   10\n;   15\n;   45\n;   55\n;   105\n;   120\n;   190\n;   210\n;\n; If we did not memoize the delayed thunk, each subsequent interation of the\n; stream would modify the sum. Iterating seq twice would produce different\n; results. For, after (define y ...) sum will be 7 and after (define z ...),\n; sum will be 17. Each evaluation of a part of the stream will offset the\n; elements more and more.\n;\n; Without this optimization, we cannot iterate a stream twice if there are\n; side effects in the stream.\n"
  },
  {
    "path": "scheme/sicp/03/53.scm",
    "content": "; SICP exercise 3.53\n;\n; Without running the program, describe the elements of the stream defined by\n;\n;   (define s (cons-stream 1 (add-streams s s)))\n\n; Every element is twice the previous, that is (1 2 4 8 16 32 ...), that is\n; the powers of two.\n"
  },
  {
    "path": "scheme/sicp/03/54.scm",
    "content": "; SICP exercise 3.54\n;\n; Define a procedure mul-streams, analogous to add-streams, that produces the\n; elementwise product of its two input streams. Use this together with the\n; stream of integers to complete the following definition of the stream whose\n; nth elemen (counting down from 0) is n + 1 factorial:\n;\n;   (define factorials (cons-stream 1\n;                                   (mul-streams <??>\n;                                                <??>)))\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (add-streams a b) (stream-map2 + a b))\n(define (mul-streams a b) (stream-map2 * a b))\n\n(define ones (stream-cons 1 ones))\n(define integers (stream-cons 1 (add-streams ones integers)))\n(define factorials (stream-cons 1 (mul-streams factorials (stream-cdr integers))))\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n"
  },
  {
    "path": "scheme/sicp/03/55.scm",
    "content": "; SICP exercise 3.55\n;\n; Define a procedure partial-sums that takes as argument a stream S and\n; returns the stream whose elements are S₀, S₀ + S₁, S₀ + S₁ + S₂, ... . For\n; example, (partial-sums integers) should be the stream 1, 3, 6, 10, 15\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (add-streams a b) (stream-map2 + a b))\n(define (mul-streams a b) (stream-map2 * a b))\n\n(define ones (stream-cons 1 ones))\n(define integers (stream-cons 1 (add-streams ones integers)))\n\n(define (partial-sums stream)\n  (define result\n    (stream-cons (stream-car stream)\n                 (add-streams (stream-cdr stream) result)))\n  result)\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n"
  },
  {
    "path": "scheme/sicp/03/56.scm",
    "content": "; SICP exercise 3.56\n;\n; A famous problem, first raised by R. Hamming, is to enumerate, in ascending\n; order with no repetitions, all positive integers with no prime factors other\n; than 2, 3, or 5. One obvious way to do this is to simply test each integer\n; in turn to see whether it has any factors other than 2, 3 and 5. But this is\n; very inefficient, since, as the integers get larger, fewer and fewer of them\n; fit the requirement. As an alternative, let us call the required stream of\n; numbers S and notice the following facts about it.\n;\n; * S begins with 1.\n; * The elements of (scale-stream S 2) are also elements of S.\n; * The same is true for (scale-stream S 3) and (scale-stream 5 s)\n; * There are all the elements of S.\n;\n; Now all we have to do is combine elements from these sources. For this we\n; define a procedure merge that combines two ordered streams into one ordered\n; result stream, eliminating repetitions:\n;\n;   (define (merge s1 s2)\n;     (cond ((stream-null? s1) s2)\n;           ((stream-null? s2) s1)\n;           (else\n;            (let ((s1car (stream-car s1))\n;                  (s2car (stream-car s2)))\n;              (cond ((< s1car s2car)\n;                     (stream-cons\n;                       s1car\n;                       (merge (stream-cdr s1) s2)))\n;                    ((> s1car s2car)\n;                     (stream-cons\n;                       s2car\n;                       (merge s1 (stream-cdr s2))))\n;                    (else\n;                     (stream-cons\n;                       s1car\n;                       (merge (stream-cdr s1) (stream-cdr s2)))))))))\n;\n; Then the required stream may be constructed with merge, as follows:\n;\n;   (define S (stream-cons 1 (merge <??> <??>)))\n;\n; Fill in the missing expressions in the places marked <??> above.\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (merge s1 s2)\n  (cond ((stream-null? s1) s2)\n        ((stream-null? s2) s1)\n        (else\n         (let ((s1car (stream-car s1))\n               (s2car (stream-car s2)))\n           (cond ((< s1car s2car)\n                  (stream-cons s1car (merge (stream-cdr s1) s2)))\n                 ((> s1car s2car)\n                  (stream-cons s2car (merge s1 (stream-cdr s2))))\n                 (else\n                  (stream-cons s1car (merge (stream-cdr s1) (stream-cdr s2)))))))))\n\n(define (scale-stream stream n)\n  (stream-map (lambda (x) (* x n)) stream))\n\n(define S (stream-cons 1 (merge (scale-stream S 2)\n                                (merge (scale-stream S 3) (scale-stream S 5)))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n"
  },
  {
    "path": "scheme/sicp/03/57.scm",
    "content": "; SICP exercise 3.57\n;\n; How many additions are performed when we compute the nth Fibonacci number\n; using the definition of fibs based on the add-streams procdure? Show that\n; the number of additions would be exponentially greater if we had implemented\n; (delay <exp>) simply as (lambda () <exp>), without using the optimization\n; provided by the memo-proc procedure described in section 3.5.1\n\n; There are n - 1 additions performed for computing the nth fibonacci number.\n; In order to calculate the kth number, we're adding the (k - 1)th and the\n; (k - 2)th.\n;\n; If we don't memoize, we'll have to compute the two previous numbers for each\n; number we want to calculate. Recursively. This is the definition of\n; exponential.\n"
  },
  {
    "path": "scheme/sicp/03/58.scm",
    "content": "; SICP exercise 3.58\n;\n; Give an interpretation of the stream computed by the following procedure:\n;\n;   (define (expand num den radix)\n;     (stream-cons\n;       (quotient (* num radix) den)\n;       (expand (remainder (* num radix) den) den radix)))\n;\n; (quotient is a primitive that returns the integer quotient of two integers.)\n; What are the successive elements produced by (expand 1 7 10)? What is\n; produced by (expand 3 8 10)?\n\n; It produces the a stream of the digits of the decimal part of num/den in\n; radix. (num * radix) / den is the first digit. Then it proceeds to calculate\n; the first digit of the remainder of that division, which is the second digit\n; of the decimal part of the number. An so on and so forth.\n;\n; (expand 1 7 10) produces (1 4 2 8 5 7 1 4 2 8 5 7 1 4 2 8 5 7 1 4)\n; (expand 3 8 10) produces (3 7 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)\n"
  },
  {
    "path": "scheme/sicp/03/59.scm",
    "content": "; SICP exercise 3.59\n;\n; Section 2.5.3 we saw how to implement a polynomial arithmetic system\n; representing polynomials as lists of terms. In a similar way, we can work\n; with power series, such as\n;\n;                  x²   x³     x⁴\n;     eⁿ = 1 + x + ─ + ─── + ───── + …\n;                  2   3·2   4·3·2\n;\n;              x²    x⁴\n;   cosx = 1 - ─ + ───── - …\n;              2   4·3·2\n;\n;               x³     x⁵\n;   sinx = x - ─── + ─────── - …\n;              3·2   5·4·3·2\n;\n; represented as infinite streams. We will represent the series a₀ + a₁x +\n; a₂x² + a₃x³ + … as the stream whose elements are the coefficients a₀, a₁,\n; a₂, a₃, ….\n;\n;\n; a. The integral of the series a₀ + a₁x + a₂x² + a₃x³ + … is the series\n;\n;             1       1       1\n;   c + a₀x + ─a₁x² + ─a₂x³ + ─a₃x⁴ + …\n;             2       3       4\n;\n;\n; where c is any constant. Define a procedure integrate-series that takes as\n; input a stream a₀, a₁, a₂, … representing a power series and returns the\n; stream a₀, ½a₁, ⅓a₂, … of coefficients of the non-constant terms of the\n; integral series. (Since the result has no constant term, it doesn't\n; represent a power series; when we use integrate-series, we will cons on the\n; appropriate constant.)\n;\n; b. The function x ↦ eⁿ is its own derivative. This implies that eⁿ and the\n; ingral of eⁿ are the same series, except for the constant term, which is\n; e⁰ = 1. Accordingly, we can generate the series for eⁿ as\n;\n;   (define exp-series\n;     (cons-stream 1 (integrate-series exp-series)))\n;\n; Show how to generate the series for sine and cosine starting from the facts\n; that the given derivative of sine is cosine and the derivative of cosine is\n; the negative of sine:\n;\n;   (define cosine-series\n;     (cons-stream 1 <??>))\n;\n;   (define sine-series\n;     (cons-stream 0 <??>))\n\n; This is ridiculously easy. So easy, I'm shocked how much time it took to\n; input the exercise in comparison to solving it.\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (neg-stream a) (stream-map - a))\n(define (add-streams a b) (stream-map2 + a b))\n(define (mul-streams a b) (stream-map2 * a b))\n(define (div-streams a b) (stream-map2 / a b))\n\n(define ones (stream-cons 1 ones))\n(define integers (stream-cons 1 (add-streams ones integers)))\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define (integrate-series stream)\n  (div-streams stream integers))\n\n(define cosine-series\n  (stream-cons 1 (integrate-series (neg-stream sine-series))))\n\n(define sine-series\n  (stream-cons 0 (integrate-series cosine-series)))\n"
  },
  {
    "path": "scheme/sicp/03/60.scm",
    "content": "; SICP exercise 3.60\n;\n; With power series represented as streams of coefficients as in exercise\n; 3.59, adding series is implemented by add-streams. Complete the definition\n; of the following procedure for multiplying series:\n;\n;   (define (mul-series s1 s2)\n;     (cons-stream <??> (add-streams <??> <??>)))\n;\n; You can test your procedure by verifying that sin²x + cos²x = 1, using the\n; series from exercise 3.59\n\n; It would have been good if I knew how to multiply series. Anyway, let's say\n; we have (a₀ + A)(b₀ + B) where A and B are the remainder of the series.\n; Then:\n;\n; (a₀ + A)(b₀ + B) = a₀b₀ + Ab₀ + Ba₀ + AB = a₀b₀ + a₀B + A(b₀ + B)\n;\n; In that expression, a₀b₀ is the first element of the series and the rest is\n; the remaining elements. The solution is at the end.\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (neg-stream a) (stream-map - a))\n(define (add-streams a b) (stream-map2 + a b))\n(define (mul-streams a b) (stream-map2 * a b))\n(define (div-streams a b) (stream-map2 / a b))\n(define (scale-stream stream n) (stream-map (lambda (x) (* x n)) stream))\n\n(define ones (stream-cons 1 ones))\n(define integers (stream-cons 1 (add-streams ones integers)))\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define (integrate-series stream) (div-streams stream integers))\n(define cosine-series (stream-cons 1 (integrate-series (neg-stream sine-series))))\n(define sine-series (stream-cons 0 (integrate-series cosine-series)))\n\n(define (mul-series s1 s2)\n  (stream-cons (* (stream-car s1) (stream-car s2))\n               (add-streams (scale-stream (stream-cdr s2) (stream-car s1))\n                            (mul-series (stream-cdr s1) s2))))\n"
  },
  {
    "path": "scheme/sicp/03/61.scm",
    "content": "; SICP exercise 3.61\n;\n; Let S be a power series (exercise 3.59) whose constant term is 1. Suppose we\n; want to find the power series 1/S, that is, the series X such that SX = 1.\n; Write S = 1 + Sᵣ where Sᵣ is the part of S after the constant term. Then we\n; can solve for X as follows:\n;\n;          S·X = 1\n;   (1 + Sᵣ)·X = 1\n;     X + Sᵣ·X = 1\n;            X = 1 - Sᵣ·X\n;\n; In other words, X is the power series whose constant term is 1 and whose\n; higher-order terms are given by the genative of Sᵣ times X. Use this idea to\n; write a procedure invert-unit-series that computes 1/S for a power series S\n; with constant term 1. You will need to use mul-series from exercise 3.60.\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (neg-stream a) (stream-map - a))\n(define (add-streams a b) (stream-map2 + a b))\n(define (mul-streams a b) (stream-map2 * a b))\n(define (div-streams a b) (stream-map2 / a b))\n(define (scale-stream stream n) (stream-map (lambda (x) (* x n)) stream))\n\n(define ones (stream-cons 1 ones))\n(define integers (stream-cons 1 (add-streams ones integers)))\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define (integrate-series stream) (div-streams stream integers))\n(define cosine-series (stream-cons 1 (integrate-series (neg-stream sine-series))))\n(define sine-series (stream-cons 0 (integrate-series cosine-series)))\n\n(define (mul-series s1 s2)\n  (stream-cons (* (stream-car s1) (stream-car s2))\n               (add-streams (scale-stream (stream-cdr s2) (stream-car s1))\n                            (mul-series (stream-cdr s1) s2))))\n\n(define (invert-unit-series series)\n  (stream-cons 1 (neg-stream (mul-series (stream-cdr series)\n                                         (invert-unit-series series)))))\n"
  },
  {
    "path": "scheme/sicp/03/62.scm",
    "content": "; SICP exercise 3.62\n;\n; Use the result of exercise 3.60 and exercise 3.61 to define a procedure\n; div-series that divides two power series. div-series should work for any two\n; series, provided that the denominator series begins with a nonzero constant\n; term. (If the denominator has a zero constant term, the div-series should\n; signal an error.) Show how to use div-series together with the result of\n; exercise 3.59 to generate the power series for tangent.\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (neg-stream a) (stream-map - a))\n(define (add-streams a b) (stream-map2 + a b))\n(define (mul-streams a b) (stream-map2 * a b))\n(define (div-streams a b) (stream-map2 / a b))\n(define (scale-stream stream n) (stream-map (lambda (x) (* x n)) stream))\n\n(define ones (stream-cons 1 ones))\n(define integers (stream-cons 1 (add-streams ones integers)))\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define (integrate-series stream) (div-streams stream integers))\n\n(define (mul-series s1 s2)\n  (stream-cons (* (stream-car s1) (stream-car s2))\n               (add-streams (scale-stream (stream-cdr s2) (stream-car s1))\n                            (mul-series (stream-cdr s1) s2))))\n\n(define (invert-unit-series series)\n  (stream-cons 1 (neg-stream (mul-series (stream-cdr series)\n                                         (invert-unit-series series)))))\n\n(define (div-series a b)\n  (if (= (stream-car b) 0)\n      (error \"Cannot divide by a power series with constant term = 0\")\n      (mul-series a (invert-unit-series b))))\n\n(define cosine-series (stream-cons 1 (integrate-series (neg-stream sine-series))))\n(define sine-series (stream-cons 0 (integrate-series cosine-series)))\n(define tangent-series (div-series sine-series cosine-series))\n"
  },
  {
    "path": "scheme/sicp/03/63.scm",
    "content": "; SICP exercise 3.63\n;\n; Louis Reasoner asks why the sqrt-stream procedure was not written in the\n; following more straightforward way, without the local variable guesses:\n;\n;   (define (sqrt-stream x)\n;     (cons-stream 1.0\n;                  (stream-map (lambda (guess)\n;                                (sqrt-improve guess x))\n;                              (sqrt-stream x))))\n;\n; Alyssa P. Hacker replies that this version of the procedure is considerably\n; less efficient because it performs redundant computation. Explain Alyssa's\n; answer. Would the two versions still differ in efficiency if our\n; implementation of delay used only (lambda () <exp>) without using the\n; optimization provided by mem-proc (section 3.5.1)?\n\n; Since sqrt-stream is dependend on itself, every calculation of the (n + 1)th\n; term would require calculating the nth term again. This is exponential. By\n; using a variable, we're reusing the stream and we don't need to recalculate\n; the previous terms. If our delay does not memoize, the two versions would be\n; equally slow.\n"
  },
  {
    "path": "scheme/sicp/03/64.scm",
    "content": "; SICP exercise 3.64\n;\n; Write a procedure stream-limit that takes as arguments a stream and a number\n; (the tolerance). It should examine the stream until it finds two successive\n; elements that differ in absolute value by less than the tolerance, and\n; return the second of the two elements. Using this, we could compute square\n; roots up to a given tolerance by\n;\n;   (define (sqrt x tolerance)\n;     (stream-limit (sqrt-stream x) tolerance))\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (average a b)\n  (/ (+ a b)\n     2))\n\n(define (sqrt-improve guess x)\n  (average guess (/ x guess)))\n\n(define (sqrt-stream x)\n  (define guesses\n    (stream-cons 1.0\n                 (stream-map (lambda (guess) (sqrt-improve guess x)) guesses)))\n  guesses)\n\n(define (stream-limit stream tolerance)\n  (let ((s1 (stream-car stream))\n        (s2 (stream-car (stream-cdr stream))))\n    (if (< (abs (- s1 s2))\n           tolerance)\n        s2\n        (stream-limit (stream-cdr stream) tolerance))))\n\n(define (sqrt-tolerance number tolerance)\n  (stream-limit (sqrt-stream number) tolerance))\n"
  },
  {
    "path": "scheme/sicp/03/65.scm",
    "content": "; SICP exercise 3.65\n;\n; Use the series\n;\n;             1   1   1\n;   ln2 = 1 - ─ + ─ - ─ + …\n;             2   3   4\n;\n; to compute three sequences of approximations of the natural logarithm of 2,\n; in the same way we did above for π. How rapidly do these sequences converge?\n\n; The definitions are at the end of file. You can run it in order to see how\n; many steps it takes to converge on a specific tolerance with all the\n; sequences. This is the result from running it:\n;\n;   ln2-stream takes 9999 steps to tolerance 0.0001\n;   ln2-stream-euler takes 12 steps to tolerance 0.0001\n;   ln2-stream-accelarated takes 4 steps to tolerance 0.0001\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (add-streams a b) (stream-map2 + a b))\n(define (neg-stream a) (stream-map - a))\n\n(define (steps-to-tolerance stream tolerance)\n  (define (count stream n)\n    (let ((s1 (stream-car stream))\n          (s2 (stream-car (stream-cdr stream))))\n      (if (< (abs (- s1 s2))\n             tolerance)\n          n\n          (count (stream-cdr stream) (+ n 1)))))\n  (count stream 1))\n\n(define (square x) (* x x))\n\n(define (partial-sums stream)\n  (define result\n    (stream-cons (stream-car stream)\n                 (add-streams (stream-cdr stream) result)))\n  result)\n\n(define (alternate-signs stream)\n  (stream-cons (stream-car stream)\n               (neg-stream (alternate-signs (stream-cdr stream)))))\n\n(define (euler-transform s)\n  (let ((s0 (stream-ref s 0))\n        (s1 (stream-ref s 1))\n        (s2 (stream-ref s 2)))\n    (stream-cons (- s2 (/ (square (- s2 s1))\n                          (+ s0 (* -2 s1) s2)))\n                 (euler-transform (stream-cdr s)))))\n\n(define (make-tableau transform s)\n  (stream-cons s (make-tableau transform (transform s))))\n\n(define (accelarated-sequence transform s)\n  (stream-map stream-car (make-tableau transform s)))\n\n\n\n(define (ln2-summands n) (stream-cons (/ 1.0 n) (neg-stream (ln2-summands (+ n 1)))))\n(define ln2-stream (partial-sums (ln2-summands 1)))\n(define ln2-stream-euler (euler-transform ln2-stream))\n(define ln2-stream-accelarated (accelarated-sequence euler-transform ln2-stream))\n\n(define tolerance 0.0001)\n(printf \"ln2-stream takes ~s steps to tolerance ~s\\n\"\n        (steps-to-tolerance ln2-stream tolerance)\n        tolerance)\n(printf \"ln2-stream-euler takes ~s steps to tolerance ~s\\n\"\n        (steps-to-tolerance ln2-stream-euler tolerance)\n        tolerance)\n(printf \"ln2-stream-accelarated takes ~s steps to tolerance ~s\\n\"\n        (steps-to-tolerance ln2-stream-accelarated tolerance)\n        tolerance)\n"
  },
  {
    "path": "scheme/sicp/03/66.scm",
    "content": "; SICP exercise 3.66\n;\n; Examine the stream (pairs integers integers). Can you make any general\n; comments about the order in which the pairs are placed into the stream? For\n; example, approximately how many pairs precede the pair (1, 100)? the pair\n; (99, 100)? the pair (100, 100)? (If you can make precise mathematical\n; statements here, all the better. But feel free to give more qualitative\n; answers if you find yourself getting bogged down.)\n\n; The stream looks like this:\n;\n;   (1 1)\n;   (1 2)\n;   (2 2)\n;   (1 3)\n;   (2 3)\n;   (1 4)\n;   (3 3)\n;   (1 5)\n;   (2 4)\n;   (1 6)\n;   (3 4)\n;   (1 7)\n;   (2 5)\n;   (1 8)\n;   (4 4)\n;   (1 9)\n;   (2 6)\n;   (1 10)\n;   (3 5)\n;   (1 11)\n;\n; After the first one, every second element starts with 1. If we remove those,\n; we get this:\n;\n;   (2 2)\n;   (2 3)\n;   (3 3)\n;   (2 4)\n;   (3 4)\n;   (2 5)\n;   (4 4)\n;   (2 6)\n;   (3 5)\n;\n; We see the same behavior - every second element after the first starts with\n; 2. That goes all the way, since the pairs starting with x are interleaved\n; with the pairs starting with (x + 1). The interleaving of both streams is\n; interleaved with the pairs that start with x - 1. Here are the positions of\n; each pair, starting with a specific element\n;\n;   (1 x):  1  2  4  6  8 10\n;   (2 x):  3  5  9 13 17 21\n;   (3 x):  7 11 19 27 35 43\n;   (4 x): 15 23 39 55 71 87\n;\n; It is easy to see that (i i) is at the 2ⁱ - 1 position, (i i+1) is 2ⁱ⁻¹\n; positions apart and all other pairs starting with i are 2ⁱ positions apart\n; afterwards.\n;\n; Thus, pos((a b)) is\n;\n;   b - a = 0,   2ⁱ - 1\n;   b - a ≥ 1,   2ⁱ - 1 + 2ⁱ⁻¹ + (b-a-1)2ⁱ\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (add-streams a b) (stream-map2 + a b))\n\n(define ones (stream-cons 1 ones))\n(define integers (stream-cons 1 (add-streams ones integers)))\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define (interleave s1 s2)\n  (if (stream-null? s1)\n      s2\n      (stream-cons (stream-car s1)\n                   (interleave s2 (stream-cdr s1)))))\n\n(define (pairs s t)\n  (stream-cons\n    (list (stream-car s) (stream-car t))\n    (interleave\n      (stream-map (lambda (x) (list (stream-car s) x))\n                  (stream-cdr t))\n      (pairs (stream-cdr s) (stream-cdr t)))))\n\n(define int-pairs (pairs integers integers))\n\n(define (location stream pair)\n  (define (count stream n)\n    (if (equal? (stream-car stream) pair)\n        n\n        (count (stream-cdr stream) (+ n 1))))\n  (count stream 1))\n\n(define (position pair)\n  (let* ((a (car pair))\n         (b (cadr pair))\n         (first (- (expt 2 a) 1))\n         (second (expt 2 (- a 1))))\n    (cond ((= a b) first)\n          ((= (+ a 1) b) (+ first second))\n          (else (+ first second (* (- b a 1) (expt 2 a)))))))\n"
  },
  {
    "path": "scheme/sicp/03/67.scm",
    "content": "; SICP exercise 3.67\n;\n; Modify the pairs procedure so that (pairs integers integers) will produce\n; the stream of all pairs of integers (i, j) (without the condition i ≤ j).\n; Hint: You will need to mix in an additional stream.\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (add-streams a b) (stream-map2 + a b))\n\n(define ones (stream-cons 1 ones))\n(define integers (stream-cons 1 (add-streams ones integers)))\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define (interleave s1 s2)\n  (if (stream-null? s1)\n      s2\n      (stream-cons (stream-car s1)\n                   (interleave s2 (stream-cdr s1)))))\n\n(define (pairs s t)\n  (stream-cons\n    (list (stream-car s) (stream-car t))\n    (interleave\n      (interleave (stream-map (lambda (x) (list (stream-car s) x)) (stream-cdr t))\n                  (stream-map (lambda (x) (list x (stream-car t))) (stream-cdr s)))\n      (pairs (stream-cdr s) (stream-cdr t)))))\n\n(define int-pairs (pairs integers integers))\n\n(display (stream-take int-pairs 100))\n"
  },
  {
    "path": "scheme/sicp/03/68.scm",
    "content": "; SICP exercise 3.68\n;\n; Louis Reasoner thinks that building a stream of pairs from three pars in\n; unnecessarily complicated. Instead of separating the pair (S₀, T₀) from the\n; rest of the pairs in the first row, he proposes to work with the whole first\n; row, as follows:\n;\n;   (define (pairs s t)\n;     (interleave (stream-map (lambda (x) (list (stream-car s) x))\n;                             t)\n;                 (pairs (stream-cdr s) (stream-cdr t))))\n;\n; Does this work? Consider what happens if we evaluate (pairs integers\n; integers) using Louis's definition of pairs.\n\n; Although conceptually sound, this doesn't work in practice. When pairs is\n; called, it has to execute interleave. Before doing that, it needs to\n; evaluate the arguments, the second of which is a call to pairs. Since call\n; is not delayed, we end up in an recursion, where pairs keeps calling itself\n; with the cdr's of its arguments. Since both streams are infinite, this is\n; never bound to end.\n"
  },
  {
    "path": "scheme/sicp/03/69.scm",
    "content": "; SICP exercise 3.69\n;\n; Write a procedure triples that takes three infinite streams, S, T and U and\n; produces the stream of triples (Sᵢ, Tᵣ, Uᵥ) such that i ≤ r ≤ v. Use triples\n; to generate the stream of all Pythagorean triples of positive integers, i.e.\n; the triples (i, j, k) such that i ≤ j and i² + j² = k².\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (add-streams a b) (stream-map2 + a b))\n\n(define ones (stream-cons 1 ones))\n(define integers (stream-cons 1 (add-streams ones integers)))\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define (interleave s1 s2)\n  (if (stream-null? s1)\n      s2\n      (stream-cons (stream-car s1)\n                   (interleave s2 (stream-cdr s1)))))\n\n(define (pairs s t)\n  (stream-cons\n    (list (stream-car s) (stream-car t))\n    (interleave\n      (stream-map (lambda (x) (list (stream-car s) x)) (stream-cdr t))\n      (pairs (stream-cdr s) (stream-cdr t)))))\n\n(define (triples s t u)\n  (stream-cons\n    (list (stream-car s) (stream-car t) (stream-car u))\n    (interleave\n      (stream-map (lambda (x) (append (list (stream-car s)) x))\n                  (stream-cdr (pairs t u)))\n      (triples (stream-cdr s) (stream-cdr t) (stream-cdr u)))))\n\n(define int-triples (triples integers integers integers))\n\n(define (square x) (* x x))\n\n(define (pythagorean? triple)\n  (let ((a (car triple))\n        (b (cadr triple))\n        (c (caddr triple)))\n    (= (+ (square a) (square b))\n       (square c))))\n\n(define pythagorean-triples (stream-filter pythagorean? int-triples))\n"
  },
  {
    "path": "scheme/sicp/03/70.scm",
    "content": "; SICP exercise 3.70\n;\n; It would be nice to be able to generate streams in which the pairs appear in\n; some useful order, rather than in the order that results from an ad hoc\n; interleaving process. We can use a technique similar to the merge procedure\n; in figure 3.56, if we define a way to say that one pair of integers is \"less\n; than\" another. One way to do this is to define a \"weighting function\"\n; W(i, j) and stipulate that (i₁, j₁) is less than (i₂, j₂) if\n; W(i₁, j₁) < W(i₂, j₂). Write a procedure merge-weighted that is like merge,\n; except that merge-weighted takes an additional argument weight, which is a\n; procedure that computes the weight of a pair, and is used to determine the\n; order in which elements should appear in the resulting merged stream. Using\n; this, generalize pairs to a procedure weighted-pairs that takes two streams,\n; together with a procedure that computes a weighting function, and generates\n; the stream of pairs, ordered according to weight. Use your procedure to\n; generate\n;\n; a. the stream of all pairs of positive integers (i, j) with i ≤ j ordered\n; according to the sum i + j\n;\n; b. the stream of all pairs of positive integers (i, j) with i ≤ j, where\n; neither i nor j is divisable by 2, 3, or 5 and the pairs are ordered\n; according to the sum 2i + 3j + 5ij.\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (add-streams a b) (stream-map2 + a b))\n\n(define ones (stream-cons 1 ones))\n(define integers (stream-cons 1 (add-streams ones integers)))\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define (merge-weighted s t weight)\n  (let* ((s0 (stream-car s))\n         (t0 (stream-car t))\n         (s0w (weight s0))\n         (t0w (weight t0)))\n    (if (< s0w t0w)\n        (stream-cons s0 (merge-weighted (stream-cdr s) t weight))\n        (stream-cons t0 (merge-weighted s (stream-cdr t) weight)))))\n\n(define (weighted-pairs s t weight)\n  (stream-cons\n    (list (stream-car s) (stream-car t))\n    (merge-weighted\n      (stream-map (lambda (x) (list (stream-car s) x)) (stream-cdr t))\n      (weighted-pairs (stream-cdr s) (stream-cdr t) weight)\n      weight)))\n\n(define (a-pairs)\n  (define (pair-sum pair) (+ (car pair) (cadr pair)))\n  (weighted-pairs integers integers pair-sum))\n\n(define (b-pairs)\n  (define (useful? integer)\n    (not (or (= (remainder integer 2) 0)\n             (= (remainder integer 3) 0)\n             (= (remainder integer 5) 0))))\n  (define (weight pair)\n    (let ((i (car pair)) (j (cadr pair)))\n      (+ (* 2 i)\n         (* 3 j)\n         (* 5 i j))))\n  (define useful-integers (stream-filter useful? integers))\n  (weighted-pairs useful-integers useful-integers weight))\n"
  },
  {
    "path": "scheme/sicp/03/71.scm",
    "content": "; SICP exercise 3.71\n;\n; Numbers that can be expressed as the sum of two cubes in more than one way\n; are sometimes called Ramanujan numbers, in honor of the mathematician\n; Srinivasa Ramanujan. Ordered streams of pairs provide an elegant solution to\n; the problem of computing these numbers. To find a number that can be written\n; as the sum of two cubes in two different ways, we need only generate the\n; stream of pairs of integers (i, j) weighted according to the sum i^3 + j^3\n; (see exercise 3.70), then search the stream for two consecutive pairs with\n; the same weight. Write a procedure to generate the Ramanujan numbers. The\n; first such number is 1,729. What are the next five?\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (add-streams a b) (stream-map2 + a b))\n\n(define ones (stream-cons 1 ones))\n(define integers (stream-cons 1 (add-streams ones integers)))\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define (merge-weighted s t weight)\n  (let* ((s0 (stream-car s))\n         (t0 (stream-car t))\n         (s0w (weight s0))\n         (t0w (weight t0)))\n    (if (< s0w t0w)\n        (stream-cons s0 (merge-weighted (stream-cdr s) t weight))\n        (stream-cons t0 (merge-weighted s (stream-cdr t) weight)))))\n\n(define (weighted-pairs s t weight)\n  (stream-cons\n    (list (stream-car s) (stream-car t))\n    (merge-weighted\n      (stream-map (lambda (x) (list (stream-car s) x)) (stream-cdr t))\n      (weighted-pairs (stream-cdr s) (stream-cdr t) weight)\n      weight)))\n\n(define (ramanujan-numbers)\n  (define (cube x) (* x x x))\n  (define (weight pair) (+ (cube (car pair)) (cube (cadr pair))))\n  (define ordered-integers (weighted-pairs integers integers weight))\n  (define (filter-ramanujan stream)\n    (let ((p1 (stream-car stream))\n          (p2 (stream-car (stream-cdr stream))))\n      (if (= (weight p1) (weight p2))\n          (stream-cons (weight p1)\n                       (filter-ramanujan (stream-cdr stream)))\n          (filter-ramanujan (stream-cdr stream)))))\n  (filter-ramanujan ordered-integers))\n"
  },
  {
    "path": "scheme/sicp/03/72.scm",
    "content": "; SICP exercise 3.72\n;\n; In a similar way to exercise 3.72 generate a stream of all numbers that can\n; be written as the sum of two squares in three different ways (showing how\n; they can be so written).\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (add-streams a b) (stream-map2 + a b))\n\n(define ones (stream-cons 1 ones))\n(define integers (stream-cons 1 (add-streams ones integers)))\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define (merge-weighted s t weight)\n  (let* ((s0 (stream-car s))\n         (t0 (stream-car t))\n         (s0w (weight s0))\n         (t0w (weight t0)))\n    (if (< s0w t0w)\n        (stream-cons s0 (merge-weighted (stream-cdr s) t weight))\n        (stream-cons t0 (merge-weighted s (stream-cdr t) weight)))))\n\n(define (weighted-pairs s t weight)\n  (stream-cons\n    (list (stream-car s) (stream-car t))\n    (merge-weighted\n      (stream-map (lambda (x) (list (stream-car s) x)) (stream-cdr t))\n      (weighted-pairs (stream-cdr s) (stream-cdr t) weight)\n      weight)))\n\n(define (three-ways-of-two-squares)\n  (define (square x) (* x x))\n  (define (weight pair) (+ (square (car pair)) (square (cadr pair))))\n  (define (uniq stream)\n    (if (= (stream-car stream) (stream-car (stream-cdr stream)))\n        (uniq (stream-cons (stream-car stream) (stream-cdr (stream-cdr stream))))\n        (stream-cons (stream-car stream) (uniq (stream-cdr stream)))))\n  (define ordered-integers (weighted-pairs integers integers weight))\n  (define (filter-numbers stream)\n    (let ((p1 (stream-car stream))\n          (p2 (stream-car (stream-cdr stream)))\n          (p3 (stream-car (stream-cdr (stream-cdr stream)))))\n      (if (= (weight p1) (weight p2) (weight p3))\n          (stream-cons (weight p1)\n                       (filter-numbers (stream-cdr stream)))\n          (filter-numbers (stream-cdr stream)))))\n  (uniq (filter-numbers ordered-integers)))\n"
  },
  {
    "path": "scheme/sicp/03/73.scm",
    "content": "; SICP exercise 3.73\n;\n; We can model electrical circuits using streams to represent the values of\n; currents or voltages at a sequence of times. For instance, suppose we have\n; an RC circuit consisting of a resistor of resistance R and a capacitor C in\n; series. The voltage response v of the circuit to an injected current i is\n; determined by the formula in figure 3.33, whose structure is shown by the\n; accomplanying signal-flow diagram:\n;\n;   [figure 3.33]\n;\n; Write a procedure RC that models this circuit. RC should take as inputs the\n; values of R, C, and dt and should return a procedure that takes as inputs a\n; stream representing the current i and an initial value for the capacitor\n; voltage v₀ and produces as output the stream of voltages v. For example, you\n; should be able to use RC to model an RC circuit with R = 5 ohms, C = 1\n; farad, and 0.5-second time step by evaluating (define RC1 (RC 5 1 0.5)).\n; This defines RC1 as a procedure that takes a stream representing the time\n; sequence of currents and an initial capacitor voltage and produces the\n; output stream of voltages.\n\n; Man, this brings me a long time back. Also, I have no idea what I'm doing.\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (add-streams a b) (stream-map2 + a b))\n(define (scale-stream stream n) (stream-map (lambda (x) (* n x)) stream))\n\n(define ones (stream-cons 1 ones))\n(define integers (stream-cons 1 (add-streams ones integers)))\n(define ones-and-zeroes (stream-cons 1 (stream-cons 0 ones-and-zeroes)))\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define (integral integrand initial-value dt)\n  (define int\n    (stream-cons initial-value\n                 (add-streams (scale-stream integrand dt) int)))\n  int)\n\n(define (RC resistance capacity dt)\n  (define (result stream initial-voltage)\n    (add-streams (scale-stream stream resistance)\n                 (integral (scale-stream stream (/ 1 capacity)) initial-voltage dt)))\n  result)\n\n(define RC1 (RC 5 1 0.5))\n"
  },
  {
    "path": "scheme/sicp/03/74.scm",
    "content": "; SICP exercise 3.74\n;\n; Alyssa P. Hacker is designing a system to process signals coming from\n; physical sensors. One important feture she wishes to produce is a signal\n; that describes the zero corssings of the input signal. That is, the\n; resulting singal should be +1 whenever the input signal changes form\n; negative to positive, -1 whenever the input signal changes from positive to\n; negative and 0 otherwise. (Assume that the sign of 0 input is positive.) For\n; example, a typical input signal with its associated zero-crossing signal\n; would be:\n;\n;   ...1  2  1.5  1  0.5  -0.1  -2  -3  -2  -0.5  0.2  3  4...\n;   ...0  0   0   0   0    -1    0   0   0    0    1   0  0...\n;\n; In Alyssa's system, the signal from the sensor is represented as a stream\n; sense-data and the stream zero-crossings is the corresponding stream of zero\n; crossings. Alyssa first writes a procedure sign-change-detector that takes\n; two values as arguments and compares the signs of the values to produce an\n; appropriate 0, 1, or -1. She then constructs her zero-crossing stream as\n; follows:\n;\n;   (define (make-zero-crossings input-stream last-value)\n;     (cons-stream\n;       (sign-change-detector (stream-car input-stream)\n;                             last-value)\n;       (make-zero-crossings (stream-cdr input-stream)\n;                            (stream-car input-stream))))\n;\n;   (define zero-crossings (make-zero-crossings sense-data 0))\n;\n; Alyssa's boss, Eva Lu Ator, walks by and suggests that this program is\n; approximately equivalent to the following one, which uses the generalized\n; version of stream-map from exercise 3.50\n;\n;   (define zero-crossings\n;     (stream-map sign-change-detector sense-data <expression>))\n;\n; Complete the program by supplying the indicated <expression>.\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define (sign-change-detector a b)\n  (cond ((and (< b 0) (< 0 a)) 1)\n        ((and (< a 0) (< 0 b)) -1)\n        (else 0)))\n\n(define (make-zero-crossings input-stream last-value)\n  (stream-cons\n    (sign-change-detector (stream-car input-stream)\n                          last-value)\n    (make-zero-crossings (stream-cdr input-stream)\n                         (stream-car input-stream))))\n\n(define (make-zero-crossings-with-map sense-data)\n  (stream-map2 sign-change-detector sense-data (stream-cons 0 sense-data)))\n"
  },
  {
    "path": "scheme/sicp/03/75.scm",
    "content": "; SICP exercise 3.75\n;\n; Unfortunately, Alyssa's zero-crossing detector in exercise 3.74 provides to\n; be insufficient, because the nosiy signal from the sensor leads to spurious\n; zero-crossings. Lem E. Tweakit, a hardware specialist, suggests that Alyssa\n; smooth the signal to filter out the noise before extracting the zero\n; crossings. Alyssa takes his advice and decides to extract the zero crossings\n; from the signal constructed by averaging each value of the sense data with\n; the previous value. She explains the problem to her assistant, Louis\n; Reasoner, who attempts to implement the idea, altering Alyssa's program as\n; follows:\n;\n;   (define (make-zero-crossings input-stream last-value)\n;     (let ((avpt (/ (+ (stream-car input-stream)\n;                       last-value)\n;                    2)))\n;       (cons-stream (sign-change-detector avpt last-value)\n;                    (make-zero-crossings\n;                      (stream-cdr input-stream) avpt))))\n;\n; This does not correctly implement Alyssa's plan. Fidn the bug that Louis has\n; installed and fix it without changing the structure of the program. (Hint:\n; You will need to increase the number of arguments to make-zero-crossings.)\n\n; The problem is that it does not average each element with the previous, but\n; with the average of the previous and its previous' average. This offsets the\n; whole calculation. Here's the real implementation. For a change, no tests,\n; since testing this is tricky.\n\n(define (make-zero-crossings input-stream last-value last-avpt)\n  (let ((avpt (/ (+ (stream-car input-stream)\n                    last-value)\n                 2)))\n    (cons-stream (sign-change-detector avpt last-value)\n                 (make-zero-crossings\n                   (stream-cdr input-stream)\n                   (stream-car input-stream)\n                   avpt))))\n"
  },
  {
    "path": "scheme/sicp/03/76.scm",
    "content": "; SICP exercise 3.76\n;\n; Eva Lu Ator has a criticism of Louis's approach in exercise 3.75. The\n; program he wrote is not modular, because it intermixes the operation of\n; smoothing with the zero-crossing extraction. For example, the extractor\n; should not have to be changed if Alyssa finds a better way to condition her\n; input signal. Help Louis by writing a procedure smooth that takes a stream\n; as input and produces a stream in which each element is the average of two\n; succesive input stream elements. Then use smooth as a component to implement\n; the zero-crossing detector in a more modular style.\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define (sign-change-detector a b)\n  (cond ((and (< b 0) (< 0 a)) 1)\n        ((and (< a 0) (< 0 b)) -1)\n        (else 0)))\n\n(define (smooth stream)\n  (define (smooth-stream stream prev)\n    (let ((first (stream-car stream))\n          (rest (stream-cdr stream)))\n      (stream-cons (/ (+ first prev) 2.0)\n                   (smooth-stream rest prev))))\n  (stream-cons (stream-car stream)\n               (smooth-stream (stream-cdr stream) (stream-car stream))))\n\n(define (make-zero-crossings input-stream last-value)\n  (let ((smooth-stream (smooth input-stream)))\n    (stream-map2 sign-change-detector smooth-stream (stream-cons 0 smooth-stream))))\n"
  },
  {
    "path": "scheme/sicp/03/77.scm",
    "content": "; SICP exercise 3.77\n;\n; The integral procedure used above was analogous to the \"implicit\" definition\n; of the infinite stream of integers in section 3.5.2. Alternatively, we can\n; give a definition of integral that is more like integres-strating-from (also\n; in section 3.5.2):\n;\n;   (define (integral integrand initial-value dt)\n;     (cons-stream initial-value\n;                  (if (stream-null? integrand)\n;                      the-empty-stream\n;                      (integral (stream-cdr integrand)\n;                                (+ (* dt (stream-car integrand))\n;                                   initial-value)\n;                                dt))))\n;\n; When used in systems with loops, this procedure has the same problem as does\n; our original version of integral. Modify the procedure so that it expects\n; the integrand as a delayed argument and hence can be used in the solve\n; procedure shown above.\n\n; This is very hard to test, given how Racket works. Anyway:\n\n(define (integral delayed-integrand initial-value dt)\n  (cons-stream initial-value\n               (if (stream-null? delayed-integrand)\n                   the-empty-stream\n                   (let ((integrand (force delayed-integrand)))\n                     (integral (delay (stream-cdr integrand))\n                               (+ (* dt (force (stream-car integrand)))\n                                  initial-value)\n                               dt)))))\n"
  },
  {
    "path": "scheme/sicp/03/78.scm",
    "content": "; SICP exercise 3.78\n;\n; Consider the problem of designing a signal-processing system to study the\n; homogeneous second-order linear differential equation\n;\n;   d²y    dy\n;   ─── - a── - by = 0\n;   dt²    dt\n;\n; The output stream, modeling y, is generated by a network that contains a\n; loop. This is because the value of d²y/dt² depends upon the values of y and\n; dy/dt and both of these are determined by integrating d²y/dt². The diagram\n; we would like to encode is shown in figure 3.35. Write a procedure solve-2nd\n; that takes as arguments the constants a, b and dt and the initial values y₀\n; and dy₀ for y and dy/dt and generates the stream of successive values of y.\n\n(define (solve-2nd a b dt y0 dy0)\n  (define y (integral (delay dy) y0 dt))\n  (define dy (integral (delay ddy) dy0 dt))\n  (define ddy (add-streams (scale-stream dy a)\n                           (scale-stream y b)))\n  y)\n"
  },
  {
    "path": "scheme/sicp/03/79.scm",
    "content": "; SICP exercise 3.79\n;\n; Generlize the solve-2nd procedure of exercise 3.78 so that it can be used to\n; solve general second-order differential equations d²y/dt² = f(dy/dt, y).\n\n(define (solve-2nd-generic f y0 dy0 dt)\n  (define y (integral (delay dy) y0 dt))\n  (define dy (integral (delay ddy) dy0 dt))\n  (define ddy (stream-map f dy y))\n  y)\n"
  },
  {
    "path": "scheme/sicp/03/80.scm",
    "content": "; SICP exercise 3.80\n;\n; A series RLC circuit consists of a resistor, a capacitor, and an inductor\n; connected in series, as shown in figure 3.36. If R, L, and C are the\n; resistance, inductance and capacitance, then the relations between voltage\n; (v) and current (i) for the three components are described by the equations\n;\n;   v(R) = i(R)R\n;\n;           di(L)\n;   v(L) = L─────\n;            dt\n;\n;           dv(C)\n;   i(C) = C─────\n;            dt\n;\n; and the circuit connections dictate the relations\n;\n;   i(R) = i(L) = -i(C)\n;   v(C) = v(L) + v(R)\n;\n; Combining these equations shows that the state of the circuit (summarized by\n; v(C), the voltage accross the capacitor, and i(L), the current in the\n; inductor) is described by the pair of differential equations\n;\n;   dv(C)     i(L)\n;   ───── = - ────\n;    dt        C\n;\n;   di(L)   1       R\n;   ───── = ─v(C) - ─i(L)\n;    dt     L       L\n;\n; The signal-flow diagram representing this system of differential equations\n; is shown in figure 3.37.\n;\n; Write a procedure RLC that takes as arguments the parameters R, L, and C of\n; the circuit and the time increment dt. In a manner similar to that of the RC\n; procedure of exercise 3.73, RLC should produce a procedure that takes the\n; initial values of the state variables, v(C₀) and i(L₀), and produces a pair\n; (using cons) of the streams of states v(C) and i(L). Using RLC, generate the\n; pair of streams that models the behavior of a series RLC circuit with R = 1\n; ohm, C = 0.2 farad, L = 1 henry, dt = 0.1 second, and initial values i(L₀) =\n; 0 amps and v(C₀) = 10 volts.\n\n; Wow. The electronics here are beyond me. To be honest - the math too.\n; Anyway:\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (add-streams a b) (stream-map2 + a b))\n(define (scale-stream stream n) (stream-map (lambda (x) (* n x)) stream))\n\n(define ones (stream-cons 1 ones))\n(define integers (stream-cons 1 (add-streams ones integers)))\n(define ones-and-zeroes (stream-cons 1 (stream-cons 0 ones-and-zeroes)))\n\n(define (stream-map2 proc . argstreams)\n  (if (stream-null? (car argstreams))\n      the-empty-stream\n      (stream-cons\n       (apply proc (map stream-car argstreams))\n       (apply stream-map2\n              (cons proc (map stream-cdr argstreams))))))\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define (integral delayed-integrand initial-value dt)\n  (define int\n    (stream-cons initial-value\n                 (add-streams (scale-stream (force delayed-integrand) dt)\n                              int)))\n  int)\n\n(define (RLC R L C dt)\n  (lambda (vc0 il0)\n    (define vc (integral (delay dvc) vc0 dt))\n    (define il (integral (delay dil) il0 dt))\n    (define dvc (scale-stream il (- (/ 1 C))))\n    (define dil (add-streams (scale-stream vc (/ 1 L))\n                             (scale-stream il (- (/ R L)))))\n    (stream-map2 cons vc il)))\n\n(define RLC1 (RLC 1 1 0.2 0.1))\n"
  },
  {
    "path": "scheme/sicp/03/81.scm",
    "content": "; SICP exercise 3.81\n;\n; Exercise 3.6 discussed generalizing the random-number generator to allow one\n; to reset the random-number sequence so as to produce repeatable sequences of\n; \"random\" numbers. Produce a stream formulation of this same generator that\n; operates on an input stream of requests to generate a new random number or\n; to reset the sequence to a specified value and that produces the desired\n; stream of random numbers. Don't use assignment in your solution.\n\n(define stream-take '())\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define (stream-take stream n)\n  (if (= n 0)\n      '()\n      (cons (stream-car stream) (stream-take (stream-cdr stream) (- n 1)))))\n\n(define random-init (current-milliseconds))\n\n(define (rand-update number)\n  (let ((modulus 4294967296)\n        (multiplier 1664525)\n        (increment 1013904223))\n    (modulo (+ (* multiplier number) increment) modulus)))\n\n(define (random-numbers requests)\n  (define (next seed requests)\n    (cond ((stream-null? requests) the-empty-stream)\n          ((eq? (stream-car requests) 'generate)\n           (let ((generated (rand-update seed))\n                 (rest (stream-cdr requests)))\n             (stream-cons generated (next generated rest))))\n          ((eq? (stream-car requests) 'reset)\n           (let ((new-seed (stream-car (stream-cdr requests)))\n                 (rest (stream-cdr (stream-cdr requests))))\n             (next new-seed rest)))))\n  (next random-init requests))\n"
  },
  {
    "path": "scheme/sicp/03/82.scm",
    "content": "; SICP exercise 3.82\n;\n; Redo exercise 3.5 on Monte Carlo integration in terms of streams. The stream\n; version of estimate-integral will not have an argument telling how many\n; trials to perform. Instead, it will produce a stream of estimates based on\n; succesively more trials.\n\n(define the-empty-stream empty-stream)\n(define stream-null? stream-empty?)\n(define stream-car stream-first)\n(define stream-cdr stream-rest)\n\n(define random-modulus 4294967296)\n(define random-init (modulo (current-milliseconds) random-modulus))\n\n(define (rand-update number)\n  (let ((modulus random-modulus)\n        (multiplier 1664525)\n        (increment 1013904223))\n    (modulo (+ (* multiplier number) increment) modulus)))\n\n(define random-integers\n  (stream-cons random-init\n               (stream-map rand-update random-integers)))\n\n(define random-floats\n  (stream-map (lambda (x) (exact->inexact (/ x random-modulus))) random-integers))\n\n(define (monte-carlo experiment-stream passed failed)\n  (define (next passed failed)\n    (stream-cons\n      (/ passed (+ passed failed))\n      (monte-carlo (stream-cdr experiment-stream) passed failed)))\n  (if (stream-car experiment-stream)\n      (next (+ passed 1) failed)\n      (next passed (+ failed 1))))\n\n(define (map-successive-pairs f s)\n  (stream-cons\n    (f (stream-car s) (stream-car (stream-cdr s)))\n    (map-successive-pairs f (stream-cdr (stream-cdr s)))))\n\n(define (estimate-integral predicate x1 x2 y1 y2)\n  (define (scale-within value low high)\n    (+ (* value (- high low)) low))\n  (define experiment-stream\n    (map-successive-pairs\n      (lambda (a b)\n        (predicate (scale-within a x1 x2)\n                   (scale-within b y1 y2)))\n      random-floats))\n  (monte-carlo experiment-stream 0 0))\n\n(define (estimate-pi tries)\n  (define (circle x y)\n    (<= (+ (* x x) (* y y)) 1))\n  (* (stream-ref (estimate-integral circle -1 1 -1 1) tries)\n     4.0))\n"
  },
  {
    "path": "scheme/sicp/03/tests/01-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../01.scm\")\n\n(define sicp-3.01-tests\n  (test-suite\n    \"Tests for SICP exercise 3.01\"\n\n    (check-equal? ((make-accumulator 10) 5) 15)\n\n    (test-begin\n      (let ((accumulator (make-accumulator 0)))\n        (accumulator 10)\n        (accumulator 20)\n        (check-equal? (accumulator 30) 60)))\n\n    (test-begin\n      (let ((first (make-accumulator 0))\n            (second (make-accumulator 0)))\n        (check-equal? (first 10) 10)\n        (check-equal? (second 20) 20)\n        (check-equal? (first 10) 20)\n        (check-equal? (second 20) 40)))\n\n\n))\n\n(run-tests sicp-3.01-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/02-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../02.scm\")\n\n(define sicp-3.02-tests\n  (test-suite\n    \"Tests for SICP exercise 3.02\"\n\n    (test-begin\n      (let ((s (make-monitored sqrt)))\n        (check-equal? (s 100) 10)\n        (check-equal? (s 'how-many-calls?) 1)))\n\n    (test-begin\n      (let ((s (make-monitored sqrt)))\n        (s 100)\n        (s 100)\n        (s 100)\n        (check-equal? (s 'how-many-calls?) 3)))\n\n    (test-begin\n      (let ((s (make-monitored sqrt)))\n        (s 100)\n        (s 'reset-count)\n        (check-equal? (s 'how-many-calls?) 0)))\n))\n\n(run-tests sicp-3.02-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/03-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../03.scm\")\n\n(define sicp-3.03-tests\n  (test-suite\n    \"Tests for SICP exercise 3.03\"\n\n    (test-begin\n      (let ((account (make-account 100 'secret)))\n        (check-equal? ((account 'deposit 'secret) 0) 100)\n        (check-equal? ((account 'deposit 'secret) 50) 150)\n        (check-equal? ((account 'withdraw 'secret) 100) 50)\n        (check-equal? ((account 'withdraw 'secret) 100) \"Insufficient funds\")))\n\n    (test-begin\n      (let ((account (make-account 100 'secret)))\n        (check-equal? ((account 'deposit 'wrong) 0) \"Incorrect password\")\n        (check-equal? ((account 'deposit 'secret) 0) 100)))\n))\n\n(run-tests sicp-3.03-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/04-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../04.scm\")\n\n(define cops-called #f)\n\n(define (call-the-cops)\n  (set! cops-called #t))\n\n(define sicp-3.04-tests\n  (test-suite\n    \"Tests for SICP exercise 3.04\"\n\n    (before\n      (set! cops-called #f)\n\n      (test-begin\n        (let ((account (make-account 100 'secret)))\n          (check-equal? ((account 'deposit 'secret) 0) 100)\n          (check-equal? ((account 'deposit 'secret) 50) 150)\n          (check-equal? ((account 'withdraw 'secret) 100) 50)\n          (check-equal? ((account 'withdraw 'secret) 100) \"Insufficient funds\")))\n\n      (test-begin\n        (let ((account (make-account 100 'secret)))\n          (check-equal? ((account 'deposit 'wrong) 0) \"Incorrect password\")\n          (check-equal? ((account 'deposit 'secret) 0) 100)))\n\n      (test-begin\n        (let ((account (make-account 100 'secret)))\n          ((account 'withdraw 'wrong) 10)\n          ((account 'withdraw 'wrong) 10)\n          ((account 'withdraw 'wrong) 10)\n\n          ((account 'withdraw 'secret) 10)\n\n          ((account 'withdraw 'wrong) 10)\n          ((account 'withdraw 'wrong) 10)\n          ((account 'withdraw 'wrong) 10)\n          ((account 'withdraw 'wrong) 10)\n\n          (check-equal? cops-called #f)))\n\n      (test-begin\n        (let ((account (make-account 100 'secret)))\n          ((account 'withdraw 'wrong) 10)\n          ((account 'withdraw 'wrong) 10)\n          ((account 'withdraw 'wrong) 10)\n          ((account 'withdraw 'wrong) 10)\n          ((account 'withdraw 'wrong) 10)\n          ((account 'withdraw 'wrong) 10)\n          ((account 'withdraw 'wrong) 10)\n\n          (check-equal? cops-called #t))))\n))\n\n(run-tests sicp-3.04-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/05-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../05.scm\")\n\n(define sicp-3.05-tests\n  (test-suite\n    \"Tests for SICP exercise 3.05\"\n\n    (check-= (estimate-pi) 3.14 0.01)\n))\n\n(run-tests sicp-3.05-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/07-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../07.scm\")\n\n(define sicp-3.07-tests\n  (test-suite\n    \"Tests for SICP exercise 3.07\"\n\n    (test-begin\n      (let* ((peter-acc (make-account 100 'open-sesame))\n             (paul-acc (make-joint peter-acc 'open-sesame 'rosebud)))\n        ((paul-acc 'deposit 'rosebud) 10)\n        ((paul-acc 'withdraw 'rosebud) 50)\n        (check-equal? ((peter-acc 'deposit 'open-sesame) 0) 60)))\n\n    (test-begin\n      (let* ((peter-acc (make-account 100 'open-sesame))\n             (paul-acc (make-joint peter-acc 'open-sesame 'rosebud)))\n        (check-equal? ((paul-acc 'deposit 'wrong) 0) \"Incorrect password\")))\n))\n\n(run-tests sicp-3.07-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/16-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../16.scm\")\n\n(define sicp-3.16-tests\n  (test-suite\n    \"Tests for SICP exercise 3.16\"\n\n    (check-equal? (count-pairs three) 3)\n    (check-equal? (count-pairs four) 4)\n    (check-equal? (count-pairs seven) 7)\n))\n\n(run-tests sicp-3.16-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/17-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../17.scm\")\n\n(define a '(a))\n(define b (cons 'b a))\n(define c (cons a a))\n\n(define three '(a b c))\n(define four (cons b a))\n(define seven (cons c c))\n\n(define sicp-3.17-tests\n  (test-suite\n    \"Tests for SICP exercise 3.17\"\n\n    (check-equal? (count-pairs three) 3)\n    (check-equal? (count-pairs four) 3)\n    (check-equal? (count-pairs seven) 3)\n))\n\n(run-tests sicp-3.17-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/18-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../18.scm\")\n\n(define sicp-3.18-tests\n  (test-suite\n    \"Tests for SICP exercise 3.18\"\n\n    (check-true (has-cycle? (make-cycle '(a b c d))))\n    (check-false (has-cycle? '(a b c d)))\n))\n\n(run-tests sicp-3.18-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/19-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../19.scm\")\n\n(define sicp-3.19-tests\n  (test-suite\n    \"Tests for SICP exercise 3.19\"\n\n    (check-true (has-cycle? (make-cycle '(a b c d))))\n    (check-true (has-cycle? (make-cycle '(a b c d e))))\n\n    (check-false (has-cycle? '()))\n    (check-false (has-cycle? '(a)))\n    (check-false (has-cycle? '(a b)))\n    (check-false (has-cycle? '(a b c)))\n    (check-false (has-cycle? '(a b c d)))\n))\n\n(run-tests sicp-3.19-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/21-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../21.scm\")\n\n(define sicp-3.21-tests\n  (test-suite\n    \"Tests for SICP exercise 3.21\"\n\n    (test-begin \"print-queue\"\n      (define q (make-queue))\n\n      (insert-queue! q 'a)\n      (insert-queue! q 'b)\n      (insert-queue! q 'c)\n\n      (check-equal? (with-output-to-string (lambda () (print-queue q)))\n                    \"#<queue:(a b c)>\\n\"))\n\n    (test-suite \"queue operations\"\n      (test-begin \"insert-queue!\"\n        (define q (make-queue))\n\n        (insert-queue! q 'a)\n        (check-equal? 'a (front-queue q)))\n\n      (test-begin \"delete-queue!\"\n        (define q (make-queue))\n\n        (insert-queue! q 'a)\n        (insert-queue! q 'b)\n\n        (check-equal? 'a (front-queue q))\n\n        (delete-queue! q)\n        (check-equal? 'b (front-queue q))))\n))\n\n(run-tests sicp-3.21-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/22-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../22.scm\")\n\n(define sicp-3.22-tests\n  (test-suite\n    \"Tests for SICP exercise 3.22\"\n\n    (test-begin \"empty-queue?\"\n      (check-true (empty-queue? (make-queue))))\n\n    (test-begin \"insert-queue!\"\n      (define q (make-queue))\n\n      (insert-queue! q 'a)\n      (check-equal? 'a (front-queue q)))\n\n    (test-begin \"delete-queue!\"\n      (define q (make-queue))\n\n      (insert-queue! q 'a)\n      (insert-queue! q 'b)\n\n      (check-equal? 'a (front-queue q))\n\n      (delete-queue! q)\n      (check-equal? 'b (front-queue q)))\n))\n\n(run-tests sicp-3.22-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/23-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../23.scm\")\n\n(define sicp-3.23-tests\n  (test-suite\n    \"Tests for SICP exercise 3.23\"\n\n    (test-case \"empty-deque?\"\n      (check-true (empty-deque? (make-deque))))\n\n    (test-case \"front-insert-deque!\"\n      (define deque (make-deque))\n      (front-insert-deque! deque 'a)\n      (front-insert-deque! deque 'b)\n      (front-insert-deque! deque 'c)\n\n      (check-equal? (front-deque deque) 'c)\n      (check-equal? (rear-deque deque) 'a))\n\n    (test-case \"rear-insert-deque!\"\n      (define deque (make-deque))\n      (rear-insert-deque! deque 'a)\n      (rear-insert-deque! deque 'b)\n      (rear-insert-deque! deque 'c)\n\n      (check-equal? (front-deque deque) 'a)\n      (check-equal? (rear-deque deque) 'c))\n\n    (test-case \"front-delete-deque!\"\n      (define deque (make-deque))\n      (rear-insert-deque! deque 'a)\n      (rear-insert-deque! deque 'b)\n      (rear-insert-deque! deque 'c)\n\n      (front-delete-deque! deque)\n\n      (check-equal? (front-deque deque) 'b)\n      (check-equal? (rear-deque deque) 'c)\n\n      (front-delete-deque! deque)\n      (check-equal? (front-deque deque) 'c)\n      (check-equal? (rear-deque deque) 'c)\n\n      (front-delete-deque! deque)\n      (check-true (empty-deque? deque)))\n\n    (test-case \"rear-delete-deque!\"\n      (define deque (make-deque))\n      (rear-insert-deque! deque 'a)\n      (rear-insert-deque! deque 'b)\n      (rear-insert-deque! deque 'c)\n\n      (rear-delete-deque! deque)\n\n      (check-equal? (front-deque deque) 'a)\n      (check-equal? (rear-deque deque) 'b)\n\n      (rear-delete-deque! deque)\n\n      (check-equal? (front-deque deque) 'a)\n      (check-equal? (rear-deque deque) 'a)\n\n      (rear-delete-deque! deque)\n      (check-true (empty-deque? deque)))\n))\n\n(run-tests sicp-3.23-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/24-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../24.scm\")\n\n(define sicp-3.24-tests\n  (test-suite\n    \"Tests for SICP exercise 3.24\"\n\n    (test-begin \"lookup\"\n      (check-equal? (lookup 'inexistant (make-table equal?)) #f))\n\n    (test-begin \"insert!\"\n      (define table (make-table equal?))\n\n      (insert! 1 'one table)\n      (insert! 2 'two table)\n\n      (check-equal? (lookup 1 table) 'one)\n      (check-equal? (lookup 2 table) 'two))\n\n    (test-begin \"make-table with a lambda\"\n      (define table (make-table (lambda (a b) (= (remainder a 10) (remainder b 10)))))\n\n      (insert! 11 'one table)\n\n      (check-equal? (lookup 11 table) 'one)\n      (check-equal? (lookup 21 table) 'one)\n      (check-equal? (lookup 1 table) 'one))\n))\n\n(run-tests sicp-3.24-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/25-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../25.scm\")\n\n(define sicp-3.25-tests\n  (test-suite\n    \"Tests for SICP exercise 3.25\"\n\n    (test-begin \"lookup\"\n      (check-equal? (lookup '(inexistant) (make-table)) #f))\n\n    (test-begin \"insert! (simple)\"\n      (define table (make-table))\n\n      (insert! '(1) 'one table)\n      (insert! '(2) 'two table)\n\n      (check-equal? (lookup '(1) table) 'one)\n      (check-equal? (lookup '(2) table) 'two))\n\n    (test-begin \"insert! (two levels)\"\n      (define table (make-table))\n\n      (insert! '(1 1) 'eleven table)\n      (insert! '(1 2) 'twelve table)\n      (insert! '(2 1) 'twenty-one table)\n      (insert! '(2 2) 'twenty-two table)\n\n      (check-equal? (lookup '(1 1) table) 'eleven)\n      (check-equal? (lookup '(1 2) table) 'twelve)\n      (check-equal? (lookup '(2 1) table) 'twenty-one)\n      (check-equal? (lookup '(2 2) table) 'twenty-two))\n\n    (test-begin \"insert! (mixed levels)\"\n      (define table (make-table))\n\n      (insert! '(1) 'one table)\n      (insert! '(2 1) 'two-one table)\n      (insert! '(2 2) 'two-two table)\n      (insert! '(3 1 1) 'three-one-one table)\n      (insert! '(3 1 2) 'three-one-two table)\n      (insert! '(3 2 1) 'three-two-one table)\n      (insert! '(3 2 2) 'three-two-two table)\n\n      (check-equal? (lookup '(1) table) 'one)\n      (check-equal? (lookup '(2 1) table) 'two-one)\n      (check-equal? (lookup '(2 2) table) 'two-two)\n      (check-equal? (lookup '(3 1 1) table) 'three-one-one)\n      (check-equal? (lookup '(3 1 2) table) 'three-one-two)\n      (check-equal? (lookup '(3 2 1) table) 'three-two-one)\n      (check-equal? (lookup '(3 2 2) table) 'three-two-two))\n))\n\n(run-tests sicp-3.25-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/28-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../28.scm\")\n\n(define sicp-3.28-tests\n  (test-suite\n    \"Tests for SICP exercise 3.28\"\n\n    (test-case \"half-adder\"\n      (define input-1 (make-wire))\n      (define input-2 (make-wire))\n      (define sum (make-wire))\n      (define carry (make-wire))\n\n      (with-output-to-string\n        (lambda ()\n          (probe 'sum sum)\n          (probe 'carry carry)))\n\n      (half-adder input-1 input-2 sum carry)\n\n      (set-signal! input-1 1)\n      (check-equal? \"sum 8  New-value = 1\\n\"\n                    (with-output-to-string propagate))\n\n      (set-signal! input-2 1)\n      (check-equal? (string-append \"carry 11  New-value = 1\\n\"\n                                   \"sum 16  New-value = 0\\n\")\n                    (with-output-to-string propagate)))\n\n    (test-case \"full-adder\"\n      (define input-1 (make-wire))\n      (define input-2 (make-wire))\n      (define carry-in (make-wire))\n      (define sum (make-wire))\n      (define carry-out (make-wire))\n\n      (define (check-adder? a b c-in c-out s)\n        (set-signal! input-1 a)\n        (set-signal! input-2 b)\n        (set-signal! carry-in c-in)\n        (propagate)\n\n        (check-equal? (list (get-signal sum) (get-signal carry-out))\n                      (list s c-out)))\n\n      (full-adder input-1 input-2 carry-in sum carry-out)\n\n      (check-adder? 0 0 0 0 0)\n      (check-adder? 0 1 0 0 1)\n      (check-adder? 1 0 0 0 1)\n      (check-adder? 1 1 0 1 0)\n      (check-adder? 0 0 1 0 1)\n      (check-adder? 0 1 1 1 0)\n      (check-adder? 1 0 1 1 0)\n      (check-adder? 1 1 1 1 1))\n))\n\n(run-tests sicp-3.28-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/29-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../29.scm\")\n\n(define sicp-3.29-tests\n  (test-suite\n    \"Tests for SICP exercise 3.29\"\n\n    (test-case \"or-gate\"\n      (define input-1 (make-wire))\n      (define input-2 (make-wire))\n      (define output (make-wire))\n\n      (define (check-or-gate? a b o)\n        (set-signal! input-1 a)\n        (set-signal! input-2 b)\n        (propagate)\n\n        (check-equal? (get-signal output) o))\n\n      (or-gate input-1 input-2 output)\n\n      (check-or-gate? 0 0 0)\n      (check-or-gate? 0 1 1)\n      (check-or-gate? 1 0 1)\n      (check-or-gate? 1 1 1))\n\n    (test-case \"full-adder\"\n      (define input-1 (make-wire))\n      (define input-2 (make-wire))\n      (define carry-in (make-wire))\n      (define sum (make-wire))\n      (define carry-out (make-wire))\n\n      (define (check-adder? a b c-in c-out s)\n        (set-signal! input-1 a)\n        (set-signal! input-2 b)\n        (set-signal! carry-in c-in)\n        (propagate)\n\n        (check-equal? (list (get-signal sum) (get-signal carry-out))\n                      (list s c-out)))\n\n      (full-adder input-1 input-2 carry-in sum carry-out)\n\n      (check-adder? 0 0 0 0 0)\n      (check-adder? 0 1 0 0 1)\n      (check-adder? 1 0 0 0 1)\n      (check-adder? 1 1 0 1 0)\n      (check-adder? 0 0 1 0 1)\n      (check-adder? 0 1 1 1 0)\n      (check-adder? 1 0 1 1 0)\n      (check-adder? 1 1 1 1 1))\n))\n\n(run-tests sicp-3.29-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/30-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../30.scm\")\n\n(define sicp-3.30-tests\n  (test-suite\n    \"Tests for SICP exercise 3.30\"\n\n    (test-case \"ripple-carry adder\"\n      (define addend1 (list (make-wire) (make-wire) (make-wire)))\n      (define addend2 (list (make-wire) (make-wire) (make-wire)))\n      (define sum (list (make-wire) (make-wire) (make-wire)))\n      (define carry-in (make-wire))\n      (define carry-out (make-wire))\n\n      (define (digits n)\n        (define (bits n r)\n          (if (= r 0)\n              '()\n              (cons (remainder n 2)\n                    (bits (quotient n 2) (- r 1)))))\n        (bits n 3))\n\n      (define (set-signals! wires signals)\n        (if (null? signals)\n            'done\n            (begin (set-signal! (car wires) (car signals))\n                   (set-signals! (cdr wires) (cdr signals)))))\n\n      (define (check-adder a b s c-in c-out)\n        (set-signals! addend1 (digits a))\n        (set-signals! addend2 (digits b))\n        (set-signal! carry-in c-in)\n\n        (propagate)\n\n        (check-equal? (map get-signal sum) (digits s))\n        (check-equal? (get-signal carry-out) c-out))\n\n      (ripple-carry-adder addend1 addend2 carry-in sum carry-out)\n\n      (check-adder 0 0 0 0 0)\n      (check-adder 1 2 3 0 0)\n      (check-adder 2 4 6 0 0)\n      (check-adder 0 0 1 1 0)\n      (check-adder 3 3 7 1 0)\n      (check-adder 3 4 0 1 1))\n\n\n))\n\n(run-tests sicp-3.30-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/33-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../33.scm\")\n\n(define sicp-3.33-tests\n  (test-suite\n    \"Tests for SICP exercise 3.33\"\n\n    (test-case \"averager\"\n      (define a (make-connector))\n      (define b (make-connector))\n      (define c (make-connector))\n\n      (averager a b c)\n\n      (set-value! a 4 'user)\n      (set-value! b 6 'user)\n      (check-equal? (get-value c) 5)\n\n      (forget-value! b 'user)\n      (set-value! c 5 'user)\n      (check-equal? (get-value b) 6)\n\n      (forget-value! a 'user)\n      (set-value! b 6 'user)\n      (check-equal? (get-value a) 4))\n\n    (test-case \"celsius-fahrenheit-converter\"\n      (define C (make-connector))\n      (define F (make-connector))\n      (celsius-fahrenheit-converter C F)\n\n      (set-value! C 25 'user)\n      (check-equal? (get-value F) 77)\n\n      (check-exn exn? (lambda () (set-value! F 212 'user)))\n\n      (forget-value! C 'user)\n      (set-value! F 212 'user)\n      (check-equal? (get-value C) 100))\n))\n\n(run-tests sicp-3.33-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/35-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../35.scm\")\n\n(define sicp-3.35-tests\n  (test-suite\n    \"Tests for SICP exercise 3.35\"\n\n    (test-case \"squarer\"\n      (define a (make-connector))\n      (define b (make-connector))\n\n      (squarer a b)\n\n      (set-value! a 2 'user)\n      (check-equal? (get-value b) 4)\n\n      (forget-value! a 'user)\n      (set-value! b 4 'user)\n      (check-equal? (get-value a) 2))\n))\n\n(run-tests sicp-3.35-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/37-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../37.scm\")\n\n(define sicp-3.37-tests\n  (test-suite\n    \"Tests for SICP exercise 3.37\"\n\n    (test-case \"celsius-fahrenheit-converter\"\n      (define C (make-connector))\n      (define F (celsius-fahrenheit-converter C))\n\n      (set-value! C 25 'user)\n      (check-equal? (get-value F) 77)\n\n      (check-exn exn? (lambda () (set-value! F 212 'user)))\n\n      (forget-value! C 'user)\n      (set-value! F 212 'user)\n      (check-equal? (get-value C) 100))\n))\n\n(run-tests sicp-3.37-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/50-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../50.scm\")\n\n(define sicp-3.50-tests\n  (test-suite\n    \"Tests for SICP exercise 3.50\"\n\n    (check-equal?\n      (stream->list (stream-map2 +\n                                 (stream-cons 1 (stream-cons 2 (stream-cons 3 the-empty-stream)))\n                                 (stream-cons 4 (stream-cons 5 (stream-cons 6 the-empty-stream)))))\n      '(5 7 9))\n\n    (check-equal?\n      (stream->list (stream-map2 +\n                                 (stream-cons 1 (stream-cons 2 (stream-cons 3 the-empty-stream)))\n                                 (stream-cons 4 (stream-cons 5 (stream-cons 6 the-empty-stream)))\n                                 (stream-cons 7 (stream-cons 8 (stream-cons 9 the-empty-stream)))))\n      '(12 15 18))\n))\n\n(run-tests sicp-3.50-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/54-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../54.scm\")\n\n(define sicp-3.54-tests\n  (test-suite\n    \"Tests for SICP exercise 3.54\"\n\n    (check-equal? (stream-take factorials 6)\n                  '(1 2 6 24 120 720))\n))\n\n(run-tests sicp-3.54-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/55-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../55.scm\")\n\n(define sicp-3.55-tests\n  (test-suite\n    \"Tests for SICP exercise 3.55\"\n\n    (check-equal? (stream-take (partial-sums integers) 5)\n                  '(1 3 6 10 15))\n))\n\n(run-tests sicp-3.55-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/56-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../56.scm\")\n\n(define sicp-3.56-tests\n  (test-suite\n    \"Tests for SICP exercise 3.56\"\n\n    (check-equal? (stream-take S 20)\n                  '(1 2 3 4 5 6 8 9 10 12 15 16 18 20 24 25 27 30 32 36))\n))\n\n(run-tests sicp-3.56-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/59-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../59.scm\")\n\n(define sicp-3.59-tests\n  (test-suite\n    \"Tests for SICP exercise 3.59\"\n\n    (check-equal? (stream-take (integrate-series integers) 6)\n                  '(1 1 1 1 1 1))\n\n    (check-equal? (stream-take cosine-series 6)\n                  (list 1 0 (/ -1 2) 0 (/ 1 24) 0))\n    (check-equal? (stream-take sine-series 6)\n                  (list 0 1 0 (/ -1 6) 0 (/ 1 120)))\n))\n\n(run-tests sicp-3.59-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/60-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../60.scm\")\n\n(define sicp-3.60-tests\n  (test-suite\n    \"Tests for SICP exercise 3.60\"\n\n    (check-equal? (stream-take (add-streams (mul-series sine-series sine-series)\n                                            (mul-series cosine-series cosine-series))\n                               6)\n                  '(1 0 0 0 0 0))\n))\n\n(run-tests sicp-3.60-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/61-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../61.scm\")\n\n(define sicp-3.61-tests\n  (test-suite\n    \"Tests for SICP exercise 3.61\"\n\n    (check-equal? (stream-take (mul-series cosine-series\n                                           (invert-unit-series cosine-series))\n                               6)\n                  '(1 0 0 0 0 0))\n))\n\n(run-tests sicp-3.61-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/62-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../62.scm\")\n\n(define sicp-3.62-tests\n  (test-suite\n    \"Tests for SICP exercise 3.62\"\n\n    (check-exn exn? (lambda () (div-series ones (stream-cons 0 ones))))\n\n    (check-equal? (stream-take tangent-series 6)\n                  (list 0 1 0 (/ 1 3) 0 (/ 2 15)))\n))\n\n(run-tests sicp-3.62-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/64-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../64.scm\")\n\n(define sicp-3.64-tests\n  (test-suite\n    \"Tests for SICP exercise 3.64\"\n\n    (check-= (sqrt-tolerance 2 0.0000000001) 1.41421356237 0.0000000001)\n))\n\n(run-tests sicp-3.64-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/66-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../66.scm\")\n\n(define sicp-3.66-tests\n  (test-suite\n    \"Tests for SICP exercise 3.66\"\n\n    (check-equal? (location int-pairs '(1 100)) (position '(1 100)))\n    (check-equal? (location int-pairs '(7 30)) (position '(7 30)))\n))\n\n(run-tests sicp-3.66-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/69-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../69.scm\")\n\n(define sicp-3.69-tests\n  (test-suite\n    \"Tests for SICP exercise 3.69\"\n\n    (check-equal? (stream-take pythagorean-triples 5)\n                  '((3 4 5) (6 8 10) (5 12 13) (9 12 15) (8 15 17)))\n))\n\n(run-tests sicp-3.69-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/70-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../70.scm\")\n\n(define sicp-3.70-tests\n  (test-suite\n    \"Tests for SICP exercise 3.70\"\n\n    (check-equal? (stream-take (a-pairs) 20)\n                  '((1 1) (1 2) (2 2) (1 3) (2 3) (1 4) (3 3)\n                    (2 4) (1 5) (3 4) (2 5) (1 6) (4 4) (3 5)\n                    (2 6) (1 7) (4 5) (3 6) (2 7) (1 8)))\n    (check-equal? (stream-take (b-pairs) 20)\n                  '((1 1) (1 7) (1 11) (1 13) (1 17) (1 19) (1 23)\n                    (1 29) (1 31) (7 7) (1 37) (1 41) (1 43) (1 47)\n                    (1 49) (1 53) (7 11) (1 59) (1 61) (7 13)))\n))\n\n(run-tests sicp-3.70-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/71-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../71.scm\")\n\n(define sicp-3.71-tests\n  (test-suite\n    \"Tests for SICP exercise 3.71\"\n\n    (check-equal? (stream-take (ramanujan-numbers) 6)\n                  '(1729 4104 13832 20683 32832 39312))\n))\n\n(run-tests sicp-3.71-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/72-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../72.scm\")\n\n(define sicp-3.72-tests\n  (test-suite\n    \"Tests for SICP exercise 3.72\"\n\n    (check-equal? (stream-take (three-ways-of-two-squares) 20)\n                  '( 325  425  650  725  845  850  925 1025 1105 1250\n                    1300 1325 1445 1450 1525 1625 1690 1700 1825 1850))\n))\n\n(run-tests sicp-3.72-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/73-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../73.scm\")\n\n(define sicp-3.73-tests\n  (test-suite\n    \"Tests for SICP exercise 3.73\"\n\n    (check-equal? (stream-take (RC1 ones-and-zeroes 0) 10)\n                  '(5 0.5 5.5 1.0 6.0 1.5 6.5 2.0 7.0 2.5))\n))\n\n(run-tests sicp-3.73-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/74-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../74.scm\")\n\n(define (list->infinite-stream list)\n  (define (next items)\n    (if (null? items)\n        (list->infinite-stream list)\n        (stream-cons (car items) (next (cdr items)))))\n  (next list))\n\n(define sense-data (list->infinite-stream '(1 2 1.5 1 0.5 -0.1 -2 -3 -2 -0.5 0.2 3 4)))\n(define zero-crossings '(0 0 0 0 0 -1 0 0 0 0 1 0 0))\n\n(define sicp-3.74-tests\n  (test-suite\n    \"Tests for SICP exercise 3.74\"\n\n    (check-equal? (stream-take (make-zero-crossings sense-data 0) 13)\n                  zero-crossings)\n    (check-equal? (stream-take (make-zero-crossings-with-map sense-data) 13)\n                  zero-crossings)\n))\n\n(run-tests sicp-3.74-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/76-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../76.scm\")\n\n(define (list->infinite-stream list)\n  (define (next items)\n    (if (null? items)\n        (list->infinite-stream list)\n        (stream-cons (car items) (next (cdr items)))))\n  (next list))\n\n(define sense-data (list->infinite-stream '(1 2 1.5 1 0.5 -0.1 -2 -3 -2 -0.5 0.2 3 4)))\n\n(define sicp-3.76-tests\n  (test-suite\n    \"Tests for SICP exercise 3.76\"\n\n    (check-equal? (stream-take (smooth sense-data) 13)\n                  '(1 1.5 1.25 1.0 0.75 0.45 -0.5 -1.0 -0.5 0.25 0.6 2.0 2.5))\n    (check-equal? (stream-take (make-zero-crossings sense-data 0) 13)\n                  '(0 0 0 0 0 0 -1 0 0 1 0 0 0))\n))\n\n(run-tests sicp-3.76-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/80-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../80.scm\")\n\n(define sicp-3.80-tests\n  (test-suite\n    \"Tests for SICP exercise 3.80\"\n\n    (check-equal? (stream-take (RLC1 10 0) 4)\n                  '((10 . 0)\n                    (10 . 1.0)\n                    (9.5 . 1.9)\n                    (8.55 . 2.66)))\n))\n\n(run-tests sicp-3.80-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/81-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../81.scm\")\n\n(define (list->infinite-stream list)\n  (define (next items)\n    (if (null? items)\n        (list->infinite-stream list)\n        (stream-cons (car items) (next (cdr items)))))\n  (next list))\n\n(define sicp-3.81-tests\n  (test-suite\n    \"Tests for SICP exercise 3.81\"\n\n    (check-equal? (stream-take\n                    (random-numbers\n                      (list->infinite-stream\n                        '(reset 1 generate generate generate generate\n                          reset 2 generate generate generate generate)))\n                    8)\n                  '(1015568748 1586005467 2165703038 3027450565\n                    1017233273 1975575172 811535379 3186434646))\n))\n\n(run-tests sicp-3.81-tests)\n"
  },
  {
    "path": "scheme/sicp/03/tests/82-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../82.scm\")\n\n(define sicp-3.82-tests\n  (test-suite\n    \"Tests for SICP exercise 3.82\"\n\n    (check-= (estimate-pi 20000) 3.14 0.01)\n))\n\n(run-tests sicp-3.82-tests)\n"
  },
  {
    "path": "scheme/sicp/04/01.scm",
    "content": "; SICP exercise 4.01\n;\n; Notice that we cannot tell whether the metacircular evaluator evaluates\n; operands from left to right or from right to left. Its evaluation order is\n; inherited from the underlying Lisp: If the arguments to cons in\n; list-of-values are evaluated from left to right, then list-of-values will\n; evaluate operands from left to right; and if the arguments to cons are\n; evaluated from right to left, then list-of-values will evaluate operands\n; from right to left.\n;\n; Write a version of list-of-values that evaluates from right to left\n; regardless of the order of evaluation in the underlying Lisp. Also write a\n; version of list-of-values that evaluates operands from right to left.\n\n; I'm basic the code on the metacircular evaluator in the book. There will be\n; a procedure that can change the behavior of list-of-values in order to be\n; able to test it.\n\n(require r5rs/init)\n\n; The solution:\n\n(define (list-of-values-left-to-right exps env)\n  (if (no-operands? exps)\n      '()\n      (let ((first (evaluate (first-operand exps) env))\n            (rest (list-of-values-left-to-right (rest-operands exps) env)))\n        (cons first rest))))\n\n(define (list-of-values-right-to-left exps env)\n  (if (no-operands? exps)\n      '()\n      (let ((rest (list-of-values-left-to-right (rest-operands exps) env))\n            (first (evaluate (first-operand exps) env)))\n        (cons first rest))))\n\n(define evaluation-order 'none)\n(define (set-evaluation-order! order)\n  (set! evaluation-order order))\n\n(define (list-of-values exps env)\n  (cond ((eq? evaluation-order 'left-to-right) (list-of-values-left-to-right exps env))\n        ((eq? evaluation-order 'right-to-left) (list-of-values-right-to-left exps env))\n        (error \"Unknown evaluation order\" evaluation-order)))\n\n; The rest of the interpreter:\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/02.scm",
    "content": "; SICP exercise 4.02\n;\n; Louis Reasoner plans to reorder the cond caluses in eval so that the clause\n; for procedure applications appears before the clause for assignment. He\n; argues that this will make the interpreter more efficient: Since program\n; usually contains more applications than assignments, definitions and so on,\n; his modified eval will usually check fewer clauses than the original eval\n; before identifying the type of an expression.\n;\n; a. What is wrong with Louis' plan? (Hint: What will Louis's evaluator do\n; with the expression (define x 3)?)\n;\n; b. Louis is upset that his plan didn't work. He is willing to go to any\n; lengths to make his evaluator recognize procedure applications before it\n; checks for most other kinds of expressions. Help him by changing the syntax\n; of the evaluated language so that procedure applications start with call.\n; For example, instead of (factorial 3) we will now have to write\n; (call factorial 3) and instead of (+ 1 2) we will have to write\n; (call + 1 2).\n\n(require r5rs/init)\n\n; a. If we do that, every list that does not appear before definition? will be\n; treated as a function application. For example, (define x 3) will be\n; considered as a function call by the evaluator.\n\n; b. OK, let's do that. We need to redefine just a bunch of functions:\n\n(define (application? exp) (tagged-list? exp 'call))\n(define (operator exp) (cadr exp))\n(define (operands exp) (cddr exp))\n\n; We also need to move the check up in evaluate:\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n; The rest of the evaluator:\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/03.scm",
    "content": "; SICP exercise 4.03\n;\n; Rewrite eval so that the dispatch is done in data-directed style. Compare\n; this with the data-directed procedure of exercise 2.73. (You may use the car\n; of a compound expression as the type of the expression, as is appropriate\n; for the syntax implemented in this section.)\n\n; That should be fun.\n;\n; I'm going to define a special-from? predicate and an evaluate-form\n; procedure. Both will look up in the table and see what to do.\n;\n; I might end up using this interpreter for some of the future exercises.\n;\n; As for the comparison with 2.73, it is nice that we can now add new special\n; forms without modifying eval. This comes with the assumption that every\n; special form should be identifiable by the first symbol in its s-exp, but I\n; believe that to hold for all of LISP.\n;\n; The modified evaluator is below:\n\n(require r5rs/init)\n\n; First we start with eval and apply.\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((special-form? exp) (evaluate-form exp env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n; Here is the data-directed infrastructure for the form:\n\n(define special-forms (make-hash))\n\n(define (define-form keyword handler)\n  (hash-set! special-forms keyword handler))\n\n(define (get-form keyword)\n  (hash-ref special-forms keyword))\n\n(define (form-defined? keyword)\n  (if (hash-ref special-forms keyword false) true false))\n\n; Here are the mentioned procedures\n\n(define (special-form? exp)\n  (and (pair? exp)\n       (form-defined? (car exp))))\n\n(define (evaluate-form exp env)\n  ((get-form (car exp)) (cdr exp) env))\n\n; And here is the definitions of the existing forms:\n\n(define-form 'quote (lambda (exp env) (car exp)))\n\n(define-form 'if\n  (lambda (exp env)\n    (if (true? (evaluate (car exp) env))\n        (evaluate (cadr exp) env)\n        (if (null? (cddr exp))\n            false\n            (evaluate (caddr exp) env)))))\n\n(define-form 'set!\n  (lambda (exp env)\n    (let ((name (car exp))\n          (value (evaluate (cadr exp) env)))\n      (set-variable-value! name value env)\n      'ok)))\n\n(define-form 'define\n  (lambda (exp env)\n    (let ((name (if (symbol? (car exp))\n                    (car exp)\n                    (caar exp)))\n          (value (if (symbol? (car exp))\n                     (cadr exp)\n                     (make-lambda (cdar exp) (cdr exp)))))\n      (define-variable! name (evaluate value env) env)\n      'ok)))\n\n(define-form 'lambda\n  (lambda (exp env)\n    (make-procedure (car exp) (cdr exp) env)))\n\n(define-form 'begin\n  (lambda (exp env)\n    (eval-sequence exp env)))\n\n(define-form 'cond\n  (lambda (exp env)\n    (define clauses exp)\n    (define (else-clause? clause)\n      (eq? (predicate clause) 'else))\n    (define (predicate clause) (car clause))\n    (define (actions clause) (cdr clause))\n    (define (expand-clauses clauses)\n      (if (null? clauses)\n          'false\n          (let ((first (car clauses))\n                (rest (cdr clauses)))\n            (if (else-clause? first)\n                (if (null? rest)\n                    (sequence->exp (actions first))\n                    (error \"ELSE clause isn't last - COND\" clauses))\n                (make-if (predicate first)\n                         (sequence->exp (actions first))\n                         (expand-clauses rest))))))\n    (evaluate (expand-clauses exp) env)))\n\n; And this is the rest of the interpreter\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n"
  },
  {
    "path": "scheme/sicp/04/04.scm",
    "content": "; SICP exercise 4.04\n;\n; Recall the definitions of the special forms and and or from chapter 1:\n;\n; • and: The expressions are evaluated from left to right. If any expression\n;   evaluates to false, false is returned; any remaining expressions are not\n;   evaluated. If all the expressions evaluate to true values, the value of\n;   the last expression is returned. If there are no expressions then true is\n;   returned.\n; • or: The expressions are evaluated from left to right. If any expression\n;   evaluates to a true value, that value is returned; any remaining\n;   expressions are not evaluated. If all expressions evaluate to false, or if\n;   there are no expressions, then false is returned.\n;\n; Install and and or as new special forms for the evaluator by defining\n; appropriate syntax procedures and evaluation procedures eval-and and\n; eval-or. Alternatively, show how to implement and and or as derived\n; expressions.\n\n; We will implement it in a similar way to exercise 4.02 - there will be an\n; option to flip which approach to use in order to be able to test both of\n; them.\n;\n; We cannot reasonably implement or without having a let. And even then, we\n; have the problem of shadowing the name of the value. So we will modify the\n; request a bit - we return true, instead of the first non-false value. Then\n; we have\n\n(require r5rs/init)\n\n(define logical-operations-implementation 'none)\n(define (set-logical-operations-implementation! type)\n  (set! logical-operations-implementation type))\n\n(define (and? exp) (tagged-list? exp 'and))\n(define (and-terms exp) (cdr exp))\n(define (or? exp) (tagged-list? exp 'or))\n(define (or-terms exp) (cdr exp))\n\n(define (eval-and exp env)\n  (cond ((eq? logical-operations-implementation 'syntax-procedures)\n         (eval-and-terms-procedures (and-terms exp) env))\n        ((eq? logical-operations-implementation 'derived-forms)\n         (eval-and-terms-derived (and-terms exp) env))\n        (error \"Unknown implementation\" logical-operations-implementation)))\n\n(define (eval-or exp env)\n  (cond ((eq? logical-operations-implementation 'syntax-procedures)\n         (eval-or-terms-procedures (or-terms exp) env))\n        ((eq? logical-operations-implementation 'derived-forms)\n         (eval-or-terms-derived (or-terms exp) env))\n        (error \"Unknown implementation\" logical-operations-implementation)))\n\n(define (eval-and-terms-procedures terms env)\n  (cond ((empty-exp? terms) true)\n        ((last-exp? terms) (evaluate (first-exp terms) env))\n        ((evaluate (first-exp terms) env) (eval-and-terms-procedures (rest-exps terms) env))\n        (else false)))\n\n(define (eval-or-terms-procedures terms env)\n  (if (empty-exp? terms)\n      false\n      (let ((value (evaluate (first-exp terms) env)))\n        (if value\n            value\n            (eval-or-terms-procedures (rest-exps terms) env)))))\n\n(define (eval-or-terms-derived terms env)\n  (define (or->if terms)\n    (if (empty-exp? terms)\n        'false\n        (make-if (first-exp terms)\n                 'true\n                 (or->if (rest-exps terms)))))\n  (evaluate (or->if terms) env))\n\n(define (eval-and-terms-derived terms env)\n  (define (and->if terms)\n    (cond ((empty-exp? terms) 'true)\n          ((last-exp? terms) (first-exp terms))\n          (else (make-if (first-exp terms)\n                         (and->if (rest-exps terms))\n                         'false))))\n  (evaluate (and->if terms) env))\n\n; The rest of the evaluator\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((and? exp) (eval-and exp env))\n        ((or? exp) (eval-or exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (empty-exp? seq) (null? seq))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/05.scm",
    "content": "; SICP exercise 4.05\n;\n; Scheme allows additional syntax for cond clauses, (<test> => <recipient>).\n; If <test> evaluates to a true value, then <recipient> is evaluated. Its\n; value must be a procedure of one argument; this procedure is then invoked on\n; the value of the <test>, and the result is returned as the value of the cond\n; expession. For example\n;\n;   (cond ((assoc 'b ((a 1) (b 2))) => cadr)\n;         (else false))\n;\n; returns 2. Modify the handling of cond so that it supports this extended\n; syntax.\n\n; We need to rewrite cond not to be a derived form, because otherwise we\n; either need to evaluate the test twice or there will be name shadowing in\n; the clauses following the stabby one.\n\n(require r5rs/init)\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-stabby-clause? clause)\n  (eq? (car (cond-actions clause)) '=>))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond-stabby-recipient clause) (caddr clause))\n\n(define (eval-cond exp env)\n  (define (eval-clauses clauses)\n    (let ((first (car clauses))\n          (rest (cdr clauses)))\n      (if (cond-else-clause? first)\n          (if (not (null? rest))\n              (error \"ELSE clause is not the last - COND\")\n              (eval-sequence (cond-actions first) env))\n          (let ((test-result (evaluate (cond-predicate first) env)))\n            (cond ((not test-result)\n                   (eval-clauses rest))\n                  ((cond-stabby-clause? first)\n                   (apply-procedure (evaluate (cond-stabby-recipient first) env)\n                                    (list test-result)))\n                  (else\n                   (eval-sequence (cond-actions first) env)))))))\n  (eval-clauses (cond-clauses exp)))\n\n; The rest of the evaluator:\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (eval-cond exp env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'eq? eq?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/06.scm",
    "content": "; SICP exercise 4.06\n;\n; Let expressions are derived expressions, because\n;\n;   (let ((<var₁> <exp₁>) ... (<varᵢ> <expᵢ>))\n;     <body>)\n;\n; is equivalent to\n;\n;   ((lambda (<var₁> ... <varᵢ>)\n;      <body>)\n;    <exp₁>\n;    ...\n;    <expᵢ>)\n;\n; Implement a syntactic transformation let->combination that reduces\n; evaluating let expressions to evaluating combinations of the type show\n; above, and add the appropriate clause to eval to handle let expressions.\n\n(require r5rs/init)\n\n(define (let? exp)\n  (tagged-list? exp 'let))\n\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n; The rest of the evaluator:\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((let? exp) (evaluate (let->combination exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/07.scm",
    "content": "; SICP exercise 4.07\n;\n; Let* is similar to let, except that the bindings of the let* variables are\n; performed sequentially from left to right, and each binding is made in an\n; environment in which all of the preceding bindings are visible. For example\n;\n;   (let* ((x 3)\n;          (y (+ x 2))\n;          (z (+ x y 5)))\n;     (* x z))\n;\n; returns 39. Explain how a let* expression can be rewritten as a set of\n; nested let expressions and write a procedure let*->nested-lets that performs\n; this transformation. If we have already implemented let (exercise 4.6) and\n; we want to extend the evaluator to handle let*, is it sufficient to add a\n; clause to eval whose action is\n;\n;   (eval (let*->nested-lets exp) env)\n;\n; or must we explicitly expand let* in terms of non-derived expressions?\n\n; Simply, the expression above can be converted to:\n;\n;   (let ((x 3))\n;     (let ((y (+ x 2)))\n;       (let ((z (+ x y 5)))\n;         (* x z))))\n;\n; You just create a new let statement for each bound name. And of course we\n; can define let* in terms of let, which itself is a derived expression.\n\n(require r5rs/init)\n\n(define (let*? exp)\n  (tagged-list? exp 'let*))\n\n(define (let*->nested-lets exp)\n  (define body (cddr exp))\n  (define (one-binding? bindings) (null? (cdr bindings)))\n  (define (convert bindings)\n    (let ((new-binding (list (car bindings)))\n          (rest (cdr bindings)))\n      (if (one-binding? bindings)\n          (cons 'let (cons new-binding body))\n          (list 'let new-binding (convert rest)))))\n\n  (convert (cadr exp)))\n\n(define (let? exp)\n  (tagged-list? exp 'let))\n\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n; The rest of the evaluator:\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((let? exp) (evaluate (let->combination exp) env))\n        ((let*? exp) (evaluate (let*->nested-lets exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/08.scm",
    "content": "; SICP exercise 4.08\n;\n; \"Named let\" is a variant of let that has the form\n;\n;   (let <var> <bindings> <body>)\n;\n; The <bindings> and <body> are just as in ordinary let, except that var is\n; bound within <body> to a procedure whose body is <body> and whose parameters\n; are the variables in the <bindings>. Thus, one can repeatedly execute the\n; <body> by invoking the procedure, named <var>. For example, the iterative\n; Fibonacci procedure (section 1.2.2) can be rewritten using named let as\n; follows:\n;\n;   (define (fib n)\n;     (let fib-iter ((a 1)\n;                    (b 0)\n;                    (count n))\n;       (if (= count 0)\n;           b\n;           (fib-iter (+ a b) a (- count 1)))))\n;\n; Modify let->combination of exercise 4.6 to also support named let.\n\n(require r5rs/init)\n\n(define (let? exp)\n  (tagged-list? exp 'let))\n\n(define (let->combination exp)\n  (if (symbol? (cadr exp))\n    (let ((name (cadr exp))\n          (names (map car (caddr exp)))\n          (values (map cadr (caddr exp)))\n          (body (cdddr exp)))\n        (list\n          (list\n            'lambda\n            null\n            (append (list 'define (cons name names)) body)\n            (cons name values))))\n    (let ((names (map car (cadr exp)))\n          (values (map cadr (cadr exp)))\n          (body (cddr exp)))\n      (cons (cons 'lambda (cons names body))\n            values))))\n\n; The rest of the evaluator:\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((let? exp) (evaluate (let->combination exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/09.scm",
    "content": "; SICP exercise 4.09\n;\n; Many languages support a variety of iteration constructs, such as do, for,\n; while and until. In scheme, iterative processes can be expressed in terms of\n; ordinart procdure calls, so special iteration constructs provide no\n; essential gain in computational power. On the other hand, such constructs\n; are often convenient. Design some iteration constructs, give examples of\n; their use, and show how to implement them as derived expressions.\n\n(require r5rs/init)\n\n; I am not sure what \"do\" is, so we will start with the for loop. This is\n; tricky, since we need to do it with recursion, and in order to accomplish\n; that, we need put a name in the environment. Of course, this will lead to\n; name-shadowing conflicts. Since the text of the book ignores this issue, we\n; shall do so too. We'll need to introduce two names in the environment -\n; items and for-loop. Same goes for the other constructs, really. It might\n; make sense to name them something obscure (like _for-loop and _while-loop),\n; since this is not a real evaluator, we don't need to do it.\n\n(define (for? exp)\n  (tagged-list? exp 'for))\n\n(define (for->lambda exp)\n  (let ((name (cadr exp))\n        (items (caddr exp))\n        (body (cdddr exp)))\n    (list\n      (list\n        'lambda\n        (list)\n        (list 'define (list 'for-loop 'items)\n              (list 'if (list 'null? 'items)\n                    ''done\n                    (append (list 'begin\n                                  (list 'define name (list 'car 'items)))\n                            body\n                            (list (list 'for-loop (list 'cdr 'items))))))\n        (list 'for-loop items)))))\n\n; Next we need to do while. We'll introduce < to our primitive functions in\n; order to be able to test it. Otherwise, it goes like this:\n\n(define (while? exp)\n  (tagged-list? exp 'while))\n\n(define (while->lambda exp)\n  (let ((condition (cadr exp))\n        (body (cddr exp)))\n    (list\n      (list\n        'lambda\n        null\n        (append '(define (while-loop))\n                (list (list 'if condition\n                                (sequence->exp (append body '((while-loop))))\n                                ''done)))\n        '(while-loop)))))\n\n; And now, let's implement until:\n\n(define (until? exp)\n  (tagged-list? exp 'until))\n\n(define (until->lambda exp)\n  (let ((condition (cadr exp))\n        (body (cddr exp)))\n    (list\n      (list\n        'lambda\n        null\n        (append '(define (until-loop))\n                (list (list 'if condition\n                                ''done\n                                (sequence->exp (append body '((until-loop)))))))\n        '(until-loop)))))\n\n; The rest of the evaluator:\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((for? exp) (evaluate (for->lambda exp) env))\n        ((while? exp) (evaluate (while->lambda exp) env))\n        ((until? exp) (evaluate (until->lambda exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '< <)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/10.scm",
    "content": "; SICP exercise 4.10\n;\n; By using data abstraction, we were able to write an eval procedure that is\n; independent of the particular syntax of the language to be evaluated. To\n; illustrate this, design and implement a new syntax for Scheme by modifying\n; the procedures in the section, without changing eval or apply.\n\n; Let's go batshit crazy about this. Check out the specs of the new \"syntax\".\n; It's horrible and unusuable, but at least it is fancy.\n\n(require r5rs/init)\n\n; Here are the unmodified procedures:\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((definition? exp) (eval-definition exp env))\n        ((assignment? exp) (eval-assignment exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n; Some auxiliary stuff:\n\n(define (ends-with? name suffix-symbol)\n  (define (take items n)\n    (if (or (null? items) (= n 0))\n        '()\n        (cons (car items) (take (cdr items) (- n 1)))))\n  (let* ((str (symbol->string name))\n         (suffix (symbol->string suffix-symbol))\n         (len (min (string-length str) (string-length suffix)))\n         (last-part (list->string (reverse (take (reverse (string->list str)) len)))))\n    (equal? last-part suffix)))\n\n(define (strip-suffix name suffix)\n  (let* ((name (symbol->string name))\n         (suffix (symbol->string suffix))\n         (name-length (string-length name))\n         (suffix-length (string-length suffix)))\n    (string->symbol (substring name 0 (- name-length suffix-length)))))\n\n; The rest of the evaluator, modified:\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp)\n  (and (pair? exp)\n       (symbol? (car exp))\n       (not (eq? (car exp) '=))\n       (ends-with? (car exp) '=)))\n(define (assignment-variable exp)\n  (strip-suffix (car exp) '=))\n(define (assignment-value exp)\n  (cadr exp))\n\n(define (definition? exp)\n  (and (pair? exp)\n       (symbol? (car exp))\n       (or (ends-with? (car exp) ':)\n           (ends-with? (car exp) ':=))))\n(define (definition-variable exp)\n  (if (ends-with? (car exp) ':)\n      (strip-suffix (car exp) ':)\n      (strip-suffix (car exp) ':=)))\n(define (definition-value exp)\n  (if (ends-with? (car exp) ':)\n      (make-lambda (cadr exp)\n                   (cddr exp))\n      (cadr exp)))\n\n(define (lambda? exp)\n  (and (pair? exp)\n       (not (null? exp))\n       (not (null? (cdr exp)))\n       (eq? (cadr exp) '=>)))\n(define (lambda-parameters exp) (car exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body)\n  (append (list parameters '=>) body))\n\n(define (if? exp) (tagged-list? exp '?))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list '? predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'do))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'do seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'switch))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/11.scm",
    "content": "; SICP exercise 4.11\n;\n; Instead of representing a frame as a pair of lists, we can represent a frame\n; as a list of bindings, where each binding is a name-value pair. Rewrite the\n; environment operations to use this alternative representation.\n\n(require r5rs/init)\n\n; Frames:\n;\n\n(define (zip a b)\n  (if (and (null? a) (null? b))\n      null\n      (cons (cons (car a) (car b))\n            (zip (cdr a) (cdr b)))))\n\n(define (make-frame variables values)\n  (cons 'frame (zip variables values)))\n(define (frame-variables frame) (map car (cdr frame)))\n(define (frame-values frame) (map cdr (cdr frame)))\n(define (frame-bindings frame) (cdr frame))\n\n(define (add-binding-to-frame! var val frame)\n  (let ((new-binding (cons var val))\n        (other-bindings (cdr frame)))\n    (set-cdr! frame (cons new-binding other-bindings))))\n\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan bindings)\n      (cond ((null? bindings)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (caar bindings))\n             (set-cdr! (car bindings) val))\n            (else (scan (cdr bindings)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (scan (frame-bindings (first-frame env)))))\n  (env-loop env))\n\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan bindings)\n      (cond ((null? bindings)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (caar bindings))\n             (set-cdr! (car bindings) val))\n            (else (scan (cdr bindings)))))\n    (scan (frame-bindings frame))))\n\n; The rest of the interpreter:\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n;(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/12.scm",
    "content": "; SICP exercise 4.12\n;\n; The procedures set-variable-value!, define-variable!, and\n; lookup-variable-value can be expressed in terms of more abstract procedures\n; for traversing the enivornment structure. Define abstractions that capture\n; the common patterns and redefine the three procedures in terms of these\n; abstractions.\n\n(require r5rs/init)\n\n; We are going two define two procedures -- one that traverses an environment\n; and one that traverses a frame, both looking for a variable defined in their\n; respective argument. They will take two callbacks -- one invoked when the\n; variable is found and one invoked when the variable could not be found. The\n; first callback will receive a list of the values in that frame whose car is\n; the value of the variable found. The other will receive no arguments.\n;\n; The functions are the following:\n\n(define (find-variable-in-frame var frame found not-found)\n  (define (scan vars vals)\n    (cond ((null? vars) (not-found))\n          ((eq? (car vars) var) (found vals))\n          (else (scan (cdr vars) (cdr vals)))))\n  (scan (frame-variables frame)\n        (frame-values frame)))\n\n(define (find-variable-in-environment var env found not-found)\n  (if (eq? env the-empty-environment)\n      (not-found)\n      (find-variable-in-frame var\n                              (first-frame env)\n                              found\n                              (lambda () (find-variable-in-environment var\n                                                                       (enclosing-environment env)\n                                                                       found\n                                                                       not-found)))))\n\n; We are going to use them to implement the environment operations:\n\n(define (lookup-variable-value var env)\n  (find-variable-in-environment var\n                                env\n                                (lambda (vals) (car vals))\n                                (lambda () (error \"Unbound variable\" var))))\n\n(define (set-variable-value! var val env)\n  (find-variable-in-environment var\n                                env\n                                (lambda (vals) (set-car! vals val))\n                                (lambda () (error \"Unbound variable - SET!\" var))))\n\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (find-variable-in-frame var\n                            frame\n                            (lambda (vals) (set-car! vals val))\n                            (lambda () (add-binding-to-frame! var val frame)))))\n\n; Note that this is not the best solution. The smell here is passing a list of\n; values to the found callback. We can, instead, introduce more refined\n; abstractions that manipulate frames instead of lists, but that's just too\n; much work. This is sufficient for this exercise.\n;\n; This is the rest of the interpreter\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/13.scm",
    "content": "; SICP exercise 4.13\n;\n; Scheme allows us to create new bindings for variables by means of define, but\n; provides no way to get rid of bindings. Implement for the evaluator a special\n; form make-unbound! that removes the binding of a given symbol from the\n; environment in which the make-unbound! expressions is evaluated. This problem\n; is not completely specified. For example, should we remove only the binding\n; in the first frame of the environment? Complete the specification and justify\n; any choices you make.\n\n; The solution is sprinkled in the interpreter. It is not that interesting, so\n; I shall not elaborate on it. I've chosen not to undefine variables, that are\n; declared in an enclosing environment. There are two reasons for this. First,\n; that way make-unbound! is symmetrical to define - they both operate on the\n; same environment. Second, if make-unbound! can undefine a variable in an\n; enclosing frame, it produces two side effects that are hard to understand.\n;\n; First, lets take a case where the same variable is defined in two\n; environments and then undefined. If we later remove the second definition,\n; the program would result in a delayed \"Unbound variable\" error. A better\n; behavior would be to let the user know that they need to remove the\n; make-unbound! form.\n;\n; Second, if a variable is shadowed, make-unbound! can be invoked multiple\n; times with the same variable. Alternatively, we can have it remove all\n; definitions in all frames, but that will lead to the form undefining a\n; variable in an enclosing frame, which is potentially confusing.\n\n(require r5rs/init)\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((unbinding? exp) (eval-unbinding exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (eval-unbinding exp env)\n  (undefine-variable! (unbinding-variable exp)\n                      env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (unbinding? exp) (tagged-list? exp 'make-unbound!))\n(define (unbinding-variable exp) (cadr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define (set-first-frame! env frame) (set-car! env frame))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (frame-without-variable frame var)\n  (define (remove vars vals)\n    (cond ((null? vars)\n           (error \"Cannot unbind a variable that is not declared in the current frame\" var))\n          ((eq? (car vars) var)\n           (list (cdr vars) (cdr vals)))\n          (else\n            (let* ((rest (remove (cdr vars) (cdr vals)))\n                   (new-vars (car rest))\n                   (new-vals (cadr rest)))\n              (list (cons (car vars) new-vars)\n                    (cons (car vals) new-vals))))))\n  (apply make-frame (remove (frame-variables frame)\n                            (frame-values frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n(define (undefine-variable! var env)\n  (set-first-frame! env (frame-without-variable (first-frame env) var)))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/14.scm",
    "content": "; SICP exercise 4.14\n;\n; Eva Lu Ator and Louis Reasoner are each experimenting with the meracircular\n; evaluator. Eva types in the definition of map, and runs some test programs\n; that use it. They work fine. Louis, in contrast, has installed the system\n; version of map as a primitve for the metacircular evaluator. When he tries\n; it, things go terribly wrong. Explain why Louis's map fails even though Eva's\n; works.\n\n; Scheme's map takes two arguments a procedure to apply and a list of things to\n; apply it to. The procedure should, of course, be a Scheme procedure. When\n; Louis installs the system version and calls map in the evaluator, the first\n; argument to apply is a procedure in the evaluator, which is a list starting\n; with either 'procedure, which is the evaluator's representation of a\n; procedure. map then results with an error that it expected a procedure and\n; it got a list.\n"
  },
  {
    "path": "scheme/sicp/04/15.scm",
    "content": "; SICP exercise 4.15\n;\n; Given a one-argument procedure p and an object a, p is said to \"halt\" on a if\n; evaluating the expresssion (p a) returns a value (as opposed to terminating\n; with an error message or running forever). Show that it is impossible to\n; write a procedure halts? that correctly determines whether p halts on a for\n; any procedure p and object a. Use the following reasoning: If you had such a\n; procedure halts?, you could implement the following program:\n;\n;   (define (run-forever) (run-forever))\n;\n;   (define (try p)\n;     (if (halts? p p)\n;         (run-forever)\n;         'halted))\n;\n; Now consider evaluating the expression (try try) and show that any possible\n; outcome (either halting or running) violates the intended behavior of halts?\n\n; try checks if the argument will halt when given itself. In case it halts, try\n; will run forever and halt otherwise. That is, try has the inverse behavior of\n; the passed procedure. So what happens when we pass try to itself?\n;\n; Let's assume that (halts? try try) returns true. In that case, (try try) will\n; run forever, which is a violation of our assumption. We're led to believe\n; that (halts? try try) should return false. But in that case, if we run (try\n; try), it will halt and return 'halted, which again, is a violation of our\n; assumption.\n;\n; We have to accept that halts? cannot exist.\n"
  },
  {
    "path": "scheme/sicp/04/16.scm",
    "content": "; SICP exercise 4.16\n;\n; In this exercise we implement the method just described for interpreting\n; internal definitions. We assume that the evaluator supports let (see exercise\n; 4.6).\n;\n; a. Change the lookup-variable-value (section 4.1.3) to singal an error if the\n; value it finds is the symbol *unassigned*.\n;\n; b. Write a procedure scan-out-defines that takes a procedure body and returns\n; an equivalent one that has no internal definitions, by making the\n; transformation described above.\n;\n; c. Install scan-out-defines in the interpreter, either in make-procedure or\n; in procedure-body (see section 4.1.3). Which place is better? Why?\n\n(require r5rs/init)\n\n; a. Here is the modified procedure:\n\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (let ((value (car vals)))\n               (if (eq? value '*unassigned*)\n                   (error \"Unassigned variable\" var)\n                   value)))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n\n; b. Here's scan-out-defines:\n\n(define (scan-out-defines body)\n  (define (definitions-in body)\n    (cond ((null? body)\n           '())\n          ((definition? (car body))\n           (cons (car body) (definitions-in (cdr body))))\n          (else\n           (definitions-in (cdr body)))))\n  (define (body-without-definitions body)\n    (cond ((null? body)\n           '())\n          ((definition? (car body))\n           (body-without-definitions (cdr body)))\n          (else\n           (cons (car body) (body-without-definitions (cdr body))))))\n  (define (definition->unassigned-pair definition)\n    (list (definition-variable definition) ''*unassigned*))\n  (define (definition->set! definition)\n    (list 'set! (definition-variable definition) (definition-value definition)))\n  (define (defines->let definitions body)\n    (list\n      (cons 'let\n            (cons (map definition->unassigned-pair definitions)\n                  (append (map definition->set! definitions) body)))))\n\n  (let ((internal-definitions (definitions-in body)))\n    (if (null? internal-definitions)\n        body\n        (defines->let internal-definitions (body-without-definitions body)))))\n\n; c. And finally, we install it in. We do it in make-procedure, because that is\n; more efficient - it is called once for each procedure. Otherwise, it will be\n; called on every procedure invocation\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters (scan-out-defines body) env))\n\n; The rest of the interpreter. Note that I added a primitive procedure list to\n; enable an easier test case.\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((let? exp) (evaluate (let->combination exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp)\n  (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/17.scm",
    "content": "; SICP exercise 4.17\n;\n; Draw diagrams of the environment in effect when evaluating the expression\n; <e3> in the procedure in the text, comparing how this will be structured when\n; definitions are interpreted sequentially with how it will be structured if\n; definitions are scanned out as described. Why is there an extra frame in the\n; transformed program? Explain why this difference in environment structure can\n; never make a difference in the behavior of a correct program. Design a way to\n; make the interpreter implement the \"simultaneous\" scope rule for internal\n; definitions without constructing the extra frame.\n\n; Here's the diagram of the sequential interpretation:\n;\n; <lambda>: +----------------------+\n;           | <vars>: ...          |\n;           +----------------------+\n;                      ^\n;                      |\n;    <let>: +----------------------+\n;           | u: <e1>              |\n;           | v: <e2>              |\n; <e3>----> +----------------------+\n;\n; In comparison, this is the environment with the sequential interpretation:\n;\n; <lambda>: +----------------------+\n;           | <vars>: ...          |\n;           | u: <e1>              |\n;           | v: <e2>              |\n; <e3>----> +----------------------+\n;\n; The extra frame is there because of the let statement, which is implemented\n; as a lambda invocation. It does not make a difference, because the variables\n; have the same values in both environments. set! will affect different\n; environments in the two cases, but the value in the inner environment will\n; still be the same. Since this construction does not allow us to create\n; outside of the let, we cannot create a new function that will use the\n; environment of the lambda, but not the environment of the let.\n;\n; If we want to remove the extra frame, we can do it just by rearranging the\n; body of the procedure and moving all the definitions to the top, kind of like\n; function hoisting in JavaScript. In that case we will only have one\n; environemnt.\n"
  },
  {
    "path": "scheme/sicp/04/18.scm",
    "content": "; SICP exercise 4.18\n;\n; Consider an alternative strategy for scanning out definitions that\n; translates the example in the text to\n;\n;   (lambda <vars>\n;     (let ((u '*unassigned*)\n;           (v '*unassigned*))\n;       (let ((a '<e1>)\n;             (b '<e2>))\n;         (set! u a)\n;         (set! v b))\n;       <e3>))\n;\n; Here a and b are meant to represent new variables names, created by the\n; interpreter, that do not appear in the user's program. Consider the solve\n; procedure from 3.5.4:\n;\n;   (define (solve f y0 dt)\n;     (define y (integral (delay dy) y0 dt))\n;     (define dy (stream-map f y))\n;     y)\n;\n; Will this procedure work if internal definitions are scanned out as shown in\n; this exercise? What if they are scanned out as shown in the text? Explain.\n\n; In the first case, the result will be:\n;\n;   (lambda (f y 0 dt)\n;     (let ((y '*unassigned*)\n;           (dy '*unassigned*))\n;       (let ((a (integral (delay dy) y0 dt))\n;             (b (stream-map f y)))\n;         (set! y a)\n;         (set! dy b))\n;       y))\n;\n; This will not work, because b will be (stream-map f '*unassigned*).\n;\n; In the second case, the expansion will produce:\n;\n;   (lambda (f y 0 dt)\n;     (let ((y '*unassigned)\n;           (dy '*unassigned))\n;       (set! y (integral (delay dy) y0 dt))\n;       (set! dy (stream-map f y))\n;       y))\n;\n; This will work, since dy will refer to the proper value of y.\n"
  },
  {
    "path": "scheme/sicp/04/19.scm",
    "content": "; SICP exercise 4.19\n;\n; Ben Bitdiddle, Alyssa P. Hacker, and Eva Lu Ator are arguing about the\n; desired result of evaluating the expression\n;\n;   (let ((a 1))\n;     (define (f x)\n;       (define b (+ a x))\n;       (define a 5)\n;       (+ a b))\n;     (f 10))\n;\n; Ben asserts that the result should be obtained using the sequential rule for\n; define: b is defined to be 11, then a is defined to be 5, so the result is\n; 16. Alyssa objects that mutual recursion requires the simultaneous scope\n; rule for internal procedure definitions, and that is unreasonable to treat\n; procedure names differently from other names. Thus, she argues, for the\n; mechanism implemented in exercise 4.16. This would lead to a being\n; unassigned at the time that the value for b is to be computed. Hence, in\n; Alyssa's view, the procedure should produce an error. Eva has a third\n; opinion. She says that if the definitions of a and b are truly meant to be\n; simultaneous, then the value 5 for a should be used in evaluating b. Hence,\n; in Eva's view a should be 5, b should be 15, and the result should be 20.\n; Which (if any) of these viewpoints do you support? Can you devise a way to\n; implement internal definitions so that they behave as Eva prefers?\n\n; Personally, I dislike the distinction between define and set!. I prefer both\n; behaving the same way, that is, allowing assignment to an unassigned name\n; and setting to an assigned one. This removes the distinction between\n; definition and assignment, which I find superflous at best. Granted, it\n; imposes an order of evaluating, but that is simple enough to understand. The\n; downside is that such a strategy would not allow name shadowing with define.\n; This is not a problem with variable names (since you can use let), but\n; results in an awkward syntax for shadowing functions.\n;\n; If you have to live with having define able to shadow names, I would prefer\n; Alyssa's approach, because of its simplicity.\n;\n; Finally, Eva's preference would require finding the dependencies between\n; definitions and reordering them. My guy feeling is that this can be done\n; compile time in an efficient manner, but it is more complex than just\n; sticking with Alyssa's approach. It also introduces a harder to understand\n; system, where the user needs to be aware of this reordering in order to\n; understand why their programming is behaving the way they observe.\n;\n; I find that simple-to-understand interpreter outweights fancy, but rarely\n; used features.\n"
  },
  {
    "path": "scheme/sicp/04/20.scm",
    "content": "; SICP exercise 4.20\n;\n; Because internal definitions look sequential but are actually simultaneous,\n; some people prefer to avoid them entirely, and use the special form letrec\n; instead. Letrec looks like let, so it is no surprising that the variables it\n; binds are bound simultaneously and have the same scope as each other. The\n; sample procedure f above can be written without internal definitions, but\n; with exactly the same meaning, as:\n;\n;   (define (f x)\n;     (letrec ((even?\n;                (lambda (n)\n;                  (if (= n 0)\n;                      true\n;                      (odd? (- n 1)))))\n;              (odd?\n;                (lambda (n)\n;                  (if (= n 0)\n;                      false\n;                      (even? (- n 1))))))\n;       <rest-of-body-of-f>))\n;\n; letrec expressions, which have the form\n;\n;   (letrec ((<var-1> <exp-1>) ... (<var-n> <exp-n>))\n;     <body>)\n;\n; are a variation on let in which the expressions <exp-k> that provide the\n; initial values for the variables <var-k> are evaluated in an environment\n; that includes all the letrec bindings. This permits recursion in the\n; bindings, such as the mutual recursion of even? and odd? in the example\n; above, or the evaluation of 10 factorial with\n;\n;   (letrec ((fact\n;              (lambda (n)\n;                (if (= n 1)\n;                    1\n;                    (* n (fact (- n 1)))))))\n;     (fact 10))\n;\n; a. Implement letrec as a derived expression, by transforming a letrec\n; expression into a let expression as shown in the text above or in exercise\n; 4.18. That is, the letrec variables should be created with a let and then be\n; assigned their values with set!.\n;\n; b. Louis Reasoner is confused by all this fuss about internal definitions.\n; The way he sees it, if you don't like to use define inside a procedure, you\n; can just use let. Illustrate what is loose about his reasoning by drawing an\n; environment diagram that shows the environment in which <rest-of-body-of-f>\n; is evaluated during evaluation of the expression (f 5), with f defined as in\n; this exercise. Draw an environment diagram for the same evaluation, but with\n; let in place of letrec in the definition of f.\n\n(require r5rs/init)\n\n; a. Let's begin with the letrec implementation:\n\n(define (letrec? exp) (tagged-list? exp 'letrec))\n(define (letrec-pairs exp) (cadr exp))\n(define (letrec-body exp) (cddr exp))\n(define (letrec->combination exp)\n  (cons 'let\n        (cons (map (lambda (pair) (list (car pair) ''*unassigned*))\n                   (letrec-pairs exp))\n              (append (map (lambda (pair) (list 'set!\n                                                (car pair)\n                                                (cadr pair)))\n                           (letrec-pairs exp))\n                      (letrec-body exp)))))\n\n; It is installed in the evaluator.\n;\n; b. This is the code Louis proposes:\n;\n;   (define (f x)\n;     (let ((even?\n;             (lambda (n)\n;               (if (= n 0)\n;                   true\n;                   (odd? (- n 1)))))\n;           (odd?\n;             (lambda (n)\n;               (if (= n 0)\n;                   false\n;                   (even? (- n 1))))))\n;       <rest-of-body-of-f>))\n;\n; Here's the environment diagram of (f 10):\n;\n; f: +-------------------+\n;    | x: 10             |\n;    +-------------------+\n;            ^ ^ ^\n;            | | |\n;            | | +---------------------------------------+\n;            | +----------------------+                  |\n;    +-------------------+            |            +----------+\n;    | even?: <lambda> ---------------|------------| <lambda> |\n;    | odd?: <lambda>  -----+         |            +----------+\n;    +-------------------+  |   +----------+        params: n\n;              ^            +---| <lambda> |        code: (if (= n 0)\n;              |                +----------+                  true\n;     <rest-of-body-of-f>        params: n                    (odd? (- n 1)))\n;                                code: (if (= n 0)\n;                                          false\n;                                          (even? (- n 1)))\n;\n; It is apparant that even? is not defined in odd?'s environment and odd? is\n; not defined in even?'s environment. Thus, it will simply not work.\n\n; The rest of the evaluator:\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((let? exp) (evaluate (let->combination exp) env))\n        ((letrec? exp) (evaluate (letrec->combination exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/21.scm",
    "content": "; SICP exercise 4.21\n;\n; Amazingly, Louis's intuition on exercise 4.20 is correct. It is indeed\n; possible to specify recursive procedures without using letrec (or even\n; define), although the method for accomplishing this is much more subtle than\n; Louis imagined. The following expression computes 10 factorial by applying a\n; recursive factorial procedure:\n;\n;   ((lambda (n)\n;      ((lambda (fact)\n;         (fact fact n))\n;       (lambda (ft k)\n;         (if (= k 1)\n;             1\n;             (* k (ft ft (- k 1)))))))\n;    10)\n;\n; a. Check (by evaluating the expression) that this really does compute\n; factorials. Devise an analogous expression for computing the Fibonacci\n; numbers.\n;\n; b. Consider the following procedure, which includes mutually recursive\n; internal definitions.\n;\n;   (define (f x)\n;     (define (even? n)\n;       (if (= n 0)\n;           true\n;           (odd? (- n 1))))\n;     (define (odd? n)\n;       (if (= n 0)\n;           false\n;           (even? (- n 1))))\n;     (even? x))\n;\n; Fill in the missing expressions to complete an alternative definition of f,\n; which uses neither internal definitions nor letrec:\n;\n;   (define (f x)\n;     ((lambda (even? odd?)\n;        (even? even? odd? x))\n;      (lambda (ev? od? n)\n;        (if (= n 0) true (od? <??> <??> <??>)))\n;      (lambda (ev? od? n)\n;        (if (= n 0) false (ev? <??> <??> <??>)))))\n\n(require r5rs/init)\n\n; a. The check is in the tests. The similar expression is:\n\n(define (y-fibonacci number)\n  ((lambda (n)\n    ((lambda (fibonacci)\n       (fibonacci fibonacci n))\n     (lambda (fib n)\n       (cond ((= n 0) 0)\n             ((= n 1) 1)\n             (else (+ (fib fib (- n 1)) (fib fib (- n 2))))))))\n   number))\n\n; b. This is the alternative definition of f:\n\n(define (f x)\n  ((lambda (even? odd?)\n     (even? even? odd? x))\n   (lambda (ev? od? n)\n     (if (= n 0) true (od? ev? od? (- n 1))))\n   (lambda (ev? od? n)\n     (if (= n 0) false (ev? ev? od? (- n 1))))))\n\n; The rest of the interpreter:\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/22.scm",
    "content": "; SICP exercise 4.22\n;\n; Extend the evaluator in this section to support the special form let. (See\n; exercise 4.6)\n\n(require r5rs/init)\n\n; Let is just a syntactic transformation, so not much additional code is\n; necessary. We have the code we had in 4.6:\n\n(define (let? exp)\n  (tagged-list? exp 'let))\n\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n; We just need to install it in the rest of the interpreter:\n\n(define (evaluate exp env)\n  ((analyze exp) env))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args)\n  (cond ((primitive-procedure? proc)\n         (apply-primitive-procedure proc args))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env) exp))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env) qval)))\n\n(define (analyze-variable exp)\n  (lambda (env) (lookup-variable-value exp env)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env)\n      (set-variable-value! var (vproc env) env)\n      'ok)))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env)\n      (define-variable! var (vproc env) env)\n      'ok)))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env)\n      (if (true? (pproc env))\n          (cproc env)\n          (aproc env)))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env) (make-procedure vars bproc env))))\n\n(define (analyze-sequence exps)\n  (define (sequentially proc1 proc2)\n    (lambda (env) (proc1 env) (proc2 env)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/23.scm",
    "content": "; SICP exercise 4.23\n;\n; Alyssa P. Hacker doesn't understand why analyze-sequence needs to be so\n; complicated. All the other analysis procedures are straightforward\n; transformations of the corresponding evaluation procedures (or eval clauses)\n; in section 4.1.1. She expected analyze-sequence to look like this:\n;\n;   (define (analyze-sequence exps)\n;     (define (execute-sequence procs env)\n;       (cond ((null? (cdr procs)) ((car procs) env))\n;             (else ((car procs) env)\n;                   (execute-sequence (cdr procs) env))))\n;     (let ((procs (map analyze exps)))\n;       (if (null? procs)\n;           (error \"Empty sequence -- ANALYZE\"))\n;       (lambda (env) (execute-sequence procs env))))\n;\n; Eva Lu Ator explains to Alyssa that the version in the text does more of the\n; work of evaluating a sequence at analysis time. Alyssa's sequence-execution\n; procedure, rather than having the calls to the individual built in, loops\n; through the procedures in order to call them: In effect, although the\n; individual expressions in the sequence have been analyzed, the sequence\n; itself has not been.\n;\n; Compare the two versions of analyze-sequence. For example, consider the\n; common case (typical of procedure bodies) where the sequence has just one\n; expression. What work will the execution procedure produced by Alyssa's\n; program do? What about the execution procedure produced by the program in\n; the text above? How do the two versions compare for a sequence with two\n; expressions?\n\n; The extra work is iterating the over each expression in the body. In the\n; case of a body with one expression, Alyssa's code will do an additional\n; cond, null?, cdr and car. In case of a procedure with two expressions in its\n; body, Alyssa's code will in addition do another cond, null?, car and two\n; extra cdrs (one for the null? check and one in the else clause).\n"
  },
  {
    "path": "scheme/sicp/04/24.scm",
    "content": "; SICP exercise 4.24\n;\n; Design and carry out some experiments to compare the speed of the original\n; metacircular evaluator with the version in this section. Use your results to\n; estimate the fraction of time spent in analysis versus execution for various\n; procedures.\n\n; This solution steps away from the traditional approach and uses a bit more\n; of Racket's functionality (although there is probably a better way to do\n; this).\n;\n; The output, slightly rearranged is:\n;\n;   evaluator recursive-fib-25: cpu time: 941 real time: 943 gc time: 10\n;   analyzing recursive-fib-25: cpu time: 475 real time: 477 gc time: 92\n;\n;   evaluator odd-even-1000000: cpu time: 221 real time: 221 gc time: 2\n;   analyzing odd-even-1000000: cpu time: 116 real time: 118 gc time: 8\n;\n;   evaluator factorial-100000: cpu time: 98 real time: 99 gc time: 27\n;   analyzing factorial-100000: cpu time: 71 real time: 73 gc time: 16\n;\n; Unsurprisingly, the analyzing evaluator is faster.\n\n(module benchmark racket/load\n  (require r5rs/init)\n\n  (define recursive-fib-25\n    '(begin (define (fib n)\n              (cond ((= n 0) 0)\n                    ((= n 1) 1)\n                    (else (+ (fib (- n 1)) (fib (- n 2))))))\n            (fib 25)))\n\n  (define factorial-100000\n    '(begin (define (factorial n)\n              (if (= n 0)\n                  1\n                  (* n (factorial (- n 1)))))\n            (factorial 10000)))\n  (define odd-even-1000000\n    '(begin (define (odd? n)\n              (if (= n 0)\n                  false\n                  (even? (- n 1))))\n            (define (even? n)\n              (if (= n 0)\n                  true\n                  (odd? (- n 1))))\n            (even? 100000)))\n\n  (define experiments\n    (list\n      (cons \"recursive-fib-25\" recursive-fib-25)\n      (cons \"odd-even-1000000\" odd-even-1000000)\n      (cons \"factorial-100000\" factorial-100000)))\n\n  (define (benchmark evaluator-name)\n    (define (loop experiments)\n      (if (null? experiments)\n          'done\n          (let ((experiment-name (caar experiments))\n                (code (cdar experiments)))\n            (printf \"~a ~a: \" evaluator-name experiment-name)\n            (time (evaluate code (setup-environment)))\n            (loop (cdr experiments)))))\n    (loop experiments))\n\n  (load-relative \"showcase/evaluator/evaluator.scm\")\n  (benchmark \"evaluator\")\n\n  (load-relative \"./showcase/analyzing/evaluator.scm\")\n  (benchmark \"analyzing\"))\n\n(require 'benchmark)\n"
  },
  {
    "path": "scheme/sicp/04/25.scm",
    "content": "; SICP exercise 4.25\n;\n; Suppose that (in ordinary applicative-order Scheme) we define unless as\n; shown above and then define factorial in terms of unless as\n;\n;   (define (factorial n)\n;     (unless (= n 1)\n;             (* n (factorial (- n 1)))\n;             1))\n;\n; What happens if we attempt to evaluate (factorial 5)? Will our definitions\n; work in a normal-order language?\n\n; The interpreter will end up in a bottomless recursion, since invoking\n; factorial always invokes factorial before returning (even before calling\n; unless). Simple, it would not do.\n;\n; In a normal-order language this definition will work, since the arguments to\n; unless won't be evaluated unless they are needed.\n"
  },
  {
    "path": "scheme/sicp/04/26.scm",
    "content": "; SICP exercise 4.26\n;\n; Ben Bitdidle and Alyssa P. Hacker disagree over the importance of lazy\n; evaluation for implementing things such as unless. Ben points out that it's\n; possible to implement unless in applicative order as a special form. Alyssa\n; counters that, if one did that, unless would be merely syntax, not a\n; procedure that could be used in conjunction with higher-order procedures.\n; Fill in the details on both sides of the argument. Show how to implement\n; unless as a derived expression (like cond or let), and give an example of a\n; situation where it might be useful to have unless as a procedure, rather\n; than as a special form.\n\n; \"Merely syntax\". Heh.\n;\n; On Ben's side, we can add that there is nothing wrong with having unless\n; implemented as a special form. I can't see a case where one would want to\n; pass unless as an argument. Granted, it requires a change to the interpreter\n; or the introduction of macro mechanisms. Converting to lazy evaluation\n; raises some hairy questions when side effects are involved (as we shall see\n; in the upcomming exercises) and carries a certain performance overhead.\n;\n; On Alyssa's side, it would actually be cool to pass unless as a function.\n; While unless is not the best example, lazy evaluation would be useful for\n; streams - the cons-stream form from the previous chapter can be replaced\n; with cons. Furthermore, we won't need a macro facility.\n;\n; Here is how unless can be implemented as a special form:\n\n(define (unless->combination condition usual-value exceptional-value)\n  (list 'if condition exceptional-value usual-value))\n\n; It of course, needs to be installed in eval.\n;\n; As for an example of a situation where it might be useful to have unless as\n; a procedure, I'm going to point out something similar I already mentioned -\n; cons-stream. Lazy evaluation would remove the necessity to add a special\n; form and we can just use cons instead.\n"
  },
  {
    "path": "scheme/sicp/04/27.scm",
    "content": "; SICP exercise 4.27\n;\n; Suppose we type in the following definitions to the lazy evaluator:\n;\n;   (define count 0)\n;   (define (id x)\n;     (set! count (+ count 1))\n;     x)\n;\n; Give the missing values in the following sequence of interactions, and\n; explain your answers:\n;\n; (define w (id (id 10)))\n; ;;; L-Eval input\n; count\n; ;;; L-Eval output\n; <response>\n; ;;; L-Eval input\n; w\n; ;;; L-Eval output\n; <response>\n; ;;; L-Eval input\n; count\n; ;;; L-Eval output\n; <response>\n\n; Here is the full interaction:\n;\n; (define w (id (id 10)))\n; ;;; L-Eval input\n; count\n; ;;; L-Eval output\n; 1\n; ;;; L-Eval input\n; w\n; ;;; L-Eval output\n; 10\n; ;;; L-Eval input\n; count\n; ;;; L-Eval output\n; 2\n;\n; When we define w, id gets executed. It takes (id 10) for an argument,\n; invokes set! to increment the count and returns a thunk containing (id 10).\n; At this point, when we print out count, we get 1.\n;\n; When we print w, the REPL forces the thunk which calls id again with 10 as\n; an argument. set! is invoked one more, incrementing counter to 2. The result\n; is printed.\n;\n; The subsequent printing of count shows the twice incremented value.\n"
  },
  {
    "path": "scheme/sicp/04/28.scm",
    "content": "; SICP exercise 4.28\n;\n; Eval uses actual-value rather than eval to evaluate the operator before\n; passing it to apply, in order to force the value of the operator. Give an\n; example that demonstrates the need for this forcing.\n\n; An example can be the following (rather weird) code:\n;\n;   ((lambda (f) (f 2))\n;    (lambda (x) (* x 2)))\n;\n; In the working interpreter it should return 4, but if we use evaluate\n; instead of actual-value, it will result to an error. The reason is that\n; apply would receive a thunk instead of a procedure and the cond will fail to\n; match in either clauses (because a thunk is not a primitive-procedure? and\n; is not a compound-procedure?).\n"
  },
  {
    "path": "scheme/sicp/04/29.scm",
    "content": "; SICP exercise 4.29\n;\n; Exhibit a program that you would expect to run much more slowly without\n; memoization than with memoization. Also, consider the following interaction,\n; where the id procedure is defined as in exercise 4.27 and count starts as 0:\n;\n;   (define (square x)\n;     (* x x))\n;\n; ;;; L-Eval input:\n; (square (id 10))\n; ;;; L-Eval output:\n; <response>\n; ;;; L-Eval input:\n; count\n; ;;; L-Eval output:\n; <response>\n\n; The interaction would go as follows:\n;\n; ;;; L-Eval input:\n; (square (id 10))\n; ;;; L-Eval output:\n; 100\n; ;;; L-Eval input:\n; count\n; ;;; L-Eval output:\n; 2\n;\n; The result from square is obvious. Count is 2, because (id 10) got evaluated\n; twice - once for each argument of the multiplication.\n;\n; We had a simple example of such a function in exercise 1.20:\n;\n; (define (gcd a b)\n;   (if (= b 0)\n;       a\n;       (gcd b (remainder a b))))\n;\n; Check out the exercise to see the expansion. The thunk b is evaluated twice\n; for every application of gcd, which will take much more time than with\n; memoization.\n"
  },
  {
    "path": "scheme/sicp/04/30.scm",
    "content": "; SICP exercise 4.30\n;\n; Cy D. Fect, a reformed C programmer, is worried that some side effects may\n; never take place, because the lazy evaluator doesn't force the expressions\n; in a sequence. Since the value of an expression in a sequence other than the\n; last one is not used (the expression is there only for its effect, such as\n; assigning to a variable or printing), there can be no subsequent use of this\n; value (e.g., as an argument to a primitive procedure) that will cause it to\n; be forced. Cy thus thinks that when evaluating sequences, we must force all\n; expressions in the sequence except the final one. He proposes to modify\n; eval-sequence from section 4.1.1 to use actual-value rather than eval:\n;\n;   (define (eval-sequence exps env)\n;     (cond ((last-exp? exps) (eval (first-exp exps) env))\n;           (else (actual-value (first-exp exps) env)\n;                 (eval-sequence (rest-exps exps) env))))\n;\n; a. Ben Bitdiddle thinks Cy is wrong. He shows Cy the for-each procedure\n; described in exercise 2.23, which gives an important example of a sequence\n; with side effects:\n;\n;   (define (for-each proc items)\n;     (if (null? items)\n;         'done\n;         (begin (proc (car items))\n;                (for-each proc (cdr items)))))\n;\n; He claims that the evaluator in the text (with the original eval-sequence)\n; handles this correctly:\n;\n; ;;; L-Eval input:\n; (for-each (lambda (x) (newline) (display x))\n;           (list 57 321 88))\n; 57\n; 321\n; 88\n; ;;; L-Eval value:\n; done\n;\n; Explain why Ben is right about the behavior of for-each.\n;\n; b. Cy agrees that Ben is right about the for-each example, but says that\n; that's not the kind of program he was thinking about when he proposed his\n; change to eval-sequence. He defines the following two procedures in the lazy\n; evaluator:\n;\n; (define (p1 x)\n;   (set! x (cons x '(2)))\n;   x)\n;\n; (define (p2 x)\n;   (define (p e)\n;     e\n;     x)\n;   (p (set! x (cons x '(2)))))\n;\n; What are the values of (p1 1) and (p2 1) with the original eval-sequence?\n; What would the values be with Cy's proposed change to eval-sequence?\n;\n; c. Cy also points out that changing eval-sequence as he proposes does not\n; affect the behavior of the example in part a. Explain why this is true.\n;\n; d. How do you think sequences ought to be treated in the lazy evaluator? Do\n; you like Cy's approach, the approach in the text, or some other approach?\n\n; a. It works, whenever eval find an application, it evalutes it. Thus, the\n; first expression in begin - (proc (car items)) will get evaluated, which\n; will in turn evaluate newline and display, and the latter will force its\n; argument.\n;\n; b. The results in with the original procedure are (1 2) and 1. With Cy's\n; version, they will both be (1 2).\n;\n; c. It is fairly obvious - (proc (car items)) passes through actual-value\n; instead of evaluate, but that doesn't change anything, since both will\n; force the value.\n;\n; d. I prefer the approach in the text, since otherwise a huge part of the\n; lazy evaluation will be lost. The problem obviously stems from side-effects\n; and that can be handled in other ways (do I hear the word \"monads\"?).\n"
  },
  {
    "path": "scheme/sicp/04/31.scm",
    "content": "; SICP exercise 4.31\n;\n; The approach taken in this section is somewhat unpleasant, because it makes\n; an incompatible change to Scheme. It might be nicer to implement lazy\n; evaluation as an upward-compatible extension, that is, so that ordinary\n; Scheme programs will work as before. We can do this by extending the syntax\n; of procedure declarations to let the user control whether or not arguments\n; are to be delayed. While we're at it, we may as well also give the user the\n; choice between delaying with and without memoization. For example, the\n; definition\n;\n;   (define f a (b lazy) c (d lazy-memo)\n;     ...)\n;\n; would define f to be a procedure of four arguments, where the first and\n; third arguments are evaluated when the procedure is called, the second\n; argument is delayed, and the fourth argument is both delayed and memoized.\n; Thus, ordinary procedure definitions will produce the same behavior as\n; ordinary Scheme, while adding the lazy-memo declaration to each parameter of\n; every compound procedure will produce the behavior of the lazy evaluator\n; defined in this section. Design and implement the changes required to\n; produce such an extension to Scheme. You will have to implement new syntax\n; procedures to handle the new syntax for define. You must also arrange for\n; eval or apply to determine when the arguments are to be delayed, and to\n; force or delay arguments accordingly, and you must arrange for forcing to\n; memoize or not, as appropriate.\n\n; Below is a lazy (as in \"not too tidy\") implementation of the requested\n; evaluator. It introduces some abstraction over procedures, that are used by\n; eval and apply.\n\n(require r5rs/init)\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (operands exp)\n                          env))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments env)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure (list-of-values arguments env)))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             (list-of-arguments (procedure-argument-types procedure) arguments env)\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (actual-value exp env)\n  (force-it (evaluate exp env)))\n\n(define (thunk exp env) (list 'thunk exp env))\n(define (memoizable-thunk exp env) (list 'memoizable-thunk exp env))\n(define (thunk? obj) (tagged-list? obj 'thunk))\n(define (memoizable-thunk? obj) (tagged-list? obj 'memoizable-thunk))\n(define (evaluated-thunk? obj) (tagged-list? obj 'evaluated-thunk))\n(define (thunk-exp thunk) (cadr thunk))\n(define (thunk-env thunk) (caddr thunk))\n(define (thunk-value evaluated-thunk) (cadr evaluated-thunk))\n\n(define (force-it obj)\n  (cond ((thunk? obj)\n         (actual-value (thunk-exp obj) (thunk-env obj)))\n        ((memoizable-thunk? obj)\n         (let ((result (actual-value (thunk-exp obj) (thunk-env obj))))\n           (set-car! obj 'evaluated-thunk)\n           (set-car! (cdr obj) result)\n           (set-cdr! (cdr obj) '())\n           result))\n        ((evaluated-thunk? obj)\n         (thunk-value obj))\n        (else obj)))\n\n(define (make-argument type arg env)\n  (cond ((eq? type 'normal) (evaluate arg env))\n        ((eq? type 'lazy) (thunk arg env))\n        ((eq? type 'lazy-memo) (memoizable-thunk arg env))\n        (error \"Unknown parameter type\" type)))\n\n(define (list-of-arguments types arguments env)\n  (map (lambda (type arg) (make-argument type arg env))\n       types\n       arguments))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (actual-value (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p)\n  (define (name-of parameter)\n    (if (pair? parameter)\n        (car parameter)\n        parameter))\n  (map name-of (cadr p)))\n(define (procedure-argument-types p)\n  (define (type-of parameter)\n    (cond ((not (pair? parameter)) 'normal)\n          ((eq? (cadr parameter) 'lazy) 'lazy)\n          ((eq? (cadr parameter) 'lazy-memo) 'lazy-memo)\n          (else (error \"Badly formed parameter\" parameter))))\n  (map type-of (cadr p)))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/32.scm",
    "content": "; SICP exercise 4.32\n;\n; Give some examples that illustrate the difference between the streams of\n; chapter 3 and the \"lazier\" lazy lists described in this section. How can you\n; take advantage of this extra laziness?\n\n; Well, one of them, obviously, is implementing solve without the necessity\n; for delays. This can be generalized for all infinite data structures -\n; instead of having to introduce a special form in the language, we can have a\n; constructor that lazily evaluates its parameters. A favourite of mine is\n; implementing map via accumulate, which cannot happen otherwise. It is not\n; the most practical, but it is cool nontheless.\n"
  },
  {
    "path": "scheme/sicp/04/33.scm",
    "content": "; SICP exercise 4.33\n;\n; Ben Bitdiddle tests the lazy list implementation given above by evaluating\n; the expression\n;\n;   (car '(a b c))\n;\n; To his surprise, this produces an error. After some thought, he realizes\n; that the \"lists\" obtained by reading in quoted expressions are different\n; from the lists manipulated by the new definitions of cons, car and cdr.\n; Modify the evaluator's treatment of quoated expressions so that quoted lists\n; typed at the driver loop will produce true lazy lists.\n\n(require r5rs/init)\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (eval-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((application? exp)\n         (apply-procedure (actual-value (operator exp) env)\n                          (operands exp)\n                          env))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments env)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure\n          procedure\n          (list-of-arg-values arguments env)))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             (list-of-delayed-args arguments env)\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (actual-value exp env)\n  (force-it (evaluate exp env)))\n\n(define (delay-it exp env) (list 'thunk exp env))\n(define (thunk? obj) (tagged-list? obj 'thunk))\n(define (thunk-exp thunk) (cadr thunk))\n(define (thunk-env thunk) (caddr thunk))\n(define (evaluated-thunk? obj)\n  (tagged-list? obj 'evaluated-thunk))\n(define (thunk-value evaluated-thunk) (cadr evaluated-thunk))\n\n(define (force-it obj)\n  (cond ((thunk? obj)\n         (let ((result (actual-value (thunk-exp obj) (thunk-env obj))))\n           (set-car! obj 'evaluated-thunk)\n           (set-car! (cdr obj) result)\n           (set-cdr! (cdr obj) '())\n           result))\n        ((evaluated-thunk? obj)\n         (thunk-value obj))\n        (else obj)))\n\n(define (list-of-arg-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (actual-value (first-operand exps) env)\n            (list-of-arg-values (rest-operands exps) env))))\n\n(define (list-of-delayed-args exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (delay-it (first-operand exps) env)\n            (list-of-delayed-args (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (actual-value (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (eval-quotation exp)\n  (let ((text (text-of-quotation exp)))\n    (if (pair? text)\n        (evaluate (list 'cons\n                        (list 'quote (car text))\n                        (list 'quote (cdr text)))\n                  the-global-environment)\n        text)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp)\n  (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list '= =)\n        (list 'null? null?)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define definitions\n  '((define (cons x y)\n      (lambda (m) (m x y)))\n    (define (car z)\n      (z (lambda (p q) p)))\n    (define (cdr z)\n      (z (lambda (p q) q)))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (evaluate definition initial-env))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; L-Eval input:\")\n(define output-prompt \";;; L-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (actual-value input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/34.scm",
    "content": "; SICP exercise 4.34\n;\n; Modify the driver loop for the evaluator so that lazy pairs and lists will\n; print in some reasonable way. (What are you going to do about infinite\n; lists?) You may also need to modify the representation of lazy pairs so that\n; the evaluator can identify them in order to print them.\n\n; Phew, this gave me some hard time. I had to take a piece of paper and sketch\n; notes. Apparently that is a good idea from time to time.\n;\n; We base the code on the previous exercise's solution. We implement a\n; procedure print in the evaluator. We change the representation to a tagged\n; list (with 'pair) and the lambda. It is far from the best solution, but at\n; least it does it in the interpreter. We also make the pair self-evaluating,\n; since we're passing it to apply-procedure in user-print.\n\n(require r5rs/init)\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (eval-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((application? exp)\n         (apply-procedure (actual-value (operator exp) env)\n                          (operands exp)\n                          env))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments env)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure\n          procedure\n          (list-of-arg-values arguments env)))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             (list-of-delayed-args arguments env)\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (actual-value exp env)\n  (force-it (evaluate exp env)))\n\n(define (delay-it exp env) (list 'thunk exp env))\n(define (thunk? obj) (tagged-list? obj 'thunk))\n(define (thunk-exp thunk) (cadr thunk))\n(define (thunk-env thunk) (caddr thunk))\n(define (evaluated-thunk? obj)\n  (tagged-list? obj 'evaluated-thunk))\n(define (thunk-value evaluated-thunk) (cadr evaluated-thunk))\n\n(define (force-it obj)\n  (cond ((thunk? obj)\n         (let ((result (actual-value (thunk-exp obj) (thunk-env obj))))\n           (set-car! obj 'evaluated-thunk)\n           (set-car! (cdr obj) result)\n           (set-cdr! (cdr obj) '())\n           result))\n        ((evaluated-thunk? obj)\n         (thunk-value obj))\n        (else obj)))\n\n(define (list-of-arg-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (actual-value (first-operand exps) env)\n            (list-of-arg-values (rest-operands exps) env))))\n\n(define (list-of-delayed-args exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (delay-it (first-operand exps) env)\n            (list-of-delayed-args (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (actual-value (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (eval-quotation exp)\n  (let ((text (text-of-quotation exp)))\n    (if (pair? text)\n        (evaluate (list 'cons\n                        (list 'quote (car text))\n                        (list 'quote (cdr text)))\n                  the-global-environment)\n        text)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        ((tagged-list? exp 'pair) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp)\n  (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list '= =)\n        (list 'null? null?)\n        (list 'scheme-eq? eq?)\n        (list 'scheme-cons cons)\n        (list 'scheme-car car)\n        (list 'scheme-cdr cdr)\n        (list 'scheme-pair? pair?)\n        (list 'display display)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define definitions\n  '((define (pair? x)\n      (if (scheme-pair? x) (scheme-eq? (scheme-car x) 'pair) false))\n    (define (cons x y)\n      (scheme-cons 'pair (lambda (m) (m x y))))\n    (define (car z)\n      ((scheme-cdr z) (lambda (p q) p)))\n    (define (cdr z)\n      ((scheme-cdr z) (lambda (p q) q)))\n    (define (memq item items)\n      (cond ((null? items) false)\n            ((scheme-eq? (car items) item) true)\n            (else (memq item (cdr items)))))\n    (define (print object)\n      (define (print object encountered)\n        (cond ((memq object encountered)\n               (display \"(...)\"))\n              ((pair? object)\n               (display \"(\")\n               (print (car object) (cons object encountered))\n               (print-cdr (cdr object) (cons object encountered)))\n              ((null? object)\n               (display \"()\"))\n              (else\n               (display object))))\n      (define (print-cdr rest encountered)\n        (cond ((memq rest encountered)\n               (display \" (...))\"))\n              ((null? rest)\n               (display \")\"))\n              ((pair? rest)\n               (display \" \")\n               (print (car rest) (cons rest encountered))\n               (print-cdr (cdr rest) (cons rest encountered)))\n              (else\n               (display \" . \")\n               (print rest encountered)\n               (display \")\"))))\n      (print object '()))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (evaluate definition initial-env))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; L-Eval input:\")\n(define output-prompt \";;; L-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (actual-value input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (apply-procedure (lookup-variable-value 'print the-global-environment)\n                       (list object)\n                       the-global-environment)))\n"
  },
  {
    "path": "scheme/sicp/04/35.scm",
    "content": "; SICP exercise 4.35\n;\n; Write a procedure an-integer-between that returns an integer between two\n; given bounds. This can be used to implement a procedure that finds\n; Pythagorean triples, i.e., triples of integers (i, j, k) between the given\n; bounds such that i ≤ j and i² + j² = k², as follows:\n;\n;   (define (a-ptyhagorean-triple-between low high)\n;     (let ((i (an-integer-between low high)))\n;       (let ((j (an-integer-between i high)))\n;         (let ((k (an-integer-between j high)))\n;           (require (= (+ (* i i) (* j j) (* k k))))\n;           (list i j k)))))\n\n(require r5rs/init)\n\n; The solution follows. There is some support code for the tests in the end of\n; the file.\n\n(define solution\n  '((define (an-integer-between low high)\n      (if (> low high)\n        (amb)\n        (amb low (an-integer-between (+ low 1) high))))\n    (define (a-pythagorean-triple-between low high)\n      (let ((i (an-integer-between low high)))\n        (let ((j (an-integer-between i high)))\n          (let ((k (an-integer-between j high)))\n            (require (= (+ (* i i) (* j j)) (* k k)))\n            (list i j k)))))))\n\n; The rest of the interpreter.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list 'not not)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n\n(define solution-environment\n  ((lambda ()\n     (define environment (setup-environment))\n     (for-each (lambda (definition)\n                 (ambeval definition\n                          environment\n                          (lambda (value fail) 'ok)\n                          (lambda () 'ok)))\n               solution)\n     environment)))\n"
  },
  {
    "path": "scheme/sicp/04/36.scm",
    "content": "; SICP exercise 4.36\n;\n; Exercise 3.69 discussed how to generate the stream of all Pythagorean\n; triples, with no upper bound on the size of the integers to be searched.\n; Explain why simply replacing an-integer-between by an-integer-starting-from\n; in the procedure in exercise 4.35 is not an adequate way to generate\n; arbitrary Pythagorean triples. Write a procedure that actually will\n; accomplish this. (That is, write a procedure for which repeatedly typing\n; try-again would in principle eventually generate all Pythagorean triples).\n\n(require r5rs/init)\n\n; Say we do said replacing. On the first backtrack, the innermost call to\n; an-integer-starting-from will result to 2. On the second backtrack, it will\n; be 3 and so on, never giving a chance to the previous calls to return\n; anything different than the initial value.\n\n; The solution follows. There is some support code for the tests in the end of\n; the file.\n\n(define solution\n  '((define (an-integer-starting-from n)\n      (amb n (an-integer-starting-from (+ n 1))))\n    (define (an-integer-between low high)\n      (if (> low high)\n        (amb)\n        (amb low (an-integer-between (+ low 1) high))))\n    (define (a-pythagorean-triple)\n      (let ((k (an-integer-starting-from 1)))\n        (let ((i (an-integer-between 1 k)))\n          (let ((j (an-integer-between i k)))\n            (require (= (+ (* i i) (* j j)) (* k k)))\n            (list i j k)))))))\n\n; The rest of the interpreter.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list 'not not)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n\n(define solution-environment\n  ((lambda ()\n     (define environment (setup-environment))\n     (for-each (lambda (definition)\n                 (ambeval definition\n                          environment\n                          (lambda (value fail) 'ok)\n                          (lambda () 'ok)))\n               solution)\n     environment)))\n"
  },
  {
    "path": "scheme/sicp/04/37.scm",
    "content": "; SICP exercise 4.37\n;\n; Ben Bitdiddle claims that the following method for generating Pythagorean\n; triples is more efficient than the one in exercise 4.35. Is he correct?\n; (Hint: Consider the number of possibilities that must be explored.)\n;\n;   (define (a-pythagorean-triple-between low high)\n;     (let ((i (an-integer-between low high))\n;           (hsq (* high high)))\n;       (let ((j (an-integer-between i high)))\n;         (let ((ksq (+ (* i i) (* j j))))\n;           (require (>= hsq ksq))\n;           (let ((k (sqrt ksq)))\n;             (require (integer? k))\n;             (list i j k))))))\n\n; It seems so. Ben's version is n², while the text version is n³. On the other\n; hand, Ben's version uses sqrt which is slower in general, so there might be\n; cases where where Ben's version is slower (probably for small values of\n; high - low).\n"
  },
  {
    "path": "scheme/sicp/04/38.scm",
    "content": "; SICP exercise 4.38\n;\n; Modify the multiple-dwelling procedure to omit the requirement that Smith\n; and Fletcher do not live on adjancent floors. How many solutions are there\n; to this modified puzzle?\n\n(require r5rs/init)\n\n; We get five values, which are the following:\n;\n;   ((baker 1) (cooper 2) (fletcher 4) (miller 3) (smith 5))\n;   ((baker 1) (cooper 2) (fletcher 4) (miller 5) (smith 3))\n;   ((baker 1) (cooper 4) (fletcher 2) (miller 5) (smith 3))\n;   ((baker 3) (cooper 2) (fletcher 4) (miller 5) (smith 1))\n;   ((baker 3) (cooper 4) (fletcher 2) (miller 5) (smith 1))\n;\n; Here's the code to reproduce it:\n\n(define solution\n  '((define (distinct? items)\n      (cond ((null? items) true)\n            ((null? (cdr items)) true)\n            ((member (car items) (cdr items)) false)\n            (else (distinct? (cdr items)))))\n    (define (multiple-dwelling)\n      (let ((baker (amb 1 2 3 4 5))\n            (cooper (amb 1 2 3 4 5))\n            (fletcher (amb 1 2 3 4 5))\n            (miller (amb 1 2 3 4 5))\n            (smith (amb 1 2 3 4 5)))\n        (require\n          (distinct? (list baker cooper fletcher miller smith)))\n        (require (not (= baker 5)))\n        (require (not (= cooper 1)))\n        (require (not (= fletcher 5)))\n        (require (not (= fletcher 1)))\n        (require (> miller cooper))\n        (require (not (= (abs (- fletcher cooper)) 1)))\n        (list (list 'baker baker)\n              (list 'cooper cooper)\n              (list 'fletcher fletcher)\n              (list 'miller miller)\n              (list 'smith smith))))))\n\n; The rest of the interpreter.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list 'not not)\n        (list 'abs abs)\n        (list 'member member)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n\n(define solution-environment\n  ((lambda ()\n     (define environment (setup-environment))\n     (for-each (lambda (definition)\n                 (ambeval definition\n                          environment\n                          (lambda (value fail) 'ok)\n                          (lambda () 'ok)))\n               solution)\n     environment)))\n"
  },
  {
    "path": "scheme/sicp/04/39.scm",
    "content": "; SICP exercise 4.39\n;\n; Does the order of the restrictions in the multiple-dwelling procedure affect\n; the answer? Does it affect the time to find an answer? If you think it\n; matters, demonstrate a faster program obtained from the given one by\n; reordering the restrictions. If you think it does not matter, argue your\n; case.\n\n(require r5rs/init)\n\n; The result is not going to change at all. The running time can change,\n; though. Doing the rearrangement below, we can achieve the following results:\n;\n;   slow-multiple-dwelling: cpu time: 1247 real time: 1264 gc time: 66\n;   fast-multiple-dwelling: cpu time: 765 real time: 774 gc time: 25\n;\n; One trick is moving (> miller cooper) up front, since it is a cheap and\n; restrictive requirement. Another is moving the distinct? check at the end,\n; because that is an expensive operation.\n\n(define solution\n  '((define (distinct? items)\n      (cond ((null? items) true)\n            ((null? (cdr items)) true)\n            ((member (car items) (cdr items)) false)\n            (else (distinct? (cdr items)))))\n    (define (slow-multiple-dwelling)\n      (let ((baker (amb 1 2 3 4 5))\n            (cooper (amb 1 2 3 4 5))\n            (fletcher (amb 1 2 3 4 5))\n            (miller (amb 1 2 3 4 5))\n            (smith (amb 1 2 3 4 5)))\n        (require\n          (distinct? (list baker cooper fletcher miller smith)))\n        (require (not (= baker 5)))\n        (require (not (= cooper 1)))\n        (require (not (= fletcher 5)))\n        (require (not (= fletcher 1)))\n        (require (> miller cooper))\n        (require (not (= (abs (- smith fletcher)) 1)))\n        (require (not (= (abs (- fletcher cooper)) 1)))\n        (list (list 'baker baker)\n              (list 'cooper cooper)\n              (list 'fletcher fletcher)\n              (list 'miller miller)\n              (list 'smith smith))))\n    (define (fast-multiple-dwelling)\n      (let ((baker (amb 1 2 3 4 5))\n            (cooper (amb 1 2 3 4 5))\n            (fletcher (amb 1 2 3 4 5))\n            (miller (amb 1 2 3 4 5))\n            (smith (amb 1 2 3 4 5)))\n        (require (> miller cooper))\n        (require (not (= cooper 1)))\n        (require (not (= fletcher 1)))\n        (require (not (= (abs (- smith fletcher)) 1)))\n        (require (not (= (abs (- fletcher cooper)) 1)))\n        (require (not (= fletcher 5)))\n        (require (not (= baker 5)))\n        (require\n          (distinct? (list baker cooper fletcher miller smith)))\n        (list (list 'baker baker)\n              (list 'cooper cooper)\n              (list 'fletcher fletcher)\n              (list 'miller miller)\n              (list 'smith smith))))))\n\n(define (time-procedure name)\n  (define (times n proc)\n    (if (= n 0)\n        'done\n        (begin (proc)\n               (times (- n 1) proc))))\n  (printf \"~a: \" name)\n  (time\n    (times 100\n           (lambda ()\n             (ambeval (list name)\n                      solution-environment\n                      (lambda (val fail) 'ok)\n                      (lambda () 'ok))))))\n\n; The rest of the interpreter.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list 'not not)\n        (list 'abs abs)\n        (list 'member member)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n\n(define solution-environment\n  ((lambda ()\n     (define environment (setup-environment))\n     (for-each (lambda (definition)\n                 (ambeval definition\n                          environment\n                          (lambda (value fail) 'ok)\n                          (lambda () 'ok)))\n               solution)\n     environment)))\n\n(time-procedure 'slow-multiple-dwelling)\n(time-procedure 'fast-multiple-dwelling)\n"
  },
  {
    "path": "scheme/sicp/04/40.scm",
    "content": "; SICP exercise 4.40\n;\n; In the multiple dwelling problem, how many sets of assignments are there of\n; people to floors, both before and after the requirement that floor\n; assignments be distinct? It is very inefficient to generate all possible\n; assignments of people to floors and then leave it to backtracking to\n; eliminate them. For example, most of the restrictions depend on only one or\n; two of the person-floor variables, and can thus be imposed before floors\n; have been selected for all the people. Write and demonstrate a much more\n; efficient nondeterministic procedure that solves this problem based upon\n; generating only those possibilities that are not already ruled out by\n; previous restrictions. (Hint: This will require a nest of let expressions).\n\n(require r5rs/init)\n\n; In the first case, there are 5⁵ lists passed to distinct?, which is\n; incredibly slow.\n;\n; Below you will find a faster version when. The comparison is:\n;\n;   slow-multiple-dwelling: cpu time: 1226 real time: 1241 gc time: 59\n;   fast-multiple-dwelling: cpu time: 40 real time: 40 gc time: 2\n;\n; ...which is way better than the previous exercise.\n\n(define solution\n  '((define (distinct? items)\n      (cond ((null? items) true)\n            ((null? (cdr items)) true)\n            ((member (car items) (cdr items)) false)\n            (else (distinct? (cdr items)))))\n    (define (fast-multiple-dwelling)\n      (let ((cooper (amb 1 2 3 4 5)))\n        (require (not (= cooper 1)))\n        (let ((miller (amb 1 2 3 4 5)))\n          (require (> miller cooper))\n          (let ((fletcher (amb 1 2 3 4 5)))\n            (require (not (= fletcher 1)))\n            (require (not (= fletcher 1)))\n            (require (not (= (abs (- fletcher cooper)) 1)))\n            (let ((smith (amb 1 2 3 4 5)))\n              (require (not (= (abs (- smith fletcher)) 1)))\n              (let ((baker (amb 1 2 3 4 5)))\n                (require (not (= baker 5)))\n                (require (distinct? (list baker cooper fletcher miller smith)))\n                (list (list 'baker baker)\n                      (list 'cooper cooper)\n                      (list 'fletcher fletcher)\n                      (list 'miller miller)\n                      (list 'smith smith))))))))\n    (define (slow-multiple-dwelling)\n      (let ((baker (amb 1 2 3 4 5))\n            (cooper (amb 1 2 3 4 5))\n            (fletcher (amb 1 2 3 4 5))\n            (miller (amb 1 2 3 4 5))\n            (smith (amb 1 2 3 4 5)))\n        (require\n          (distinct? (list baker cooper fletcher miller smith)))\n        (require (not (= baker 5)))\n        (require (not (= cooper 1)))\n        (require (not (= fletcher 5)))\n        (require (not (= fletcher 1)))\n        (require (> miller cooper))\n        (require (not (= (abs (- smith fletcher)) 1)))\n        (require (not (= (abs (- fletcher cooper)) 1)))\n        (list (list 'baker baker)\n              (list 'cooper cooper)\n              (list 'fletcher fletcher)\n              (list 'miller miller)\n              (list 'smith smith))))))\n\n(define (time-procedure name)\n  (define (times n proc)\n    (if (= n 0)\n        'done\n        (begin (proc)\n               (times (- n 1) proc))))\n  (printf \"~a: \" name)\n  (time\n    (times 100\n           (lambda ()\n             (ambeval (list name)\n                      solution-environment\n                      (lambda (val fail) 'ok)\n                      (lambda () 'ok))))))\n\n\n; The rest of the interpreter.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list 'not not)\n        (list 'abs abs)\n        (list 'member member)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n\n(define solution-environment\n  ((lambda ()\n     (define environment (setup-environment))\n     (for-each (lambda (definition)\n                 (ambeval definition\n                          environment\n                          (lambda (value fail) 'ok)\n                          (lambda () 'ok)))\n               solution)\n     environment)))\n\n(time-procedure 'slow-multiple-dwelling)\n(time-procedure 'fast-multiple-dwelling)\n"
  },
  {
    "path": "scheme/sicp/04/41.scm",
    "content": "; SICP exercise 4.41\n;\n; Write an ordinary Scheme program to solve the multiple dwelling puzzle.\n\n; Wow, really? OK!\n\n(define (multiple-dwellings)\n  (define (solution? baker cooper fletcher miller smith)\n    (and (not (= baker 5))\n         (not (= cooper 1))\n         (not (= fletcher 5))\n         (not (= fletcher 1))\n         (> miller cooper)\n         (not (= (abs (- smith fletcher)) 1))\n         (not (= (abs (- fletcher cooper)) 1))))\n  (define (combine-lists a b)\n    (if (null? a)\n        '()\n        (cons (list (car a) (car b))\n              (combine-lists (cdr a) (cdr b)))))\n  (map (lambda (floors) (combine-lists '(baker cooper fletcher miller smith) floors))\n       (filter (lambda (floors) (apply solution? floors))\n               (permute 5))))\n\n(define (permute n)\n  (define (insert-into n items)\n    (if (null? items)\n        (list (cons n '()))\n        (cons (cons n items)\n              (map (lambda (rest) (cons (car items) rest))\n                   (insert-into n (cdr items))))))\n  (if (= n 1)\n      '((1))\n      (flat-map (lambda (items) (insert-into n items))\n                (permute (- n 1)))))\n\n(define (flat-map proc items)\n  (if (null? items)\n      '()\n      (append (proc (car items))\n              (flat-map proc (cdr items)))))\n"
  },
  {
    "path": "scheme/sicp/04/42.scm",
    "content": "; SICP exercise 4.42\n;\n; Solve the following \"Liars\" puzzle (from Phillips 1934):\n;\n;   Five schoolgirls sat for an examination. Their parents - so they thought -\n;   showed an undue degree of interest in the result. They therefore agreed\n;   that, in writing home about the examination, each girl should make one\n;   true statement and one untrue one. The following are the relevant passages\n;   from their letters:\n;\n;    * Betty: Kitty was second in the examination. I was only third.\n;    * Ethel: You'll be glad to hear I was on top. Joan was second.\n;    * Joan: I was third, and poor old Ethel was bottom.\n;    * Kitty: I came out second. Mary was only fourth.\n;    * Mary: I was fourth. Top place was taked by Betty.\n;\n;   What in fact was the order in which the five girls were placed?\n\n(require r5rs/init)\n\n; The solution to the puzzle is:\n;\n;   ((betty 3) (ethel 5) (joan 2) (kitty 1) (mary 4))\n;\n; The code that discovers it is below.\n\n(define solution\n  '((define (distinct? items)\n      (cond ((null? items) true)\n            ((null? (cdr items)) true)\n            ((member (car items) (cdr items)) false)\n            (else (distinct? (cdr items)))))\n    (define (xor a b)\n      (if a (not b) b))\n    (define (lairs)\n      (let ((betty (amb 1 2 3 4 5))\n            (ethel (amb 1 2 3 4 5))\n            (joan (amb 1 2 3 4 5))\n            (kitty (amb 1 2 3 4 5))\n            (mary (amb 1 2 3 4 5)))\n        (require (xor (= kitty 2) (= betty 3)))\n        (require (xor (= ethel 1) (= joan 2)))\n        (require (xor (= joan 3) (= ethel 5)))\n        (require (xor (= kitty 2) (= mary 4)))\n        (require (xor (= mary 4) (= betty 1)))\n        (require (distinct? (list betty ethel joan kitty mary)))\n        (list (list 'betty betty)\n              (list 'ethel ethel)\n              (list 'joan joan)\n              (list 'kitty kitty)\n              (list 'mary mary))))))\n\n; The rest of the interpreter.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list 'not not)\n        (list 'abs abs)\n        (list 'member member)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n\n(define solution-environment\n  ((lambda ()\n     (define environment (setup-environment))\n     (for-each (lambda (definition)\n                 (ambeval definition\n                          environment\n                          (lambda (value fail) 'ok)\n                          (lambda () 'ok)))\n               solution)\n     environment)))\n"
  },
  {
    "path": "scheme/sicp/04/43.scm",
    "content": "; SICP exercise 4.43\n;\n; Use the amb evaluator to solve the following puzzle:\n;\n;   Mary Ann Moore's father has a yacht and so has each of his four friends.\n;   Colonel Downing, Mr. Hall, Sir Barnacle Hood, and Dr. Parker. Each of the\n;   five also has one daughter and each has named his yacht after a daughter\n;   of one of the others. Sir Barnacle's yacht is the Gabrielle, Mr. Moore\n;   owns the Lorna; Mr. Hall the Rosalind. The Melissa, owned by Colonel\n;   Downing, is named after Sir Barnacle's daughter. Gabrielle's father owns\n;   the yacht that is named after Dr. Parker's daughter. Who is Lorna's\n;   father?\n;\n; Try to write the program so that it runs efficiently (see exercise 4.40).\n; Also determine how many solutions are there if we are not told that Mary\n; Ann's last name is Moore.\n\n(require r5rs/init)\n\n; The solution to the puzzle is Colonel Downing.\n;\n; If we omit the fact that Mary Ann's last name is Moore, then there would be\n; two solutions, the second of which is Dr. Parker.\n\n(define solution\n  '((define (map proc items)\n      (if (null? items)\n          '()\n          (cons (proc (car items))\n                (map proc (cdr items)))))\n    (define (distinct? items)\n      (cond ((null? items) true)\n            ((null? (cdr items)) true)\n            ((member (car items) (cdr items)) false)\n            (else (distinct? (cdr items)))))\n    (define (xor a b)\n      (if a (not b) b))\n    (define (yachts-and-daughters mary-ann-is-moore)\n      (define (names) (amb 'gabrielle 'lorna 'rosalind 'mary-ann 'melissa))\n      (define (daughter pair) (car pair))\n      (define (yacht pair) (car (cdr pair)))\n      (define (father-of girl fathers)\n        (cond ((null? fathers) (error))\n              ((eq? (daughter (car fathers)) girl) (car fathers))\n              (else (father-of girl (cdr fathers)))))\n      (define (daughter-and-yacht)\n        (let ((daughter (names))\n              (yacht (names)))\n          (require (not (eq? daughter yacht)))\n          (list daughter yacht)))\n      (define (name-of-father daughter results)\n        (if (eq? (car (cdr (car results))) daughter)\n            (car (car results))\n            (name-of-father daughter (cdr results))))\n      (let ((moore (daughter-and-yacht)))\n        (if mary-ann-is-moore\n            (require (eq? (daughter moore) 'mary-ann))\n            'ok)\n        (require (eq? (yacht moore) 'lorna))\n        (let ((barnacle (daughter-and-yacht)))\n          (require (eq? (yacht barnacle) 'gabrielle))\n          (require (eq? (daughter barnacle) 'melissa))\n          (let ((hall (daughter-and-yacht)))\n            (require (eq? (yacht hall) 'rosalind))\n            (let ((downing (daughter-and-yacht)))\n              (require (eq? (yacht downing) 'melissa))\n              (let ((parker (daughter-and-yacht)))\n                (let ((fathers (list moore barnacle hall downing parker)))\n                  (require (distinct? (map yacht fathers)))\n                  (require (distinct? (map daughter fathers)))\n                  (require (eq? (daughter parker)\n                                (yacht (father-of 'gabrielle fathers))))\n                  (name-of-father 'lorna\n                                  (list (cons 'moore moore)\n                                        (cons 'barnacle barnacle)\n                                        (cons 'hall hall)\n                                        (cons 'downing downing)\n                                        (cons 'parker parker))))))))))\n    ))\n\n; The rest of the interpreter.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'eq? eq?)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list 'not not)\n        (list 'abs abs)\n        (list 'member member)\n        (list 'display display)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n\n(define solution-environment\n  ((lambda ()\n     (define environment (setup-environment))\n     (for-each (lambda (definition)\n                 (ambeval definition\n                          environment\n                          (lambda (value fail) 'ok)\n                          (lambda () 'ok)))\n               solution)\n     environment)))\n"
  },
  {
    "path": "scheme/sicp/04/44.scm",
    "content": "; SICP exercise 4.44\n;\n; Exercise 2.42 described the \"eight-queens puzzle\" of placing queens on a\n; chessboard so that no two attack each other. Write a nondeterministic\n; program to solve this puzzle.\n\n(require r5rs/init)\n\n; The solution is simpler than the one in exercise 2.42. First, it does not\n; have awkward requirements on representing queen positions. Second, the\n; algorithm does not require map-ing, flatmap-ing and filtering like crazy.\n\n(define solution\n  '((define (map proc items)\n      (if (null? items)\n          '()\n          (cons (proc (car items))\n                (map proc (cdr items)))))\n    (define (all? proc items)\n      (cond ((null? items) true)\n            ((proc (car items)) (all? proc (cdr items)))\n            (else false)))\n    (define (an-integer-between low high)\n      (if (> low high)\n        (amb)\n        (amb low (an-integer-between (+ low 1) high))))\n    (define (queens board-size)\n      (define (safe? position other-queens)\n        (let ((q1r (car position))\n              (q1f (cadr position)))\n          (all?\n            (lambda (queen)\n              (let ((q2r (car queen))\n                    (q2f (cadr queen)))\n                (cond ((= q1r q2r) false)\n                      ((= q1f q2f) false)\n                      ((= (+ q1r q1f) (+ q2r q2f)) false)\n                      ((= (- q1r q1f) (- q2r q2f)) false)\n                      (else true))))\n            other-queens)))\n      (define (place-queens rank queens)\n        (if (> rank board-size)\n            (reverse (map cadr queens))\n            (let ((file (an-integer-between 1 board-size)))\n              (let ((position (list rank file)))\n                (require (safe? position queens))\n              (place-queens (+ rank 1) (cons position queens))))))\n      (place-queens 1 '()))\n    ))\n\n; The rest of the interpreter.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cadr cadr)\n        (list 'cons cons)\n        (list 'eq? eq?)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list 'not not)\n        (list 'abs abs)\n        (list 'member member)\n        (list 'reverse reverse)\n        (list 'display display)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n\n(define solution-environment\n  ((lambda ()\n     (define environment (setup-environment))\n     (for-each (lambda (definition)\n                 (ambeval definition\n                          environment\n                          (lambda (value fail) 'ok)\n                          (lambda () 'ok)))\n               solution)\n     environment)))\n"
  },
  {
    "path": "scheme/sicp/04/45.scm",
    "content": "; SICP exercise 4.45\n;\n; With the grammar give above, the following sentence can be parsed in five\n; different ways: \"The professor lectures to the student in the class with the\n; cat\". Give the five parses and explain the differences in shades of meaning\n; among them.\n\n(require r5rs/init)\n\n; The possible meanings are:\n;\n; (sentence\n;   (simple-noun-phrase (article the) (noun professor))\n;   (verb-phrase\n;     (verb-phrase\n;       (verb-phrase\n;         (verb lectures)\n;         (prep-phrase\n;           (prep to)\n;           (simple-noun-phrase (article the) (noun student))))\n;       (prep-phrase\n;         (prep in)\n;         (simple-noun-phrase (article the) (noun class))))\n;     (prep-phrase\n;       (prep with)\n;       (simple-noun-phrase (article the) (noun cat)))))\n;\n; The profer is lecuring in a class using a cat to a student that is in the class.\n;\n; (sentence\n;   (simple-noun-phrase (article the) (noun professor))\n;   (verb-phrase\n;     (verb-phrase\n;       (verb lectures)\n;       (prep-phrase\n;         (prep to)\n;         (simple-noun-phrase (article the) (noun student))))\n;     (prep-phrase\n;       (prep in)\n;       (noun-phrase\n;         (simple-noun-phrase (article the) (noun class))\n;         (prep-phrase\n;           (prep with)\n;           (simple-noun-phrase (article the) (noun cat)))))))\n;\n; The professor is lecturing a student, which being in a class that has a cat.\n;\n; (sentence\n;   (simple-noun-phrase (article the) (noun professor))\n;   (verb-phrase\n;     (verb-phrase\n;       (verb lectures)\n;       (prep-phrase\n;         (prep to)\n;         (noun-phrase\n;           (simple-noun-phrase (article the) (noun student))\n;           (prep-phrase\n;             (prep in)\n;             (simple-noun-phrase (article the) (noun class))))))\n;     (prep-phrase\n;       (prep with)\n;       (simple-noun-phrase (article the) (noun cat)))))\n;\n; The professor is using a lact to lecture a student that is in the class.\n;\n; (sentence\n;   (simple-noun-phrase (article the) (noun professor))\n;   (verb-phrase\n;     (verb lectures)\n;     (prep-phrase\n;       (prep to)\n;       (noun-phrase\n;         (noun-phrase\n;           (simple-noun-phrase (article the) (noun student))\n;           (prep-phrase\n;             (prep in)\n;             (simple-noun-phrase (article the) (noun class))))\n;         (prep-phrase\n;           (prep with)\n;           (simple-noun-phrase (article the) (noun cat)))))))\n;\n; There is a student in the class that has a cat, that is being lectured by\n; the professor.\n;\n; (sentence\n;   (simple-noun-phrase (article the) (noun professor))\n;   (verb-phrase\n;     (verb lectures)\n;     (prep-phrase\n;       (prep to)\n;       (noun-phrase\n;         (simple-noun-phrase (article the) (noun student))\n;         (prep-phrase\n;           (prep in)\n;           (noun-phrase\n;             (simple-noun-phrase (article the) (noun class))\n;             (prep-phrase\n;               (prep with)\n;               (simple-noun-phrase (article the) (noun cat)))))))))))\n;\n; In the class with the cat, there is a student, that is being lectured by the\n; professor.\n\n(define solution\n  '((define nouns '(noun student professor cat class))\n    (define verbs '(verb studies lectures eats sleeps))\n    (define articles '(article the a))\n    (define prepositions '(prep for to in by with))\n\n    (define (parse-sentence)\n      (list 'sentence\n            (parse-noun-phrase)\n            (parse-verb-phrase)))\n\n    (define (parse-noun-phrase)\n      (define (maybe-extend noun-phrase)\n        (amb noun-phrase\n             (maybe-extend (list 'noun-phrase\n                                 noun-phrase\n                                 (parse-prepositional-phrase)))))\n      (maybe-extend (parse-simple-noun-phrase)))\n\n    (define (parse-simple-noun-phrase)\n      (list 'simple-noun-phrase\n            (parse-word articles)\n            (parse-word nouns)))\n\n    (define (parse-verb-phrase)\n      (define (maybe-extend verb-phrase)\n        (amb verb-phrase\n             (maybe-extend (list 'verb-phrase\n                                 verb-phrase\n                                 (parse-prepositional-phrase)))))\n      (maybe-extend (parse-word verbs)))\n\n    (define (parse-prepositional-phrase)\n      (list 'prep-phrase\n            (parse-word prepositions)\n            (parse-noun-phrase)))\n\n    (define (parse-word word-list)\n      (require (not (null? *unparsed*)))\n      (require (memq (car *unparsed*) (cdr word-list)))\n      (let ((found-word (car *unparsed*)))\n        (set! *unparsed* (cdr *unparsed*))\n        (list (car word-list) found-word)))\n\n    (define *unparsed* '())\n    (define (parse input)\n      (set! *unparsed* input)\n      (let ((sent (parse-sentence)))\n        (require (null? *unparsed*))\n        sent))\n    ))\n\n; The rest of the interpreter.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cadr cadr)\n        (list 'cons cons)\n        (list 'eq? eq?)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list 'not not)\n        (list 'abs abs)\n        (list 'member member)\n        (list 'memq memq)\n        (list 'reverse reverse)\n        (list 'display display)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n\n(define solution-environment\n  ((lambda ()\n     (define environment (setup-environment))\n     (for-each (lambda (definition)\n                 (ambeval definition\n                          environment\n                          (lambda (value fail) 'ok)\n                          (lambda () 'ok)))\n               solution)\n     environment)))\n"
  },
  {
    "path": "scheme/sicp/04/46.scm",
    "content": "; SICP exercise 4.46\n;\n; The evaluators in section 4.1 and 4.2 do not determine what order operands\n; are evaluated in. We will see that the amb evaluator evaluates them from\n; left to right. Explain why our parsing program wouldn't work if the operands\n; are evaluated in some other order.\n\n; Well, that's painstakingly straightforward.\n;\n; Given the initial parse-noun-phrase definition:\n;\n; (define (parse-noun-phrase)\n;   (list 'noun-phrase\n;         (parse-word articles)\n;         (parse-word nouns)))\n;\n; When we evaluate right to left instead of left to right, (parse-word nouns)\n; would consume input before (parse-word articles), changing the meaning of\n; (parse-noun-phrase) as if those two were reversed in the left to right\n; evaluator.\n"
  },
  {
    "path": "scheme/sicp/04/47.scm",
    "content": "; SICP exercise 4.47\n;\n; Louis Reasoner suggests that, since a verb phrase is either a verb or a verb\n; phrase followed by a prepositional phrase, it would be much more\n; straightforward to define the procedure parse-verb-phrase as follows (and\n; similarly for noun phrases):\n;\n;   (define (parse-verb-phrase)\n;     (amb (parse-word verbs)\n;          (list 'verb-phrase\n;                (parse-verb-phrase)\n;                (parse-prepositional-phrase))))\n;\n; Does this work? Does the program's behavior change if we interchange the\n; order of expressions in amb?\n\n; It does not work. The problem is apparent when we rearrange the statements.\n; parse-verb-phrase falls into an infinite recurssion.\n;\n; When the expressions in amb are in the order Louis' suggets, it might\n; produce a result if (parse-word verbs) matches anything, but calling\n; try-again will get it stuck in the other infinite recursion branch. That\n; might also produce a result, but eventually, trying to exhaust all\n; posibilities will be stuck in that recursion.\n"
  },
  {
    "path": "scheme/sicp/04/48.scm",
    "content": "; SICP exercise 4.48\n;\n; Extend the grammar given above to handle more complex sentences. For\n; example, you could extend noun phrases and verb phrases to include\n; adjectives and adverbs, or you could handle compound sentences.\n\n(require r5rs/init)\n\n; Since this isn't very interesting, we only introducing adjectives and\n; adverbs. A noun phrase is [article adjective* noun] and a verb phrase\n; becomes [verb preposition-phrase* adverb?].\n\n(define solution\n  '((define nouns '(noun student professor cat class))\n    (define verbs '(verb studies lectures eats sleeps))\n    (define adjectives '(adjective brown fast quick sharp))\n    (define adverbs '(adverb solemnly quietly loudly silently))\n    (define articles '(article the a))\n    (define prepositions '(prep for to in by with))\n\n    (define (parse-sentence)\n      (list 'sentence\n            (parse-noun-phrase)\n            (parse-verb-phrase)))\n\n    (define (parse-noun-phrase)\n      (define (maybe-extend noun-phrase)\n        (amb noun-phrase\n             (maybe-extend (list 'noun-phrase\n                                 noun-phrase\n                                 (parse-prepositional-phrase)))))\n      (maybe-extend (parse-simple-noun-phrase)))\n\n    (define (parse-simple-noun-phrase)\n      (list 'simple-noun-phrase\n            (parse-word articles)\n            (optional-list-of 'adjective-list parse-adjective)\n            (parse-word nouns)))\n\n    (define (parse-verb-phrase)\n      (define (maybe-extend verb-phrase)\n        (amb verb-phrase\n             (list 'verb-phrase verb-phrase (parse-adverb))\n             (maybe-extend (list 'verb-phrase\n                                 verb-phrase\n                                 (parse-prepositional-phrase)))))\n      (maybe-extend (parse-word verbs)))\n\n    (define (parse-prepositional-phrase)\n      (list 'prep-phrase\n            (parse-word prepositions)\n            (parse-noun-phrase)))\n\n    (define (parse-adverb)\n      (parse-word adverbs))\n    (define (parse-adjective)\n      (parse-word adjectives))\n\n    (define (optional-list-of name parse-function)\n      (amb (list name)\n           (cons name\n                 (cons (parse-function)\n                       (cdr (optional-list-of name parse-function))))))\n\n    (define (parse-word word-list)\n      (require (not (null? *unparsed*)))\n      (require (memq (car *unparsed*) (cdr word-list)))\n      (let ((found-word (car *unparsed*)))\n        (set! *unparsed* (cdr *unparsed*))\n        (list (car word-list) found-word)))\n\n    (define *unparsed* '())\n    (define (parse input)\n      (set! *unparsed* input)\n      (let ((sent (parse-sentence)))\n        (require (null? *unparsed*))\n        sent))\n    ))\n\n; The rest of the interpreter.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cadr cadr)\n        (list 'cons cons)\n        (list 'eq? eq?)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list 'not not)\n        (list 'abs abs)\n        (list 'member member)\n        (list 'memq memq)\n        (list 'reverse reverse)\n        (list 'display display)\n        (list 'append append)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n\n(define solution-environment\n  ((lambda ()\n     (define environment (setup-environment))\n     (for-each (lambda (definition)\n                 (ambeval definition\n                          environment\n                          (lambda (value fail) 'ok)\n                          (lambda () 'ok)))\n               solution)\n     environment)))\n"
  },
  {
    "path": "scheme/sicp/04/49.scm",
    "content": "; SICP exercise 4.49\n;\n; Alyssa P. Hacker is more interested in generating interesting sentences than\n; in parsing them. She reasons that by simply changing the procedure\n; parse-word so that it ignores the \"input sentence\" and instead always\n; succeeds and generates an appropriate word, we can use the programs we had\n; built for parsing to do generation instead. Implement Alyssa's idea, and\n; show the first half-dozen or so sentences generated.\n\n(require r5rs/init)\n\n; The modification is below. There is an additional procedure terminals that\n; extracts the terminal symbols of the parsed sentence to form a list that\n; looks like a sentence. Here are the first half-dozen sentences:\n;\n; (the student studies)\n; (the student studies for the student)\n; (the student studies for the student for the student)\n; (the student studies for the student for the student for the student)\n; (the student studies for the student for the student for the student for the student)\n; (the student studies for the student for the student for the student for the student for the student)\n;\n; Obviously, there are not very useful, even if they are \"gramatically\n; correct\" for some definition of the term.\n\n(define solution\n  '((define nouns '(noun student professor cat class))\n    (define verbs '(verb studies lectures eats sleeps))\n    (define articles '(article the a))\n    (define prepositions '(prep for to in by with))\n\n    (define (parse-sentence)\n      (list 'sentence\n            (parse-noun-phrase)\n            (parse-verb-phrase)))\n\n    (define (parse-noun-phrase)\n      (define (maybe-extend noun-phrase)\n        (amb noun-phrase\n             (maybe-extend (list 'noun-phrase\n                                 noun-phrase\n                                 (parse-prepositional-phrase)))))\n      (maybe-extend (parse-simple-noun-phrase)))\n\n    (define (parse-simple-noun-phrase)\n      (list 'simple-noun-phrase\n            (parse-word articles)\n            (parse-word nouns)))\n\n    (define (parse-verb-phrase)\n      (define (maybe-extend verb-phrase)\n        (amb verb-phrase\n             (maybe-extend (list 'verb-phrase\n                                 verb-phrase\n                                 (parse-prepositional-phrase)))))\n      (maybe-extend (parse-word verbs)))\n\n    (define (parse-prepositional-phrase)\n      (list 'prep-phrase\n            (parse-word prepositions)\n            (parse-noun-phrase)))\n\n    (define (parse-word word-list)\n      (if (null? (cdr word-list))\n          (amb)\n          (amb (list (car word-list) (cadr word-list))\n               (parse-word (cons (car word-list) (cddr word-list))))))\n\n    (define (generate-sentence)\n      (parse-sentence))\n\n    (define (terminals sentence)\n      (cond ((null? sentence) '())\n            ((pair? (car sentence)) (append (terminals (car sentence))\n                                            (terminals (cdr sentence))))\n            ((memq (car sentence) '(noun verb article prep)) (list (cadr sentence)))\n            (else (terminals (cdr sentence)))))\n\n    ))\n\n; The rest of the interpreter.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cadr cadr)\n        (list 'cons cons)\n        (list 'eq? eq?)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list 'not not)\n        (list 'abs abs)\n        (list 'member member)\n        (list 'append append)\n        (list 'memq memq)\n        (list 'reverse reverse)\n        (list 'display display)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n\n(define solution-environment\n  ((lambda ()\n     (define environment (setup-environment))\n     (for-each (lambda (definition)\n                 (ambeval definition\n                          environment\n                          (lambda (value fail) 'ok)\n                          (lambda () 'ok)))\n               solution)\n     environment)))\n"
  },
  {
    "path": "scheme/sicp/04/50.scm",
    "content": "; SICP exercise 4.50\n;\n; Implement a new special form ramb that is like amb except that it searches\n; alternatives in a random order, rather than from left to right. Show how\n; this can help with Alyssa's problem in exercise 4.49.\n\n(require r5rs/init)\n\n; Just run this file to get an output.\n\n(define solution\n  '((define nouns '(noun student professor cat class))\n    (define verbs '(verb studies lectures eats sleeps))\n    (define articles '(article the a))\n    (define prepositions '(prep for to in by with))\n\n    (define (parse-sentence)\n      (list 'sentence\n            (parse-noun-phrase)\n            (parse-verb-phrase)))\n\n    (define (parse-noun-phrase)\n      (define (maybe-extend noun-phrase)\n        (ramb noun-phrase\n             (maybe-extend (list 'noun-phrase\n                                 noun-phrase\n                                 (parse-prepositional-phrase)))))\n      (maybe-extend (parse-simple-noun-phrase)))\n\n    (define (parse-simple-noun-phrase)\n      (list 'simple-noun-phrase\n            (parse-word articles)\n            (parse-word nouns)))\n\n    (define (parse-verb-phrase)\n      (define (maybe-extend verb-phrase)\n        (ramb verb-phrase\n             (maybe-extend (list 'verb-phrase\n                                 verb-phrase\n                                 (parse-prepositional-phrase)))))\n      (maybe-extend (parse-word verbs)))\n\n    (define (parse-prepositional-phrase)\n      (list 'prep-phrase\n            (parse-word prepositions)\n            (parse-noun-phrase)))\n\n    (define (parse-word word-list)\n      (if (null? (cdr word-list))\n          (ramb)\n          (ramb (list (car word-list) (cadr word-list))\n                (parse-word (cons (car word-list) (cddr word-list))))))\n\n    (define (generate-sentence)\n      (parse-sentence))\n\n    (define (terminals sentence)\n      (cond ((null? sentence) '())\n            ((pair? (car sentence)) (append (terminals (car sentence))\n                                            (terminals (cdr sentence))))\n            ((memq (car sentence) '(noun verb article prep)) (list (cadr sentence)))\n            (else (terminals (cdr sentence)))))\n\n    ))\n\n; The rest of the interpreter.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((ramb? exp) (analyze-ramb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (randomize items)\n  (define (remove-item item items)\n    (if (eq? item (car items))\n        (cdr items)\n        (cons (car items) (remove-item item (cdr items)))))\n\n  (define (list-item n items)\n    (if (= n 0)\n        (car items)\n        (list-item (- n 1) (cdr items))))\n\n  (if (null? items)\n      '()\n      (let ((item (list-item (random (length items)) items)))\n        (cons item\n              (randomize (remove-item item items))))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (analyze-ramb exp)\n  (let ((cprocs (map analyze (ramb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next (randomize cprocs)))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (ramb? exp) (tagged-list? exp 'ramb))\n(define (ramb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cadr cadr)\n        (list 'cddr cddr)\n        (list 'cons cons)\n        (list 'eq? eq?)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list 'not not)\n        (list 'abs abs)\n        (list 'member member)\n        (list 'append append)\n        (list 'memq memq)\n        (list 'reverse reverse)\n        (list 'display display)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n\n(define solution-environment\n  ((lambda ()\n     (define environment (setup-environment))\n     (for-each (lambda (definition)\n                 (ambeval definition\n                          environment\n                          (lambda (value fail) 'ok)\n                          (lambda () 'ok)))\n               solution)\n     environment)))\n\n(define (a-value-of exp)\n  (ambeval exp\n           solution-environment\n           (lambda (value fail) value)\n           (lambda () '())))\n\n(display (a-value-of '(terminals (generate-sentence))))\n(newline)\n"
  },
  {
    "path": "scheme/sicp/04/51.scm",
    "content": "; SICP exercise 4.51\n;\n; Implement a new kind of assignment called permanent-set! that is not undone\n; upon failure. For example, we can choose two distinct elements from a list\n; and count the number of trials required to make a successful choice as\n; follows:\n;\n;   (define count 0)\n;   (let ((x (an-element-of '(a b c)))\n;         (y (an-element-of '(a b c))))\n;     (permanent-set! count (+ count 1))\n;     (require (not (eq? x y)))\n;     (list x y count))\n;\n;   ;;; Starting a new problem\n;   ;;; Amb-Eval value:\n;   (a b 2)\n;   ;;; Amb-Eval input\n;   try-again\n;   ;;; Amb-Eval value\n;   (a c 3)\n;\n; What values would have been displayed if we had used set! here rather than\n; permanent-set! ?\n\n(require r5rs/init)\n\n; The implementation is below.\n;\n; The values would be (a b 1), (a c 1) and so on...\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((permantent-assignment? exp) (analyze-permanent-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-permanent-assignment exp)\n  (let ((var (permantent-assignment-variable exp))\n        (vproc (analyze (permantent-assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (set-variable-value! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (permantent-assignment? exp) (tagged-list? exp 'permanent-set!))\n(define (permantent-assignment-variable exp) (cadr exp))\n(define (permantent-assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'eq? eq?)\n        (list 'list list)\n        (list 'not not)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/52.scm",
    "content": "; SICP exercise 4.52\n;\n; Implement a new construct called if-fail that permits the user to catch the\n; failure of an expression. If-fail takes two expressions. It evaluates the\n; first expression as usual and returns as usual if the evaluation succeeds.\n; If the evaluation fails, however, the value of the second expression is\n; returned, as in the following example:\n;\n; (if-fail (let ((x (an-element-of '(1 3 5))))\n;            (require (even? x))\n;            x)\n;          'all-odd)\n; ;;; Starting a new problem\n; ;;; Amb-Eval value:\n; all-odd\n; ;;; Amb-Eval input:\n; (if-fail (let ((x (an-element-of '(1 3 5 8))))\n;            (require (even? x))\n;            x)\n;          'all-odd)\n; ;;; Starting a new problem\n; ;;; Amb-Eval value:\n; 8\n\n(require r5rs/init)\n\n; The implementation is below.\n;\n; I'm basing this on the previous exercise, because we are going to need both\n; fail-if and permanent-set! in the next one.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((permantent-assignment? exp) (analyze-permanent-assignment exp))\n        ((if-fail? exp) (analyze-if-fail exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-permanent-assignment exp)\n  (let ((var (permantent-assignment-variable exp))\n        (vproc (analyze (permantent-assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (set-variable-value! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (analyze-if-fail exp)\n  (let ((eproc (analyze (if-fail-body exp)))\n        (fproc (analyze (if-fail-failure-callback exp))))\n    (lambda (env succeed fail)\n      (eproc env\n             succeed\n             (lambda () (fproc env succeed fail))))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (permantent-assignment? exp) (tagged-list? exp 'permanent-set!))\n(define (permantent-assignment-variable exp) (cadr exp))\n(define (permantent-assignment-value exp) (caddr exp))\n\n(define (if-fail? exp) (tagged-list? exp 'if-fail))\n(define (if-fail-body exp) (cadr exp))\n(define (if-fail-failure-callback exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'even? even?)\n        (list 'eq? eq?)\n        (list 'list list)\n        (list 'not not)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/53.scm",
    "content": "; SICP exercise 4.53\n;\n; With permanent-set! as described in exercise 4.51 and if-fail as in exercise\n; 4.52, what will be the result of evaluating\n;\n;   (let ((pairs '()))\n;     (if-fail (let ((p (prime-sum-pair '(1 3 5 8) '(20 35 110))))\n;                (permanent-set! pairs (cons p pairs))\n;                (amb))\n;              pairs))\n\n(require r5rs/init)\n\n; The result will be:\n;\n;   ((8 35) (3 110) (3 20)))\n;\n; We're essentially using backtracking as part of backtracking, which is\n; fancy.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((permantent-assignment? exp) (analyze-permanent-assignment exp))\n        ((if-fail? exp) (analyze-if-fail exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-permanent-assignment exp)\n  (let ((var (permantent-assignment-variable exp))\n        (vproc (analyze (permantent-assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (set-variable-value! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (analyze-if-fail exp)\n  (let ((eproc (analyze (if-fail-body exp)))\n        (fproc (analyze (if-fail-failure-callback exp))))\n    (lambda (env succeed fail)\n      (eproc env\n             succeed\n             (lambda () (fproc env succeed fail))))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (permantent-assignment? exp) (tagged-list? exp 'permanent-set!))\n(define (permantent-assignment-variable exp) (cadr exp))\n(define (permantent-assignment-value exp) (caddr exp))\n\n(define (if-fail? exp) (tagged-list? exp 'if-fail))\n(define (if-fail-body exp) (cadr exp))\n(define (if-fail-failure-callback exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'even? even?)\n        (list 'eq? eq?)\n        (list 'list list)\n        (list 'not not)\n        (list 'remainder remainder)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))\n    (define (prime? n)\n      (= n (smallest-divisor n)))\n\n    (define (smallest-divisor n)\n      (find-divisor n 2))\n\n    (define (find-divisor n test-divisor)\n      (cond ((> (square test-divisor) n) n)\n            ((divides? test-divisor n) test-divisor)\n            (else (find-divisor n (+ test-divisor 1)))))\n\n    (define (square a)\n      (* a a))\n\n    (define (divides? a b)\n      (= (remainder b a) 0))))\n\n(define (divides? a b)\n  (= (remainder b a) 0))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/54.scm",
    "content": "; SICP exercise 4.54\n;\n; If we had not realized that require could be implemented as an ordinary\n; procedure that uses amb, to be defined by the user as part of a\n; nondeterministic program, we would have had to implement it as a special\n; form. This would require syntax procedures\n;\n;   (define (require? exp) (tagged-list? exp 'require))\n;   (define (require-predicate exp) (cadr exp))\n;\n; and a new clause in the dispatch in analyze\n;\n;   ((require? exp) (analyze-require exp))\n;\n; as well the procedure analyze-require that handles require expressions.\n; Complete the following definition of analyze-require.\n;\n;   (define (analyze-require exp)\n;     (let ((pproc (analyze (require-predicate exp))))\n;       (lambda (env succeed fail)\n;         (pproc env\n;                (lambda (value fail2)\n;                  (if <??>\n;                      <??>\n;                      (succeed 'ok fail2)))\n;                fail))))\n\n(require r5rs/init)\n\n; The full definition is:\n;\n;   (define (analyze-require exp)\n;     (let ((pproc (analyze (require-predicate exp))))\n;       (lambda (env succeed fail)\n;         (pproc env\n;                (lambda (value fail2)\n;                  (if (not (true? value))\n;                      (fail)\n;                      (succeed 'ok fail2)))\n;                fail))))\n;\n; The test case uses the code from the previous exercise.\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((require? exp) (analyze-require exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((permantent-assignment? exp) (analyze-permanent-assignment exp))\n        ((if-fail? exp) (analyze-if-fail exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((let? exp) (analyze (let->combination exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-permanent-assignment exp)\n  (let ((var (permantent-assignment-variable exp))\n        (vproc (analyze (permantent-assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (set-variable-value! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (analyze-require exp)\n  (let ((pproc (analyze (require-predicate exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (value fail2)\n               (if (not (true? value))\n                   (fail)\n                   (succeed 'ok fail2)))\n             fail))))\n\n(define (analyze-if-fail exp)\n  (let ((eproc (analyze (if-fail-body exp)))\n        (fproc (analyze (if-fail-failure-callback exp))))\n    (lambda (env succeed fail)\n      (eproc env\n             succeed\n             (lambda () (fproc env succeed fail))))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (require? exp) (tagged-list? exp 'require))\n(define (require-predicate exp) (cadr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (permantent-assignment? exp) (tagged-list? exp 'permanent-set!))\n(define (permantent-assignment-variable exp) (cadr exp))\n(define (permantent-assignment-value exp) (caddr exp))\n\n(define (if-fail? exp) (tagged-list? exp 'if-fail))\n(define (if-fail-body exp) (cadr exp))\n(define (if-fail-failure-callback exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'even? even?)\n        (list 'eq? eq?)\n        (list 'list list)\n        (list 'not not)\n        (list 'remainder remainder)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '> >)\n        (list '/ /)))\n\n(define definitions\n  '((define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))\n    (define (prime? n)\n      (= n (smallest-divisor n)))\n    (define (smallest-divisor n)\n      (find-divisor n 2))\n    (define (find-divisor n test-divisor)\n      (cond ((> (square test-divisor) n) n)\n            ((divides? test-divisor n) test-divisor)\n            (else (find-divisor n (+ test-divisor 1)))))\n    (define (square a)\n      (* a a))\n    (define (divides? a b)\n      (= (remainder b a) 0))))\n\n(define (divides? a b)\n  (= (remainder b a) 0))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/55.scm",
    "content": "; SICP exercise 4.55\n;\n; Give simple queries that retrieve the following information from the data\n; base:\n;\n; a. all people supervised by Ben Bitdiddle\n; b. the names and jobs of all people in the accounting division\n; c. the names and addresses of all people who live in Slumerville\n\n(define query-a '(supervisor ?person (Bitdiddle Ben)))\n(define query-b '(job ?person (accounting . ?rest)))\n(define query-c '(address ?person (Slumerville . ?rest)))\n"
  },
  {
    "path": "scheme/sicp/04/56.scm",
    "content": "; SICP exercise 4.56\n;\n; Formulate compound queries that retrieve the following information:\n;\n; a. the names of all people who are supervised by Ben Bitdiddle, together\n;    with their addresses\n; b. all people whose salary is less than Ben Bitdiddle's, together with their\n;    salary and Ben Bitdiddle's salary\n; c. all people who are supervised by someone who is not in the computer\n;    division, together with the supervisor's name and job\n\n(define query-a '(and (address ?person ?address)\n                      (supervisor ?person (Bitdiddle Ben))))\n(define query-b '(and (salary ?person ?person-salary)\n                      (salary (Bitdiddle Ben) ?bens-salary)\n                      (lisp-value < ?person-salary ?bens-salary)))\n(define query-c '(and (supervisor ?person ?supervisor)\n                      (not (job ?supervisor (computer . ?title)))))\n"
  },
  {
    "path": "scheme/sicp/04/57.scm",
    "content": "; SICP exercise 4.57\n;\n; Define a rule that says that person 1 can replace person 2 if either 1 does\n; the same job as person 2 or someone who does person 1's job can also do\n; person 2's job, and if person 1 and person 2 are not the same person. Using\n; your rule, give queries that find the following:\n;\n; a. all people who can replace Cy D Fect;\n; b. all people who can replace someone who is being paid more than they are,\n;    together with the two salaries\n\n(add-to-data-base!\n  '((rule (can-replace ?person-1 ?person-2)\n          (and (job ?person-1 ?job-1)\n               (job ?person-2 ?job-2)\n               (can-do-job ?job-1 ?job-2)))\n    (rule (can-replace ?person-1 ?person-2)\n          (and (can-do-job ?middle-man ?person-2)\n               (can-replace ?person-1 ?middle-man)))))\n\n(define query-a '(can-replace ?person-1 (Fect Cy D)))\n(define query-b '(and (can-replace ?person-1 ?person-2)\n                      (salary ?person-1 ?salary-1)\n                      (salary ?person-2 ?salary-2)\n                      (lisp-value < ?salary-1 ?salary-2)))\n"
  },
  {
    "path": "scheme/sicp/04/58.scm",
    "content": "; SICP exercise 4.58\n;\n; Define a rule that says that a person is a \"big shot\" in a division if the\n; person works in the division but does not have a supervisor who works in the\n; division.\n\n(add-to-data-base!\n  '((rule (big-shot ?person)\n          (and (job ?person (?division . ?person-title))\n               (not (and (supervisor ?person ?supervisor)\n                         (job ?supervisor (?division . ?supervisor-title))))))))\n"
  },
  {
    "path": "scheme/sicp/04/59.scm",
    "content": "; SICP exercise 4.59\n;\n; Ben Bitdiddle has missed on meeting too many. Fearing that his habit of\n; forgetting meetings could cost him his job, Ben decides to do something\n; about it. He adds the weekly meetings of the firm to the Microshaft data\n; base by asserting the following:\n;\n; (meeting accounting (Monday 9am))\n; (meeting administration (Monday 10am))\n; (meeting computer (Wednesday 3pm))\n; (meeting administration (Friday 1pm))\n;\n; Each of the above assertions is for a meeting of an entire division. Ben\n; also adds an entry for company-wide meeting that spans all the divisions.\n; All of the company's employees attend this meeting.\n;\n; (meeting whole-company (Wednesday 4pm))\n;\n; a. On Friday morning, Ben wants to query the data base for all the meetings\n;    that occur that day. What query should he use?\n;\n; b. Alyssa P. Hacker is unimpressed. She thinks it would be much more useful\n;    to be able to ask for her meetings by specifying her name. So she designs\n;    a rule that says a person's mettings include all whole-company meetings\n;    plus all meetings of that person's division. Fill in the body of Alyssa's\n;    rule.\n;\n;    (rule (meeting-time ?person ?day-and-time)\n;          <rule-body>)\n;\n; c. Alyssa arrives at work on Wednesday morning and wonders what meetings she\n; has to attend that day. Having defined the above rule, what query should she\n; make to find this out?\n\n(add-to-data-base!\n  '((meeting accounting (Monday 9am))\n    (meeting administration (Monday 10am))\n    (meeting computer (Wednesday 3pm))\n    (meeting administration (Friday 1pm))\n    (meeting whole-company (Wednesday 4pm))\n\n    (rule (meeting-time ?person ?day-and-time)\n          (or (and (job ?person (?division . ?title))\n                   (meeting ?division ?day-and-time))\n              (meeting whole-company ?day-and-time)))))\n\n(define bens-query '(meeting ?division (Friday ?time)))\n(define alyssas-query '(meeting-time (Hacker Alyssa P) (Wednesday ?time)))\n"
  },
  {
    "path": "scheme/sicp/04/60.scm",
    "content": "; SICP exercise 4.60\n;\n; By giving the query\n;\n; (lives-near ?person (Hacker Alyssa P))\n;\n; Alyssa P. Hacker is able to find people who live near her, with whom she can\n; ride to work. On the other hand, when she tries to find all pairs of people\n; who live near each other by querying\n;\n; (lives-near ?person-1 ?person-2)\n;\n; she notices that each pair of people who live near each other is listed\n; twice; for example,\n;\n; (lives-near (Hacker Alyssa P) (Fect Cy D))\n; (lives-near (Fect Cy D) (Hacker Alyssa P))\n;\n; Why does this happen? Is there a way to find a list of people who live near\n; each other, in which each pair appears only once? Explain.\n\n; When the runtime executes lives-near, it matches the following pattern in\n; the body of the rule\n;\n; (and (address ?person-1 (?town . ?rest-1))\n;      (address ?person-2 (?town . ?rest-2))\n;      (not (same ?person-1 ?person-2))))\n;\n; If scans the assertions for (address ?person-1 (?town . ?rest-1)) and it\n; first finds Alyssa. Then it matches the second pattern to eventually find it\n; matches Cy and subsequently figure out that he is not the same as Alyssa.\n;\n; Afterwards, the runtime continues to scan the assertions and it matches the\n; first pattern to Cy, subsequently matching the second to Alyssa. That why\n; each pair appears twice.\n;\n; We can find a list in which each pair is listed once if we resort to some\n; trickery. We can order the people in some way and assert that the pair has\n; to be ordered. A good way to do that is order people alphabetically. Here is\n; the new rule:\n\n(add-to-data-base!\n  '((rule (ordered-neighbour-pair ?person-1 ?person-2)\n          (and (lives-near ?person-1 ?person-2)\n               (lisp-value (lambda (person-1 person-2)\n                             (string<? (string-join (map symbol->string person-1) \" \")\n                                       (string-join (map symbol->string person-2) \" \")))\n                           ?person-1\n                           ?person-2)))))\n"
  },
  {
    "path": "scheme/sicp/04/61.scm",
    "content": "; SICP exercise 4.61\n;\n; The following rules implement a next-to relation that finds adjancent\n; elements of a list.\n;\n; (rule (?x next-to ?y in (?x ?y . ?u)))\n;\n; (rule (?x next-to ?y in (?v . ?z))\n;       (?x next-to ?y in ?z))\n;\n; What will the response be to the following queries?\n;\n; (?x next-to ?y in (1 (2 3) 4))\n; (?x next-to 1 in (2 1 3 1))\n\n(add-to-data-base!\n '((rule (?x next-to ?y in (?x ?y . ?u)))\n   (rule (?x next-to ?y in (?v . ?z))\n         (?x next-to ?y in ?z))))\n\n(define query-1 '(?x next-to ?y in (1 (2 3) 4)))\n(define query-2 '(?x next-to 1 in (2 1 3 1)))\n\n(define response-1 '((1 next-to (2 3) in (1 (2 3) 4))\n                     ((2 3) next-to 4 in (1 (2 3) 4))))\n\n(define response-2 '((2 next-to 1 in (2 1 3 1))\n                     (3 next-to 1 in (2 1 3 1))))\n"
  },
  {
    "path": "scheme/sicp/04/62.scm",
    "content": "; SICP exercise 4.62\n;\n; Define rules to implement the last-pair operation of exercise 2.17, which\n; returns a list containing the last element of a nonempty list. Check your\n; rules on queries such as (last-pair (3) ?x), (last-pair (1 2 3) ?x), and\n; (last-pair (2 ?x) (3)). Do your rules work correctly on queries such as\n; (last-pair ?x (3)).\n\n; The rule gets stuck in an infinite recursion. This is to be expected, since\n; there are infinitely many pairs whose last pair is (3). That is to say, they\n; don't work.\n\n(add-to-data-base!\n  '((rule (last-pair (?x) (?x)))\n    (rule (last-pair (?any . ?x) ?y)\n          (last-pair ?x ?y))))\n"
  },
  {
    "path": "scheme/sicp/04/63.scm",
    "content": "; SICP exercise 4.63\n;\n; The following data base (see Genesis 4) traces the genealogy of the\n; descendants of Ada back to Adam, by way of Cain:\n;\n; (son Adam Cain)\n; (son Cain Enoch)\n; (son Enoch Irad)\n; (son Irad Mehujael)\n; (son Mehujael Methushael)\n; (son Methushael Lamech)\n; (wife Lamech Ada)\n; (son Ada Jabal)\n; (son Ada Jubal)\n;\n; Formulate rules such as \"If S is the son of F, and F is the son of G, then S\n; is the grandson of G\" and \"If W is the wife of M, and S is the son of W,\n; then S is the son of M\" (which was supposedly more true in biblical times\n; than today) that will enable to query the system to find grandson of Cain;\n; the sons of Lamech; the grandsons of Methushael. (See exercise 4.69 for some\n; rules to deduce more complicated relationships.)\n\n(add-to-data-base!\n  '((son Adam Cain)\n    (son Cain Enoch)\n    (son Enoch Irad)\n    (son Irad Mehujael)\n    (son Mehujael Methushael)\n    (son Methushael Lamech)\n    (wife Lamech Ada)\n    (son Ada Jabal)\n    (son Ada Jubal)\n\n    (rule (grandson ?grandfather ?son)\n          (and (son ?grandfather ?father)\n               (son ?father ?son)))\n\n    (rule (son ?father ?son)\n          (and (wife ?father ?mother)\n               (son ?mother ?son)))))\n\n(define grandson-of-cain '(grandson Cain ?grandson))\n(define sons-of-lamech '(son Lamech ?son))\n(define grandsons-of-methushael '(grandson Methushael ?grandson))\n"
  },
  {
    "path": "scheme/sicp/04/64.scm",
    "content": "; SICP exercise 4.64\n;\n; Louis Reasoner mistakenly deletes the outranked-by rule (section 4.4.1) from\n; the data base. When he realizes this, he quickly reinstalls it.\n; Unfortunatelly, he makes a slight change in the rule, and types it in as\n;\n; (rule (outranked-by ?staff-person ?boss)\n;       (or (supervisor ?staff-person ?boss)\n;           (and (outranked-by ?middle-manager ?boss)\n;                (supervisor ?staff-person ?middle-manager))))\n;\n; Just after Louis types this information into the system, DeWitt Aull comes\n; by to find out who outranks Ben Bitdiddle. He issues the query\n;\n; (outranked-by (Bitdiddle Ben) ?who)\n;\n; After answering, the system goes into an infinite loop. Explain why.\n\n; First the system will answer with\n;\n; (outranked-by (Bitdiddle Ben) (Warbucks Oliver))\n;\n; because the first disjunct will match an existing assertion. Afterwards, the\n; system will try to match (outranked-by ?middle-manager ?boss), which means\n; applying the rule again. In this second application, we will first get all\n; supervisor assertions (because they are the first clause of the disjunction),\n; but when the second disjunct gets evaluated, it will invoke the rule again.\n; This will get everything stuck in a loop.\n"
  },
  {
    "path": "scheme/sicp/04/65.scm",
    "content": "; SICP exercise 4.65\n;\n; Cy D. Fect, looking forward to the day when he will rise in the\n; organization, gives a query to find all the wheels (using the wheel rule of\n; section 4.4.1):\n;\n; (wheel ?who)\n;\n; To his surprise, the system responds\n;\n; ;;; Query results:\n; (wheel (Warbucks Oliver))\n; (wheel (Bitdiddle Ben))\n; (wheel (Warbucks Oliver))\n; (wheel (Warbucks Oliver))\n; (wheel (Warbucks Oliver))\n;\n; Why is Oliver listed four times?\n\n; The rule looks like this:\n;\n;   (rule (wheel ?person)\n;         (and (supervisor ?middle-manager ?person)\n;              (supervisor ?x ?middle-manager)))\n;\n; With this definition, it lists the wheel once for each employee supervised\n; by a middle manager under them. Alyssa, Lem and Cy are under Ben, while\n; Robert is under Eben. This is why Oliver is listed four times. The only\n; supervisor under Ben is Alyssa and she is supervising one employee - Louis,\n; which is why Ben is listed once.\n;\n; The order is not as straightfoward, since stream-flatmap interleaves the\n; streams it maps to.\n"
  },
  {
    "path": "scheme/sicp/04/66.scm",
    "content": "; SICP exercise 4.66\n;\n; Ben has been generalizing the query system to provide statistics about the\n; company. For example, to find the total salaries of all the computer\n; programmers one will be able to say\n;\n; (sum ?amount\n;      (and (job ?x (computer programmer))\n;           (salary ?x ?amount)))\n;\n; In general, Ben's new system allows expressions of the form\n;\n; (accumulation-function <variable>\n;                        <query pattern>)\n;\n; where accumulation-function can be things like sum, average, or maximum. Ben\n; reasons that it should be a cinch to implement this. He will simnply feed\n; the query pattern to qeval. This will produce a stream of frames. He will\n; then pass this stream through a mapping function that extracts the value of\n; the designated variable from each frame in the stream and feed the resulting\n; stream of values to the accumulation function. Just as Ben completes the\n; implementation and is about to try it out, Cy walks by, still puzzling over\n; the wheel query result in exercise 4.65. When Cy shows Ben the system's\n; response, Ben groans, \"Oh, no, my simple accumulation scheme won't work!\".\n;\n; What has Ben just realized? Outline a method he can use to salvage this\n; situation.\n\n; He has realizes that a result may be matched multiple times due to how a\n; rule is written. For example, trying to sum the salaries of the wheels will\n; result in Oliver Warbucks' salary being counted four times (see exercise\n; 4.65).\n;\n; This can be salvaged by filtering the stream to remove the duplication. We\n; can instantiate the query with each frame and check it against previous\n; instances. If we encounted a query for a second time, we don't pass it to\n; the aggregation function.\n"
  },
  {
    "path": "scheme/sicp/04/67.scm",
    "content": "; SICP exercise 4.67\n;\n; Devise a way to install a loop detector in the query system so as to avoid\n; the kinds of simple loops illustrated in the text and in exercise 4.64. The\n; general idea is that the system should maintain some sort of history of its\n; current chain of deductions and should not begin processing a query that it\n; is already working on. Describe what kind of information (patterns and\n; frames) is included in this history, and how the check should be made.\n; (After you study the details of the query-system implementation in section\n; 4.4.4, you may want to modify the system to include your loop detector).\n\n; We need to maintain a history of each rule we applied. We can instantiate\n; the rule with the current frame and store it (the result is a query where\n; all the variables are free variables in the current frame). Every time we\n; apply a rule, we check to see if we are not already processing the rule. We\n; can do that by unifying the current rule with each one in the history. If\n; they can be unified and all of the variables of the rule in the history\n; remain free, then we are already processing the rule and we have detected a\n; loop.\n;\n; The code below implements this. There are a bunch of new functions defined\n; and the existing ones are modified so qeval takes an additional history\n; argument. apply-a-rule is also modified to return the empty stream if it\n; detects a loop.\n\n(define loopy-rules\n  '((married Minnie Mickey)\n    (rule (married ?x ?y)\n          (married ?y ?x))\n\n    (rule (loopy-outranked-by ?staff-person ?boss)\n          (or (supervisor ?staff-person ?boss)\n              (and (loopy-outranked-by ?middle-manager ?boss)\n                   (supervisor ?staff-person ?middle-manager))))))\n\n; Loop Detection\n\n(define (instantiate-pattern query frame)\n  (define (rename-variable var)\n    (if (number? (cadr var))\n        (cons '? (cons (- (cadr var)) (cddr var)))\n        (cons '? (cons '- (cdr var)))))\n  (instantiate-exp query\n                   frame\n                   (lambda (v f) (rename-variable v))))\n\n(define (free-var? var frame)\n  (let ((binding (binding-in-frame var frame)))\n    (or (not binding)\n        (and (var? (binding-value binding))\n             (free-var? (binding-value binding) frame)))))\n\n(define (all-free? vars frame)\n  (andmap (lambda (var) (free-var? var frame))\n          vars))\n\n(define (processing-query? query history)\n  (ormap (lambda (history-entry) (same-query? history-entry query))\n         history))\n\n(define (variables query)\n  (cond ((var? query)\n         (list query))\n        ((pair? query)\n         (append (variables (car query))\n                 (variables (cdr query))))\n        (else '())))\n\n(define (same-query? history-entry query)\n  (let ((vars (variables history-entry))\n        (unify-result (unify-match history-entry query '())))\n    (and (not (eq? unify-result 'failed))\n         (all-free? vars unify-result))))\n\n; The Driver Loop and Instantiation\n\n(define input-prompt \";;; Query input:\")\n(define output-prompt \";;; Query output:\")\n(define (query-driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((q (query-syntax-process (read))))\n    (cond ((assertion-to-be-added? q)\n           (add-rule-or-assertion! (add-assertion-body q))\n           (newline)\n           (display \"Assertion added to data base.\")\n           (query-driver-loop))\n          (else\n           (newline)\n           (display output-prompt)\n           (display-stream\n             (stream-map\n               (lambda (frame)\n                 (instantiate-exp q\n                                  frame\n                                  (lambda (v f) (contract-question-mark v))))\n               (qeval q (singleton-stream '()) '())))\n           (query-driver-loop)))))\n\n(define (instantiate-exp exp frame unbound-var-handler)\n  (define (copy exp)\n    (cond ((var? exp)\n           (let ((binding (binding-in-frame exp frame)))\n             (if binding\n                 (copy (binding-value binding))\n                 (unbound-var-handler exp frame))))\n          ((pair? exp)\n           (cons (copy (car exp)) (copy (cdr exp))))\n          (else exp)))\n  (copy exp))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (display-stream stream)\n  (unless (stream-empty? stream)\n          (newline)\n          (display (stream-first stream))\n          (display-stream (stream-rest stream))))\n\n; The Evaluator\n\n(define (qeval query frame-stream history)\n  (let ((qproc (get (type query) 'qeval)))\n    (if qproc\n        (qproc (contents query) frame-stream history)\n        (simple-query query frame-stream history))))\n\n(define (execute exp)\n  (apply (eval (predicate exp))\n         (args exp)))\n\n(define (simple-query query-pattern frame-stream history)\n  (stream-flatmap\n    (lambda (frame)\n      (stream-append\n        (find-assertions query-pattern frame)\n        (apply-rules query-pattern frame history)))\n    frame-stream))\n\n(define (con-join conjuncts frame-stream history)\n  (if (empty-conjunction? conjuncts)\n      frame-stream\n      (con-join (rest-conjuncts conjuncts)\n               (qeval (first-conjunct conjuncts)\n                      frame-stream\n                      history)\n               history)))\n\n(define (dis-join disjuncts frame-stream history)\n  (if (empty-disjunction? disjuncts)\n      empty-stream\n      (interleave (qeval (first-disjunct disjuncts) frame-stream history)\n                  (dis-join (rest-disjuncts disjuncts)\n                           frame-stream\n                           history))))\n\n(define (negate operands frame-stream history)\n  (stream-flatmap\n    (lambda (frame)\n      (if (stream-empty? (qeval (negated-query operands) (singleton-stream frame) history))\n          (singleton-stream frame)\n          empty-stream))\n    frame-stream))\n\n(define (lisp-value call frame-stream history)\n  (stream-flatmap\n    (lambda (frame)\n      (if (execute\n            (instantiate-exp call\n                             frame\n                             (lambda (v f) (error \"Unknown pat var -- LISP-VALUE\" v))))\n          (singleton-stream frame)\n          empty-stream))\n    frame-stream))\n\n(define (always-true ignore frame-stream history)\n  frame-stream)\n\n; Finding Assertions by Pattern Matching\n\n(define (find-assertions pattern frame)\n  (stream-flatmap (lambda (datum) (check-an-assertion datum pattern frame))\n                  (fetch-assertions pattern frame)))\n\n(define (check-an-assertion assertion query-pat query-frame)\n  (let ((match-result (pattern-match query-pat assertion query-frame)))\n    (if (eq? match-result 'failed)\n        empty-stream\n        (singleton-stream match-result))))\n\n(define (pattern-match pat dat frame)\n  (cond ((eq? frame 'failed) 'failed)\n        ((equal? pat dat) frame)\n        ((var? pat) (extend-if-consistent pat dat frame))\n        ((and (pair? pat) (pair? dat))\n         (pattern-match (cdr pat)\n                        (cdr dat)\n                        (pattern-match (car pat)\n                                       (car dat)\n                                       frame)))\n        (else 'failed)))\n\n(define (extend-if-consistent var dat frame)\n  (let ((binding (binding-in-frame var frame)))\n    (if binding\n        (pattern-match (binding-value binding) dat frame)\n        (extend var dat frame))))\n\n; Rules and Unification\n\n(define (apply-rules pattern frame history)\n  (stream-flatmap (lambda (rule) (apply-a-rule rule pattern frame history))\n                  (fetch-rules pattern frame)))\n\n(define (apply-a-rule rule query-pattern query-frame history)\n  (let ((clean-rule (rename-variables-in rule)))\n    (let ((unify-result (unify-match query-pattern\n                                     (conclusion clean-rule)\n                                     query-frame)))\n      (if (eq? unify-result 'failed)\n          empty-stream\n          (let ((current-query (instantiate-pattern (conclusion clean-rule) unify-result)))\n            (if (processing-query? current-query history)\n                empty-stream\n                (qeval (rule-body clean-rule)\n                       (singleton-stream unify-result)\n                       (cons current-query history))))))))\n\n(define (rename-variables-in rule)\n  (let ((rule-application-id (new-rule-application-id)))\n    (define (tree-walk exp)\n      (cond ((var? exp)\n             (make-new-variable exp rule-application-id))\n            ((pair? exp)\n             (cons (tree-walk (car exp))\n                   (tree-walk (cdr exp))))\n            (else exp)))\n    (tree-walk rule)))\n\n(define (unify-match p1 p2 frame)\n  (cond ((eq? frame 'failed) 'failed)\n        ((equal? p1 p2) frame)\n        ((var? p1) (extend-if-possible p1 p2 frame))\n        ((var? p2) (extend-if-possible p2 p1 frame))\n        ((and (pair? p1) (pair? p2))\n         (unify-match (cdr p1)\n                      (cdr p2)\n                      (unify-match (car p1)\n                                   (car p2)\n                                   frame)))\n        (else 'failed)))\n\n(define (extend-if-possible var val frame)\n  (let ((binding (binding-in-frame var frame)))\n    (cond (binding (unify-match (binding-value binding) val frame))\n          ((var? val)\n           (let ((binding (binding-in-frame val frame)))\n             (if binding\n                 (unify-match var (binding-value binding) frame)\n                 (extend var val frame))))\n          ((depends-on? val var frame) 'failed)\n          (else (extend var val frame)))))\n\n(define (depends-on? exp var frame)\n  (define (tree-walk e)\n    (cond ((var? e)\n           (if (equal? var e)\n               true\n               (let ((b (binding-in-frame e frame)))\n                 (if b\n                     (tree-walk (binding-value b))\n                     false))))\n          ((pair? e)\n           (or (tree-walk (car e))\n               (tree-walk (cdr e))))\n          (else false)))\n  (tree-walk exp))\n\n; Maintaining the Data Base\n\n(define THE-ASSERTIONS '())\n(define (fetch-assertions pattern frame)\n  (if (use-index? pattern)\n      (get-indexed-assertions pattern)\n      (get-all-assertions)))\n(define (get-all-assertions)\n  (reverse-list->stream THE-ASSERTIONS))\n(define (get-indexed-assertions pattern)\n  (reverse-list->stream\n    (get-list (index-key-of pattern) 'assertion-list)))\n\n(define THE-RULES '())\n(define (fetch-rules pattern frame)\n  (if (use-index? pattern)\n      (get-indexed-rules pattern)\n      (get-all-rules)))\n(define (get-all-rules)\n  (reverse-list->stream THE-RULES))\n(define (get-indexed-rules pattern)\n  (reverse-list->stream\n    (append\n      (get-list '? 'rule-list)\n      (get-list (index-key-of pattern) 'rule-list))))\n\n(define (add-rule-or-assertion! assertion)\n  (if (rule? assertion)\n      (add-rule! assertion)\n      (add-assertion! assertion)))\n\n(define (add-assertion! assertion)\n  (store-assertion-in-index assertion)\n  (let ((old-assertions THE-ASSERTIONS))\n    (set! THE-ASSERTIONS (cons assertion old-assertions))\n    'ok))\n\n(define (add-rule! rule)\n  (store-rule-in-index rule)\n  (let ((old-rules THE-RULES))\n    (set! THE-RULES (cons rule old-rules))\n    'ok))\n\n(define (store-assertion-in-index assertion)\n  (when (indexable? assertion)\n        (let ((key (index-key-of assertion)))\n          (let ((current-assertion-list (get-list key 'assertion-list)))\n            (put key\n                 'assertion-list\n                 (cons assertion current-assertion-list))))))\n\n(define (store-rule-in-index rule)\n  (let ((pattern (conclusion rule)))\n    (when (indexable? pattern)\n          (let ((key (index-key-of pattern)))\n            (let ((current-rule-list (get-list key 'rule-list)))\n              (put key\n                   'rule-list\n                   (cons rule current-rule-list)))))))\n\n(define (indexable? pattern)\n  (or (constant-symbol? (car pattern))\n      (var? (car pattern))))\n\n(define (index-key-of pattern)\n  (let ((key (car pattern)))\n    (if (var? key) '? key)))\n\n(define (use-index? pattern)\n  (constant-symbol? (car pattern)))\n\n(define (list->stream items)\n  (if (null? items)\n      empty-stream\n      (stream-cons (car items)\n                   (list->stream (cdr items)))))\n\n(define (reverse-list->stream items)\n  (list->stream (reverse items)))\n\n(define (get-list key1 key2)\n  (let ((s (get key1 key2)))\n    (if s s '())))\n\n; Operator table\n\n(define table (make-hash))\n\n(define (put op type item)\n  (hash-set! table (list op type) item))\n\n(define (get op type)\n  (hash-ref table (list op type) #f))\n\n; Stream Operations\n\n(define (interleave s1 s2)\n  (if (stream-empty? s1)\n      s2\n      (stream-cons\n        (stream-first s1)\n        (interleave s2 (stream-rest s1)))))\n\n(define (stream-flatmap proc s)\n  (flatten-stream (stream-map proc s)))\n\n(define (flatten-stream stream)\n  (if (stream-empty? stream)\n      empty-stream\n      (interleave (stream-first stream)\n                  (flatten-stream (stream-rest stream)))))\n\n(define (singleton-stream x)\n  (stream-cons x empty-stream))\n\n; Query Syntax Procedures\n\n(define (type exp)\n  (if (pair? exp)\n    (car exp)\n    (error \"Unknown expression TYPE\" exp)))\n\n(define (contents exp)\n  (if (pair? exp)\n      (cdr exp)\n      (error \"Unknown expression CONTENTS\" exp)))\n\n(define (assertion-to-be-added? exp) (eq? (type exp) 'assert!))\n(define (add-assertion-body exp) (car (contents exp)))\n\n(define (empty-conjunction? exps) (null? exps))\n(define (first-conjunct exps) (car exps))\n(define (rest-conjuncts exps) (cdr exps))\n(define (empty-disjunction? exps) (null? exps))\n(define (first-disjunct exps) (car exps))\n(define (rest-disjuncts exps) (cdr exps))\n(define (negated-query exps) (car exps))\n(define (predicate exps) (car exps))\n(define (args exps) (cdr exps))\n\n(define (rule? statement) (tagged-list? statement 'rule))\n(define (conclusion rule) (cadr rule))\n(define (rule-body rule) (if (null? (cddr rule)) '(always-true) (caddr rule)))\n\n(define (query-syntax-process exp)\n  (map-over-symbols expand-question-mark exp))\n\n(define (map-over-symbols proc exp)\n  (cond ((pair? exp)\n         (cons (map-over-symbols proc (car exp))\n               (map-over-symbols proc (cdr exp))))\n        ((symbol? exp) (proc exp))\n        (else exp)))\n\n(define (expand-question-mark symbol)\n  (let ((chars (symbol->string symbol)))\n    (if (string=? (substring chars 0 1) \"?\")\n        (list '?\n              (string->symbol\n                (substring chars 1 (string-length chars))))\n        symbol)))\n\n(define (var? exp) (tagged-list? exp '?))\n(define (constant-symbol? exp) (symbol? exp))\n\n(define rule-counter 0)\n(define (new-rule-application-id)\n  (set! rule-counter (+ 1 rule-counter))\n  rule-counter)\n(define (make-new-variable var rule-application-id)\n  (cons '? (cons rule-application-id (cdr var))))\n\n(define (contract-question-mark variable)\n  (string->symbol\n    (string-append \"?\"\n                   (if (number? (cadr variable))\n                       (string-append (symbol->string (caddr variable))\n                                      \"-\"\n                                      (number->string (cadr variable)))\n                       (symbol->string (cadr variable))))))\n\n(define (tagged-list? exp tag)\n  (and (pair? exp)\n       (eq? (car exp) tag)))\n\n; Frames and Bindings\n\n(define (make-binding variable value)\n  (cons variable value))\n(define (binding-variable binding)\n  (car binding))\n(define (binding-value binding)\n  (cdr binding))\n(define (binding-in-frame variable frame)\n  (assoc variable frame))\n(define (extend variable value frame)\n  (cons (make-binding variable value) frame))\n\n; Reseting the state\n\n(define (reset-state!)\n  (set! table (make-hash))\n  (set! rule-counter 0)\n  (set! THE-ASSERTIONS '())\n  (set! THE-RULES '())\n\n  (put 'and 'qeval con-join)\n  (put 'or 'qeval dis-join)\n  (put 'not 'qeval negate)\n  (put 'lisp-value 'qeval lisp-value)\n  (put 'always-true 'qeval always-true))\n\n(reset-state!)\n"
  },
  {
    "path": "scheme/sicp/04/68.scm",
    "content": "; SICP exercise 4.68\n;\n; Define rules to implement the reverse operation of exercise 2.18, which\n; returns a list containing the same elements as a given list in reverse\n; order. (Hint: Use append-to-form.) Can your rules answer both\n; (reverse (1 2 3) ?x) and (reverse ?x (1 2 3))?\n\n; They can't. (reverse ?x (1 2 3)) gets the system stuck in an infinite loop.\n\n(add-to-data-base!\n  '((rule (reverse (?x) (?x)))\n    (rule (reverse (?a . ?b) ?c)\n          (and (reverse ?b ?r-b)\n               (append-to-form ?r-b (?a) ?c)))))\n"
  },
  {
    "path": "scheme/sicp/04/69.scm",
    "content": "; SICP exercise 4.69\n;\n; Beginning with the data base and the rules you formulated in exercise 4.63,\n; devise a rule for adding \"greats\" to a grandson relationship. This should\n; enable the system to deduce that Irad is the great-grandson of Adam, or that\n; Jabal and Jubal are the great-great-great-great-great-grandsons of Adam.\n; (Hint: Represent the fact about Irad, for example, as ((great grandson) Adam\n; Irad). Write rules that determine if a list ends in the word grandson. Use\n; this to express a rule that allows one to derive the relationship\n; ((great . ?rel) ?x ?y), where ?rel is a list ending in grandson). Check your\n; rules on queries such as ((great grandson) ?g ?ggs) and\n; (?relationship Adam Irad).\n\n; We base this on the loop detection in 4.67, since otherwise\n; (?relationship Adam Irad) will fall into such a loop.\n\n(define grands-rules\n  '((son Adam Cain)\n    (son Cain Enoch)\n    (son Enoch Irad)\n    (son Irad Mehujael)\n    (son Mehujael Methushael)\n    (son Methushael Lamech)\n    (wife Lamech Ada)\n    (son Ada Jabal)\n    (son Ada Jubal)\n\n    (rule (son ?father ?son)\n          (and (wife ?father ?mother)\n               (son ?mother ?son)))\n\n    (rule (grandson ?grandfather ?son)\n          (and (son ?grandfather ?father)\n               (son ?father ?son)))\n\n    (rule (ends-with-grandson (grandson)))\n    (rule (ends-with-grandson (?x . ?rest))\n          (ends-with-grandson ?rest))\n\n    (rule ((grandson) ?grandfather ?grandson)\n          (grandson ?grandfather ?grandson))\n\n    (rule ((great . ?rel) ?ancestor ?descendant)\n          (and (ends-with-grandson ?rel)\n               (son ?ancestor ?son-of-ancestor)\n               (?rel ?son-of-ancestor ?descendant)))))\n\n; Loop Detection\n\n(define (instantiate-pattern query frame)\n  (define (rename-variable var)\n    (if (number? (cadr var))\n        (cons '? (cons (- (cadr var)) (cddr var)))\n        (cons '? (cons '- (cdr var)))))\n  (instantiate-exp query\n                   frame\n                   (lambda (v f) (rename-variable v))))\n\n(define (free-var? var frame)\n  (let ((binding (binding-in-frame var frame)))\n    (or (not binding)\n        (and (var? (binding-value binding))\n             (free-var? (binding-value binding) frame)))))\n\n(define (all-free? vars frame)\n  (andmap (lambda (var) (free-var? var frame))\n          vars))\n\n(define (processing-query? query history)\n  (ormap (lambda (history-entry) (same-query? history-entry query))\n         history))\n\n(define (variables query)\n  (cond ((var? query)\n         (list query))\n        ((pair? query)\n         (append (variables (car query))\n                 (variables (cdr query))))\n        (else '())))\n\n(define (same-query? history-entry query)\n  (let ((vars (variables history-entry))\n        (unify-result (unify-match history-entry query '())))\n    (and (not (eq? unify-result 'failed))\n         (all-free? vars unify-result))))\n\n; The Driver Loop and Instantiation\n\n(define input-prompt \";;; Query input:\")\n(define output-prompt \";;; Query output:\")\n(define (query-driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((q (query-syntax-process (read))))\n    (cond ((assertion-to-be-added? q)\n           (add-rule-or-assertion! (add-assertion-body q))\n           (newline)\n           (display \"Assertion added to data base.\")\n           (query-driver-loop))\n          (else\n           (newline)\n           (display output-prompt)\n           (display-stream\n             (stream-map\n               (lambda (frame)\n                 (instantiate-exp q\n                                  frame\n                                  (lambda (v f) (contract-question-mark v))))\n               (qeval q (singleton-stream '()) '())))\n           (query-driver-loop)))))\n\n(define (instantiate-exp exp frame unbound-var-handler)\n  (define (copy exp)\n    (cond ((var? exp)\n           (let ((binding (binding-in-frame exp frame)))\n             (if binding\n                 (copy (binding-value binding))\n                 (unbound-var-handler exp frame))))\n          ((pair? exp)\n           (cons (copy (car exp)) (copy (cdr exp))))\n          (else exp)))\n  (copy exp))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (display-stream stream)\n  (unless (stream-empty? stream)\n          (newline)\n          (display (stream-first stream))\n          (display-stream (stream-rest stream))))\n\n; The Evaluator\n\n(define (qeval query frame-stream history)\n  (let ((qproc (get (type query) 'qeval)))\n    (if qproc\n        (qproc (contents query) frame-stream history)\n        (simple-query query frame-stream history))))\n\n(define (execute exp)\n  (apply (eval (predicate exp))\n         (args exp)))\n\n(define (simple-query query-pattern frame-stream history)\n  (stream-flatmap\n    (lambda (frame)\n      (stream-append\n        (find-assertions query-pattern frame)\n        (apply-rules query-pattern frame history)))\n    frame-stream))\n\n(define conjoin '())\n(define (conjoin conjuncts frame-stream history)\n  (if (empty-conjunction? conjuncts)\n      frame-stream\n      (conjoin (rest-conjuncts conjuncts)\n               (qeval (first-conjunct conjuncts)\n                      frame-stream\n                      history)\n               history)))\n\n(define disjoin '())\n(define (disjoin disjuncts frame-stream history)\n  (if (empty-disjunction? disjuncts)\n      empty-stream\n      (interleave (qeval (first-disjunct disjuncts) frame-stream history)\n                  (disjoin (rest-disjuncts disjuncts)\n                           frame-stream\n                           history))))\n\n(define (negate operands frame-stream history)\n  (stream-flatmap\n    (lambda (frame)\n      (if (stream-empty? (qeval (negated-query operands) (singleton-stream frame) history))\n          (singleton-stream frame)\n          empty-stream))\n    frame-stream))\n\n(define (lisp-value call frame-stream history)\n  (stream-flatmap\n    (lambda (frame)\n      (if (execute\n            (instantiate-exp call\n                             frame\n                             (lambda (v f) (error \"Unknown pat var -- LISP-VALUE\" v))))\n          (singleton-stream frame)\n          empty-stream))\n    frame-stream))\n\n(define (always-true ignore frame-stream history)\n  frame-stream)\n\n; Finding Assertions by Pattern Matching\n\n(define (find-assertions pattern frame)\n  (stream-flatmap (lambda (datum) (check-an-assertion datum pattern frame))\n                  (fetch-assertions pattern frame)))\n\n(define (check-an-assertion assertion query-pat query-frame)\n  (let ((match-result (pattern-match query-pat assertion query-frame)))\n    (if (eq? match-result 'failed)\n        empty-stream\n        (singleton-stream match-result))))\n\n(define (pattern-match pat dat frame)\n  (cond ((eq? frame 'failed) 'failed)\n        ((equal? pat dat) frame)\n        ((var? pat) (extend-if-consistent pat dat frame))\n        ((and (pair? pat) (pair? dat))\n         (pattern-match (cdr pat)\n                        (cdr dat)\n                        (pattern-match (car pat)\n                                       (car dat)\n                                       frame)))\n        (else 'failed)))\n\n(define (extend-if-consistent var dat frame)\n  (let ((binding (binding-in-frame var frame)))\n    (if binding\n        (pattern-match (binding-value binding) dat frame)\n        (extend var dat frame))))\n\n; Rules and Unification\n\n(define (apply-rules pattern frame history)\n  (stream-flatmap (lambda (rule) (apply-a-rule rule pattern frame history))\n                  (fetch-rules pattern frame)))\n\n(define (apply-a-rule rule query-pattern query-frame history)\n  (let ((clean-rule (rename-variables-in rule)))\n    (let ((unify-result (unify-match query-pattern\n                                     (conclusion clean-rule)\n                                     query-frame)))\n      (if (eq? unify-result 'failed)\n          empty-stream\n          (let ((current-query (instantiate-pattern (conclusion clean-rule) unify-result)))\n            (if (processing-query? current-query history)\n                empty-stream\n                (qeval (rule-body clean-rule)\n                       (singleton-stream unify-result)\n                       (cons current-query history))))))))\n\n(define (rename-variables-in rule)\n  (let ((rule-application-id (new-rule-application-id)))\n    (define (tree-walk exp)\n      (cond ((var? exp)\n             (make-new-variable exp rule-application-id))\n            ((pair? exp)\n             (cons (tree-walk (car exp))\n                   (tree-walk (cdr exp))))\n            (else exp)))\n    (tree-walk rule)))\n\n(define (unify-match p1 p2 frame)\n  (cond ((eq? frame 'failed) 'failed)\n        ((equal? p1 p2) frame)\n        ((var? p1) (extend-if-possible p1 p2 frame))\n        ((var? p2) (extend-if-possible p2 p1 frame))\n        ((and (pair? p1) (pair? p2))\n         (unify-match (cdr p1)\n                      (cdr p2)\n                      (unify-match (car p1)\n                                   (car p2)\n                                   frame)))\n        (else 'failed)))\n\n(define (extend-if-possible var val frame)\n  (let ((binding (binding-in-frame var frame)))\n    (cond (binding (unify-match (binding-value binding) val frame))\n          ((var? val)\n           (let ((binding (binding-in-frame val frame)))\n             (if binding\n                 (unify-match var (binding-value binding) frame)\n                 (extend var val frame))))\n          ((depends-on? val var frame) 'failed)\n          (else (extend var val frame)))))\n\n(define (depends-on? exp var frame)\n  (define (tree-walk e)\n    (cond ((var? e)\n           (if (equal? var e)\n               true\n               (let ((b (binding-in-frame e frame)))\n                 (if b\n                     (tree-walk (binding-value b))\n                     false))))\n          ((pair? e)\n           (or (tree-walk (car e))\n               (tree-walk (cdr e))))\n          (else false)))\n  (tree-walk exp))\n\n; Maintaining the Data Base\n\n(define THE-ASSERTIONS '())\n(define (fetch-assertions pattern frame)\n  (if (use-index? pattern)\n      (get-indexed-assertions pattern)\n      (get-all-assertions)))\n(define (get-all-assertions)\n  (reverse-list->stream THE-ASSERTIONS))\n(define (get-indexed-assertions pattern)\n  (reverse-list->stream\n    (get-list (index-key-of pattern) 'assertion-list)))\n\n(define THE-RULES '())\n(define (fetch-rules pattern frame)\n  (if (use-index? pattern)\n      (get-indexed-rules pattern)\n      (get-all-rules)))\n(define (get-all-rules)\n  (reverse-list->stream THE-RULES))\n(define (get-indexed-rules pattern)\n  (reverse-list->stream\n    (append\n      (get-list '? 'rule-list)\n      (get-list (index-key-of pattern) 'rule-list))))\n\n(define (add-rule-or-assertion! assertion)\n  (if (rule? assertion)\n      (add-rule! assertion)\n      (add-assertion! assertion)))\n\n(define (add-assertion! assertion)\n  (store-assertion-in-index assertion)\n  (let ((old-assertions THE-ASSERTIONS))\n    (set! THE-ASSERTIONS (cons assertion old-assertions))\n    'ok))\n\n(define (add-rule! rule)\n  (store-rule-in-index rule)\n  (let ((old-rules THE-RULES))\n    (set! THE-RULES (cons rule old-rules))\n    'ok))\n\n(define (store-assertion-in-index assertion)\n  (when (indexable? assertion)\n        (let ((key (index-key-of assertion)))\n          (let ((current-assertion-list (get-list key 'assertion-list)))\n            (put key\n                 'assertion-list\n                 (cons assertion current-assertion-list))))))\n\n(define (store-rule-in-index rule)\n  (let ((pattern (conclusion rule)))\n    (when (indexable? pattern)\n          (let ((key (index-key-of pattern)))\n            (let ((current-rule-list (get-list key 'rule-list)))\n              (put key\n                   'rule-list\n                   (cons rule current-rule-list)))))))\n\n(define (indexable? pattern)\n  (or (constant-symbol? (car pattern))\n      (var? (car pattern))))\n\n(define (index-key-of pattern)\n  (let ((key (car pattern)))\n    (if (var? key) '? key)))\n\n(define (use-index? pattern)\n  (constant-symbol? (car pattern)))\n\n(define (list->stream items)\n  (if (null? items)\n      empty-stream\n      (stream-cons (car items)\n                   (list->stream (cdr items)))))\n\n(define (reverse-list->stream items)\n  (list->stream (reverse items)))\n\n(define (get-list key1 key2)\n  (let ((s (get key1 key2)))\n    (if s s '())))\n\n; Operator table\n\n(define table (make-hash))\n\n(define (put op type item)\n  (hash-set! table (list op type) item))\n\n(define (get op type)\n  (hash-ref table (list op type) #f))\n\n; Stream Operations\n\n(define (interleave s1 s2)\n  (if (stream-empty? s1)\n      s2\n      (stream-cons\n        (stream-first s1)\n        (interleave s2 (stream-rest s1)))))\n\n(define (stream-flatmap proc s)\n  (flatten-stream (stream-map proc s)))\n\n(define (flatten-stream stream)\n  (if (stream-empty? stream)\n      empty-stream\n      (interleave (stream-first stream)\n                  (flatten-stream (stream-rest stream)))))\n\n(define (singleton-stream x)\n  (stream-cons x empty-stream))\n\n; Query Syntax Procedures\n\n(define (type exp)\n  (if (pair? exp)\n    (car exp)\n    (error \"Unknown expression TYPE\" exp)))\n\n(define (contents exp)\n  (if (pair? exp)\n      (cdr exp)\n      (error \"Unknown expression CONTENTS\" exp)))\n\n(define (assertion-to-be-added? exp) (eq? (type exp) 'assert!))\n(define (add-assertion-body exp) (car (contents exp)))\n\n(define (empty-conjunction? exps) (null? exps))\n(define (first-conjunct exps) (car exps))\n(define (rest-conjuncts exps) (cdr exps))\n(define (empty-disjunction? exps) (null? exps))\n(define (first-disjunct exps) (car exps))\n(define (rest-disjuncts exps) (cdr exps))\n(define (negated-query exps) (car exps))\n(define (predicate exps) (car exps))\n(define (args exps) (cdr exps))\n\n(define (rule? statement) (tagged-list? statement 'rule))\n(define (conclusion rule) (cadr rule))\n(define (rule-body rule) (if (null? (cddr rule)) '(always-true) (caddr rule)))\n\n(define (query-syntax-process exp)\n  (map-over-symbols expand-question-mark exp))\n\n(define (map-over-symbols proc exp)\n  (cond ((pair? exp)\n         (cons (map-over-symbols proc (car exp))\n               (map-over-symbols proc (cdr exp))))\n        ((symbol? exp) (proc exp))\n        (else exp)))\n\n(define (expand-question-mark symbol)\n  (let ((chars (symbol->string symbol)))\n    (if (string=? (substring chars 0 1) \"?\")\n        (list '?\n              (string->symbol\n                (substring chars 1 (string-length chars))))\n        symbol)))\n\n(define (var? exp) (tagged-list? exp '?))\n(define (constant-symbol? exp) (symbol? exp))\n\n(define rule-counter 0)\n(define (new-rule-application-id)\n  (set! rule-counter (+ 1 rule-counter))\n  rule-counter)\n(define (make-new-variable var rule-application-id)\n  (cons '? (cons rule-application-id (cdr var))))\n\n(define (contract-question-mark variable)\n  (string->symbol\n    (string-append \"?\"\n                   (if (number? (cadr variable))\n                       (string-append (symbol->string (caddr variable))\n                                      \"-\"\n                                      (number->string (cadr variable)))\n                       (symbol->string (cadr variable))))))\n\n(define (tagged-list? exp tag)\n  (and (pair? exp)\n       (eq? (car exp) tag)))\n\n; Frames and Bindings\n\n(define (make-binding variable value)\n  (cons variable value))\n(define (binding-variable binding)\n  (car binding))\n(define (binding-value binding)\n  (cdr binding))\n(define (binding-in-frame variable frame)\n  (assoc variable frame))\n(define (extend variable value frame)\n  (cons (make-binding variable value) frame))\n\n; Reseting the state\n\n(define (reset-state!)\n  (set! table (make-hash))\n  (set! rule-counter 0)\n  (set! THE-ASSERTIONS '())\n  (set! THE-RULES '())\n\n  (put 'and 'qeval conjoin)\n  (put 'or 'qeval disjoin)\n  (put 'not 'qeval negate)\n  (put 'lisp-value 'qeval lisp-value)\n  (put 'always-true 'qeval always-true))\n\n(reset-state!)\n\n(load-relative \"showcase/query/database.scm\")\n(add-to-data-base! grands-rules)\n"
  },
  {
    "path": "scheme/sicp/04/70.scm",
    "content": "; SICP exercise 4.70\n;\n; What is the purpose of the let bindings in the procedures add-assertion! and\n; add-rule! ? What would be wrong with the following implementation of\n; add-assertion! ? Hint: Recall the definition of the infinite stream of ones\n; in section 3.5.2: (define ones (cons-stream 1 ones)).\n; \n; (define (add-assertion! assertion)\n;   (store-assertion-in-index assertion)\n;   (set! THE-ASSERTIONS\n;         (cons-stream assertion THE-ASSERTIONS))\n;   'ok)\n\n; If we define add-assertion! that way, THE-ASSERTIONS will effectively be a\n; stream containing infinitely many times the passed assertion. The reason is\n; that THE-ASSERTIONS is evaluated in a lazy way.\n"
  },
  {
    "path": "scheme/sicp/04/71.scm",
    "content": "; SICP exercise 4.71\n;\n; Louis Reasoner wonders why the simple-query and disjoin procedures (section\n; 4.4.4.2) are implemented using explicit delay operations, rather than being\n; defined as follows:\n;\n; (define (simple-query query-pattern frame-stream)\n;   (stream-flatmap\n;     (lambda (frame)\n;       (stream-append (find-assertions query-pattern frame)\n;                      (apply-rules query-pattern frame)))\n;     frame-stream))\n; (define (disjoin disjuncts frame-stream)\n;   (if (empty-disjunction? disjuncts)\n;       the-empty-stream\n;       (interleave\n;         (qeval (first-disjunct disjuncts) frame-stream)\n;         (disjoin (rest-disjuncts disjuncts) frame-stream))))\n;\n; Can you give examples of queries where these simpler definitions would lead\n; to undesirable behavior?\n\n; Assuming the implementation of streams suggested in the book, the second\n; argument to both function will get evaluated before calling the function,\n; which might lead to infinite recursions. To be fair, this has only a single\n; disadvantage - using the delayed versions we can get some results printed,\n; before the interpreter gets stuck in an infinite loop. With this adjustment,\n; we won't get any results before getting stuck.\n;\n; An example is the following rule:\n;\n; (something a)\n; (rule (something ?a)\n;       (something ?a))\n;\n; And the query is:\n;\n; (something ?what)\n"
  },
  {
    "path": "scheme/sicp/04/72.scm",
    "content": "; SICP exercise 4.72\n;\n; Why do disjoin and stream-flatmap interleave the streams rather than simply\n; append them? Give examples that illustrate why interleaving works better.\n; (Hint: Why did we use interleave in section 3.5.3?)\n\n; It is pretty much the same as in last exercise. If the first stream is\n; infinite, this gives a chance for elements of the second stream to be\n; returned. If we don't interleave, the first stream will possibly not let the\n; interpreter report terminating results from the second stream.\n;\n; However, this still does not make a big difference in my opinion. The\n; interpreter gets a chance to to report some results before getting stuck,\n; but in the long run, I don't think that makes a meaningful difference.\n"
  },
  {
    "path": "scheme/sicp/04/73.scm",
    "content": "; SICP exercise 4.73\n;\n; Why does flatten-stream use delay explicitly? What would be wrong with\n; defining it as follows:\n;\n; (define (flatten-stream stream)\n;   (if (stream-null? stream)\n;       the-empty-stream\n;       (interleave\n;         (stream-car stream)\n;         (flatten-stream (stream-cdr stream)))))\n\n; Well, to be fair, this is just how I implemented it. If it is defined that\n; way, flatten-stream would not terminate if the stream is infinite.\n"
  },
  {
    "path": "scheme/sicp/04/74.scm",
    "content": "; SICP exercise 4.74\n;\n; Alyssa P. Hacker proposes to use a simpler version of stream-flatmap in\n; negate, lisp-value, and find-assertions. She observes that the procedure\n; that is mapped over the frame stream in these cases always produces either\n; the empty stream or a singleton stream, so no interleaving is needed when\n; combining those streams.\n;\n; a. Fill in the missing expressions in Alyssa's program.\n;\n; (define (simple-stream-flatmap proc s)\n;   (simple-flatten (stream-map proc s)))\n;\n; (define (simple-flatten stream)\n;   (stream-map <??>\n;               (stream-filter <??> stream)))\n;\n; b. Does the query system's behavior change if we change it in this way?\n\n; a. This is the solution:\n;\n; (define (simple-stream-flatmap proc s)\n;   (simple-flatten (stream-map proc s)))\n;\n; (define (simple-flatten stream)\n;   (stream-map stream-car\n;               (stream-filter (lambda (s) (not (stream-null? s))) stream)))\n;\n; b. I don't see how the system behavior might change.\n"
  },
  {
    "path": "scheme/sicp/04/75.scm",
    "content": "; SICP exercise 4.75\n;\n; Implement for the query language a new special form called unique. Unique\n; should succeed if there is precisely one item in the data base satisfying a\n; specified query. For example,\n;\n; (unique (job ?x (computer wizard)))\n;\n; should print the one-item stream\n;\n; (unique (job (Bitdiddle Ben) (computer wizard)))\n;\n; since Ben is the only computer wizard, and\n;\n; (unique (job ?x (computer programmer)))\n;\n; should print the empty stream, since there is more than one computer\n; programmer. Moreover,\n;\n; (and (job ?x ?j) (unique (job ?anyone ?j)))\n;\n; should list all the jobs that are filled by only one person, and the people\n; who fill them.\n;\n; There are two parts to implementing unique. The first is to write a\n; procedure that handles this special form, and the second is to make qeval\n; dispatch to that procedure. The second part is trivial, since qeval does its\n; dispatching in a data-directed way. If your procedure is called\n; uniquely-asserted, all you need to do is:\n;\n; (put 'unique 'qeval uniquely-asserted)\n;\n; and qeval will dispatch to this procedure for every query whose type (car)\n; is the symbol unique.\n;\n; The real problem is to write the procedure uniquely-asserted. This should\n; take as input the contents (cdr) of the unique query, together with a stream\n; of frames. For each frame in the stream, it should use qeval to find the\n; stream of all extensions to the frame that satisfy the given query. Any\n; stream that does not have exactly one item in it should be eliminated. The\n; remaining strems should be passed back to be accumulated into one big stream\n; that is the result of the unique query. This is similar to the\n; implementation of the not special form.\n;\n; Test your implementation by forming a query that lists all people who\n; supervise precisely one person.\n\n(define (uniquely-asserted query frame-stream)\n  (stream-flatmap\n    (lambda (frame)\n      (let ((result (qeval (car query) (singleton-stream frame))))\n        (cond ((stream-empty? result) empty-stream)\n              ((not (stream-empty? (stream-rest result))) empty-stream)\n              (else (singleton-stream (stream-first result))))))\n    frame-stream))\n\n(put 'unique 'qeval uniquely-asserted)\n\n(define supervises-one-person '(and (supervisor ?j ?x) (unique (supervisor ?anyone ?x))))\n"
  },
  {
    "path": "scheme/sicp/04/76.scm",
    "content": "; SICP exercise 4.76\n;\n; Our implementation of and as a series combination of queries (figure 4.5) is\n; elegant, but it is inefficient because in processing the second query of the\n; and we must scan the data base for each frame produced by the first query.\n; If the data base has N elements, and a typical query produces a number of\n; output frames proportional to N (say N/k), then scanning the data base for\n; each frame produced by the first query will require N²/k calls to the\n; pattern matcher. Another approach would be to process the two clauses of the\n; and separately, then look for all pairs of output frames that are\n; compatible. If each query produces N/k output frames, then this means that\n; we must perform N²/k² compatibility checks -- a factor of k fewer than the\n; number of matches required in our current method.\n;\n; Devise an implementation of and that uses this strategy. You must implement\n; a procedure that takes two frames as inputs, checks whether the bindings in\n; the frames are compatible, and, if so, produces a frame that merges the two\n; sets of bindings. This operation is similar to unification.\n\n; The implementation is below. It has its disadvantages, though. First, the\n; following query stops working:\n;\n; (and (supervisor ?x (Bitdiddle Ben))\n;      (not (job ?x (computer programmer))))\n;\n; The reason is that (not (job ?x (computer programmer))) results to the empty\n; stream of frames.\n;\n; There is another issue, which is illustrated in the outranked-by rule:\n;\n; (rule (outranked-by ?staff-person ?boss)\n;       (or (supervisor ?staff-person ?boss)\n;           (and (supervisor ?staff-person ?middle-manager)\n;                (outranked-by ?middle-manager ?boss))))\n;\n; In this case, outranked-by results to an infinte loop, since\n;\n; (outranked-by ?staff-person ?boss)\n;\n; calls directly\n;\n; (outranked-by ?middle-manager ?boss)\n;\n; and all frames (not just the reduced set of frames from the previous\n; conjunct.\n\n(define (merge-frames frame1 frame2)\n  (cond ((null? frame1) frame2)\n        ((eq? 'failed frame2) 'failed)\n        (else\n         (let ((var (binding-variable (car frame1)))\n               (val (binding-value (car frame1))))\n           (let ((extension (extend-if-possible var val frame2)))\n             (merge-frames (cdr frame1) extension))))))\n\n(define (conjoin-frame-streams stream1 stream2)\n  (stream-flatmap\n    (lambda (frame1)\n      (stream-filter\n        (lambda (frame) (not (eq? frame 'failed)))\n        (stream-map\n          (lambda (frame2) (merge-frames frame1 frame2))\n          stream2)))\n    stream1))\n\n(define (faster-conjoin conjuncts frame-stream)\n  (if (empty-conjunction? conjuncts)\n      frame-stream\n      (conjoin-frame-streams\n        (qeval (first-conjunct conjuncts) frame-stream)\n        (conjoin (rest-conjuncts conjuncts) frame-stream))))\n\n(put 'and 'qeval faster-conjoin)\n"
  },
  {
    "path": "scheme/sicp/04/77.scm",
    "content": "; SICP exercise 4.77\n;\n; In section 4.4.3 we saw that not and lisp-value can cause the query langauge\n; to give \"wrong\" answers if these filtering operations are applied to frames\n; in which variables are unbound. Devise a way to fix this shortcoming. One\n; idea is to perform the filtering in a \"delayed\" manner by appending to the\n; frame a \"promise\" to filter that is fulfilled only when enough variables\n; have been bound to make the operation possible. We could wait to perform\n; filtering until all other operations have been performed. However, for\n; efficiency's sake, we would like to perform filtering as soon as possible so\n; as to cut down on the number of intermediate frames generated.\n\n; Sure. This is fun.\n;\n; We extend the frame to store an list of promises. Each promise is list of\n; free variables and a predicate. Once all the free variables have been bound,\n; the predicate is evaluted on the frame.\n;\n; This process is handled by the procedure compact-frame. It evaluates to\n; topmost promise if all the necessary free variables have been bound. If the\n; predicate fails, it returns 'failed. If it passes, it constructs a frame\n; without the topmost promise and applies itself recursively. The process\n; stops until (1) a promise with free variables is encountered, (2) all\n; promises have been fulfiled or (3) a promise fails and compact-frame returns\n; 'failed.\n;\n; compact-frame is invoked in extend after the new frame has been constructed.\n; Since all the calls to extend take into account the possiblity of returing\n; the symbol 'failed, there is system works like a charm.\n\n; Frames, Bindings and Promises\n\n(define (make-frame bindings promises)\n  (list bindings promises))\n(define (frame-bindings frame)\n  (car frame))\n(define (frame-promises frame)\n  (cadr frame))\n(define empty-frame (make-frame '() '()))\n\n(define (make-binding variable value)\n  (cons variable value))\n(define (binding-variable binding)\n  (car binding))\n(define (binding-value binding)\n  (cdr binding))\n(define (binding-in-frame variable frame)\n  (assoc variable (frame-bindings frame)))\n(define (extend variable value frame)\n  (compact-frame\n    (make-frame (cons (make-binding variable value)\n                      (frame-bindings frame))\n                (frame-promises frame))))\n\n(define (make-promise variables predicate)\n  (cons variables predicate))\n(define (promise-variables promise)\n  (car promise))\n(define (promise-predicate promise)\n  (cdr promise))\n\n(define (free-var? var frame)\n  (let ((binding (binding-in-frame var frame)))\n    (or (not binding)\n        (and (var? (binding-value binding))\n             (free-var? (binding-value binding) frame)))))\n\n(define (free-variables-in query frame)\n  (cond ((null? query) '())\n        ((and (var? query) (free-var? query frame)) (list query))\n        ((pair? query) (append (free-variables-in (car query) frame)\n                               (free-variables-in (cdr query) frame)))\n        (else '())))\n\n(define (compact-frame frame)\n  (let ((promises (frame-promises frame)))\n    (if (null? promises)\n        frame\n        (let* ((promise (car promises))\n               (rest-promises (cdr promises))\n               (vars (promise-variables promise))\n               (predicate (promise-predicate promise))\n               (has-free-vars? (ormap (lambda (var) (free-var? var frame)) vars)))\n          (cond (has-free-vars? frame)\n                ((predicate frame)\n                 (compact-frame (make-frame (frame-bindings frame)\n                                            rest-promises)))\n                (else 'failed))))))\n\n(define (promise-to-frame frame free-vars predicate)\n  (make-frame (frame-bindings frame)\n              (cons (make-promise free-vars predicate)\n                    (frame-promises frame))))\n\n; negate and lisp-value, modified to suit the new implementation\n\n(define (negate operands frame-stream)\n  (stream-map\n    (lambda (frame)\n      (promise-to-frame\n        frame\n        (free-variables-in (negated-query operands) frame)\n        (lambda (frame)\n          (stream-empty? (qeval (negated-query operands) (singleton-stream frame))))))\n    frame-stream))\n\n(define (lisp-value call frame-stream)\n  (stream-map\n    (lambda (frame)\n      (promise-to-frame\n        frame\n        (free-variables-in call frame)\n        (lambda (frame)\n          (execute\n            (instantiate-exp call\n                             frame\n                             (lambda (v f) (error \"Unknown var -- LISP-VALUE\" v)))))))\n    frame-stream))\n\n; The Driver Loop and Instantiation\n\n(define input-prompt \";;; Query input:\")\n(define output-prompt \";;; Query output:\")\n(define (query-driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((q (query-syntax-process (read))))\n    (cond ((assertion-to-be-added? q)\n           (add-rule-or-assertion! (add-assertion-body q))\n           (newline)\n           (display \"Assertion added to data base.\")\n           (query-driver-loop))\n          (else\n           (newline)\n           (display output-prompt)\n           (display-stream\n             (stream-map\n               (lambda (frame)\n                 (instantiate-exp q\n                                  frame\n                                  (lambda (v f) (contract-question-mark v))))\n               (qeval q (singleton-stream '()))))\n           (query-driver-loop)))))\n\n(define (instantiate-exp exp frame unbound-var-handler)\n  (define (copy exp)\n    (cond ((var? exp)\n           (let ((binding (binding-in-frame exp frame)))\n             (if binding\n                 (copy (binding-value binding))\n                 (unbound-var-handler exp frame))))\n          ((pair? exp)\n           (cons (copy (car exp)) (copy (cdr exp))))\n          (else exp)))\n  (copy exp))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (display-stream stream)\n  (unless (stream-empty? stream)\n          (newline)\n          (display (stream-first stream))\n          (display-stream (stream-rest stream))))\n\n; The Evaluator\n\n(define (qeval query frame-stream)\n  (let ((qproc (get (type query) 'qeval)))\n    (if qproc\n        (qproc (contents query) frame-stream)\n        (simple-query query frame-stream))))\n\n(define (execute exp)\n  (apply (eval (predicate exp))\n         (args exp)))\n\n(define (simple-query query-pattern frame-stream)\n  (stream-flatmap\n    (lambda (frame)\n      (stream-append\n        (find-assertions query-pattern frame)\n        (apply-rules query-pattern frame)))\n    frame-stream))\n\n(define conjoin '())\n(define (conjoin conjuncts frame-stream)\n  (if (empty-conjunction? conjuncts)\n      frame-stream\n      (conjoin (rest-conjuncts conjuncts)\n               (qeval (first-conjunct conjuncts)\n                      frame-stream))))\n\n(define disjoin '())\n(define (disjoin disjuncts frame-stream)\n  (if (empty-disjunction? disjuncts)\n      empty-stream\n      (interleave (qeval (first-disjunct disjuncts) frame-stream)\n                  (disjoin (rest-disjuncts disjuncts)\n                           frame-stream))))\n\n(define (always-true ignore frame-stream)\n  frame-stream)\n\n; Finding Assertions by Pattern Matching\n\n(define (find-assertions pattern frame)\n  (stream-flatmap (lambda (datum) (check-an-assertion datum pattern frame))\n                  (fetch-assertions pattern frame)))\n\n(define (check-an-assertion assertion query-pat query-frame)\n  (let ((match-result (pattern-match query-pat assertion query-frame)))\n    (if (eq? match-result 'failed)\n        empty-stream\n        (singleton-stream match-result))))\n\n(define (pattern-match pat dat frame)\n  (cond ((eq? frame 'failed) 'failed)\n        ((equal? pat dat) frame)\n        ((var? pat) (extend-if-consistent pat dat frame))\n        ((and (pair? pat) (pair? dat))\n         (pattern-match (cdr pat)\n                        (cdr dat)\n                        (pattern-match (car pat)\n                                       (car dat)\n                                       frame)))\n        (else 'failed)))\n\n(define (extend-if-consistent var dat frame)\n  (let ((binding (binding-in-frame var frame)))\n    (if binding\n        (pattern-match (binding-value binding) dat frame)\n        (extend var dat frame))))\n\n; Rules and Unification\n\n(define (apply-rules pattern frame)\n  (stream-flatmap (lambda (rule) (apply-a-rule rule pattern frame))\n                  (fetch-rules pattern frame)))\n\n(define (apply-a-rule rule query-pattern query-frame)\n  (let ((clean-rule (rename-variables-in rule)))\n    (let ((unify-result (unify-match query-pattern\n                                     (conclusion clean-rule)\n                                     query-frame)))\n      (if (eq? unify-result 'failed)\n          empty-stream\n          (qeval (rule-body clean-rule)\n                 (singleton-stream unify-result))))))\n\n(define (rename-variables-in rule)\n  (let ((rule-application-id (new-rule-application-id)))\n    (define (tree-walk exp)\n      (cond ((var? exp)\n             (make-new-variable exp rule-application-id))\n            ((pair? exp)\n             (cons (tree-walk (car exp))\n                   (tree-walk (cdr exp))))\n            (else exp)))\n    (tree-walk rule)))\n\n(define (unify-match p1 p2 frame)\n  (cond ((eq? frame 'failed) 'failed)\n        ((equal? p1 p2) frame)\n        ((var? p1) (extend-if-possible p1 p2 frame))\n        ((var? p2) (extend-if-possible p2 p1 frame))\n        ((and (pair? p1) (pair? p2))\n         (unify-match (cdr p1)\n                      (cdr p2)\n                      (unify-match (car p1)\n                                   (car p2)\n                                   frame)))\n        (else 'failed)))\n\n(define (extend-if-possible var val frame)\n  (let ((binding (binding-in-frame var frame)))\n    (cond (binding (unify-match (binding-value binding) val frame))\n          ((var? val)\n           (let ((binding (binding-in-frame val frame)))\n             (if binding\n                 (unify-match var (binding-value binding) frame)\n                 (extend var val frame))))\n          ((depends-on? val var frame) 'failed)\n          (else (extend var val frame)))))\n\n(define (depends-on? exp var frame)\n  (define (tree-walk e)\n    (cond ((var? e)\n           (if (equal? var e)\n               true\n               (let ((b (binding-in-frame e frame)))\n                 (if b\n                     (tree-walk (binding-value b))\n                     false))))\n          ((pair? e)\n           (or (tree-walk (car e))\n               (tree-walk (cdr e))))\n          (else false)))\n  (tree-walk exp))\n\n; Maintaining the Data Base\n\n(define THE-ASSERTIONS '())\n(define (fetch-assertions pattern frame)\n  (if (use-index? pattern)\n      (get-indexed-assertions pattern)\n      (get-all-assertions)))\n(define (get-all-assertions)\n  (reverse-list->stream THE-ASSERTIONS))\n(define (get-indexed-assertions pattern)\n  (reverse-list->stream\n    (get-list (index-key-of pattern) 'assertion-list)))\n\n(define THE-RULES '())\n(define (fetch-rules pattern frame)\n  (if (use-index? pattern)\n      (get-indexed-rules pattern)\n      (get-all-rules)))\n(define (get-all-rules)\n  (reverse-list->stream THE-RULES))\n(define (get-indexed-rules pattern)\n  (reverse-list->stream\n    (append\n      (get-list '? 'rule-list)\n      (get-list (index-key-of pattern) 'rule-list))))\n\n(define (add-rule-or-assertion! assertion)\n  (if (rule? assertion)\n      (add-rule! assertion)\n      (add-assertion! assertion)))\n\n(define (add-assertion! assertion)\n  (store-assertion-in-index assertion)\n  (let ((old-assertions THE-ASSERTIONS))\n    (set! THE-ASSERTIONS (cons assertion old-assertions))\n    'ok))\n\n(define (add-rule! rule)\n  (store-rule-in-index rule)\n  (let ((old-rules THE-RULES))\n    (set! THE-RULES (cons rule old-rules))\n    'ok))\n\n(define (store-assertion-in-index assertion)\n  (when (indexable? assertion)\n        (let ((key (index-key-of assertion)))\n          (let ((current-assertion-list (get-list key 'assertion-list)))\n            (put key\n                 'assertion-list\n                 (cons assertion current-assertion-list))))))\n\n(define (store-rule-in-index rule)\n  (let ((pattern (conclusion rule)))\n    (when (indexable? pattern)\n          (let ((key (index-key-of pattern)))\n            (let ((current-rule-list (get-list key 'rule-list)))\n              (put key\n                   'rule-list\n                   (cons rule current-rule-list)))))))\n\n(define (indexable? pattern)\n  (or (constant-symbol? (car pattern))\n      (var? (car pattern))))\n\n(define (index-key-of pattern)\n  (let ((key (car pattern)))\n    (if (var? key) '? key)))\n\n(define (use-index? pattern)\n  (constant-symbol? (car pattern)))\n\n(define (list->stream items)\n  (if (null? items)\n      empty-stream\n      (stream-cons (car items)\n                   (list->stream (cdr items)))))\n\n(define (reverse-list->stream items)\n  (list->stream (reverse items)))\n\n(define (get-list key1 key2)\n  (let ((s (get key1 key2)))\n    (if s s '())))\n\n; Operator table\n\n(define table (make-hash))\n\n(define (put op type item)\n  (hash-set! table (list op type) item))\n\n(define (get op type)\n  (hash-ref table (list op type) #f))\n\n; Stream Operations\n\n(define (interleave s1 s2)\n  (if (stream-empty? s1)\n      s2\n      (stream-cons\n        (stream-first s1)\n        (interleave s2 (stream-rest s1)))))\n\n(define (stream-flatmap proc s)\n  (flatten-stream (stream-map proc s)))\n\n(define (flatten-stream stream)\n  (if (stream-empty? stream)\n      empty-stream\n      (interleave (stream-first stream)\n                  (flatten-stream (stream-rest stream)))))\n\n(define (singleton-stream x)\n  (stream-cons x empty-stream))\n\n; Query Syntax Procedures\n\n(define (type exp)\n  (if (pair? exp)\n    (car exp)\n    (error \"Unknown expression TYPE\" exp)))\n\n(define (contents exp)\n  (if (pair? exp)\n      (cdr exp)\n      (error \"Unknown expression CONTENTS\" exp)))\n\n(define (assertion-to-be-added? exp) (eq? (type exp) 'assert!))\n(define (add-assertion-body exp) (car (contents exp)))\n\n(define (empty-conjunction? exps) (null? exps))\n(define (first-conjunct exps) (car exps))\n(define (rest-conjuncts exps) (cdr exps))\n(define (empty-disjunction? exps) (null? exps))\n(define (first-disjunct exps) (car exps))\n(define (rest-disjuncts exps) (cdr exps))\n(define (negated-query exps) (car exps))\n(define (predicate exps) (car exps))\n(define (args exps) (cdr exps))\n\n(define (rule? statement) (tagged-list? statement 'rule))\n(define (conclusion rule) (cadr rule))\n(define (rule-body rule) (if (null? (cddr rule)) '(always-true) (caddr rule)))\n\n(define (query-syntax-process exp)\n  (map-over-symbols expand-question-mark exp))\n\n(define (map-over-symbols proc exp)\n  (cond ((pair? exp)\n         (cons (map-over-symbols proc (car exp))\n               (map-over-symbols proc (cdr exp))))\n        ((symbol? exp) (proc exp))\n        (else exp)))\n\n(define (expand-question-mark symbol)\n  (let ((chars (symbol->string symbol)))\n    (if (string=? (substring chars 0 1) \"?\")\n        (list '?\n              (string->symbol\n                (substring chars 1 (string-length chars))))\n        symbol)))\n\n(define (var? exp) (tagged-list? exp '?))\n(define (constant-symbol? exp) (symbol? exp))\n\n(define rule-counter 0)\n(define (new-rule-application-id)\n  (set! rule-counter (+ 1 rule-counter))\n  rule-counter)\n(define (make-new-variable var rule-application-id)\n  (cons '? (cons rule-application-id (cdr var))))\n\n(define (contract-question-mark variable)\n  (string->symbol\n    (string-append \"?\"\n                   (if (number? (cadr variable))\n                       (string-append (symbol->string (caddr variable))\n                                      \"-\"\n                                      (number->string (cadr variable)))\n                       (symbol->string (cadr variable))))))\n\n(define (tagged-list? exp tag)\n  (and (pair? exp)\n       (eq? (car exp) tag)))\n\n; Reseting the state\n\n(define (reset-state!)\n  (set! table (make-hash))\n  (set! rule-counter 0)\n  (set! THE-ASSERTIONS '())\n  (set! THE-RULES '())\n\n  (put 'and 'qeval conjoin)\n  (put 'or 'qeval disjoin)\n  (put 'not 'qeval negate)\n  (put 'lisp-value 'qeval lisp-value)\n  (put 'always-true 'qeval always-true))\n\n(reset-state!)\n"
  },
  {
    "path": "scheme/sicp/04/78.scm",
    "content": "; SICP exercise 4.78\n;\n; Redesign the query langauge as a nondeterministic program to be implemented\n; using the evaluator of section 4.3, rather than as a stream process. In this\n; approach, each query will produce a single answer (rather than the stream of\n; all answers) and the user can type try-again to see more answers. You should\n; find that much of the mechanism we built in this section is subsumed by\n; nondeterministic search and backtracking. You will probably also find,\n; however, that your new query language has subtle differences in behavior\n; from the one implemented here. Can you find examples that illustrate this\n; difference?\n\n; Let's not overdo it.\n;\n; I will implement this using an obscure PLaneT package that implements amb.\n; Afterwards it will be straightforward enough to port this to the\n; nondeterministic evaluator. I will, however, not do that yet. Maybe in the\n; future.\n;\n; I would also cheat a bit by using amb-collect in negate.\n;\n; Furthermore, the all subtle differences have to do with either getting stuck\n; in an infinite loop, having an infinite stream or the order of operations. I\n; don't find that very interesting, so I will not elaborate.\n\n(require (planet murphy/amb:1:1/amb))\n\n; Some amb mumbo-jumbo\n\n(define (require p)\n  (unless p (amb)))\n\n(define (an-element-of items)\n  (require (not (null? items)))\n  (amb (car items) (an-element-of (cdr items))))\n\n; The Driver Loop and Instantiation\n\n(define (instantiate-exp exp frame unbound-var-handler)\n  (define (copy exp)\n    (cond ((var? exp)\n           (let ((binding (binding-in-frame exp frame)))\n             (if binding\n                 (copy (binding-value binding))\n                 (unbound-var-handler exp frame))))\n          ((pair? exp)\n           (cons (copy (car exp)) (copy (cdr exp))))\n          (else exp)))\n  (copy exp))\n\n; The Evaluator\n\n(define (qeval query frame)\n  (let ((qproc (get (type query) 'qeval)))\n    (if qproc\n        (qproc (contents query) frame)\n        (simple-query query frame))))\n\n(define (execute exp)\n  (apply (eval (predicate exp))\n         (args exp)))\n\n(define (simple-query query-pattern frame)\n  (amb (find-assertions query-pattern frame)\n       (apply-rules query-pattern frame)))\n\n(define conjoin '())\n(define (conjoin conjuncts frame)\n  (if (empty-conjunction? conjuncts)\n      frame\n      (let ((match (qeval (first-conjunct conjuncts) frame)))\n        (require (matched? match))\n        (conjoin (rest-conjuncts conjuncts) match))))\n\n(define disjoin '())\n(define (disjoin disjuncts frame)\n  (if (empty-disjunction? disjuncts)\n      (amb)\n      (amb (qeval (first-disjunct disjuncts) frame)\n           (disjoin (rest-disjuncts disjuncts) frame))))\n\n(define (negate operands frame)\n  (require (null? (amb-collect (qeval (negated-query operands) frame))))\n  frame)\n\n(define (lisp-value call frame)\n  (require\n    (execute\n      (instantiate-exp call\n                       frame\n                       (lambda (v f) (error \"Unknown pat var -- LISP-VALUE\" v)))))\n  frame)\n\n(define (always-true ignore frame)\n  frame)\n\n; Finding Assertions by Pattern Matching\n\n(define (failed? result)\n  (eq? result 'failed))\n\n(define (matched? result)\n  (not (failed? result)))\n\n(define (find-assertions pattern frame)\n  (let ((assertion (an-element-of (fetch-assertions pattern frame))))\n    (let ((match (pattern-match pattern assertion frame)))\n      (require (matched? match))\n      match)))\n\n(define (pattern-match pat dat frame)\n  (cond ((eq? frame 'failed) 'failed)\n        ((equal? pat dat) frame)\n        ((var? pat) (extend-if-consistent pat dat frame))\n        ((and (pair? pat) (pair? dat))\n         (pattern-match (cdr pat)\n                        (cdr dat)\n                        (pattern-match (car pat)\n                                       (car dat)\n                                       frame)))\n        (else 'failed)))\n\n(define (extend-if-consistent var dat frame)\n  (let ((binding (binding-in-frame var frame)))\n    (if binding\n        (pattern-match (binding-value binding) dat frame)\n        (extend var dat frame))))\n\n; Rules and Unification\n\n(define (apply-rules pattern frame)\n  (let ((rule (an-element-of (fetch-rules pattern frame))))\n    (let ((clean-rule (rename-variables-in rule)))\n      (let ((unify-result (unify-match pattern\n                                       (conclusion clean-rule)\n                                       frame)))\n        (require (matched? unify-result))\n        (qeval (rule-body clean-rule) unify-result)))))\n\n(define (rename-variables-in rule)\n  (let ((rule-application-id (new-rule-application-id)))\n    (define (tree-walk exp)\n      (cond ((var? exp)\n             (make-new-variable exp rule-application-id))\n            ((pair? exp)\n             (cons (tree-walk (car exp))\n                   (tree-walk (cdr exp))))\n            (else exp)))\n    (tree-walk rule)))\n\n(define (unify-match p1 p2 frame)\n  (cond ((eq? frame 'failed) 'failed)\n        ((equal? p1 p2) frame)\n        ((var? p1) (extend-if-possible p1 p2 frame))\n        ((var? p2) (extend-if-possible p2 p1 frame))\n        ((and (pair? p1) (pair? p2))\n         (unify-match (cdr p1)\n                      (cdr p2)\n                      (unify-match (car p1)\n                                   (car p2)\n                                   frame)))\n        (else 'failed)))\n\n(define (extend-if-possible var val frame)\n  (let ((binding (binding-in-frame var frame)))\n    (cond (binding (unify-match (binding-value binding) val frame))\n          ((var? val)\n           (let ((binding (binding-in-frame val frame)))\n             (if binding\n                 (unify-match var (binding-value binding) frame)\n                 (extend var val frame))))\n          ((depends-on? val var frame) 'failed)\n          (else (extend var val frame)))))\n\n(define (depends-on? exp var frame)\n  (define (tree-walk e)\n    (cond ((var? e)\n           (if (equal? var e)\n               true\n               (let ((b (binding-in-frame e frame)))\n                 (if b\n                     (tree-walk (binding-value b))\n                     false))))\n          ((pair? e)\n           (or (tree-walk (car e))\n               (tree-walk (cdr e))))\n          (else false)))\n  (tree-walk exp))\n\n; Maintaining the Data Base\n\n(define THE-ASSERTIONS '())\n(define (fetch-assertions pattern frame)\n  (if (use-index? pattern)\n      (get-indexed-assertions pattern)\n      (get-all-assertions)))\n(define (get-all-assertions)\n  (reverse THE-ASSERTIONS))\n(define (get-indexed-assertions pattern)\n  (reverse (get-list (index-key-of pattern) 'assertion-list)))\n\n(define THE-RULES '())\n(define (fetch-rules pattern frame)\n  (if (use-index? pattern)\n      (get-indexed-rules pattern)\n      (get-all-rules)))\n(define (get-all-rules)\n  (reverse THE-RULES))\n(define (get-indexed-rules pattern)\n  (reverse\n    (append\n      (get-list '? 'rule-list)\n      (get-list (index-key-of pattern) 'rule-list))))\n\n(define (add-rule-or-assertion! assertion)\n  (if (rule? assertion)\n      (add-rule! assertion)\n      (add-assertion! assertion)))\n\n(define (add-assertion! assertion)\n  (store-assertion-in-index assertion)\n  (let ((old-assertions THE-ASSERTIONS))\n    (set! THE-ASSERTIONS (cons assertion old-assertions))\n    'ok))\n\n(define (add-rule! rule)\n  (store-rule-in-index rule)\n  (let ((old-rules THE-RULES))\n    (set! THE-RULES (cons rule old-rules))\n    'ok))\n\n(define (store-assertion-in-index assertion)\n  (when (indexable? assertion)\n        (let ((key (index-key-of assertion)))\n          (let ((current-assertion-list (get-list key 'assertion-list)))\n            (put key\n                 'assertion-list\n                 (cons assertion current-assertion-list))))))\n\n(define (store-rule-in-index rule)\n  (let ((pattern (conclusion rule)))\n    (when (indexable? pattern)\n          (let ((key (index-key-of pattern)))\n            (let ((current-rule-list (get-list key 'rule-list)))\n              (put key\n                   'rule-list\n                   (cons rule current-rule-list)))))))\n\n(define (indexable? pattern)\n  (or (constant-symbol? (car pattern))\n      (var? (car pattern))))\n\n(define (index-key-of pattern)\n  (let ((key (car pattern)))\n    (if (var? key) '? key)))\n\n(define (use-index? pattern)\n  (constant-symbol? (car pattern)))\n\n(define (get-list key1 key2)\n  (let ((s (get key1 key2)))\n    (if s s '())))\n\n; Operator table\n\n(define table (make-hash))\n\n(define (put op type item)\n  (hash-set! table (list op type) item))\n\n(define (get op type)\n  (hash-ref table (list op type) #f))\n\n; Query Syntax Procedures\n\n(define (type exp)\n  (if (pair? exp)\n    (car exp)\n    (error \"Unknown expression TYPE\" exp)))\n\n(define (contents exp)\n  (if (pair? exp)\n      (cdr exp)\n      (error \"Unknown expression CONTENTS\" exp)))\n\n(define (assertion-to-be-added? exp) (eq? (type exp) 'assert!))\n(define (add-assertion-body exp) (car (contents exp)))\n\n(define (empty-conjunction? exps) (null? exps))\n(define (first-conjunct exps) (car exps))\n(define (rest-conjuncts exps) (cdr exps))\n(define (empty-disjunction? exps) (null? exps))\n(define (first-disjunct exps) (car exps))\n(define (rest-disjuncts exps) (cdr exps))\n(define (negated-query exps) (car exps))\n(define (predicate exps) (car exps))\n(define (args exps) (cdr exps))\n\n(define (rule? statement) (tagged-list? statement 'rule))\n(define (conclusion rule) (cadr rule))\n(define (rule-body rule) (if (null? (cddr rule)) '(always-true) (caddr rule)))\n\n(define (query-syntax-process exp)\n  (map-over-symbols expand-question-mark exp))\n\n(define (map-over-symbols proc exp)\n  (cond ((pair? exp)\n         (cons (map-over-symbols proc (car exp))\n               (map-over-symbols proc (cdr exp))))\n        ((symbol? exp) (proc exp))\n        (else exp)))\n\n(define (expand-question-mark symbol)\n  (let ((chars (symbol->string symbol)))\n    (if (string=? (substring chars 0 1) \"?\")\n        (list '?\n              (string->symbol\n                (substring chars 1 (string-length chars))))\n        symbol)))\n\n(define (var? exp) (tagged-list? exp '?))\n(define (constant-symbol? exp) (symbol? exp))\n\n(define rule-counter 0)\n(define (new-rule-application-id)\n  (set! rule-counter (+ 1 rule-counter))\n  rule-counter)\n(define (make-new-variable var rule-application-id)\n  (cons '? (cons rule-application-id (cdr var))))\n\n(define (contract-question-mark variable)\n  (string->symbol\n    (string-append \"?\"\n                   (if (number? (cadr variable))\n                       (string-append (symbol->string (caddr variable))\n                                      \"-\"\n                                      (number->string (cadr variable)))\n                       (symbol->string (cadr variable))))))\n\n(define (tagged-list? exp tag)\n  (and (pair? exp)\n       (eq? (car exp) tag)))\n\n; Frames and Bindings\n\n(define (make-binding variable value)\n  (cons variable value))\n(define (binding-variable binding)\n  (car binding))\n(define (binding-value binding)\n  (cdr binding))\n(define (binding-in-frame variable frame)\n  (assoc variable frame))\n(define (extend variable value frame)\n  (cons (make-binding variable value) frame))\n\n; Reseting the state\n\n(define (reset-state!)\n  (set! table (make-hash))\n  (set! rule-counter 0)\n  (set! THE-ASSERTIONS '())\n  (set! THE-RULES '())\n\n  (put 'and 'qeval conjoin)\n  (put 'or 'qeval disjoin)\n  (put 'not 'qeval negate)\n  (put 'lisp-value 'qeval lisp-value)\n  (put 'always-true 'qeval always-true))\n\n(reset-state!)\n"
  },
  {
    "path": "scheme/sicp/04/79.scm",
    "content": "; SICP exercise 4.79\n;\n; When we implemented the Lisp evaluator in section 4.1, we saw how to use\n; local environments to avoid name conflicts between the parameters of\n; procedures. For example, in evaluating\n;\n; (define (square x)\n;   (* x x))\n; (define (sum-of-squares x y)\n;   (+ (square x) (square y)))\n; (sum-of-squares 3 4)\n;\n; there is no confusion between the x in square and the x in sum-of-squares,\n; because we evaluate the body of each procedure in an environment that is\n; specially constructed to contain bindings for the local variables. In the\n; query system, we used a different strategy to avoid name conflicts in\n; applying rules. Each time we apply a rule we rename the variables with new\n; names that are guaranteed to be unique. The analogous strategy for the Lisp\n; evaluator would be to do away with local environments and simply rename the\n; variables in the body of a procedure each time we apply the procedure.\n;\n; Implement for the query language a rule-application method that uses\n; environments rather than renaming. See if you can build on your environment\n; structure to create constructs in the query language for dealing with large\n; systems, such as the rule analog of block-structured procedures. Can you\n; relate any of this to the problem of making deductions in a context (e.g.,\n; \"If I supposed that P were true, then I would be able to deduce A and B.\")\n; as a method of problem solving? (This problem is open-ended. A good answer\n; is probably worth a Ph. D.).\n\n; Phew. That was some seriously tricky business.\n;\n; Our environment would be a list of frame, where each frame is a list of\n; bindings (a binding is an associative list, mapping variable to value). We\n; will also have a special kind of variables, called \"outer\" variables. If a\n; frame has a value for (? outer y), then this is the value of (? y) in the\n; parent frame.\n;\n; We also need a procedure that \"pops\" an environment. It removes the top\n; frame of the environment after copying all the outer variable assignments it\n; has to its parents. That is, when the first frame in an environment binds\n; (? outer y) to (1 2), then the procedure returns the second frame, extended\n; with a binding form ?y to (1 2).\n;\n; The rule application is as follows:\n;   1. We rename all variables in the query to outer variables\n;   2. We unify the rule conclusion with the renamed query in a new\n;      environment, whose parent is the current environment.\n;   3. If the unification was successful, we proceed to evaluate the body of\n;      the rule in the frame that resulted from the unification.\n;   4. We map the resulting stream to the procedure that pops the enviornment\n;\n; This results to a stream of frames, that have bindings for all the\n; variables in the query.\n;\n; In order to define rule-scoped rules and assertions, we are going to attach\n; rules and assertions to each frame. We have a special (if awkward) syntax\n; for inner definitions. Check out the tests for details.\n;\n; As for the implementation, there was a nice hint in the book. Namely, that\n; fetch-rules and fetch-assertions take an extra environment argument. That\n; way we can retrieve the rules or assertions in the current environment along\n; with the ones in the database.\n;\n; For retrieving the rules, we take the rules of each frame and instantiate\n; them in the frame (leaving the free variables as they are). We flatmap the\n; result and remove duplicates to avoid checking a rule multiple times (this\n; happens if a rule recursively invokes itself or the rule that defines it).\n; This introduce an important semantic: the variables in the conclusion of the\n; rule are bound within the inner rules. That is, a variable has the same\n; value within the body of the rule and the bodies and conclusions of its\n; inner rules.\n;\n; The process for assertions is the same.\n;\n; And I'm just going to ignore the open-ended question that gets you a Ph. D.\n\n; Environments, Frames and Bindings\n\n(define (empty-frame) (make-frame '() '() '() '()))\n(define (make-frame bindings assertions rules parent)\n  (list bindings assertions rules parent))\n(define (frame-bindings frame) (car frame))\n(define (frame-assertions frame) (cadr frame))\n(define (frame-rules frame) (caddr frame))\n(define (frame-parent frame) (cadddr frame))\n(define (make-binding variable value) (cons variable value))\n(define (binding-variable binding) (car binding))\n(define (binding-value binding) (cdr binding))\n(define (binding-in-env variable env)\n  (assoc variable (frame-bindings env)))\n\n; The selectors for rules\n\n(define (rule? statement) (tagged-list? statement 'rule))\n(define (conclusion rule) (cadr rule))\n(define (rule-inner-assertions rule)\n  (map cadr\n       (filter (lambda (sexp) (eq? (car sexp) 'assert!))\n               (cddr rule))))\n(define (rule-inner-rules rule)\n  (filter (lambda (sexp) (eq? (car sexp) 'rule))\n          (cddr rule)))\n(define (rule-body rule)\n  (let ((stripped (filter (lambda (sexp)\n                            (and (not (eq? (car sexp) 'rule))\n                                 (not (eq? (car sexp) 'assert!))))\n                          (cddr rule))))\n    (if (null? stripped)\n        '(always-true)\n        (car stripped))))\n(define (build-frame-for rule parent-env)\n  (make-frame '()\n              (rule-inner-assertions rule)\n              (rule-inner-rules rule)\n              parent-env))\n\n; Helper procedures for \"outer\" variables\n\n(define (outer? var)\n  (and (not (null? (cddr var)))\n       (eq? 'outer (cadr var))))\n\n(define (remove-outer var)\n  (cons '? (cddr var)))\n\n(define (add-outer-to-variables pattern env)\n  (instantiate-exp pattern\n                   env\n                   (lambda (var f) (append '(? outer) (cdr var)))))\n\n; Helper procedures for environments\n\n(define (substitute-variables expr env)\n  (instantiate-exp expr env (lambda (var frame) var)))\n\n(define (extend var val env)\n  (make-frame (add-or-redefine var val (frame-bindings env))\n              (frame-rules env)\n              (frame-assertions env)\n              (frame-parent env)))\n\n(define (add-or-redefine var val bindings)\n  (cons (make-binding var val)\n        (filter (lambda (binding) (not (equal? (binding-variable binding) var)))\n                bindings)))\n\n(define (pop-env env)\n  (define (merge binding frame)\n    (let ((var (binding-variable binding))\n          (val (binding-value binding)))\n      (if (outer? var)\n          (extend (remove-outer var)\n                  (substitute-variables val env)\n                  frame)\n          frame)))\n  (foldr merge (frame-parent env) (frame-bindings env)))\n\n; Extracting rules and assertions from environments\n\n(define (get-assertions-in-env env)\n  (if (null? env)\n      '()\n      (append (map (lambda (assertion) (substitute-variables assertion env))\n                   (frame-assertions env))\n              (get-assertions-in-env (frame-parent env)))))\n\n(define (get-rules-in-env env)\n  (if (null? env)\n      '()\n      (append (map (lambda (rule) (substitute-variables rule env))\n                   (frame-rules env))\n              (get-rules-in-env (frame-parent env)))))\n\n; Rule application\n\n(define (apply-a-rule rule query-pattern query-env)\n  (let ((new-env (build-frame-for rule query-env))\n        (renamed-query (add-outer-to-variables query-pattern query-env)))\n    (let ((unify-result (unify-match renamed-query\n                                     (conclusion rule)\n                                     new-env)))\n      (if (eq? unify-result 'failed)\n          empty-stream\n          (stream-map\n            pop-env\n            (qeval (rule-body rule)\n                   (singleton-stream unify-result)))))))\n\n; The result of the interpreter:\n; Instantiation\n\n(define (instantiate-exp exp env unbound-var-handler)\n  (define (copy exp)\n    (cond ((var? exp)\n           (let ((binding (binding-in-env exp env)))\n             (if binding\n                 (copy (binding-value binding))\n                 (unbound-var-handler exp env))))\n          ((pair? exp)\n           (cons (copy (car exp)) (copy (cdr exp))))\n          (else exp)))\n  (copy exp))\n\n; The Evaluator\n\n(define (qeval query env-stream)\n  (let ((qproc (get (type query) 'qeval)))\n    (if qproc\n        (qproc (contents query) env-stream)\n        (simple-query query env-stream))))\n\n(define (execute exp)\n  (apply (eval (predicate exp))\n         (args exp)))\n\n(define (simple-query query-pattern env-stream)\n  (stream-flatmap\n    (lambda (env)\n      (stream-append\n        (find-assertions query-pattern env)\n        (apply-rules query-pattern env)))\n    env-stream))\n\n(define conjoin '())\n(define (conjoin conjuncts env-stream)\n  (if (empty-conjunction? conjuncts)\n      env-stream\n      (conjoin (rest-conjuncts conjuncts)\n               (qeval (first-conjunct conjuncts)\n                      env-stream))))\n\n(define disjoin '())\n(define (disjoin disjuncts env-stream)\n  (if (empty-disjunction? disjuncts)\n      empty-stream\n      (interleave (qeval (first-disjunct disjuncts) env-stream)\n                  (disjoin (rest-disjuncts disjuncts)\n                           env-stream))))\n\n(define (negate operands env-stream)\n  (stream-flatmap\n    (lambda (env)\n      (if (stream-empty? (qeval (negated-query operands) (singleton-stream env)))\n          (singleton-stream env)\n          empty-stream))\n    env-stream))\n\n(define (lisp-value call env-stream)\n  (stream-flatmap\n    (lambda (env)\n      (if (execute\n            (instantiate-exp call\n                             env\n                             (lambda (v e) (error \"Unknown pat var -- LISP-VALUE\" v))))\n          (singleton-stream env)\n          empty-stream))\n    env-stream))\n\n(define (always-true ignore env-stream)\n  env-stream)\n\n; Finding Assertions by Pattern Matching\n\n(define (find-assertions pattern env)\n  (stream-flatmap (lambda (datum) (check-an-assertion datum pattern env))\n                  (fetch-assertions pattern env)))\n\n(define (check-an-assertion assertion query-pat query-env)\n  (let ((match-result (pattern-match query-pat assertion query-env)))\n    (if (eq? match-result 'failed)\n        empty-stream\n        (singleton-stream match-result))))\n\n(define (pattern-match pat dat env)\n  (cond ((eq? env 'failed) 'failed)\n        ((equal? pat dat) env)\n        ((var? pat) (extend-if-consistent pat dat env))\n        ((and (pair? pat) (pair? dat))\n         (pattern-match (cdr pat)\n                        (cdr dat)\n                        (pattern-match (car pat)\n                                       (car dat)\n                                       env)))\n        (else 'failed)))\n\n(define (extend-if-consistent var dat env)\n  (let ((binding (binding-in-env var env)))\n    (if binding\n        (pattern-match (binding-value binding) dat env)\n        (extend var dat env))))\n\n; Rules and Unification\n\n(define (apply-rules pattern env)\n  (stream-flatmap (lambda (rule) (apply-a-rule rule pattern env))\n                  (fetch-rules pattern env)))\n\n(define (unify-match p1 p2 env)\n  (cond ((eq? env 'failed) 'failed)\n        ((equal? p1 p2) env)\n        ((var? p1) (extend-if-possible p1 p2 env))\n        ((var? p2) (extend-if-possible p2 p1 env))\n        ((and (pair? p1) (pair? p2))\n         (unify-match (cdr p1)\n                      (cdr p2)\n                      (unify-match (car p1)\n                                   (car p2)\n                                   env)))\n        (else 'failed)))\n\n(define (extend-if-possible var val env)\n  (let ((binding (binding-in-env var env)))\n    (cond (binding (unify-match (binding-value binding) val env))\n          ((var? val)\n           (let ((binding (binding-in-env val env)))\n             (if binding\n                 (unify-match var (binding-value binding) env)\n                 (extend var val env))))\n          ((depends-on? val var env) 'failed)\n          (else (extend var val env)))))\n\n(define (depends-on? exp var env)\n  (define (tree-walk e)\n    (cond ((var? e)\n           (if (equal? var e)\n               true\n               (let ((b (binding-in-env e env)))\n                 (if b\n                     (tree-walk (binding-value b))\n                     false))))\n          ((pair? e)\n           (or (tree-walk (car e))\n               (tree-walk (cdr e))))\n          (else false)))\n  (tree-walk exp))\n\n; Maintaining the Data Base\n\n(define THE-ASSERTIONS '())\n(define (fetch-assertions pattern env)\n  (reverse-list->stream\n    (remove-duplicates\n      (append (get-assertions-in-env env)\n              (if (use-index? pattern)\n                (get-indexed-assertions pattern)\n                (get-all-assertions))))))\n(define (get-all-assertions)\n  THE-ASSERTIONS)\n(define (get-indexed-assertions pattern)\n  (get-list (index-key-of pattern) 'assertion-list))\n\n(define THE-RULES '())\n(define (fetch-rules pattern env)\n  (reverse-list->stream\n    (remove-duplicates\n      (append (get-rules-in-env env)\n              (if (use-index? pattern)\n                (get-indexed-rules pattern)\n                (get-all-rules))))))\n(define (get-all-rules)\n  THE-RULES)\n(define (get-indexed-rules pattern)\n  (append\n    (get-list '? 'rule-list)\n    (get-list (index-key-of pattern) 'rule-list)))\n\n(define (add-rule-or-assertion! assertion)\n  (if (rule? assertion)\n      (add-rule! assertion)\n      (add-assertion! assertion)))\n\n(define (add-assertion! assertion)\n  (store-assertion-in-index assertion)\n  (let ((old-assertions THE-ASSERTIONS))\n    (set! THE-ASSERTIONS (cons assertion old-assertions))\n    'ok))\n\n(define (add-rule! rule)\n  (store-rule-in-index rule)\n  (let ((old-rules THE-RULES))\n    (set! THE-RULES (cons rule old-rules))\n    'ok))\n\n(define (store-assertion-in-index assertion)\n  (when (indexable? assertion)\n        (let ((key (index-key-of assertion)))\n          (let ((current-assertion-list (get-list key 'assertion-list)))\n            (put key\n                 'assertion-list\n                 (cons assertion current-assertion-list))))))\n\n(define (store-rule-in-index rule)\n  (let ((pattern (conclusion rule)))\n    (when (indexable? pattern)\n          (let ((key (index-key-of pattern)))\n            (let ((current-rule-list (get-list key 'rule-list)))\n              (put key\n                   'rule-list\n                   (cons rule current-rule-list)))))))\n\n(define (indexable? pattern)\n  (or (constant-symbol? (car pattern))\n      (var? (car pattern))))\n\n(define (index-key-of pattern)\n  (let ((key (car pattern)))\n    (if (var? key) '? key)))\n\n(define (use-index? pattern)\n  (constant-symbol? (car pattern)))\n\n(define (list->stream items)\n  (if (null? items)\n      empty-stream\n      (stream-cons (car items)\n                   (list->stream (cdr items)))))\n\n(define (reverse-list->stream items)\n  (list->stream (reverse items)))\n\n(define (get-list key1 key2)\n  (let ((s (get key1 key2)))\n    (if s s '())))\n\n; Operator table\n\n(define table (make-hash))\n\n(define (put op type item)\n  (hash-set! table (list op type) item))\n\n(define (get op type)\n  (hash-ref table (list op type) #f))\n\n; Stream Operations\n\n(define (interleave s1 s2)\n  (if (stream-empty? s1)\n      s2\n      (stream-cons\n        (stream-first s1)\n        (interleave s2 (stream-rest s1)))))\n\n(define (stream-flatmap proc s)\n  (flatten-stream (stream-map proc s)))\n\n(define (flatten-stream stream)\n  (if (stream-empty? stream)\n      empty-stream\n      (interleave (stream-first stream)\n                  (flatten-stream (stream-rest stream)))))\n\n(define (singleton-stream x)\n  (stream-cons x empty-stream))\n\n; Query Syntax Procedures\n\n(define (type exp)\n  (if (pair? exp)\n    (car exp)\n    (error \"Unknown expression TYPE\" exp)))\n\n(define (contents exp)\n  (if (pair? exp)\n      (cdr exp)\n      (error \"Unknown expression CONTENTS\" exp)))\n\n(define (assertion-to-be-added? exp) (eq? (type exp) 'assert!))\n(define (add-assertion-body exp) (car (contents exp)))\n\n(define (empty-conjunction? exps) (null? exps))\n(define (first-conjunct exps) (car exps))\n(define (rest-conjuncts exps) (cdr exps))\n(define (empty-disjunction? exps) (null? exps))\n(define (first-disjunct exps) (car exps))\n(define (rest-disjuncts exps) (cdr exps))\n(define (negated-query exps) (car exps))\n(define (predicate exps) (car exps))\n(define (args exps) (cdr exps))\n\n(define (query-syntax-process exp)\n  (map-over-symbols expand-question-mark exp))\n\n(define (map-over-symbols proc exp)\n  (cond ((pair? exp)\n         (cons (map-over-symbols proc (car exp))\n               (map-over-symbols proc (cdr exp))))\n        ((symbol? exp) (proc exp))\n        (else exp)))\n\n(define (expand-question-mark symbol)\n  (let ((chars (symbol->string symbol)))\n    (if (string=? (substring chars 0 1) \"?\")\n        (list '?\n              (string->symbol\n                (substring chars 1 (string-length chars))))\n        symbol)))\n\n(define (var? exp) (tagged-list? exp '?))\n(define (constant-symbol? exp) (symbol? exp))\n\n(define rule-counter 0)\n(define (new-rule-application-id)\n  (set! rule-counter (+ 1 rule-counter))\n  rule-counter)\n(define (make-new-variable var rule-application-id)\n  (cons '? (cons rule-application-id (cdr var))))\n\n(define (contract-question-mark variable)\n  (string->symbol\n    (string-append \"?\"\n                   (if (number? (cadr variable))\n                       (string-append (symbol->string (caddr variable))\n                                      \"-\"\n                                      (number->string (cadr variable)))\n                       (symbol->string (cadr variable))))))\n\n(define (tagged-list? exp tag)\n  (and (pair? exp)\n       (eq? (car exp) tag)))\n\n; Reseting the state\n\n(define (reset-state!)\n  (set! table (make-hash))\n  (set! rule-counter 0)\n  (set! THE-ASSERTIONS '())\n  (set! THE-RULES '())\n\n  (put 'and 'qeval conjoin)\n  (put 'or 'qeval disjoin)\n  (put 'not 'qeval negate)\n  (put 'lisp-value 'qeval lisp-value)\n  (put 'always-true 'qeval always-true))\n\n(reset-state!)\n"
  },
  {
    "path": "scheme/sicp/04/showcase/amb/evaluator.scm",
    "content": "; Our interpreter will not scan out definitions. Instead, it will rely on the\n; programmer putting their internal definitions in the beginning of the\n; procedures. This is a simplifying assumption.\n\n(require r5rs/init)\n\n(define (ambeval exp env succeed fail)\n  ((analyze exp) env succeed fail))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((amb? exp) (analyze-amb exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args succeed fail)\n  (cond ((primitive-procedure? proc)\n         (succeed (apply-primitive-procedure proc args) fail))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))\n          succeed\n          fail))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env succeed fail)\n    (succeed exp fail)))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env succeed fail)\n      (succeed qval fail))))\n\n(define (analyze-variable exp)\n  (lambda (env succeed fail)\n    (succeed (lookup-variable-value exp env) fail)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (let ((old-value (lookup-variable-value var env)))\n                 (set-variable-value! var val env)\n                 (succeed 'ok\n                          (lambda ()\n                            (set-variable-value! var old-value env)\n                            (fail2)))))\n             fail))))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env succeed fail)\n      (vproc env\n             (lambda (val fail2)\n               (define-variable! var val env)\n               (succeed 'ok fail2))\n             fail))))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env succeed fail)\n      (pproc env\n             (lambda (pred-value fail2)\n               (if (true? pred-value)\n                 (cproc env succeed fail2)\n                 (aproc env succeed fail2)))\n             fail))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env succeed fail)\n      (succeed (make-procedure vars bproc env) fail))))\n\n(define (analyze-sequence exps)\n  (define (sequentially a b)\n    (lambda (env succeed fail)\n      (a env\n         (lambda (a-value fail2)\n           (b env succeed fail2))\n         fail)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env succeed fail)\n      (fproc env\n             (lambda (proc fail2)\n               (get-args aprocs\n                         env\n                         (lambda (args fail3)\n                           (execute-application proc args succeed fail3))\n                         fail2))\n             fail))))\n\n(define (analyze-amb exp)\n  (let ((cprocs (map analyze (amb-choices exp))))\n    (lambda (env succeed fail)\n      (define (try-next choices)\n        (if (null? choices)\n            (fail)\n            ((car choices) env\n                           succeed\n                           (lambda () (try-next (cdr choices))))))\n      (try-next cprocs))))\n\n(define (get-args aprocs env succeed fail)\n  (if (null? aprocs)\n      (succeed '() fail)\n      ((car aprocs) env\n                    (lambda (arg fail2)\n                      (get-args (cdr aprocs)\n                                env\n                                (lambda (args fail3)\n                                  (succeed (cons arg args) fail3))\n                                fail2))\n                    fail)))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (amb? exp) (tagged-list? exp 'amb))\n(define (amb-choices exp) (cdr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list 'list list)\n        (list 'not not)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define definitions\n  '((define (require p)\n      (if (not p) (amb)))\n    (define (an-element-of items)\n      (require (not (null? items)))\n      (amb (car items) (an-element-of (cdr items))))))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    (for-each (lambda (definition)\n                (ambeval definition initial-env (lambda (value fail) 'ok) (lambda () 'ok)))\n              definitions)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; Amb-Eval input:\")\n(define output-prompt \";;; Amb-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (driver-loop)\n  (define (internal-loop try-again)\n    (prompt-for-input input-prompt)\n    (let ((input (read)))\n      (if (eq? input 'try-again)\n          (try-again)\n          (begin\n            (newline)\n            (display \";;; Starting a new problem\")\n            (ambeval input\n                     the-global-environment\n                     (lambda (val next-alternative)\n                       (announce-output output-prompt)\n                       (user-print val)\n                       (internal-loop next-alternative))\n                     (lambda ()\n                       (announce-output \";;; There are no more values of\")\n                       (user-print input)\n                       (driver-loop)))))))\n  (internal-loop\n    (lambda ()\n      (newline)\n      (display \";;; There is no current problem\")\n      (driver-loop))))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/showcase/amb/main.scm",
    "content": "(load \"evaluator.scm\")\n(driver-loop)\n"
  },
  {
    "path": "scheme/sicp/04/showcase/amb/tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n\n(load \"evaluator.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define evaluator-tests\n  (test-suite\n    \"Tests for the nondeterministic evaluator\"\n\n    (test-suite \"Self-evaluating expressions\"\n      (check-equal? (run '1) 1)\n      (check-equal? (run '\"something\") \"something\"))\n\n    (test-suite \"Variables\"\n      (check-equal? (evaluate 'x (extend-environment '(x) '(1) the-empty-environment))\n                    1)\n      (check-exn exn? (lambda () (evaluate 'x the-empty-environment))))\n\n    (test-suite \"Quotation\"\n      (check-equal? (run '(quote foo)) 'foo))\n\n    (test-suite \"Begin\"\n      (check-equal? (run '(begin 1 2)) 2))\n\n    (test-suite \"Define\"\n      (check-equal? (run '(define x 1)) 'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 x))\n                    1)\n      (check-equal? (run '(define (x) 1)) 'ok)\n      (check-equal? (run '(begin (define (x) 1)\n                                 (x)))\n                    1))\n\n    (test-suite \"Set!\"\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)))\n                    'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)\n                                 x))\n                    2))\n\n    (test-suite \"If\"\n      (check-equal? (run '(if true 1 2)) 1)\n      (check-equal? (run '(if false 1 2)) 2)\n      (check-equal? (run '(if true 1)) 1)\n      (check-equal? (run '(if false 1)) false))\n\n    (test-suite \"Lambda\"\n      (check-equal? (run '((lambda () 1))) 1)\n      (check-equal? (run '((lambda (x) x) 1)) 1)\n      (check-equal? (run '((lambda (a b) (cons a b)) 1 2)) '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 ((lambda (a) (cons a b)) 3)))\n                    '(3 . 2)))\n\n    (test-suite \"Cond\"\n      (check-equal? (run '(cond (true 1))) 1)\n      (check-equal? (run '(cond (false 1) (true 2))) 2)\n      (check-equal? (run '(cond (false 1) (else 2))) 2)\n      (check-exn exn? (lambda () (run '(cond (else 1) (true 2))))))\n\n    (test-suite \"Procedure application\"\n      (check-equal? (run '(begin (define (a) 1)\n                                 (a)))\n                    1)\n      (check-equal? (run '(begin (define (pair a b) (cons a b))\n                                 (pair 1 2)))\n                    '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define (pair b) (cons a b))\n                                 (pair 2)))\n                    '(1 . 2)))\n\n    (test-suite \"Defining append\"\n      (check-equal? (run '(begin (define (append x y)\n                                   (if (null? x)\n                                       y\n                                       (cons (car x)\n                                             (append (cdr x) y))))\n                                 (append '(a b c) '(d e f))))\n                    '(a b c d e f)))\n\n    (test-suite \"Factorial\"\n      (check-equal? (run '(begin (define (factorial n)\n                                   (if (= n 1)\n                                       1\n                                       (* n (factorial (- n 1)))))\n                                 (factorial 5)))\n                    120)\n      (check-equal? (run '(begin (define (factorial n)\n                                   (define (iter n result)\n                                     (if (= n 0)\n                                         result\n                                         (iter (- n 1) (* result n))))\n                                   (iter n 1))\n                                 (factorial 5)))\n                    120)) \n))\n\n(run-tests evaluator-tests)\n"
  },
  {
    "path": "scheme/sicp/04/showcase/analyzing/evaluator.scm",
    "content": "; This is the analyzing evaluator, implemented in SICP 4.1.7. eval is renamed\n; to evaluate because of naming issues in Racket. It uses r5rs in order to get\n; set-car! and set-cdr!\n\n(require r5rs/init)\n\n(define (evaluate exp env)\n  ((analyze exp) env))\n\n(define (analyze exp)\n  (cond ((self-evaluating? exp) (analyze-self-evaluating exp))\n        ((quoted? exp) (analyze-quoted exp))\n        ((variable? exp) (analyze-variable exp))\n        ((assignment? exp) (analyze-assignment exp))\n        ((definition? exp) (analyze-definition exp))\n        ((if? exp) (analyze-if exp))\n        ((lambda? exp) (analyze-lambda exp))\n        ((begin? exp) (analyze-sequence (begin-actions exp)))\n        ((cond? exp) (analyze (cond->if exp)))\n        ((application? exp) (analyze-application exp))\n        (else\n         (error \"Unknown expression type -- ANALYZE\" exp))))\n\n(define (execute-application proc args)\n  (cond ((primitive-procedure? proc)\n         (apply-primitive-procedure proc args))\n        ((compound-procedure? proc)\n         ((procedure-body proc)\n          (extend-environment (procedure-parameters proc)\n                              args\n                              (procedure-environment proc))))\n        (else\n         (error \"Unknown procedure type -- EXECUTE-APPLICATION\" proc))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (analyze-self-evaluating exp)\n  (lambda (env) exp))\n\n(define (analyze-quoted exp)\n  (let ((qval (text-of-quotation exp)))\n    (lambda (env) qval)))\n\n(define (analyze-variable exp)\n  (lambda (env) (lookup-variable-value exp env)))\n\n(define (analyze-assignment exp)\n  (let ((var (assignment-variable exp))\n        (vproc (analyze (assignment-value exp))))\n    (lambda (env)\n      (set-variable-value! var (vproc env) env)\n      'ok)))\n\n(define (analyze-definition exp)\n  (let ((var (definition-variable exp))\n        (vproc (analyze (definition-value exp))))\n    (lambda (env)\n      (define-variable! var (vproc env) env)\n      'ok)))\n\n(define (analyze-if exp)\n  (let ((pproc (analyze (if-predicate exp)))\n        (cproc (analyze (if-consequent exp)))\n        (aproc (analyze (if-alternative exp))))\n    (lambda (env)\n      (if (true? (pproc env))\n          (cproc env)\n          (aproc env)))))\n\n(define (analyze-lambda exp)\n  (let ((vars (lambda-parameters exp))\n        (bproc (analyze-sequence (lambda-body exp))))\n    (lambda (env) (make-procedure vars bproc env))))\n\n(define (analyze-sequence exps)\n  (define (sequentially proc1 proc2)\n    (lambda (env) (proc1 env) (proc2 env)))\n  (define (loop first-proc rest-procs)\n    (if (null? rest-procs)\n        first-proc\n        (loop (sequentially first-proc (car rest-procs))\n              (cdr rest-procs))))\n  (let ((procs (map analyze exps)))\n    (if (null? procs)\n        (error \"Empty sequence -- ANALYZE\"))\n    (loop (car procs) (cdr procs))))\n\n(define (analyze-application exp)\n  (let ((fproc (analyze (operator exp)))\n        (aprocs (map analyze (operands exp))))\n    (lambda (env)\n      (execute-application (fproc env)\n                           (map (lambda (aproc) (aproc env))\n                                aprocs)))))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/showcase/analyzing/main.scm",
    "content": "(load \"evaluator.scm\")\n(driver-loop)\n"
  },
  {
    "path": "scheme/sicp/04/showcase/analyzing/tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n\n(load \"evaluator.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define evaluator-tests\n  (test-suite\n    \"Tests for the analyzing evaluator\"\n\n    (test-suite \"Self-evaluating expressions\"\n      (check-equal? (run '1) 1)\n      (check-equal? (run '\"something\") \"something\"))\n\n    (test-suite \"Variables\"\n      (check-equal? (evaluate 'x (extend-environment '(x) '(1) the-empty-environment))\n                    1)\n      (check-exn exn? (lambda () (evaluate 'x the-empty-environment))))\n\n    (test-suite \"Quotation\"\n      (check-equal? (run '(quote foo)) 'foo))\n\n    (test-suite \"Begin\"\n      (check-equal? (run '(begin 1 2)) 2))\n\n    (test-suite \"Define\"\n      (check-equal? (run '(define x 1)) 'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 x))\n                    1)\n      (check-equal? (run '(define (x) 1)) 'ok)\n      (check-equal? (run '(begin (define (x) 1)\n                                 (x)))\n                    1))\n\n    (test-suite \"Set!\"\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)))\n                    'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)\n                                 x))\n                    2))\n\n    (test-suite \"If\"\n      (check-equal? (run '(if true 1 2)) 1)\n      (check-equal? (run '(if false 1 2)) 2)\n      (check-equal? (run '(if true 1)) 1)\n      (check-equal? (run '(if false 1)) false))\n\n    (test-suite \"Lambda\"\n      (check-equal? (run '((lambda () 1))) 1)\n      (check-equal? (run '((lambda (x) x) 1)) 1)\n      (check-equal? (run '((lambda (a b) (cons a b)) 1 2)) '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 ((lambda (a) (cons a b)) 3)))\n                    '(3 . 2)))\n\n    (test-suite \"Cond\"\n      (check-equal? (run '(cond (true 1))) 1)\n      (check-equal? (run '(cond (false 1) (true 2))) 2)\n      (check-equal? (run '(cond (false 1) (else 2))) 2)\n      (check-exn exn? (lambda () (run '(cond (else 1) (true 2))))))\n\n    (test-suite \"Procedure application\"\n      (check-equal? (run '(begin (define (a) 1)\n                                 (a)))\n                    1)\n      (check-equal? (run '(begin (define (pair a b) (cons a b))\n                                 (pair 1 2)))\n                    '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define (pair b) (cons a b))\n                                 (pair 2)))\n                    '(1 . 2)))\n\n    (test-suite \"Defining append\"\n      (check-equal? (run '(begin (define (append x y)\n                                   (if (null? x)\n                                       y\n                                       (cons (car x)\n                                             (append (cdr x) y))))\n                                 (append '(a b c) '(d e f))))\n                    '(a b c d e f)))\n\n    (test-suite \"Factorial\"\n      (check-equal? (run '(begin (define (factorial n)\n                                   (if (= n 1)\n                                       1\n                                       (* n (factorial (- n 1)))))\n                                 (factorial 5)))\n                    120)\n      (check-equal? (run '(begin (define (factorial n)\n                                   (define (iter n result)\n                                     (if (= n 0)\n                                         result\n                                         (iter (- n 1) (* result n))))\n                                   (iter n 1))\n                                 (factorial 5)))\n                    120)) \n))\n\n(run-tests evaluator-tests)\n"
  },
  {
    "path": "scheme/sicp/04/showcase/evaluator/evaluator.scm",
    "content": "; This is an implementation of the SICP metacircular evaluator as-is. Due to\n; Racket semantics I don't really get, I had to rename eval and apply to\n; evaluate and apply-procedure. It runs in R5RS because of set-car! and\n; set-cdr!, which are notoriously annoying in plain Racket.\n\n(require r5rs/init)\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((application? exp)\n         (apply-procedure (evaluate (operator exp) env)\n                          (list-of-values (operands exp) env)))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure procedure arguments))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             arguments\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (list-of-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (evaluate (first-operand exps) env)\n            (list-of-values (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (evaluate (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; M-Eval input:\")\n(define output-prompt \";;; M-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (evaluate input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/showcase/evaluator/main.scm",
    "content": "; A straightforward runner for the basic metacircular evaluator in chapter 4.\n; Running it throws you in a REPL that's quite straightfoward, although it\n; does not support good error reporting.\n\n(load \"evaluator.scm\")\n(driver-loop)\n"
  },
  {
    "path": "scheme/sicp/04/showcase/evaluator/tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n\n(load \"evaluator.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define evaluator-tests\n  (test-suite\n    \"Tests for the metacircular evaluator\"\n\n    (test-suite \"Self-evaluating expressions\"\n      (check-equal? (run '1) 1)\n      (check-equal? (run '\"something\") \"something\"))\n\n    (test-suite \"Variables\"\n      (check-equal? (evaluate 'x (extend-environment '(x) '(1) the-empty-environment))\n                    1)\n      (check-exn exn? (lambda () (evaluate 'x the-empty-environment))))\n\n    (test-suite \"Quotation\"\n      (check-equal? (run '(quote foo)) 'foo))\n\n    (test-suite \"Begin\"\n      (check-equal? (run '(begin 1 2)) 2))\n\n    (test-suite \"Define\"\n      (check-equal? (run '(define x 1)) 'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 x))\n                    1)\n      (check-equal? (run '(define (x) 1)) 'ok)\n      (check-equal? (run '(begin (define (x) 1)\n                                 (x)))\n                    1))\n\n    (test-suite \"Set!\"\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)))\n                    'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)\n                                 x))\n                    2))\n\n    (test-suite \"If\"\n      (check-equal? (run '(if true 1 2)) 1)\n      (check-equal? (run '(if false 1 2)) 2)\n      (check-equal? (run '(if true 1)) 1)\n      (check-equal? (run '(if false 1)) false))\n\n    (test-suite \"Lambda\"\n      (check-equal? (run '((lambda () 1))) 1)\n      (check-equal? (run '((lambda (x) x) 1)) 1)\n      (check-equal? (run '((lambda (a b) (cons a b)) 1 2)) '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 ((lambda (a) (cons a b)) 3)))\n                    '(3 . 2)))\n\n    (test-suite \"Cond\"\n      (check-equal? (run '(cond (true 1))) 1)\n      (check-equal? (run '(cond (false 1) (true 2))) 2)\n      (check-equal? (run '(cond (false 1) (else 2))) 2)\n      (check-exn exn? (lambda () (run '(cond (else 1) (true 2))))))\n\n    (test-suite \"Procedure application\"\n      (check-equal? (run '(begin (define (a) 1)\n                                 (a)))\n                    1)\n      (check-equal? (run '(begin (define (pair a b) (cons a b))\n                                 (pair 1 2)))\n                    '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define (pair b) (cons a b))\n                                 (pair 2)))\n                    '(1 . 2)))\n\n    (test-suite \"Defining append\"\n      (check-equal? (run '(begin (define (append x y)\n                                   (if (null? x)\n                                       y\n                                       (cons (car x)\n                                             (append (cdr x) y))))\n                                 (append '(a b c) '(d e f))))\n                    '(a b c d e f)))\n\n    (test-suite \"Factorial\"\n      (check-equal? (run '(begin (define (factorial n)\n                                   (if (= n 1)\n                                       1\n                                       (* n (factorial (- n 1)))))\n                                 (factorial 5)))\n                    120)\n      (check-equal? (run '(begin (define (factorial n)\n                                   (define (iter n result)\n                                     (if (= n 0)\n                                         result\n                                         (iter (- n 1) (* result n))))\n                                   (iter n 1))\n                                 (factorial 5)))\n                    120)) \n))\n\n(run-tests evaluator-tests)\n"
  },
  {
    "path": "scheme/sicp/04/showcase/lazy/evaluator.scm",
    "content": "; The lazy evaluator, explored in SICP.\n\n(require r5rs/init)\n\n(define (evaluate exp env)\n  (cond ((self-evaluating? exp) exp)\n        ((variable? exp) (lookup-variable-value exp env))\n        ((quoted? exp) (text-of-quotation exp))\n        ((assignment? exp) (eval-assignment exp env))\n        ((definition? exp) (eval-definition exp env))\n        ((if? exp) (eval-if exp env))\n        ((lambda? exp)\n         (make-procedure (lambda-parameters exp)\n                         (lambda-body exp)\n                         env))\n        ((begin? exp)\n         (eval-sequence (begin-actions exp) env))\n        ((cond? exp) (evaluate (cond->if exp) env))\n        ((application? exp)\n         (apply-procedure (actual-value (operator exp) env)\n                          (operands exp)\n                          env))\n        (else\n         (error \"Unknown expression type - EVALUATE\" exp))))\n\n(define (apply-procedure procedure arguments env)\n  (cond ((primitive-procedure? procedure)\n         (apply-primitive-procedure\n          procedure\n          (list-of-arg-values arguments env)))\n        ((compound-procedure? procedure)\n         (eval-sequence\n           (procedure-body procedure)\n           (extend-environment\n             (procedure-parameters procedure)\n             (list-of-delayed-args arguments env)\n             (procedure-environment procedure))))\n        (else\n         (error\n          \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n(define (actual-value exp env)\n  (force-it (evaluate exp env)))\n\n(define (delay-it exp env) (list 'thunk exp env))\n(define (thunk? obj) (tagged-list? obj 'thunk))\n(define (thunk-exp thunk) (cadr thunk))\n(define (thunk-env thunk) (caddr thunk))\n(define (evaluated-thunk? obj)\n  (tagged-list? obj 'evaluated-thunk))\n(define (thunk-value evaluated-thunk) (cadr evaluated-thunk))\n\n(define (force-it obj)\n  (cond ((thunk? obj)\n         (let ((result (actual-value (thunk-exp obj) (thunk-env obj))))\n           (set-car! obj 'evaluated-thunk)\n           (set-car! (cdr obj) result)\n           (set-cdr! (cdr obj) '())\n           result))\n        ((evaluated-thunk? obj)\n         (thunk-value obj))\n        (else obj)))\n\n\n(define (list-of-arg-values exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (actual-value (first-operand exps) env)\n            (list-of-arg-values (rest-operands exps) env))))\n\n(define (list-of-delayed-args exps env)\n  (if (no-operands? exps)\n      '()\n      (cons (delay-it (first-operand exps) env)\n            (list-of-delayed-args (rest-operands exps) env))))\n\n(define (eval-if exp env)\n  (if (true? (actual-value (if-predicate exp) env))\n      (evaluate (if-consequent exp) env)\n      (evaluate (if-alternative exp) env)))\n\n(define (eval-sequence exps env)\n  (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n        (else (evaluate (first-exp exps) env)\n              (eval-sequence (rest-exps exps) env))))\n\n(define (eval-assignment exp env)\n  (set-variable-value! (assignment-variable exp)\n                       (evaluate (assignment-value exp) env)\n                       env)\n  'ok)\n\n(define (eval-definition exp env)\n  (define-variable! (definition-variable exp)\n                    (evaluate (definition-value exp) env)\n                    env)\n  'ok)\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (text-of-quotation exp) (cadr exp))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (true? x) (not (eq? x false)))\n(define (false? x) (eq? x false))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (cons variables values))\n(define (frame-variables frame) (car frame))\n(define (frame-values frame) (cdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-car! frame (cons var (car frame)))\n  (set-cdr! frame (cons val (cdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars vals) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (car vals))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-car! vals val))\n            (else (scan (cdr vars) (cdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n(define the-global-environment (setup-environment))\n\n(define input-prompt \";;; L-Eval input:\")\n(define output-prompt \";;; L-Eval value:\")\n\n(define (driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((input (read)))\n    (let ((output (actual-value input the-global-environment)))\n      (announce-output output-prompt)\n      (user-print output)))\n  (driver-loop))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n"
  },
  {
    "path": "scheme/sicp/04/showcase/lazy/main.scm",
    "content": "(load \"evaluator.scm\")\n(driver-loop)\n"
  },
  {
    "path": "scheme/sicp/04/showcase/lazy/tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n\n(load \"evaluator.scm\")\n\n(define (run exp)\n  (actual-value exp (setup-environment)))\n\n(define evaluator-tests\n  (test-suite\n    \"Tests for the lazy evaluator\"\n\n    (test-suite \"Lazy evaluation\"\n      (check-equal? 1 (run '(begin (define (try a b)\n                                     (if (= a 0) 1 b))\n                                   (try 0 (/ 1 0))))))\n\n    (test-suite \"Self-evaluating expressions\"\n      (check-equal? (run '1) 1)\n      (check-equal? (run '\"something\") \"something\"))\n\n    (test-suite \"Variables\"\n      (check-equal? (evaluate 'x (extend-environment '(x) '(1) the-empty-environment))\n                    1)\n      (check-exn exn? (lambda () (evaluate 'x the-empty-environment))))\n\n    (test-suite \"Quotation\"\n      (check-equal? (run '(quote foo)) 'foo))\n\n    (test-suite \"Begin\"\n      (check-equal? (run '(begin 1 2)) 2))\n\n    (test-suite \"Define\"\n      (check-equal? (run '(define x 1)) 'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 x))\n                    1)\n      (check-equal? (run '(define (x) 1)) 'ok)\n      (check-equal? (run '(begin (define (x) 1)\n                                 (x)))\n                    1))\n\n    (test-suite \"Set!\"\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)))\n                    'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)\n                                 x))\n                    2))\n\n    (test-suite \"If\"\n      (check-equal? (run '(if true 1 2)) 1)\n      (check-equal? (run '(if false 1 2)) 2)\n      (check-equal? (run '(if true 1)) 1)\n      (check-equal? (run '(if false 1)) false))\n\n    (test-suite \"Lambda\"\n      (check-equal? (run '((lambda () 1))) 1)\n      (check-equal? (run '((lambda (x) x) 1)) 1)\n      (check-equal? (run '((lambda (a b) (cons a b)) 1 2)) '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 ((lambda (a) (cons a b)) 3)))\n                    '(3 . 2)))\n\n    (test-suite \"Cond\"\n      (check-equal? (run '(cond (true 1))) 1)\n      (check-equal? (run '(cond (false 1) (true 2))) 2)\n      (check-equal? (run '(cond (false 1) (else 2))) 2)\n      (check-exn exn? (lambda () (run '(cond (else 1) (true 2))))))\n\n    (test-suite \"Procedure application\"\n      (check-equal? (run '(begin (define (a) 1)\n                                 (a)))\n                    1)\n      (check-equal? (run '(begin (define (pair a b) (cons a b))\n                                 (pair 1 2)))\n                    '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define (pair b) (cons a b))\n                                 (pair 2)))\n                    '(1 . 2)))\n\n    (test-suite \"Defining append\"\n      (check-equal? (run '(begin (define (append x y)\n                                   (if (null? x)\n                                       y\n                                       (cons (car x)\n                                             (append (cdr x) y))))\n                                 (append '(a b c) '(d e f))))\n                    '(a b c d e f)))\n\n    (test-suite \"Factorial\"\n      (check-equal? (run '(begin (define (factorial n)\n                                   (if (= n 1)\n                                       1\n                                       (* n (factorial (- n 1)))))\n                                 (factorial 5)))\n                    120)\n      (check-equal? (run '(begin (define (factorial n)\n                                   (define (iter n result)\n                                     (if (= n 0)\n                                         result\n                                         (iter (- n 1) (* result n))))\n                                   (iter n 1))\n                                 (factorial 5)))\n                    120)) \n))\n\n(run-tests evaluator-tests)\n"
  },
  {
    "path": "scheme/sicp/04/showcase/query/database.scm",
    "content": "(define database-assertions\n  '((address (Warbucks Oliver) (Swellesley (Top Head Road)))\n    (job (Warbucks Oliver) (administration big wheel))\n    (salary (Warbucks Oliver) 150000)\n\n    (address (Bitdiddle Ben) (Slumerville (Ridge Road) 10))\n    (job (Bitdiddle Ben) (computer wizard))\n    (salary (Bitdiddle Ben) 60000)\n    (supervisor (Bitdiddle Ben) (Warbucks Oliver))\n\n    (address (Hacker Alyssa P) (Cambridge (Mass Ave) 78))\n    (job (Hacker Alyssa P) (computer programmer))\n    (salary (Hacker Alyssa P) 40000)\n    (supervisor (Hacker Alyssa P) (Bitdiddle Ben))\n\n    (address (Fect Cy D) (Cambridge (Ames Street) 3))\n    (job (Fect Cy D) (computer programmer))\n    (salary (Fect Cy D) 35000)\n    (supervisor (Fect Cy D) (Bitdiddle Ben))\n\n    (address (Tweakit Lem E) (Boston (Bay State Road) 22))\n    (job (Tweakit Lem E) (computer technician))\n    (salary (Tweakit Lem E) 25000)\n    (supervisor (Tweakit Lem E) (Bitdiddle Ben))\n\n    (address (Reasoner Louis) (Slumerville (Pine Tree Road) 80))\n    (job (Reasoner Louis) (computer programmer trainee))\n    (salary (Reasoner Louis) 30000)\n    (supervisor (Reasoner Louis) (Hacker Alyssa P))\n\n    (address (Scrooge Eben) (Westen (Shady Lane) 10))\n    (job (Scrooge Eben) (accounting chief accountant))\n    (salary (Scrooge Eben) 75000)\n    (supervisor (Scrooge Eben) (Warbucks Oliver))\n\n    (address (Cratchet Robert) (Allston (N Harvard Street) 16))\n    (job (Cratchet Robert) (accounting scrivener))\n    (salary (Cratchet Robert) 18000)\n    (supervisor (Cratchet Robert) (Scrooge Eben))\n\n    (address (Aull DeWitt) (Slumerville (Onion Square) 5))\n    (job (Aull DeWitt) (administration secretary))\n    (salary (Aull DeWitt) 25000)\n    (supervisor (Aull DeWitt) (Warbucks Oliver))\n\n    (can-do-job (computer wizard) (computer programmer))\n    (can-do-job (computer wizard) (computer technician))\n    (can-do-job (computer programmer) (computer programmer trainee))\n    (can-do-job (administration secretary) (administration big wheel))\n\n    (rule (lives-near ?person-1 ?person-2)\n          (and (address ?person-1 (?town . ?rest-1))\n               (address ?person-2 (?town . ?rest-2))\n               (not (same ?person-1 ?person-2))))\n\n    (rule (same ?x ?x))\n\n    (rule (wheel ?person)\n          (and (supervisor ?middle-manager ?person)\n               (supervisor ?x ?middle-manager)))\n\n    (rule (outranked-by ?staff-person ?boss)\n          (or (supervisor ?staff-person ?boss)\n              (and (supervisor ?staff-person ?middle-manager)\n                   (outranked-by ?middle-manager ?boss))))\n\n    (rule (append-to-form () ?y ?y))\n    (rule (append-to-form (?u . ?v) ?y (?u . ?z))\n          (append-to-form ?v ?y ?z))))\n\n(define (add-to-data-base! assertions)\n  (for-each (compose add-rule-or-assertion! query-syntax-process)\n            assertions))\n\n(add-to-data-base! database-assertions)\n"
  },
  {
    "path": "scheme/sicp/04/showcase/query/evaluator.scm",
    "content": "; This is the query language from the Logic Programming section in SICP. There\n; are some modifications to the original code:\n;\n; * Racket stream procedures are differently named than the ones described in\n;   the book.\n; * Racket streams are different than the streams described in SICP in that\n;   they delay their cdr. This removes the need to have delayed versions of\n;   the stream procedures.\n; * The query system in the book stores rules and assertions in an order that\n;   is the reverse of their definition order, which introduces inconsistencies\n;   between the shown examples and the actual results. This implementation\n;   stores the rules and assertions as lists and converts them to a stream in\n;   which their elements appear in reverse order upon retrieval.\n\n; The Driver Loop and Instantiation\n\n(define input-prompt \";;; Query input:\")\n(define output-prompt \";;; Query output:\")\n(define (query-driver-loop)\n  (prompt-for-input input-prompt)\n  (let ((q (query-syntax-process (read))))\n    (cond ((assertion-to-be-added? q)\n           (add-rule-or-assertion! (add-assertion-body q))\n           (newline)\n           (display \"Assertion added to data base.\")\n           (query-driver-loop))\n          (else\n           (newline)\n           (display output-prompt)\n           (display-stream\n             (stream-map\n               (lambda (frame)\n                 (instantiate-exp q\n                                  frame\n                                  (lambda (v f) (contract-question-mark v))))\n               (qeval q (singleton-stream '()))))\n           (query-driver-loop)))))\n\n(define (instantiate-exp exp frame unbound-var-handler)\n  (define (copy exp)\n    (cond ((var? exp)\n           (let ((binding (binding-in-frame exp frame)))\n             (if binding\n                 (copy (binding-value binding))\n                 (unbound-var-handler exp frame))))\n          ((pair? exp)\n           (cons (copy (car exp)) (copy (cdr exp))))\n          (else exp)))\n  (copy exp))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (display-stream stream)\n  (unless (stream-empty? stream)\n          (newline)\n          (display (stream-first stream))\n          (display-stream (stream-rest stream))))\n\n; The Evaluator\n\n(define (qeval query frame-stream)\n  (let ((qproc (get (type query) 'qeval)))\n    (if qproc\n        (qproc (contents query) frame-stream)\n        (simple-query query frame-stream))))\n\n(define (execute exp)\n  (apply (eval (predicate exp))\n         (args exp)))\n\n(define (simple-query query-pattern frame-stream)\n  (stream-flatmap\n    (lambda (frame)\n      (stream-append\n        (find-assertions query-pattern frame)\n        (apply-rules query-pattern frame)))\n    frame-stream))\n\n(define (conjoin conjuncts frame-stream)\n  (if (empty-conjunction? conjuncts)\n      frame-stream\n      (conjoin (rest-conjuncts conjuncts)\n               (qeval (first-conjunct conjuncts)\n                      frame-stream))))\n\n(define (disjoin disjuncts frame-stream)\n  (if (empty-disjunction? disjuncts)\n      empty-stream\n      (interleave (qeval (first-disjunct disjuncts) frame-stream)\n                  (disjoin (rest-disjuncts disjuncts)\n                           frame-stream))))\n\n(define (negate operands frame-stream)\n  (stream-flatmap\n    (lambda (frame)\n      (if (stream-empty? (qeval (negated-query operands) (singleton-stream frame)))\n          (singleton-stream frame)\n          empty-stream))\n    frame-stream))\n\n(define (lisp-value call frame-stream)\n  (stream-flatmap\n    (lambda (frame)\n      (if (execute\n            (instantiate-exp call\n                             frame\n                             (lambda (v f) (error \"Unknown pat var -- LISP-VALUE\" v))))\n          (singleton-stream frame)\n          empty-stream))\n    frame-stream))\n\n(define (always-true ignore frame-stream)\n  frame-stream)\n\n; Finding Assertions by Pattern Matching\n\n(define (find-assertions pattern frame)\n  (stream-flatmap (lambda (datum) (check-an-assertion datum pattern frame))\n                  (fetch-assertions pattern frame)))\n\n(define (check-an-assertion assertion query-pat query-frame)\n  (let ((match-result (pattern-match query-pat assertion query-frame)))\n    (if (eq? match-result 'failed)\n        empty-stream\n        (singleton-stream match-result))))\n\n(define (pattern-match pat dat frame)\n  (cond ((eq? frame 'failed) 'failed)\n        ((equal? pat dat) frame)\n        ((var? pat) (extend-if-consistent pat dat frame))\n        ((and (pair? pat) (pair? dat))\n         (pattern-match (cdr pat)\n                        (cdr dat)\n                        (pattern-match (car pat)\n                                       (car dat)\n                                       frame)))\n        (else 'failed)))\n\n(define (extend-if-consistent var dat frame)\n  (let ((binding (binding-in-frame var frame)))\n    (if binding\n        (pattern-match (binding-value binding) dat frame)\n        (extend var dat frame))))\n\n; Rules and Unification\n\n(define (apply-rules pattern frame)\n  (stream-flatmap (lambda (rule) (apply-a-rule rule pattern frame))\n                  (fetch-rules pattern frame)))\n\n(define (apply-a-rule rule query-pattern query-frame)\n  (let ((clean-rule (rename-variables-in rule)))\n    (let ((unify-result (unify-match query-pattern\n                                     (conclusion clean-rule)\n                                     query-frame)))\n      (if (eq? unify-result 'failed)\n          empty-stream\n          (qeval (rule-body clean-rule)\n                 (singleton-stream unify-result))))))\n\n(define (rename-variables-in rule)\n  (let ((rule-application-id (new-rule-application-id)))\n    (define (tree-walk exp)\n      (cond ((var? exp)\n             (make-new-variable exp rule-application-id))\n            ((pair? exp)\n             (cons (tree-walk (car exp))\n                   (tree-walk (cdr exp))))\n            (else exp)))\n    (tree-walk rule)))\n\n(define (unify-match p1 p2 frame)\n  (cond ((eq? frame 'failed) 'failed)\n        ((equal? p1 p2) frame)\n        ((var? p1) (extend-if-possible p1 p2 frame))\n        ((var? p2) (extend-if-possible p2 p1 frame))\n        ((and (pair? p1) (pair? p2))\n         (unify-match (cdr p1)\n                      (cdr p2)\n                      (unify-match (car p1)\n                                   (car p2)\n                                   frame)))\n        (else 'failed)))\n\n(define (extend-if-possible var val frame)\n  (let ((binding (binding-in-frame var frame)))\n    (cond (binding (unify-match (binding-value binding) val frame))\n          ((var? val)\n           (let ((binding (binding-in-frame val frame)))\n             (if binding\n                 (unify-match var (binding-value binding) frame)\n                 (extend var val frame))))\n          ((depends-on? val var frame) 'failed)\n          (else (extend var val frame)))))\n\n(define (depends-on? exp var frame)\n  (define (tree-walk e)\n    (cond ((var? e)\n           (if (equal? var e)\n               true\n               (let ((b (binding-in-frame e frame)))\n                 (if b\n                     (tree-walk (binding-value b))\n                     false))))\n          ((pair? e)\n           (or (tree-walk (car e))\n               (tree-walk (cdr e))))\n          (else false)))\n  (tree-walk exp))\n\n; Maintaining the Data Base\n\n(define THE-ASSERTIONS '())\n(define (fetch-assertions pattern frame)\n  (if (use-index? pattern)\n      (get-indexed-assertions pattern)\n      (get-all-assertions)))\n(define (get-all-assertions)\n  (reverse-list->stream THE-ASSERTIONS))\n(define (get-indexed-assertions pattern)\n  (reverse-list->stream\n    (get-list (index-key-of pattern) 'assertion-list)))\n\n(define THE-RULES '())\n(define (fetch-rules pattern frame)\n  (if (use-index? pattern)\n      (get-indexed-rules pattern)\n      (get-all-rules)))\n(define (get-all-rules)\n  (reverse-list->stream THE-RULES))\n(define (get-indexed-rules pattern)\n  (reverse-list->stream\n    (append\n      (get-list '? 'rule-list)\n      (get-list (index-key-of pattern) 'rule-list))))\n\n(define (add-rule-or-assertion! assertion)\n  (if (rule? assertion)\n      (add-rule! assertion)\n      (add-assertion! assertion)))\n\n(define (add-assertion! assertion)\n  (store-assertion-in-index assertion)\n  (let ((old-assertions THE-ASSERTIONS))\n    (set! THE-ASSERTIONS (cons assertion old-assertions))\n    'ok))\n\n(define (add-rule! rule)\n  (store-rule-in-index rule)\n  (let ((old-rules THE-RULES))\n    (set! THE-RULES (cons rule old-rules))\n    'ok))\n\n(define (store-assertion-in-index assertion)\n  (when (indexable? assertion)\n        (let ((key (index-key-of assertion)))\n          (let ((current-assertion-list (get-list key 'assertion-list)))\n            (put key\n                 'assertion-list\n                 (cons assertion current-assertion-list))))))\n\n(define (store-rule-in-index rule)\n  (let ((pattern (conclusion rule)))\n    (when (indexable? pattern)\n          (let ((key (index-key-of pattern)))\n            (let ((current-rule-list (get-list key 'rule-list)))\n              (put key\n                   'rule-list\n                   (cons rule current-rule-list)))))))\n\n(define (indexable? pattern)\n  (or (constant-symbol? (car pattern))\n      (var? (car pattern))))\n\n(define (index-key-of pattern)\n  (let ((key (car pattern)))\n    (if (var? key) '? key)))\n\n(define (use-index? pattern)\n  (constant-symbol? (car pattern)))\n\n(define (list->stream items)\n  (if (null? items)\n      empty-stream\n      (stream-cons (car items)\n                   (list->stream (cdr items)))))\n\n(define (reverse-list->stream items)\n  (list->stream (reverse items)))\n\n(define (get-list key1 key2)\n  (let ((s (get key1 key2)))\n    (if s s '())))\n\n; Operator table\n\n(define table (make-hash))\n\n(define (put op type item)\n  (hash-set! table (list op type) item))\n\n(define (get op type)\n  (hash-ref table (list op type) #f))\n\n; Stream Operations\n\n(define (interleave s1 s2)\n  (if (stream-empty? s1)\n      s2\n      (stream-cons\n        (stream-first s1)\n        (interleave s2 (stream-rest s1)))))\n\n(define (stream-flatmap proc s)\n  (flatten-stream (stream-map proc s)))\n\n(define (flatten-stream stream)\n  (if (stream-empty? stream)\n      empty-stream\n      (interleave (stream-first stream)\n                  (flatten-stream (stream-rest stream)))))\n\n(define (singleton-stream x)\n  (stream-cons x empty-stream))\n\n; Query Syntax Procedures\n\n(define (type exp)\n  (if (pair? exp)\n    (car exp)\n    (error \"Unknown expression TYPE\" exp)))\n\n(define (contents exp)\n  (if (pair? exp)\n      (cdr exp)\n      (error \"Unknown expression CONTENTS\" exp)))\n\n(define (assertion-to-be-added? exp) (eq? (type exp) 'assert!))\n(define (add-assertion-body exp) (car (contents exp)))\n\n(define (empty-conjunction? exps) (null? exps))\n(define (first-conjunct exps) (car exps))\n(define (rest-conjuncts exps) (cdr exps))\n(define (empty-disjunction? exps) (null? exps))\n(define (first-disjunct exps) (car exps))\n(define (rest-disjuncts exps) (cdr exps))\n(define (negated-query exps) (car exps))\n(define (predicate exps) (car exps))\n(define (args exps) (cdr exps))\n\n(define (rule? statement) (tagged-list? statement 'rule))\n(define (conclusion rule) (cadr rule))\n(define (rule-body rule) (if (null? (cddr rule)) '(always-true) (caddr rule)))\n\n(define (query-syntax-process exp)\n  (map-over-symbols expand-question-mark exp))\n\n(define (map-over-symbols proc exp)\n  (cond ((pair? exp)\n         (cons (map-over-symbols proc (car exp))\n               (map-over-symbols proc (cdr exp))))\n        ((symbol? exp) (proc exp))\n        (else exp)))\n\n(define (expand-question-mark symbol)\n  (let ((chars (symbol->string symbol)))\n    (if (string=? (substring chars 0 1) \"?\")\n        (list '?\n              (string->symbol\n                (substring chars 1 (string-length chars))))\n        symbol)))\n\n(define (var? exp) (tagged-list? exp '?))\n(define (constant-symbol? exp) (symbol? exp))\n\n(define rule-counter 0)\n(define (new-rule-application-id)\n  (set! rule-counter (+ 1 rule-counter))\n  rule-counter)\n(define (make-new-variable var rule-application-id)\n  (cons '? (cons rule-application-id (cdr var))))\n\n(define (contract-question-mark variable)\n  (string->symbol\n    (string-append \"?\"\n                   (if (number? (cadr variable))\n                       (string-append (symbol->string (caddr variable))\n                                      \"-\"\n                                      (number->string (cadr variable)))\n                       (symbol->string (cadr variable))))))\n\n(define (tagged-list? exp tag)\n  (and (pair? exp)\n       (eq? (car exp) tag)))\n\n; Frames and Bindings\n\n(define (make-binding variable value)\n  (cons variable value))\n(define (binding-variable binding)\n  (car binding))\n(define (binding-value binding)\n  (cdr binding))\n(define (binding-in-frame variable frame)\n  (assoc variable frame))\n(define (extend variable value frame)\n  (cons (make-binding variable value) frame))\n\n; Reseting the state\n\n(define (reset-state!)\n  (set! table (make-hash))\n  (set! rule-counter 0)\n  (set! THE-ASSERTIONS '())\n  (set! THE-RULES '())\n\n  (put 'and 'qeval conjoin)\n  (put 'or 'qeval disjoin)\n  (put 'not 'qeval negate)\n  (put 'lisp-value 'qeval lisp-value)\n  (put 'always-true 'qeval always-true))\n\n(reset-state!)\n"
  },
  {
    "path": "scheme/sicp/04/showcase/query/main.scm",
    "content": "(load \"evaluator.scm\")\n(query-driver-loop)\n"
  },
  {
    "path": "scheme/sicp/04/showcase/query/test-helpers.scm",
    "content": "(load-relative \"evaluator.scm\")\n(load-relative \"database.scm\")\n\n(define (matches-of query)\n  (let ((processed-query (query-syntax-process query)))\n    (stream->list\n      (stream-map\n        (lambda (frame)\n          (instantiate-exp processed-query frame (lambda (v f) (contract-question-mark v))))\n        (qeval processed-query (singleton-stream '()))))))\n\n(define (matches? query)\n  (not (null? (matches-of query))))\n"
  },
  {
    "path": "scheme/sicp/04/showcase/query/tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n\n(load \"test-helpers.scm\")\n\n(define (stream . items)\n  (if (null? items)\n      empty-stream\n      (stream-cons (car items) (apply stream (cdr items)))))\n\n(define (env items)\n  (if (null? items)\n      '()\n      (cons (cons (list '? (caar items))\n                  (cadar items))\n            (env (cdr items)))))\n\n(define evaluator-tests\n  (test-suite\n    \"Tests for the query language\"\n\n    (test-suite \"simple queries\"\n      (check-equal? (matches-of '(job ?x (computer programmer)))\n                    '((job (Hacker Alyssa P) (computer programmer))\n                      (job (Fect Cy D) (computer programmer))))\n\n      (check-equal? (matches-of '(job ?x (computer ?type)))\n                    '((job (Bitdiddle Ben) (computer wizard))\n                      (job (Hacker Alyssa P) (computer programmer))\n                      (job (Fect Cy D) (computer programmer))\n                      (job (Tweakit Lem E) (computer technician))))\n\n      (check-equal? (matches-of '(job ?x (computer . ?type)))\n                    '((job (Bitdiddle Ben) (computer wizard))\n                      (job (Hacker Alyssa P) (computer programmer))\n                      (job (Fect Cy D) (computer programmer))\n                      (job (Tweakit Lem E) (computer technician))\n                      (job (Reasoner Louis) (computer programmer trainee))))\n\n      (check-equal? (matches-of '(and (job ?person (computer programmer))\n                                      (address ?person ?where)))\n                    '((and (job (Hacker Alyssa P) (computer programmer))\n                           (address (Hacker Alyssa P) (Cambridge (Mass Ave) 78)))\n                      (and (job (Fect Cy D) (computer programmer))\n                           (address (Fect Cy D) (Cambridge (Ames Street) 3)))))\n\n      (check-equal? (matches-of '(or (supervisor ?x (Bitdiddle Ben))\n                                     (supervisor ?x (Hacker Alyssa P))))\n                    '((or (supervisor (Hacker Alyssa P) (Bitdiddle Ben))\n                          (supervisor (Hacker Alyssa P) (Hacker Alyssa P)))\n                      (or (supervisor (Reasoner Louis) (Bitdiddle Ben))\n                          (supervisor (Reasoner Louis) (Hacker Alyssa P)))\n                      (or (supervisor (Fect Cy D) (Bitdiddle Ben))\n                          (supervisor (Fect Cy D) (Hacker Alyssa P)))\n                      (or (supervisor (Tweakit Lem E) (Bitdiddle Ben))\n                          (supervisor (Tweakit Lem E) (Hacker Alyssa P)))))\n\n      (check-equal? (matches-of '(and (supervisor ?x (Bitdiddle Ben))\n                                      (not (job ?x (computer programmer)))))\n                    '((and (supervisor (Tweakit Lem E) (Bitdiddle Ben))\n                           (not (job (Tweakit Lem E) (computer programmer))))))\n\n      (check-equal? (matches-of '(and (salary ?person ?amount)\n                                      (lisp-value > ?amount 30000)))\n                    '((and (salary (Warbucks Oliver) 150000)\n                           (lisp-value > 150000 30000))\n                      (and (salary (Bitdiddle Ben) 60000)\n                           (lisp-value > 60000 30000))\n                      (and (salary (Hacker Alyssa P) 40000)\n                           (lisp-value > 40000 30000))\n                      (and (salary (Fect Cy D) 35000)\n                           (lisp-value > 35000 30000))\n                      (and (salary (Scrooge Eben) 75000)\n                           (lisp-value > 75000 30000)))))\n\n    (test-suite \"rules\"\n      (check-true (matches? '(same x x)))\n\n      (check-true (matches? '(lives-near (Hacker Alyssa P) (Fect Cy D))))\n      (check-false (matches? '(lives-near (Hacker Alyssa P) (Bitdiddle Ben))))\n\n      (check-true (matches? '(wheel (Warbucks Oliver))))\n      (check-true (matches? '(wheel (Bitdiddle Ben))))\n      (check-false (matches? '(wheel (Hacker Alyssa P))))\n\n      (check-true (matches? '(outranked-by (Bitdiddle Ben) (Warbucks Oliver))))\n      (check-true (matches? '(outranked-by (Hacker Alyssa P) (Warbucks Oliver))))\n      (check-true (matches? '(outranked-by (Reasoner Louis) (Warbucks Oliver))))\n      (check-true (matches? '(outranked-by (Hacker Alyssa P) (Bitdiddle Ben))))\n      (check-true (matches? '(outranked-by (Reasoner Louis) (Bitdiddle Ben))))\n      (check-true (matches? '(outranked-by (Reasoner Louis) (Hacker Alyssa P))))\n\n      (check-false (matches? '(outranked-by (Warbucks Oliver) (Bitdiddle Ben))))\n      (check-false (matches? '(outranked-by (Eben Scrooge) (Bitdiddle Ben))))\n      (check-false (matches? '(outranked-by (Bitdiddle Ben) (Eben Scrooge)))))\n\n    (test-suite \"logic as programs\"\n      (check-equal? (matches-of '(append-to-form (a b) (c d) ?z))\n                    '((append-to-form (a b) (c d) (a b c d))))\n      (check-equal? (matches-of '(append-to-form (a b) ?y (a b c d)))\n                    '((append-to-form (a b) (c d) (a b c d))))\n      (check-equal? (matches-of '(append-to-form ?x ?y (a b c d)))\n                    '((append-to-form () (a b c d) (a b c d))\n                      (append-to-form (a) (b c d) (a b c d))\n                      (append-to-form (a b) (c d) (a b c d))\n                      (append-to-form (a b c) (d) (a b c d))\n                      (append-to-form (a b c d) () (a b c d)))))\n\n    (test-suite \"always true\"\n      (check-equal? (stream->list (qeval '(always-true) (singleton-stream '())))\n                    '(())))\n\n    (test-suite \"pattern matching\"\n      (check-equal? (pattern-match 'a 'a '()) '())\n      (check-equal? (pattern-match 'a 'b '()) 'failed)\n      (check-equal? (pattern-match '(? x) 'a '()) (env '((x a))))\n\n      (check-equal?\n        (pattern-match '(same (? x) (? x)) '(same a a) '())\n        (env '((x a))))\n\n      (check-equal?\n        (pattern-match '(same (? x) (? x)) '(same a b) '())\n        'failed)\n\n      (check-equal?\n        (pattern-match '(same (? x) a) '(same a a) (env '((x a))))\n        (env '((x a))))\n\n      (check-equal?\n        (pattern-match '(? x) '(f b) (env '((x (f (? y))))))\n        (env '((y b) (x (f (? y))))))\n\n      (check-equal?\n        (pattern-match '(? x) '(f b) (env '((x (f (? y))) (y b))))\n        (env '((x (f (? y))) (y b))))\n\n      (check-equal?\n        (pattern-match '(? x) '(f b) (env '((x (f (? y))) (y c))))\n        'failed))\n\n    (test-suite \"rename variables\"\n      (before (reset-state!)\n        (check-equal?\n          (rename-variables-in '(same (? x) (? y)))\n          '(same (? 1 x) (? 1 y)))))\n\n    (test-suite \"depends-on?\"\n      (check-false (depends-on? '(same (? x)) '(? y) '()))\n      (check-true (depends-on? '(same (? x)) '(? x) '()))\n      (check-true (depends-on? '(same (? x)) '(? y) (env '((x (? y)))))))\n\n    (test-suite \"unification\"\n      (check-equal?\n        (unify-match 'a 'a '())\n        '())\n\n      (check-equal?\n        (unify-match 'a 'b '())\n        'failed)\n\n      (check-equal?\n        (unify-match '(? x) '(? y) '())\n        (env '((x (? y)))))\n\n      (check-equal?\n        (unify-match '(same (? x) b) '(same a (? y)) '())\n        (env '((y b) (x a))))\n\n      (check-equal?\n        (unify-match '((? x) (? x)) '((? y) (? y)) '())\n        (env '((x (? y)))))\n\n      (check-equal?\n        (unify-match '(same (person (? a)) (? b)) '(same (? c) (? c)) (env '((b (person smith)))))\n        (env '((a smith)\n               (c (person (? a)))\n               (b (person smith))))))\n\n    (test-suite \"adding to the database\"\n      (test-case \"adding an assertion\"\n        (reset-state!)\n\n        (add-assertion! '(father luke anakin))\n\n        (check-equal? (stream->list (get-all-assertions))\n                      '((father luke anakin))))\n\n      (test-case \"indexing assertions\"\n        (reset-state!)\n\n        (add-assertion! '(father luke anakin))\n        (add-assertion! '(son anakin luke))\n\n        (check-equal? (stream->list (fetch-assertions '(son (? x) (? x)) '()))\n                      '((son anakin luke)))\n\n        (check-equal? (stream->list (fetch-assertions '(father (? x) (? x)) '()))\n                      '((father luke anakin))))\n\n      (test-case \"adding a rule\"\n        (reset-state!)\n\n        (add-rule! '(rule (same (? x) (? x))))\n\n        (check-equal? (stream->list (get-all-rules))\n                      '((rule (same (? x) (? x))))))\n\n      (test-case \"indexing rules\"\n        (reset-state!)\n\n        (add-rule! '(rule (same (? x) (? x))))\n        (add-rule! '(rule (two (? x) (? y))))\n        (add-rule! '(rule ((? x) might-be (? y))))\n\n        (check-equal? (stream->list (fetch-rules '(same a a) '()))\n                      '((rule (same (? x) (? x)))\n                        (rule ((? x) might-be (? y)))))\n\n        (check-equal? (stream->list (fetch-rules '((? x) a a) '()))\n                      '((rule (same (? x) (? x)))\n                        (rule (two (? x) (? y)))\n                        (rule ((? x) might-be (? y)))))))\n\n    (test-suite \"query-syntax-process\"\n      (check-equal? (query-syntax-process '?a) '(? a))\n      (check-equal? (query-syntax-process '(?a ?b)) '((? a) (? b)))\n      (check-equal? (query-syntax-process '(a (b ?c) ?d)) '(a (b (? c)) (? d))))\n\n    (test-suite \"make-new-variable\"\n      (check-equal? (make-new-variable '(? x) 1) '(? 1 x)))\n\n    (test-suite \"contract-question-mark\"\n      (check-equal? (contract-question-mark '(? x)) '?x)\n      (check-equal? (contract-question-mark '(? 1 x)) '?x-1))\n\n    (test-suite \"stream operations\"\n      (check-equal? (stream->list (interleave (stream 1 3 5 7 9) (stream 2 4 6 8 10)))\n                    '(1 2 3 4 5 6 7 8 9 10))\n      (check-equal? (stream->list (stream-flatmap (lambda (n) (stream (* n 10) (+ (* n 10) 5)))\n                                                  (stream 1 2 3 4 5)))\n                    '(10 20 15 30 25 40 35 50 45 55))\n      (check-equal? (stream->list (singleton-stream 1))\n                    '(1)))\n))\n\n(run-tests evaluator-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/01-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../01.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.01-tests\n  (test-suite\n    \"Tests for SICP exercise 4.01\"\n\n    (test-case \"Left-to-right evaluation\"\n      (set-evaluation-order! 'left-to-right)\n      (check-equal? (run '(begin (define x 1)\n                                 (cons (set! x 2)\n                                       (set! x 3))\n                                 x))\n                    3))\n\n    (test-case \"Right-to-left evaluation\"\n      (set-evaluation-order! 'right-to-left)\n      (check-equal? (run '(begin (define x 1)\n                                 (cons (set! x 2)\n                                       (set! x 3))\n                                 x))\n                    2))\n))\n\n(run-tests sicp-4.01-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/02-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../02.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.02-tests\n  (test-suite\n    \"Tests for SICP exercise 4.02\"\n\n    (check-equal? (run '(begin (define (factorial n)\n                                 (if (call = n 1)\n                                     1\n                                     (call * n (call factorial (call - n 1)))))\n                               (call factorial 5)))\n                  120)\n    (check-equal? (run '(begin (define (factorial n)\n                                 (define (iter n result)\n                                   (if (call = n 0)\n                                       result\n                                       (call iter (call - n 1) (call * result n))))\n                                 (call iter n 1))\n                               (call factorial 5)))\n                  120)\n))\n\n(run-tests sicp-4.02-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/03-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../03.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.03-tests\n  (test-suite\n    \"Tests for SICP exercise 4.03\"\n\n    (test-suite \"Self-evaluating expressions\"\n      (check-equal? (run '1) 1)\n      (check-equal? (run '\"something\") \"something\"))\n\n    (test-suite \"Variables\"\n      (check-equal? (evaluate 'x (extend-environment '(x) '(1) the-empty-environment))\n                    1)\n      (check-exn exn? (lambda () (evaluate 'x the-empty-environment))))\n\n    (test-suite \"Quotation\"\n      (check-equal? (run '(quote foo)) 'foo))\n\n    (test-suite \"Begin\"\n      (check-equal? (run '(begin 1 2)) 2))\n\n    (test-suite \"Define\"\n      (check-equal? (run '(define x 1)) 'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 x))\n                    1)\n      (check-equal? (run '(define (x) 1)) 'ok)\n      (check-equal? (run '(begin (define (x) 1)\n                                 (x)))\n                    1))\n\n    (test-suite \"Set!\"\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)))\n                    'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)\n                                 x))\n                    2))\n\n    (test-suite \"If\"\n      (check-equal? (run '(if true 1 2)) 1)\n      (check-equal? (run '(if false 1 2)) 2)\n      (check-equal? (run '(if true 1)) 1)\n      (check-equal? (run '(if false 1)) false))\n\n    (test-suite \"Lambda\"\n      (check-equal? (run '((lambda () 1))) 1)\n      (check-equal? (run '((lambda (x) x) 1)) 1)\n      (check-equal? (run '((lambda (a b) (cons a b)) 1 2)) '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 ((lambda (a) (cons a b)) 3)))\n                    '(3 . 2)))\n\n    (test-suite \"Cond\"\n      (check-equal? (run '(cond (true 1))) 1)\n      (check-equal? (run '(cond (false 1) (true 2))) 2)\n      (check-equal? (run '(cond (false 1) (else 2))) 2)\n      (check-exn exn? (lambda () (run '(cond (else 1) (true 2))))))\n\n    (test-suite \"Procedure application\"\n      (check-equal? (run '(begin (define (a) 1)\n                                 (a)))\n                    1)\n      (check-equal? (run '(begin (define (pair a b) (cons a b))\n                                 (pair 1 2)))\n                    '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define (pair b) (cons a b))\n                                 (pair 2)))\n                    '(1 . 2)))\n\n    (test-suite \"Defining append\"\n      (check-equal? (run '(begin (define (append x y)\n                                   (if (null? x)\n                                       y\n                                       (cons (car x)\n                                             (append (cdr x) y))))\n                                 (append '(a b c) '(d e f))))\n                    '(a b c d e f)))\n\n    (test-suite \"Factorial\"\n      (check-equal? (run '(begin (define (factorial n)\n                                   (if (= n 1)\n                                       1\n                                       (* n (factorial (- n 1)))))\n                                 (factorial 5)))\n                    120)\n      (check-equal? (run '(begin (define (factorial n)\n                                   (define (iter n result)\n                                     (if (= n 0)\n                                         result\n                                         (iter (- n 1) (* result n))))\n                                   (iter n 1))\n                                 (factorial 5)))\n                    120)) \n))\n\n(run-tests sicp-4.03-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/04-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../04.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.04-tests\n  (test-suite\n    \"Tests for SICP exercise 4.04\"\n\n    (test-case \"And with evaluation procedures\"\n      (set-logical-operations-implementation! 'syntax-procedures)\n      (check-equal? (run '(and)) true)\n      (check-equal? (run '(and false)) false)\n      (check-equal? (run '(and false false)) false)\n      (check-equal? (run '(and 1)) 1)\n      (check-equal? (run '(and 1 2)) 2)\n      (check-equal? (run '(and false (fail))) false)\n      (check-equal? (run '(begin (define (x) 2)\n                                 (and 1 (x))))\n                    2))\n\n    (test-case \"And as a derived form\"\n      (set-logical-operations-implementation! 'derived-forms)\n      (check-equal? (run '(and)) true)\n      (check-equal? (run '(and false)) false)\n      (check-equal? (run '(and false false)) false)\n      (check-equal? (run '(and 1)) 1)\n      (check-equal? (run '(and 1 2)) 2)\n      (check-equal? (run '(and false (fail))) false)\n      (check-equal? (run '(begin (define (x) 2)\n                                 (and 1 (x))))\n                    2))\n\n    (test-case \"Or with evaluation procedures\"\n      (set-logical-operations-implementation! 'syntax-procedures)\n      (check-equal? (run '(or)) false)\n      (check-equal? (run '(or false)) false)\n      (check-equal? (run '(or false false)) false)\n      (check-equal? (run '(or 1)) 1)\n      (check-equal? (run '(or 1 2)) 1)\n      (check-equal? (run '(or 1 (fail))) 1)\n      (check-equal? (run '(or false 2)) 2)\n      (check-equal? (run '(begin (define (x) false)\n                                 (or (x) 1)))\n                    1))\n\n    (test-case \"Or as a derived form\"\n      (set-logical-operations-implementation! 'derived-forms)\n      (check-equal? (run '(or)) false)\n      (check-equal? (run '(or false)) false)\n      (check-equal? (run '(or false false)) false)\n      (check-equal? (run '(or 1)) true)\n      (check-equal? (run '(or 1 2)) true)\n      (check-equal? (run '(or 1 (fail))) true)\n      (check-equal? (run '(or false 2)) true)\n      (check-equal? (run '(begin (define (x) false)\n                                 (or (x) 1)))\n                    true))\n))\n\n(run-tests sicp-4.04-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/05-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../05.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.05-tests\n  (test-suite\n    \"Tests for SICP exercise 4.05\"\n\n    (check-equal? (run '(begin (define (assoc key items)\n                                 (cond ((null? items) false)\n                                       ((eq? key (car (car items))) (car items))\n                                       (else (assoc key (cdr items)))))\n                               (define (cadr x) (car (cdr x)))\n                               (cond ((assoc 'b '((a 1) (b 2))) => cadr)\n                                     (else false))))\n                  2)\n\n    (check-equal? (run '(begin (define (assoc key items)\n                                 (cond ((null? items) false)\n                                       ((eq? key (car (car items))) (car items))\n                                       (else (assoc key (cdr items)))))\n                               (define (cadr x) (car (cdr x)))\n                               (cond ((assoc 'c '((a 1) (b 2))) => cadr)\n                                     (else 3))))\n                  3)\n))\n\n(run-tests sicp-4.05-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/06-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../06.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.06-tests\n  (test-suite\n    \"Tests for SICP exercise 4.06\"\n\n    (check-equal? (run '(let ((x 1)) x)) 1)\n    (check-equal? (run '(let ((a 1) (b 2)) (+ a b))) 3)\n    (check-equal? (run '(let ((a 1) (b 2)) a b)) 2)\n    (check-equal? (run '(begin (define a 1)\n                               (let ((b 2)\n                                     (c 3))\n                                 (+ a b c))))\n                  6)\n\n))\n\n(run-tests sicp-4.06-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/07-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../07.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.07-tests\n  (test-suite\n    \"Tests for SICP exercise 4.07\"\n\n    (check-equal? (run '(let* ((x 3)\n                               (y (+ x 2))\n                               (z (+ x y 5)))\n                          (* x z)))\n                  39)\n))\n\n(run-tests sicp-4.07-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/08-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../08.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.08-tests\n  (test-suite\n    \"Tests for SICP exercise 4.08\"\n\n\n    (check-equal? (run '(let ((x 1)) x)) 1)\n    (check-equal? (run '(let ((a 1) (b 2)) (+ a b))) 3)\n    (check-equal? (run '(let ((a 1) (b 2)) a b)) 2)\n    (check-equal? (run '(begin (define a 1)\n                               (let ((b 2)\n                                     (c 3))\n                                 (+ a b c))))\n                  6)\n\n    (check-equal? (run '(begin (define (fib n)\n                                 (let fib-iter ((a 1)\n                                                (b 0)\n                                                (count n))\n                                   (if (= count 0)\n                                     b\n                                     (fib-iter (+ a b) a (- count 1)))))\n                               (fib 12)))\n                  144)\n))\n\n(run-tests sicp-4.08-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/09-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../09.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.09-tests\n  (test-suite\n    \"Tests for SICP exercise 4.09\"\n\n    (test-suite \"For\"\n      (check-equal? (run '(begin (define sum 0)\n                                 (for x '(1 2 3 4 5)\n                                      (set! sum (+ sum x)))\n                                 sum))\n                    15)\n      (check-equal? (run '(begin (define sum 0)\n                                 (for x '(1 2 3 4 5)\n                                      (set! sum (+ sum x))\n                                      (set! sum (+ sum x)))\n                                 sum))\n                    30))\n\n    (test-suite \"While\"\n      (check-equal? (run '(begin (define sum 0)\n                                 (define n 1)\n                                 (while (< n 10)\n                                        (set! sum (+ sum n))\n                                        (set! n (+ n 1)))\n                                 sum))\n                    45))\n\n    (test-suite \"Until\"\n      (check-equal? (run '(begin (define sum 0)\n                                 (define n 1)\n                                 (until (= n 10)\n                                        (set! sum (+ sum n))\n                                        (set! n (+ n 1)))\n                                 sum))\n                    45))\n))\n\n(run-tests sicp-4.09-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/10-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../10.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.10-tests\n  (test-suite\n    \"Tests for SICP exercise 4.10\"\n\n    (check-true (ends-with? 'foo: ':))\n    (check-true (ends-with? 'foo:= ':=))\n    (check-true (ends-with? 'foo= '=))\n    (check-false (ends-with? 'foo ':))\n    (check-false (ends-with? 'a ':=))\n\n    (check-equal? (strip-suffix 'foo: ':) 'foo)\n    (check-equal? (strip-suffix 'foo:= ':=) 'foo)\n\n    (test-suite \"Self-evaluating expressions\"\n      (check-equal? (run '1) 1)\n      (check-equal? (run '\"something\") \"something\"))\n\n    (test-suite \"Variables\"\n      (check-equal? (evaluate 'x (extend-environment '(x) '(1) the-empty-environment))\n                    1)\n      (check-exn exn? (lambda () (evaluate 'x the-empty-environment))))\n\n    (test-suite \"Quotation\"\n      (check-equal? (run '(quote foo)) 'foo))\n\n    (test-suite \"Begin\"\n      (check-equal? (run '(do 1 2)) 2))\n\n    (test-suite \"Define\"\n      (check-equal? (run '(x:= 1)) 'ok)\n      (check-equal? (run '(do (x:= 1)\n                              x))\n                    1)\n      (check-equal? (run '(x: () 1)) 'ok)\n      (check-equal? (run '(do (x: () 1)\n                              (x)))\n                    1))\n\n    (test-suite \"Set!\"\n      (check-equal? (run '(do (x:= 1)\n                              (x= 2)))\n                    'ok)\n      (check-equal? (run '(do (x:= 1)\n                              (x= 2)\n                              x))\n                    2))\n\n    (test-suite \"If\"\n      (check-equal? (run '(? true 1 2)) 1)\n      (check-equal? (run '(? false 1 2)) 2)\n      (check-equal? (run '(? true 1)) 1)\n      (check-equal? (run '(? false 1)) false))\n\n    (test-suite \"Lambda\"\n      (check-equal? (run '((() => 1))) 1)\n      (check-equal? (run '(((x) => x) 1)) 1)\n      (check-equal? (run '(((a b) => (cons a b)) 1 2)) '(1 . 2))\n      (check-equal? (run '(do (a:= 1)\n                              (b:= 2)\n                              (((a) => (cons a b)) 3)))\n                    '(3 . 2)))\n\n    (test-suite \"Cond\"\n      (check-equal? (run '(switch (true 1))) 1)\n      (check-equal? (run '(switch (false 1) (true 2))) 2)\n      (check-equal? (run '(switch (false 1) (else 2))) 2)\n      (check-exn exn? (lambda () (run '(switch (else 1) (true 2))))))\n\n    (test-suite \"Procedure application\"\n      (check-equal? (run '(do (a: () 1)\n                              (a)))\n                    1)\n      (check-equal? (run '(do (pair: (a b) (cons a b))\n                              (pair 1 2)))\n                    '(1 . 2))\n      (check-equal? (run '(do (a:= 1)\n                              (pair: (b) (cons a b))\n                              (pair 2)))\n                    '(1 . 2)))\n\n    (test-suite \"Defining append\"\n      (check-equal? (run '(do (append: (x y)\n                              (? (null? x)\n                                 y\n                                 (cons (car x)\n                                       (append (cdr x) y))))\n                              (append '(a b c) '(d e f))))\n                    '(a b c d e f)))\n\n    (test-suite \"Factorial\"\n      (check-equal? (run '(do (factorial: (n)\n                                (? (= n 1)\n                                   1\n                                   (* n (factorial (- n 1)))))\n                              (factorial 5)))\n                    120)\n      (check-equal? (run '(do (factorial: (n)\n                                (iter: (n result)\n                                  (? (= n 0)\n                                     result\n                                     (iter (- n 1) (* result n))))\n                                (iter n 1))\n                              (factorial 5)))\n                    120))\n))\n\n(run-tests sicp-4.10-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/11-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../11.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.11-tests\n  (test-suite\n    \"Tests for SICP exercise 4.11\"\n\n    (check-equal? (make-frame '(a b c) '(1 2 3))\n                  '(frame (a . 1) (b . 2) (c . 3)))\n    (check-equal? (frame-variables (make-frame '(a b c) '(1 2 3)))\n                  '(a b c))\n    (check-equal? (frame-values (make-frame '(a b c) '(1 2 3)))\n                  '(1 2 3))\n\n    (check-equal? (extend-environment '(a b) '(1 2)\n                                      (extend-environment '(a c) '(3 4)\n                                                          the-empty-environment))\n                  '((frame (a . 1) (b . 2))\n                    (frame (a . 3) (c . 4))))\n\n    (check-equal? (lookup-variable-value 'a\n                    (extend-environment '(a) '(1) the-empty-environment))\n                  1)\n    (check-equal? (lookup-variable-value 'a\n                    (extend-environment '(b) '(1)\n                      (extend-environment '(a) '(2) the-empty-environment)))\n                  2)\n    (check-equal? (lookup-variable-value 'b\n                    (extend-environment '(a b) '(1 2) the-empty-environment))\n                  2)\n    (check-equal? (lookup-variable-value 'c\n                    (extend-environment '(a b) '(1 2)\n                      (extend-environment '(a c) '(3 4) the-empty-environment)))\n                  4)\n    (check-equal? (lookup-variable-value 'a\n                    (extend-environment '(a b) '(1 2)\n                      (extend-environment '(a c) '(3 4) the-empty-environment)))\n                  1)\n\n    (test-begin\n      (define frame (make-frame '(a b) '(1 2)))\n      (add-binding-to-frame! 'c 3 frame)\n      (check-equal? frame '(frame (c . 3) (a . 1) (b . 2))))\n\n    (test-begin\n      (define env (extend-environment '(a b) '(1 2) the-empty-environment))\n      (set-variable-value! 'b 3 env)\n      (check-equal? (lookup-variable-value 'b env) 3))\n\n    (test-begin\n      (define env (extend-environment '(a b) '(1 2)\n                    (extend-environment '(a c) '(3 4) the-empty-environment)))\n      (set-variable-value! 'c 5 env)\n      (check-equal? env\n                    '((frame (a . 1) (b . 2))\n                      (frame (a . 3) (c . 5)))))\n\n    (test-begin\n      (define env (extend-environment '(a b) '(1 2) the-empty-environment))\n      (define-variable! 'c 3 env)\n      (check-equal? env '((frame (c . 3) (a . 1) (b . 2)))))\n\n    (test-begin\n      (define env (extend-environment '(a b) '(1 2) the-empty-environment))\n      (define-variable! 'b 3 env)\n      (check-equal? env '((frame (a . 1) (b . 3)))))\n))\n\n(run-tests sicp-4.11-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/12-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../12.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.12-tests\n  (test-suite\n    \"Tests for SICP exercise 4.12\"\n\n    (test-suite \"Self-evaluating expressions\"\n      (check-equal? (run '1) 1)\n      (check-equal? (run '\"something\") \"something\"))\n\n    (test-suite \"Variables\"\n      (check-equal? (evaluate 'x (extend-environment '(x) '(1) the-empty-environment))\n                    1)\n      (check-exn exn? (lambda () (evaluate 'x the-empty-environment))))\n\n    (test-suite \"Quotation\"\n      (check-equal? (run '(quote foo)) 'foo))\n\n    (test-suite \"Begin\"\n      (check-equal? (run '(begin 1 2)) 2))\n\n    (test-suite \"Define\"\n      (check-equal? (run '(define x 1)) 'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 x))\n                    1)\n      (check-equal? (run '(define (x) 1)) 'ok)\n      (check-equal? (run '(begin (define (x) 1)\n                                 (x)))\n                    1))\n\n    (test-suite \"Set!\"\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)))\n                    'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)\n                                 x))\n                    2))\n\n    (test-suite \"If\"\n      (check-equal? (run '(if true 1 2)) 1)\n      (check-equal? (run '(if false 1 2)) 2)\n      (check-equal? (run '(if true 1)) 1)\n      (check-equal? (run '(if false 1)) false))\n\n    (test-suite \"Lambda\"\n      (check-equal? (run '((lambda () 1))) 1)\n      (check-equal? (run '((lambda (x) x) 1)) 1)\n      (check-equal? (run '((lambda (a b) (cons a b)) 1 2)) '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 ((lambda (a) (cons a b)) 3)))\n                    '(3 . 2)))\n\n    (test-suite \"Cond\"\n      (check-equal? (run '(cond (true 1))) 1)\n      (check-equal? (run '(cond (false 1) (true 2))) 2)\n      (check-equal? (run '(cond (false 1) (else 2))) 2)\n      (check-exn exn? (lambda () (run '(cond (else 1) (true 2))))))\n\n    (test-suite \"Procedure application\"\n      (check-equal? (run '(begin (define (a) 1)\n                                 (a)))\n                    1)\n      (check-equal? (run '(begin (define (pair a b) (cons a b))\n                                 (pair 1 2)))\n                    '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define (pair b) (cons a b))\n                                 (pair 2)))\n                    '(1 . 2)))\n\n    (test-suite \"Defining append\"\n      (check-equal? (run '(begin (define (append x y)\n                                   (if (null? x)\n                                       y\n                                       (cons (car x)\n                                             (append (cdr x) y))))\n                                 (append '(a b c) '(d e f))))\n                    '(a b c d e f)))\n\n    (test-suite \"Factorial\"\n      (check-equal? (run '(begin (define (factorial n)\n                                   (if (= n 1)\n                                       1\n                                       (* n (factorial (- n 1)))))\n                                 (factorial 5)))\n                    120)\n      (check-equal? (run '(begin (define (factorial n)\n                                   (define (iter n result)\n                                     (if (= n 0)\n                                         result\n                                         (iter (- n 1) (* result n))))\n                                   (iter n 1))\n                                 (factorial 5)))\n                    120)) \n\n))\n\n(run-tests sicp-4.12-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/13-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../13.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.13-tests\n  (test-suite\n    \"Tests for SICP exercise 4.13\"\n\n    (check-exn (regexp \"Unbound variable x\")\n               (lambda () (run '(begin (define x 10)\n                                       (make-unbound! x)\n                                       x))))\n\n    (check-exn (regexp \"Cannot unbind a variable that is not declared in the current frame x\")\n               (lambda () (run '(begin (define x 10)\n                                       ((lambda ()\n                                          (make-unbound! x)))))))\n))\n\n(run-tests sicp-4.13-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/16-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../16.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.16-tests\n  (test-suite\n    \"Tests for SICP exercise 4.16\"\n\n    (check-exn (regexp \"Unassigned variable x\")\n               (lambda () (run '(begin (define x '*unassigned*)\n                                       x))))\n\n    (check-equal? (scan-out-defines '((* x x)))\n                  '((* x x)))\n    (check-equal? (scan-out-defines '((define x 1)\n                                      (+ x 2)))\n                  '((let ((x '*unassigned*))\n                     (set! x 1)\n                     (+ x 2))))\n    (check-equal? (scan-out-defines '((define x 1)\n                                      (define y 2)\n                                      (+ x y 3)))\n                  '((let ((x '*unassigned*)\n                          (y '*unassigned*))\n                     (set! x 1)\n                     (set! y 2)\n                     (+ x y 3))))\n\n    (check-equal? '(#t #f)\n                  (run '(begin (define (f x)\n                                 (list (even? x) (odd? x))\n                                 (define (even? n)\n                                   (if (= n 0)\n                                       true\n                                       (odd? (- n 1))))\n                                 (define (odd? n)\n                                   (if (= n 0)\n                                       false\n                                       (even? (- n 1)))))\n                               (f 4))))\n))\n\n(run-tests sicp-4.16-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/20-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../20.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.20-tests\n  (test-suite\n    \"Tests for SICP exercise 4.20\"\n\n    (check-equal? (letrec->combination '(letrec ((a 1)\n                                                 (b 2))\n                                          (+ a b)))\n                  '(let ((a '*unassigned*)\n                         (b '*unassigned*))\n                     (set! a 1)\n                     (set! b 2)\n                     (+ a b)))\n    (check-equal? '(#t #f)\n                  (run '(begin (define (f x)\n                                 (letrec ((even?\n                                            (lambda (n)\n                                              (if (= n 0)\n                                                true\n                                                (odd? (- n 1)))))\n                                          (odd?\n                                            (lambda (n)\n                                              (if (= n 0)\n                                                false\n                                                (even? (- n 1))))))\n                                   (list (odd? x) (even? x))))\n                               (f 3))))\n    (check-equal? 3628800\n                  (run '(letrec ((fact\n                                   (lambda (n)\n                                     (if (= n 1)\n                                       1\n                                       (* n (fact (- n 1)))))))\n                          (fact 10))))\n))\n\n(run-tests sicp-4.20-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/21-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../21.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.21-tests\n  (test-suite\n    \"Tests for SICP exercise 4.21\"\n\n    (check-equal? 3628800\n                  (run '((lambda (n)\n                           ((lambda (fact)\n                              (fact fact n))\n                            (lambda (ft k)\n                              (if (= k 1)\n                                1\n                                (* k (ft ft (- k 1)))))))\n                         10)))\n\n    (check-equal? (y-fibonacci 3) 2)\n    (check-equal? (y-fibonacci 4) 3)\n    (check-equal? (y-fibonacci 5) 5)\n    (check-equal? (y-fibonacci 6) 8)\n    (check-equal? (y-fibonacci 7) 13)\n\n    (check-true (f 0))\n    (check-false (f 1))\n    (check-true (f 2))\n    (check-false (f 3))\n    (check-true (f 4))\n    (check-false (f 5))\n))\n\n(run-tests sicp-4.21-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/22-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../22.scm\")\n\n(define (run exp)\n  (evaluate exp (setup-environment)))\n\n(define sicp-4.22-tests\n  (test-suite\n    \"Tests for SICP exercise 4.22\"\n\n    (check-equal? (run '(let ((x 1)) x)) 1)\n    (check-equal? (run '(let ((a 1) (b 2)) (+ a b))) 3)\n    (check-equal? (run '(let ((a 1) (b 2)) a b)) 2)\n    (check-equal? (run '(begin (define a 1)\n                               (let ((b 2)\n                                     (c 3))\n                                 (+ a b c))))\n                  6)\n))\n\n(run-tests sicp-4.22-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/31-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../31.scm\")\n\n(define (run exp)\n  (actual-value exp (setup-environment)))\n\n(define sicp-4.31-tests\n  (test-suite\n    \"Tests for SICP exercise 4.31\"\n\n    (test-suite \"Lazy evaluation\"\n      (check-equal? 1 (run '(begin (define (try a (b lazy))\n                                     (if (= a 0) 1 b))\n                                   (try 0 (/ 1 0)))))\n      (check-equal? 2 (run '(begin (define counter 0)\n                                   (define (square (x lazy))\n                                     (* x x))\n                                   (define (two)\n                                     (set! counter (+ 1 counter))\n                                     2)\n                                   (square (two))\n                                   counter)))\n      (check-equal? 1 (run '(begin (define counter 0)\n                                   (define (square (x lazy-memo))\n                                     (* x x))\n                                   (define (two)\n                                     (set! counter (+ 1 counter))\n                                     2)\n                                   (square (two))\n                                   counter)))\n      (check-equal? 1\n                    (run\n                      '(begin\n                         (define (unless (condition lazy) (on-fail lazy) (on-success lazy))\n                           (if condition on-success on-fail))\n                         (unless (= 0 0)\n                                 (/ 1 0)\n                                 1))))\n      )\n\n    (test-suite \"Self-evaluating expressions\"\n      (check-equal? (run '1) 1)\n      (check-equal? (run '\"something\") \"something\"))\n\n    (test-suite \"Variables\"\n      (check-equal? (evaluate 'x (extend-environment '(x) '(1) the-empty-environment))\n                    1)\n      (check-exn exn? (lambda () (evaluate 'x the-empty-environment))))\n\n    (test-suite \"Quotation\"\n      (check-equal? (run '(quote foo)) 'foo))\n\n    (test-suite \"Begin\"\n      (check-equal? (run '(begin 1 2)) 2))\n\n    (test-suite \"Define\"\n      (check-equal? (run '(define x 1)) 'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 x))\n                    1)\n      (check-equal? (run '(define (x) 1)) 'ok)\n      (check-equal? (run '(begin (define (x) 1)\n                                 (x)))\n                    1))\n\n    (test-suite \"Set!\"\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)))\n                    'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)\n                                 x))\n                    2))\n\n    (test-suite \"If\"\n      (check-equal? (run '(if true 1 2)) 1)\n      (check-equal? (run '(if false 1 2)) 2)\n      (check-equal? (run '(if true 1)) 1)\n      (check-equal? (run '(if false 1)) false))\n\n    (test-suite \"Lambda\"\n      (check-equal? (run '((lambda () 1))) 1)\n      (check-equal? (run '((lambda (x) x) 1)) 1)\n      (check-equal? (run '((lambda (a b) (cons a b)) 1 2)) '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 ((lambda (a) (cons a b)) 3)))\n                    '(3 . 2)))\n\n    (test-suite \"Cond\"\n      (check-equal? (run '(cond (true 1))) 1)\n      (check-equal? (run '(cond (false 1) (true 2))) 2)\n      (check-equal? (run '(cond (false 1) (else 2))) 2)\n      (check-exn exn? (lambda () (run '(cond (else 1) (true 2))))))\n\n    (test-suite \"Procedure application\"\n      (check-equal? (run '(begin (define (a) 1)\n                                 (a)))\n                    1)\n      (check-equal? (run '(begin (define (pair a b) (cons a b))\n                                 (pair 1 2)))\n                    '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define (pair b) (cons a b))\n                                 (pair 2)))\n                    '(1 . 2)))\n\n    (test-suite \"Defining append\"\n      (check-equal? (run '(begin (define (append x y)\n                                   (if (null? x)\n                                       y\n                                       (cons (car x)\n                                             (append (cdr x) y))))\n                                 (append '(a b c) '(d e f))))\n                    '(a b c d e f)))\n\n    (test-suite \"Factorial\"\n      (check-equal? (run '(begin (define (factorial n)\n                                   (if (= n 1)\n                                       1\n                                       (* n (factorial (- n 1)))))\n                                 (factorial 5)))\n                    120)\n      (check-equal? (run '(begin (define (factorial n)\n                                   (define (iter n result)\n                                     (if (= n 0)\n                                         result\n                                         (iter (- n 1) (* result n))))\n                                   (iter n 1))\n                                 (factorial 5)))\n                    120)) \n))\n\n(run-tests sicp-4.31-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/33-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../33.scm\")\n\n(define (run exp)\n  (actual-value exp (setup-environment)))\n\n(define sicp-4.33-tests\n  (test-suite\n    \"Tests for SICP exercise 4.33\"\n\n    (check-true (run '(null? '())))\n    (check-true (run '(null? (cdr '(a)))))\n    (check-true (run '(null? (car '(() a)))))\n    (check-equal? 'a (run '(car '(a b c))))\n    (check-equal? 'c (run '(car (cdr (car (cdr '(a (b c))))))))\n    (check-equal? '() (run '(car '(() a))))\n    (check-equal? '() (run '(cdr (cdr '(() a)))))\n))\n\n(run-tests sicp-4.33-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/34-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../34.scm\")\n\n(define (run exp)\n  (actual-value exp (setup-environment)))\n\n(define (to-s exp)\n  (with-output-to-string (lambda () (run `(begin (define result ,exp)\n                                                 (print result))))))\n\n(define sicp-4.34-tests\n  (test-suite\n    \"Tests for SICP exercise 4.34\"\n\n    (check-equal? (to-s ''()) \"()\")\n    (check-equal? (to-s ''(() a)) \"(() a)\")\n    (check-equal? (to-s ''(a b c)) \"(a b c)\")\n    (check-equal? (to-s ''(a (b c) d)) \"(a (b c) d)\")\n    (check-equal? (to-s ''(a . b)) \"(a . b)\")\n    (check-equal? (to-s '(begin (define pair (cons 'a pair))\n                                pair))\n                  \"(a (...))\")\n    (check-equal? (to-s '(begin (define pair (cons 'a (cons pair 'b)))\n                                pair))\n                  \"(a (...) . b)\" )\n    (check-equal? (to-s '(begin (define pair (cons 'a (cons pair (cons 'b '()))))\n                                pair))\n                  \"(a (...) b)\")\n))\n\n(run-tests sicp-4.34-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/35-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../35.scm\")\n\n(define (all-values exp)\n  (ambeval exp\n           solution-environment\n           (lambda (value fail) (cons value (fail)))\n           (lambda () '())))\n\n(define sicp-4.35-tests\n  (test-suite\n    \"Tests for SICP exercise 4.35\"\n\n    (check-equal? (all-values '(begin (a-pythagorean-triple-between 2 10)))\n                  '((3 4 5) (6 8 10)))\n))\n\n(run-tests sicp-4.35-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/36-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../36.scm\")\n\n(define (first-n-values n exp)\n  (define (take n results)\n    (if (= n 0)\n        '()\n        (cons (car results)\n              (take (- n 1) (force (cdr results))))))\n  (take n\n        (ambeval exp\n                 solution-environment\n                 (lambda (value fail) (cons value (delay (fail))))\n                 (lambda () '()))))\n\n(define sicp-4.36-tests\n  (test-suite\n    \"Tests for SICP exercise 4.36\"\n\n    (check-equal? (first-n-values 5 '(a-pythagorean-triple))\n                  '((3 4 5) (6 8 10) (5 12 13) (9 12 15) (8 15 17)))\n\n))\n\n(run-tests sicp-4.36-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/38-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../38.scm\")\n\n(define (all-values exp)\n  (ambeval exp\n           solution-environment\n           (lambda (value fail) (cons value (fail)))\n           (lambda () '())))\n\n(define sicp-4.38-tests\n  (test-suite\n    \"Tests for SICP exercise 4.38\"\n\n    (check-equal? (all-values '(multiple-dwelling))\n                  '(((baker 1) (cooper 2) (fletcher 4) (miller 3) (smith 5))\n                    ((baker 1) (cooper 2) (fletcher 4) (miller 5) (smith 3))\n                    ((baker 1) (cooper 4) (fletcher 2) (miller 5) (smith 3))\n                    ((baker 3) (cooper 2) (fletcher 4) (miller 5) (smith 1))\n                    ((baker 3) (cooper 4) (fletcher 2) (miller 5) (smith 1))))\n))\n\n(run-tests sicp-4.38-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/41-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../41.scm\")\n\n(define sicp-4.41-tests\n  (test-suite\n    \"Tests for SICP exercise 4.41\"\n\n    (check-equal? (multiple-dwellings)\n                  '(((baker 3) (cooper 2) (fletcher 4) (miller 5) (smith 1))))\n))\n\n(run-tests sicp-4.41-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/42-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../42.scm\")\n\n(define (all-values exp)\n  (ambeval exp\n           solution-environment\n           (lambda (value fail) (cons value (fail)))\n           (lambda () '())))\n\n(define sicp-4.42-tests\n  (test-suite\n    \"Tests for SICP exercise 4.42\"\n\n    (check-equal? (all-values '(lairs))\n                  '(((betty 3) (ethel 5) (joan 2) (kitty 1) (mary 4))))\n\n))\n\n(run-tests sicp-4.42-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/43-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../43.scm\")\n\n(define (all-values exp)\n  (ambeval exp\n           solution-environment\n           (lambda (value fail) (cons value (fail)))\n           (lambda () '())))\n\n(define sicp-4.43-tests\n  (test-suite\n    \"Tests for SICP exercise 4.43\"\n\n    (check-equal? (all-values '(yachts-and-daughters true))\n                  '(downing))\n    (check-equal? (all-values '(yachts-and-daughters false))\n                  '(parker downing))\n))\n\n(run-tests sicp-4.43-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/44-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../44.scm\")\n\n(define (all-values exp)\n  (ambeval exp\n           solution-environment\n           (lambda (value fail) (cons value (fail)))\n           (lambda () '())))\n\n(define sicp-4.44-tests\n  (test-suite\n    \"Tests for SICP exercise 4.44\"\n\n    (check-equal? (length (all-values '(queens 8)))\n                  92)\n    (check member '(4 2 8 5 7 1 3 6) (all-values '(queens 8)))\n))\n\n(run-tests sicp-4.44-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/45-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../45.scm\")\n\n(define (all-values exp)\n  (ambeval exp\n           solution-environment\n           (lambda (value fail) (cons value (fail)))\n           (lambda () '())))\n\n(define sicp-4.45-tests\n  (test-suite\n    \"Tests for SICP exercise 4.45\"\n\n    (check-equal? (all-values\n                    '(parse\n                       '(the professor lectures to the student in the class with the cat)))\n                  '((sentence\n                      (simple-noun-phrase (article the) (noun professor))\n                      (verb-phrase\n                        (verb-phrase\n                          (verb-phrase\n                            (verb lectures)\n                            (prep-phrase\n                              (prep to)\n                              (simple-noun-phrase (article the) (noun student))))\n                          (prep-phrase\n                            (prep in)\n                            (simple-noun-phrase (article the) (noun class))))\n                        (prep-phrase\n                          (prep with)\n                          (simple-noun-phrase (article the) (noun cat)))))\n\n                    (sentence\n                      (simple-noun-phrase (article the) (noun professor))\n                      (verb-phrase\n                        (verb-phrase\n                          (verb lectures)\n                          (prep-phrase\n                            (prep to)\n                            (simple-noun-phrase (article the) (noun student))))\n                        (prep-phrase\n                          (prep in)\n                          (noun-phrase\n                            (simple-noun-phrase (article the) (noun class))\n                            (prep-phrase\n                              (prep with)\n                              (simple-noun-phrase (article the) (noun cat)))))))\n\n                    (sentence\n                      (simple-noun-phrase (article the) (noun professor))\n                      (verb-phrase\n                        (verb-phrase\n                          (verb lectures)\n                          (prep-phrase\n                            (prep to)\n                            (noun-phrase\n                              (simple-noun-phrase (article the) (noun student))\n                              (prep-phrase\n                                (prep in)\n                                (simple-noun-phrase (article the) (noun class))))))\n                        (prep-phrase\n                          (prep with)\n                          (simple-noun-phrase (article the) (noun cat)))))\n\n                    (sentence\n                      (simple-noun-phrase (article the) (noun professor))\n                      (verb-phrase\n                        (verb lectures)\n                        (prep-phrase\n                          (prep to)\n                          (noun-phrase\n                            (noun-phrase\n                              (simple-noun-phrase (article the) (noun student))\n                              (prep-phrase\n                                (prep in)\n                                (simple-noun-phrase (article the) (noun class))))\n                            (prep-phrase\n                              (prep with)\n                              (simple-noun-phrase (article the) (noun cat)))))))\n\n                    (sentence\n                      (simple-noun-phrase (article the) (noun professor))\n                      (verb-phrase\n                        (verb lectures)\n                        (prep-phrase\n                          (prep to)\n                          (noun-phrase\n                            (simple-noun-phrase (article the) (noun student))\n                            (prep-phrase\n                              (prep in)\n                              (noun-phrase\n                                (simple-noun-phrase (article the) (noun class))\n                                (prep-phrase\n                                  (prep with)\n                                  (simple-noun-phrase (article the) (noun cat)))))))))))\n))\n\n(run-tests sicp-4.45-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/48-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../48.scm\")\n\n(define (all-values exp)\n  (ambeval exp\n           solution-environment\n           (lambda (value fail) (cons value (fail)))\n           (lambda () '())))\n\n(define (parses? exp)\n  (not (null? (all-values `(parse (quote ,exp))))))\n\n(define sicp-4.48-tests\n  (test-suite\n    \"Tests for SICP exercise 4.48\"\n\n    (check-true (parses? '(the cat sleeps quietly)))\n    (check-true (parses? '(the brown cat sleeps)))\n    (check-true (parses? '(the quick brown cat sleeps)))\n    (check-true (parses? '(the quick brown cat sleeps in the class)))\n    (check-true (parses? '(the quick brown cat sleeps in the class quietly)))\n))\n\n(run-tests sicp-4.48-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/49-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../49.scm\")\n\n(define (first-n-values n exp)\n  (define (take n results)\n    (if (= n 0)\n        '()\n        (cons (car results)\n              (take (- n 1) (force (cdr results))))))\n  (take n\n        (ambeval exp\n                 solution-environment\n                 (lambda (value fail) (cons value (delay (fail))))\n                 (lambda () '()))))\n\n\n(define sicp-4.49-tests\n  (test-suite\n    \"Tests for SICP exercise 4.49\"\n\n    (check-equal? (first-n-values 6 '(terminals (generate-sentence)))\n                  '((the student studies)\n                    (the student studies for the student)\n                    (the student studies for the student for the student)\n                    (the student studies for the student for the student for the student)\n                    (the student studies for the student for the student for the student for the student)\n                    (the student studies for the student for the student for the student for the student for the student)))\n))\n\n(run-tests sicp-4.49-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/51-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../51.scm\")\n\n(define (all-values exp)\n  (ambeval exp\n           (setup-environment)\n           (lambda (value fail) (cons value (fail)))\n           (lambda () '())))\n\n(define sicp-4.51-tests\n  (test-suite\n    \"Tests for SICP exercise 4.51\"\n\n    (check-equal? (all-values '(begin (define count 0)\n                                      (let ((x (an-element-of '(a b c)))\n                                            (y (an-element-of '(a b c))))\n                                        (permanent-set! count (+ count 1))\n                                        (require (not (eq? x y)))\n                                        (list x y count))))\n                  '((a b 2)\n                    (a c 3)\n                    (b a 4)\n                    (b c 6)\n                    (c a 7)\n                    (c b 8)))\n))\n\n(run-tests sicp-4.51-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/52-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../52.scm\")\n\n(define (first-value exp)\n  (ambeval exp\n           (setup-environment)\n           (lambda (value fail) value)\n           (lambda () '())))\n\n(define sicp-4.52-tests\n  (test-suite\n    \"Tests for SICP exercise 4.52\"\n\n    (check-equal? (first-value '(if-fail (let ((x (an-element-of '(1 3 5))))\n                                           (require (even? x))\n                                           x)\n                                         'all-odd))\n                  'all-odd)\n    (check-equal? (first-value '(if-fail (let ((x (an-element-of '(1 3 5 8))))\n                                           (require (even? x))\n                                           x)\n                                         'all-odd))\n                  8)\n))\n\n(run-tests sicp-4.52-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/53-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../53.scm\")\n\n(define (first-value exp)\n  (ambeval exp\n           (setup-environment)\n           (lambda (value fail) value)\n           (lambda () '())))\n\n(define sicp-4.53-tests\n  (test-suite\n    \"Tests for SICP exercise 4.53\"\n\n    (check-equal?\n      (first-value\n        '(begin\n           (define (prime-sum-pair list1 list2)\n             (let ((a (an-element-of list1))\n                   (b (an-element-of list2)))\n               (require (prime? (+ a b)))\n               (list a b)))\n           (let ((pairs '()))\n             (if-fail (let ((p (prime-sum-pair '(1 3 5 8) '(20 35 110))))\n                        (permanent-set! pairs (cons p pairs))\n                        (amb))\n                      pairs))))\n      '((8 35) (3 110) (3 20)))\n))\n\n(run-tests sicp-4.53-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/54-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../54.scm\")\n\n(define (first-value exp)\n  (ambeval exp\n           (setup-environment)\n           (lambda (value fail) value)\n           (lambda () '())))\n\n(define sicp-4.54-tests\n  (test-suite\n    \"Tests for SICP exercise 4.54\"\n\n    (check-equal?\n      (first-value\n        '(begin\n           (define (prime-sum-pair list1 list2)\n             (let ((a (an-element-of list1))\n                   (b (an-element-of list2)))\n               (require (prime? (+ a b)))\n               (list a b)))\n           (let ((pairs '()))\n             (if-fail (let ((p (prime-sum-pair '(1 3 5 8) '(20 35 110))))\n                        (permanent-set! pairs (cons p pairs))\n                        (amb))\n                      pairs))))\n      '((8 35) (3 110) (3 20)))\n))\n\n(run-tests sicp-4.54-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/55-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../55.scm\")\n\n(load \"helpers/query.scm\")\n\n(define sicp-4.55-tests\n  (test-suite\n    \"Tests for SICP exercise 4.55\"\n\n    (check-equal? (matches-of query-a)\n                  '((supervisor (Hacker Alyssa P) (Bitdiddle Ben))\n                    (supervisor (Fect Cy D) (Bitdiddle Ben))\n                    (supervisor (Tweakit Lem E) (Bitdiddle Ben))))\n\n    (check-equal? (matches-of query-b)\n                  '((job (Scrooge Eben) (accounting chief accountant))\n                    (job (Cratchet Robert) (accounting scrivener))))\n\n    (check-equal? (matches-of query-c)\n                  '((address (Bitdiddle Ben) (Slumerville (Ridge Road) 10))\n                    (address (Reasoner Louis) (Slumerville (Pine Tree Road) 80))\n                    (address (Aull DeWitt) (Slumerville (Onion Square) 5))))\n))\n\n(run-tests sicp-4.55-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/56-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../56.scm\")\n\n(load \"helpers/query.scm\")\n\n(define sicp-4.56-tests\n  (test-suite\n    \"Tests for SICP exercise 4.56\"\n\n    (check-equal? (matches-of query-a)\n                  '((and (address (Hacker Alyssa P) (Cambridge (Mass Ave) 78))\n                         (supervisor (Hacker Alyssa P) (Bitdiddle Ben)))\n                    (and (address (Fect Cy D) (Cambridge (Ames Street) 3))\n                         (supervisor (Fect Cy D) (Bitdiddle Ben)))\n                    (and (address (Tweakit Lem E) (Boston (Bay State Road) 22))\n                         (supervisor (Tweakit Lem E) (Bitdiddle Ben)))))\n\n    (check-equal? (matches-of query-b)\n                  '((and (salary (Hacker Alyssa P) 40000)\n                         (salary (Bitdiddle Ben) 60000)\n                         (lisp-value < 40000 60000))\n                    (and (salary (Fect Cy D) 35000)\n                         (salary (Bitdiddle Ben) 60000)\n                         (lisp-value < 35000 60000))\n                    (and (salary (Tweakit Lem E) 25000)\n                         (salary (Bitdiddle Ben) 60000)\n                         (lisp-value < 25000 60000))\n                    (and (salary (Reasoner Louis) 30000)\n                         (salary (Bitdiddle Ben) 60000)\n                         (lisp-value < 30000 60000))\n                    (and (salary (Cratchet Robert) 18000)\n                         (salary (Bitdiddle Ben) 60000)\n                         (lisp-value < 18000 60000))\n                    (and (salary (Aull DeWitt) 25000)\n                         (salary (Bitdiddle Ben) 60000)\n                         (lisp-value < 25000 60000))))\n\n    (check-equal? (matches-of query-c)\n                  '((and (supervisor (Bitdiddle Ben) (Warbucks Oliver))\n                         (not (job (Warbucks Oliver) (computer . ?title))))\n                    (and (supervisor (Scrooge Eben) (Warbucks Oliver))\n                         (not (job (Warbucks Oliver) (computer . ?title))))\n                    (and (supervisor (Cratchet Robert) (Scrooge Eben))\n                         (not (job (Scrooge Eben) (computer . ?title))))\n                    (and (supervisor (Aull DeWitt) (Warbucks Oliver))\n                         (not (job (Warbucks Oliver) (computer . ?title))))))\n))\n\n(run-tests sicp-4.56-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/57-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/query.scm\")\n(load \"../57.scm\")\n\n(define sicp-4.57-tests\n  (test-suite\n    \"Tests for SICP exercise 4.57\"\n\n    (check-equal? (matches-of query-a)\n                  '((can-replace (Bitdiddle Ben) (Fect Cy D))))\n\n    (check-equal? (matches-of query-b)\n                  '((and (can-replace (Aull DeWitt) (Warbucks Oliver))\n                         (salary (Aull DeWitt) 25000)\n                         (salary (Warbucks Oliver) 150000)\n                         (lisp-value < 25000 150000))))\n\n))\n\n(run-tests sicp-4.57-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/58-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/query.scm\")\n(load \"../58.scm\")\n\n(define sicp-4.58-tests\n  (test-suite\n    \"Tests for SICP exercise 4.58\"\n\n    (check-equal? (matches-of '(big-shot ?person))\n                  '((big-shot (Warbucks Oliver))\n                    (big-shot (Bitdiddle Ben))\n                    (big-shot (Scrooge Eben))))\n))\n\n(run-tests sicp-4.58-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/59-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/query.scm\")\n(load \"../59.scm\")\n\n(define sicp-4.59-tests\n  (test-suite\n    \"Tests for SICP exercise 4.59\"\n\n    (check-equal? (matches-of bens-query)\n                  '((meeting administration (Friday 1pm))))\n\n    (check-equal? (matches-of alyssas-query)\n                  '((meeting-time (Hacker Alyssa P) (Wednesday 3pm))\n                    (meeting-time (Hacker Alyssa P) (Wednesday 4pm))))\n))\n\n(run-tests sicp-4.59-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/60-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/query.scm\")\n(load \"../60.scm\")\n\n(define sicp-4.60-tests\n  (test-suite\n    \"Tests for SICP exercise 4.60\"\n\n    (check-equal? (matches-of '(ordered-neighbour-pair ?person-1 ?person-2))\n                  '((ordered-neighbour-pair (Bitdiddle Ben) (Reasoner Louis))\n                    (ordered-neighbour-pair (Fect Cy D) (Hacker Alyssa P))\n                    (ordered-neighbour-pair (Aull DeWitt) (Bitdiddle Ben))\n                    (ordered-neighbour-pair (Aull DeWitt) (Reasoner Louis))))\n))\n\n(run-tests sicp-4.60-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/61-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/query.scm\")\n(load \"../61.scm\")\n\n(define sicp-4.61-tests\n  (test-suite\n    \"Tests for SICP exercise 4.61\"\n\n    (check-equal? (matches-of query-1) response-1)\n    (check-equal? (matches-of query-2) response-2)\n))\n\n(run-tests sicp-4.61-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/62-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/query.scm\")\n(load \"../62.scm\")\n\n(define sicp-4.62-tests\n  (test-suite\n    \"Tests for SICP exercise 4.62\"\n\n    (check-equal? (matches-of '(last-pair (3) ?x))\n                  '((last-pair (3) (3))))\n\n    (check-equal? (matches-of '(last-pair (1 2 3) ?x))\n                  '((last-pair (1 2 3) (3))))\n\n    (check-equal? (matches-of '(last-pair (2 ?x) (3)))\n                  '((last-pair (2 3) (3))))\n))\n\n(run-tests sicp-4.62-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/63-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/query.scm\")\n(load \"../63.scm\")\n\n(define sicp-4.63-tests\n  (test-suite\n    \"Tests for SICP exercise 4.63\"\n\n    (check-equal? (matches-of grandson-of-cain)\n                  '((grandson Cain Irad)))\n\n    (check-equal? (matches-of sons-of-lamech)\n                  '((son Lamech Jabal)\n                    (son Lamech Jubal)))\n\n    (check-equal? (matches-of grandsons-of-methushael)\n                  '((grandson Methushael Jabal)\n                    (grandson Methushael Jubal)))\n\n))\n\n(run-tests sicp-4.63-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/67-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../67.scm\")\n(load-relative \"../showcase/query/database.scm\")\n\n(define (matches-of query)\n  (let ((processed-query (query-syntax-process query)))\n    (stream->list\n      (stream-map\n        (lambda (frame)\n          (instantiate-exp processed-query frame (lambda (v f) (contract-question-mark v))))\n        (qeval processed-query (singleton-stream '()) '())))))\n\n(define (matches? query)\n  (not (null? (matches-of query))))\n\n(define sicp-4.67-tests\n  (test-suite\n    \"Tests for SICP exercise 4.67\"\n\n    (add-to-data-base! loopy-rules)\n\n    (test-suite \"loopy rules\"\n      (check-equal? (matches-of '(loopy-outranked-by (Bitdiddle Ben) ?who))\n                    '((loopy-outranked-by (Bitdiddle Ben) (Warbucks Oliver))))\n      (check-equal? (matches-of '(married Mickey ?who))\n                    '((married Mickey Minnie))))\n\n    (test-suite \"simple queries\"\n      (check-equal? (matches-of '(job ?x (computer programmer)))\n                    '((job (Hacker Alyssa P) (computer programmer))\n                      (job (Fect Cy D) (computer programmer))))\n\n      (check-equal? (matches-of '(job ?x (computer ?type)))\n                    '((job (Bitdiddle Ben) (computer wizard))\n                      (job (Hacker Alyssa P) (computer programmer))\n                      (job (Fect Cy D) (computer programmer))\n                      (job (Tweakit Lem E) (computer technician))))\n\n      (check-equal? (matches-of '(job ?x (computer . ?type)))\n                    '((job (Bitdiddle Ben) (computer wizard))\n                      (job (Hacker Alyssa P) (computer programmer))\n                      (job (Fect Cy D) (computer programmer))\n                      (job (Tweakit Lem E) (computer technician))\n                      (job (Reasoner Louis) (computer programmer trainee))))\n\n      (check-equal? (matches-of '(and (job ?person (computer programmer))\n                                      (address ?person ?where)))\n                    '((and (job (Hacker Alyssa P) (computer programmer))\n                           (address (Hacker Alyssa P) (Cambridge (Mass Ave) 78)))\n                      (and (job (Fect Cy D) (computer programmer))\n                           (address (Fect Cy D) (Cambridge (Ames Street) 3)))))\n\n      (check-equal? (matches-of '(or (supervisor ?x (Bitdiddle Ben))\n                                     (supervisor ?x (Hacker Alyssa P))))\n                    '((or (supervisor (Hacker Alyssa P) (Bitdiddle Ben))\n                          (supervisor (Hacker Alyssa P) (Hacker Alyssa P)))\n                      (or (supervisor (Reasoner Louis) (Bitdiddle Ben))\n                          (supervisor (Reasoner Louis) (Hacker Alyssa P)))\n                      (or (supervisor (Fect Cy D) (Bitdiddle Ben))\n                          (supervisor (Fect Cy D) (Hacker Alyssa P)))\n                      (or (supervisor (Tweakit Lem E) (Bitdiddle Ben))\n                          (supervisor (Tweakit Lem E) (Hacker Alyssa P)))))\n\n      (check-equal? (matches-of '(and (supervisor ?x (Bitdiddle Ben))\n                                      (not (job ?x (computer programmer)))))\n                    '((and (supervisor (Tweakit Lem E) (Bitdiddle Ben))\n                           (not (job (Tweakit Lem E) (computer programmer))))))\n\n      (check-equal? (matches-of '(and (salary ?person ?amount)\n                                      (lisp-value > ?amount 30000)))\n                    '((and (salary (Warbucks Oliver) 150000)\n                           (lisp-value > 150000 30000))\n                      (and (salary (Bitdiddle Ben) 60000)\n                           (lisp-value > 60000 30000))\n                      (and (salary (Hacker Alyssa P) 40000)\n                           (lisp-value > 40000 30000))\n                      (and (salary (Fect Cy D) 35000)\n                           (lisp-value > 35000 30000))\n                      (and (salary (Scrooge Eben) 75000)\n                           (lisp-value > 75000 30000)))))\n\n    (test-suite \"rules\"\n      (check-true (matches? '(same x x)))\n\n      (check-true (matches? '(lives-near (Hacker Alyssa P) (Fect Cy D))))\n      (check-false (matches? '(lives-near (Hacker Alyssa P) (Bitdiddle Ben))))\n\n      (check-true (matches? '(wheel (Warbucks Oliver))))\n      (check-true (matches? '(wheel (Bitdiddle Ben))))\n      (check-false (matches? '(wheel (Hacker Alyssa P))))\n\n      (check-true (matches? '(outranked-by (Bitdiddle Ben) (Warbucks Oliver))))\n      (check-true (matches? '(outranked-by (Hacker Alyssa P) (Warbucks Oliver))))\n      (check-true (matches? '(outranked-by (Reasoner Louis) (Warbucks Oliver))))\n      (check-true (matches? '(outranked-by (Hacker Alyssa P) (Bitdiddle Ben))))\n      (check-true (matches? '(outranked-by (Reasoner Louis) (Bitdiddle Ben))))\n      (check-true (matches? '(outranked-by (Reasoner Louis) (Hacker Alyssa P))))\n\n      (check-false (matches? '(outranked-by (Warbucks Oliver) (Bitdiddle Ben))))\n      (check-false (matches? '(outranked-by (Eben Scrooge) (Bitdiddle Ben))))\n      (check-false (matches? '(outranked-by (Bitdiddle Ben) (Eben Scrooge)))))\n\n    (test-suite \"logic as programs\"\n      (check-equal? (matches-of '(append-to-form (a b) (c d) ?z))\n                    '((append-to-form (a b) (c d) (a b c d))))\n      (check-equal? (matches-of '(append-to-form (a b) ?y (a b c d)))\n                    '((append-to-form (a b) (c d) (a b c d))))\n      (check-equal? (matches-of '(append-to-form ?x ?y (a b c d)))\n                    '((append-to-form () (a b c d) (a b c d))\n                      (append-to-form (a) (b c d) (a b c d))\n                      (append-to-form (a b) (c d) (a b c d))\n                      (append-to-form (a b c) (d) (a b c d))\n                      (append-to-form (a b c d) () (a b c d)))))\n))\n\n(run-tests sicp-4.67-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/68-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load-relative \"helpers/query.scm\")\n(load \"../68.scm\")\n\n(define sicp-4.68-tests\n  (test-suite\n    \"Tests for SICP exercise 4.68\"\n\n    (check-equal? (matches-of '(reverse (1 2 3) ?x))\n                  '((reverse (1 2 3) (3 2 1))))\n\n))\n\n(run-tests sicp-4.68-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/69-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../69.scm\")\n\n(define (matches-of query)\n  (let ((processed-query (query-syntax-process query)))\n    (stream->list\n      (stream-map\n        (lambda (frame)\n          (instantiate-exp processed-query frame (lambda (v f) (contract-question-mark v))))\n        (qeval processed-query (singleton-stream '()) '())))))\n\n\n(define sicp-4.69-tests\n  (test-suite\n    \"Tests for SICP exercise 4.69\"\n\n    (check-equal? (matches-of '((great grandson) ?g ?ggs))\n                  '(((great grandson) Adam Irad)\n                    ((great grandson) Cain Mehujael)\n                    ((great grandson) Enoch Methushael)\n                    ((great grandson) Irad Lamech)\n                    ((great grandson) Mehujael Jabal)\n                    ((great grandson) Mehujael Jubal)))\n\n    (check-equal? (matches-of '(?relationship Adam Irad))\n                  '(((great grandson) Adam Irad)))\n))\n\n(run-tests sicp-4.69-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/75-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/query.scm\")\n(load \"../75.scm\")\n\n(define sicp-4.75-tests\n  (test-suite\n    \"Tests for SICP exercise 4.75\"\n\n    (check-equal? (matches-of '(unique (job ?x (computer wizard))))\n                  '((unique (job (Bitdiddle Ben) (computer wizard)))))\n\n    (check-equal? (matches-of '(and (job ?x ?j) (unique (job ?anyone ?j))))\n                  '((and (job (Warbucks Oliver) (administration big wheel))\n                         (unique (job (Warbucks Oliver) (administration big wheel))))\n                    (and (job (Bitdiddle Ben) (computer wizard))\n                         (unique (job (Bitdiddle Ben) (computer wizard))))\n                    (and (job (Tweakit Lem E) (computer technician))\n                         (unique (job (Tweakit Lem E) (computer technician))))\n                    (and (job (Reasoner Louis) (computer programmer trainee))\n                         (unique (job (Reasoner Louis) (computer programmer trainee))))\n                    (and (job (Scrooge Eben) (accounting chief accountant))\n                         (unique (job (Scrooge Eben) (accounting chief accountant))))\n                    (and (job (Cratchet Robert) (accounting scrivener))\n                         (unique (job (Cratchet Robert) (accounting scrivener))))\n                    (and (job (Aull DeWitt) (administration secretary))\n                         (unique (job (Aull DeWitt) (administration secretary))))))\n\n    (check-equal? (matches-of supervises-one-person)\n                  '((and (supervisor (Reasoner Louis) (Hacker Alyssa P))\n                         (unique (supervisor (Reasoner Louis) (Hacker Alyssa P))))\n                    (and (supervisor (Cratchet Robert) (Scrooge Eben))\n                         (unique (supervisor (Cratchet Robert) (Scrooge Eben))))))\n))\n\n(run-tests sicp-4.75-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/76-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/query.scm\")\n(load \"../76.scm\")\n\n(define (env items)\n  (if (null? items)\n      '()\n      (cons (cons (list '? (caar items))\n                  (cadar items))\n            (env (cdr items)))))\n\n(define sicp-4.76-tests\n  (test-suite\n    \"Tests for SICP exercise 4.76\"\n\n    (test-suite \"merging frames\"\n      (check-equal? (merge-frames (env '((x 1) (y 2)))\n                                  (env '((z 3) (x 1))))\n                    (env '((y 2) (z 3) (x 1))))\n\n      (check-equal? (merge-frames (env '((x (? y)) (z (1 2))))\n                                  (env '((x (? z)) (y (1 (? two))))))\n                    (env '((two 2) (z (1 (? two))) (x (? z)) (y (1 (? two)))))))\n\n    (test-suite \"simple queries\"\n      (check-equal? (matches-of '(and (job ?person (computer programmer))\n                                      (address ?person ?where)))\n                    '((and (job (Hacker Alyssa P) (computer programmer))\n                           (address (Hacker Alyssa P) (Cambridge (Mass Ave) 78)))\n                      (and (job (Fect Cy D) (computer programmer))\n                           (address (Fect Cy D) (Cambridge (Ames Street) 3))))))\n\n    (test-suite \"rules\"\n      (check-true (matches? '(same x x)))\n\n      (check-true (matches? '(lives-near (Hacker Alyssa P) (Fect Cy D))))\n      (check-false (matches? '(lives-near (Hacker Alyssa P) (Bitdiddle Ben))))\n\n      (check-true (matches? '(wheel (Warbucks Oliver))))\n      (check-true (matches? '(wheel (Bitdiddle Ben))))\n      (check-false (matches? '(wheel (Hacker Alyssa P)))))\n\n    (test-suite \"logic as programs\"\n      (check-equal? (matches-of '(append-to-form (a b) (c d) ?z))\n                    '((append-to-form (a b) (c d) (a b c d))))\n      (check-equal? (matches-of '(append-to-form (a b) ?y (a b c d)))\n                    '((append-to-form (a b) (c d) (a b c d))))\n      (check-equal? (matches-of '(append-to-form ?x ?y (a b c d)))\n                    '((append-to-form () (a b c d) (a b c d))\n                      (append-to-form (a) (b c d) (a b c d))\n                      (append-to-form (a b) (c d) (a b c d))\n                      (append-to-form (a b c) (d) (a b c d))\n                      (append-to-form (a b c d) () (a b c d)))))\n\n))\n\n(run-tests sicp-4.76-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/77-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../77.scm\")\n(load-relative \"../showcase/query/database.scm\")\n\n(define (matches-of query)\n  (let ((processed-query (query-syntax-process query)))\n    (stream->list\n      (stream-map\n        (lambda (frame)\n          (instantiate-exp processed-query frame (lambda (v f) (contract-question-mark v))))\n        (qeval processed-query (singleton-stream empty-frame))))))\n\n(define sicp-4.77-tests\n  (test-suite\n    \"Tests for SICP exercise 4.77\"\n\n    (check-equal? (matches-of '(and (lisp-value > ?amount 30000)\n                                    (salary ?person ?amount)))\n                  '((and (lisp-value > 150000 30000)\n                         (salary (Warbucks Oliver) 150000))\n                    (and (lisp-value > 60000 30000)\n                         (salary (Bitdiddle Ben) 60000))\n                    (and (lisp-value > 40000 30000)\n                         (salary (Hacker Alyssa P) 40000))\n                    (and (lisp-value > 35000 30000)\n                         (salary (Fect Cy D) 35000))\n                    (and (lisp-value > 75000 30000)\n                         (salary (Scrooge Eben) 75000))))\n\n    (check-equal? (matches-of '(and (not (job ?x (computer programmer)))\n                                    (supervisor ?x (Bitdiddle Ben))))\n                  '((and (not (job (Tweakit Lem E) (computer programmer)))\n                         (supervisor (Tweakit Lem E) (Bitdiddle Ben)))))\n))\n\n(run-tests sicp-4.77-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/78-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../78.scm\")\n(load-relative \"../showcase/query/database.scm\")\n\n(define (matches-of query)\n  (let ((processed-query (query-syntax-process query)))\n    (map (lambda (frame)\n           (instantiate-exp processed-query frame (lambda (v f) (contract-question-mark v))))\n        (amb-collect (qeval processed-query '())))))\n\n(define (matches? query)\n  (not (null? (matches-of query))))\n\n(define sicp-4.78-tests\n  (test-suite\n    \"Tests for SICP exercise 4.78\"\n\n    (test-suite \"simple queries\"\n      (check-equal? (matches-of '(job ?x (computer programmer)))\n                    '((job (Hacker Alyssa P) (computer programmer))\n                      (job (Fect Cy D) (computer programmer))))\n\n      (check-equal? (matches-of '(job ?x (computer ?type)))\n                    '((job (Bitdiddle Ben) (computer wizard))\n                      (job (Hacker Alyssa P) (computer programmer))\n                      (job (Fect Cy D) (computer programmer))\n                      (job (Tweakit Lem E) (computer technician))))\n\n      (check-equal? (matches-of '(job ?x (computer . ?type)))\n                    '((job (Bitdiddle Ben) (computer wizard))\n                      (job (Hacker Alyssa P) (computer programmer))\n                      (job (Fect Cy D) (computer programmer))\n                      (job (Tweakit Lem E) (computer technician))\n                      (job (Reasoner Louis) (computer programmer trainee))))\n\n      (check-equal? (matches-of '(and (job ?person (computer programmer))\n                                      (address ?person ?where)))\n                    '((and (job (Hacker Alyssa P) (computer programmer))\n                           (address (Hacker Alyssa P) (Cambridge (Mass Ave) 78)))\n                      (and (job (Fect Cy D) (computer programmer))\n                           (address (Fect Cy D) (Cambridge (Ames Street) 3)))))\n\n      (check-equal? (matches-of '(or (supervisor ?x (Bitdiddle Ben))\n                                     (supervisor ?x (Hacker Alyssa P))))\n                    '((or (supervisor (Hacker Alyssa P) (Bitdiddle Ben))\n                          (supervisor (Hacker Alyssa P) (Hacker Alyssa P)))\n                      (or (supervisor (Fect Cy D) (Bitdiddle Ben))\n                          (supervisor (Fect Cy D) (Hacker Alyssa P)))\n                      (or (supervisor (Tweakit Lem E) (Bitdiddle Ben))\n                          (supervisor (Tweakit Lem E) (Hacker Alyssa P)))\n                      (or (supervisor (Reasoner Louis) (Bitdiddle Ben))\n                          (supervisor (Reasoner Louis) (Hacker Alyssa P)))))\n\n      (check-equal? (matches-of '(and (supervisor ?x (Bitdiddle Ben))\n                                      (not (job ?x (computer programmer)))))\n                    '((and (supervisor (Tweakit Lem E) (Bitdiddle Ben))\n                           (not (job (Tweakit Lem E) (computer programmer))))))\n\n      (check-equal? (matches-of '(and (salary ?person ?amount)\n                                      (lisp-value > ?amount 30000)))\n                    '((and (salary (Warbucks Oliver) 150000)\n                           (lisp-value > 150000 30000))\n                      (and (salary (Bitdiddle Ben) 60000)\n                           (lisp-value > 60000 30000))\n                      (and (salary (Hacker Alyssa P) 40000)\n                           (lisp-value > 40000 30000))\n                      (and (salary (Fect Cy D) 35000)\n                           (lisp-value > 35000 30000))\n                      (and (salary (Scrooge Eben) 75000)\n                           (lisp-value > 75000 30000)))))\n\n    (test-suite \"rules\"\n      (check-true (matches? '(same x x)))\n\n      (check-true (matches? '(lives-near (Hacker Alyssa P) (Fect Cy D))))\n      (check-false (matches? '(lives-near (Hacker Alyssa P) (Bitdiddle Ben))))\n\n      (check-true (matches? '(wheel (Warbucks Oliver))))\n      (check-true (matches? '(wheel (Bitdiddle Ben))))\n      (check-false (matches? '(wheel (Hacker Alyssa P))))\n\n      (check-true (matches? '(outranked-by (Bitdiddle Ben) (Warbucks Oliver))))\n      (check-true (matches? '(outranked-by (Hacker Alyssa P) (Warbucks Oliver))))\n      (check-true (matches? '(outranked-by (Reasoner Louis) (Warbucks Oliver))))\n      (check-true (matches? '(outranked-by (Hacker Alyssa P) (Bitdiddle Ben))))\n      (check-true (matches? '(outranked-by (Reasoner Louis) (Bitdiddle Ben))))\n      (check-true (matches? '(outranked-by (Reasoner Louis) (Hacker Alyssa P))))\n\n      (check-false (matches? '(outranked-by (Warbucks Oliver) (Bitdiddle Ben))))\n      (check-false (matches? '(outranked-by (Eben Scrooge) (Bitdiddle Ben))))\n      (check-false (matches? '(outranked-by (Bitdiddle Ben) (Eben Scrooge)))))\n\n    (test-suite \"logic as programs\"\n      (check-equal? (matches-of '(append-to-form (a b) (c d) ?z))\n                    '((append-to-form (a b) (c d) (a b c d))))\n      (check-equal? (matches-of '(append-to-form (a b) ?y (a b c d)))\n                    '((append-to-form (a b) (c d) (a b c d))))\n      (check-equal? (matches-of '(append-to-form ?x ?y (a b c d)))\n                    '((append-to-form () (a b c d) (a b c d))\n                      (append-to-form (a) (b c d) (a b c d))\n                      (append-to-form (a b) (c d) (a b c d))\n                      (append-to-form (a b c) (d) (a b c d))\n                      (append-to-form (a b c d) () (a b c d)))))\n))\n\n(run-tests sicp-4.78-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/79-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../79.scm\")\n(load-relative \"../showcase/query/database.scm\")\n\n(define (matches-of query)\n  (let ((processed-query (query-syntax-process query)))\n    (stream->list\n      (stream-map\n        (lambda (frame)\n          (instantiate-exp processed-query frame (lambda (v f) (contract-question-mark v))))\n        (qeval processed-query (singleton-stream (empty-frame)))))))\n\n(define (matches? query)\n  (not (null? (matches-of query))))\n\n(define sicp-4.79-tests\n  (test-suite\n    \"Tests for SICP exercise 4.79\"\n\n    (test-suite \"inner rules\"\n      (add-to-data-base!\n        '((rule (reverse (?x) (?x)))\n          (rule (reverse (?a . ?b) ?c)\n                (rule (i-append-to-form () ?y ?y))\n                (rule (i-append-to-form (?u . ?v) ?y (?u . ?z))\n                      (i-append-to-form ?v ?y ?z))\n                (and (reverse ?b ?r-b)\n                     (i-append-to-form ?r-b (?a) ?c)))\n          (rule (surrounded-by ?char (?char . ?rest))\n                (rule (proper-ending (?char)))\n                (rule (proper-ending (?head . ?tail))\n                      (proper-ending ?tail))\n                (proper-ending ?rest))))\n\n      (check-equal? (matches-of '(reverse (1 2 3) (3 2 1)))\n                    '((reverse (1 2 3) (3 2 1))))\n      (check-equal? (matches-of '(reverse (1 2 3) ?x))\n                    '((reverse (1 2 3) (3 2 1))))\n      (check-true (matches? '(surrounded-by a (a b c b a))))\n      (check-false (matches? '(surrounded-by a (a b c b))))\n      (check-false (matches? '(surrounded-by b (a b c b a)))))\n\n\n    (test-suite \"simple queries\"\n      (check-equal? (matches-of '(job ?x (computer programmer)))\n                    '((job (Hacker Alyssa P) (computer programmer))\n                      (job (Fect Cy D) (computer programmer))))\n\n      (check-equal? (matches-of '(job ?x (computer ?type)))\n                    '((job (Bitdiddle Ben) (computer wizard))\n                      (job (Hacker Alyssa P) (computer programmer))\n                      (job (Fect Cy D) (computer programmer))\n                      (job (Tweakit Lem E) (computer technician))))\n\n      (check-equal? (matches-of '(job ?x (computer . ?type)))\n                    '((job (Bitdiddle Ben) (computer wizard))\n                      (job (Hacker Alyssa P) (computer programmer))\n                      (job (Fect Cy D) (computer programmer))\n                      (job (Tweakit Lem E) (computer technician))\n                      (job (Reasoner Louis) (computer programmer trainee))))\n\n      (check-equal? (matches-of '(and (job ?person (computer programmer))\n                                      (address ?person ?where)))\n                    '((and (job (Hacker Alyssa P) (computer programmer))\n                           (address (Hacker Alyssa P) (Cambridge (Mass Ave) 78)))\n                      (and (job (Fect Cy D) (computer programmer))\n                           (address (Fect Cy D) (Cambridge (Ames Street) 3)))))\n\n      (check-equal? (matches-of '(or (supervisor ?x (Bitdiddle Ben))\n                                     (supervisor ?x (Hacker Alyssa P))))\n                    '((or (supervisor (Hacker Alyssa P) (Bitdiddle Ben))\n                          (supervisor (Hacker Alyssa P) (Hacker Alyssa P)))\n                      (or (supervisor (Reasoner Louis) (Bitdiddle Ben))\n                          (supervisor (Reasoner Louis) (Hacker Alyssa P)))\n                      (or (supervisor (Fect Cy D) (Bitdiddle Ben))\n                          (supervisor (Fect Cy D) (Hacker Alyssa P)))\n                      (or (supervisor (Tweakit Lem E) (Bitdiddle Ben))\n                          (supervisor (Tweakit Lem E) (Hacker Alyssa P)))))\n\n      (check-equal? (matches-of '(and (supervisor ?x (Bitdiddle Ben))\n                                      (not (job ?x (computer programmer)))))\n                    '((and (supervisor (Tweakit Lem E) (Bitdiddle Ben))\n                           (not (job (Tweakit Lem E) (computer programmer))))))\n\n      (check-equal? (matches-of '(and (salary ?person ?amount)\n                                      (lisp-value > ?amount 30000)))\n                    '((and (salary (Warbucks Oliver) 150000)\n                           (lisp-value > 150000 30000))\n                      (and (salary (Bitdiddle Ben) 60000)\n                           (lisp-value > 60000 30000))\n                      (and (salary (Hacker Alyssa P) 40000)\n                           (lisp-value > 40000 30000))\n                      (and (salary (Fect Cy D) 35000)\n                           (lisp-value > 35000 30000))\n                      (and (salary (Scrooge Eben) 75000)\n                           (lisp-value > 75000 30000)))))\n\n    (test-suite \"rules\"\n      (check-true (matches? '(same x x)))\n\n      (check-true (matches? '(lives-near (Hacker Alyssa P) (Fect Cy D))))\n      (check-false (matches? '(lives-near (Hacker Alyssa P) (Bitdiddle Ben))))\n\n      (check-true (matches? '(wheel (Warbucks Oliver))))\n      (check-true (matches? '(wheel (Bitdiddle Ben))))\n      (check-false (matches? '(wheel (Hacker Alyssa P))))\n\n      (check-true (matches? '(outranked-by (Bitdiddle Ben) (Warbucks Oliver))))\n      (check-true (matches? '(outranked-by (Hacker Alyssa P) (Warbucks Oliver))))\n      (check-true (matches? '(outranked-by (Reasoner Louis) (Warbucks Oliver))))\n      (check-true (matches? '(outranked-by (Hacker Alyssa P) (Bitdiddle Ben))))\n      (check-true (matches? '(outranked-by (Reasoner Louis) (Bitdiddle Ben))))\n      (check-true (matches? '(outranked-by (Reasoner Louis) (Hacker Alyssa P))))\n\n      (check-false (matches? '(outranked-by (Warbucks Oliver) (Bitdiddle Ben))))\n      (check-false (matches? '(outranked-by (Eben Scrooge) (Bitdiddle Ben))))\n      (check-false (matches? '(outranked-by (Bitdiddle Ben) (Eben Scrooge)))))\n\n    (test-suite \"logic as programs\"\n      (check-equal? (matches-of '(append-to-form () (a b) ?y))\n                    '((append-to-form () (a b) (a b))))\n      (check-equal? (matches-of '(append-to-form (a) (b c d) ?p))\n                    '((append-to-form (a) (b c d) (a b c d))))\n      (check-equal? (matches-of '(append-to-form (a b) ?m (a b c d)))\n                    '((append-to-form (a b) (c d) (a b c d))))\n      (check-equal? (matches-of '(append-to-form ?x ?y (a b c d)))\n                    '((append-to-form () (a b c d) (a b c d))\n                      (append-to-form (a) (b c d) (a b c d))\n                      (append-to-form (a b) (c d) (a b c d))\n                      (append-to-form (a b c) (d) (a b c d))\n                      (append-to-form (a b c d) () (a b c d)))))\n))\n\n(run-tests sicp-4.79-tests)\n"
  },
  {
    "path": "scheme/sicp/04/tests/helpers/query.scm",
    "content": "(load-relative \"../../showcase/query/evaluator.scm\")\n(load-relative \"../../showcase/query/database.scm\")\n(load-relative \"../../showcase/query/test-helpers.scm\")\n"
  },
  {
    "path": "scheme/sicp/05/01.scm",
    "content": "; SICP exercise 5.01\n;\n; Design a register machine to compute factorials using the iterative\n; algorithm specified by the following procedure. Draw data-path and\n; controller diagrams for this machine.\n;\n; (define (factorial n)\n;   (define (iter product counter)\n;     (if (> counter n)\n;         product\n;         (iter (* counter product)\n;               (+ counter 1))))\n;   (iter 1 1))\n\n; Whee! More drawing! I had some fun trying to figure out how to draw this as a\n; planar graph. I wonder if the exercise designers thought about that.\n;\n; The number we are calculating factorial of should be stored in the register\n; n. When the machine finishes, the result will be stored in register p.\n;\n; This is the data-path diagram:\n;\n;                +---------+\n;  +---(  >  )---|    n    |\n;  |             +---------+\n;  |\n; +---------+  c<-1 +-----+  p<-1 +---------+\n; |    c    |<-(x)-/   1   \\-(x)->|    p    |\n; +---------+     +---------+     +---------+\n;  |   ^   |       |               |       ^\n;  |   |  +---------+              |       |\n;  |   |   \\   +   /               |      (x) p<-*\n;  |   |    +-----+                |       |\n;  |  (x) c++  |                   |       |\n;  |   +-------+                   |       |\n;  +-----------------------+       |       |\n;                          |       |       |\n;                         +---------+      |\n;                          \\   *   /       |\n;                           +-----+        |\n;                              |           |\n;                              +-----------+\n;\n; Here's the controller diagram:\n;\n;       start\n;         |\n;         V\n;     +-------+\n;     | c<-1  |\n;     +-------+\n;         |\n;         V\n;     +-------+\n;     | p<-1  |\n;     +-------+\n;         |\n;         V     yes\n;  +-->(  >  )--------> done\n;  |      |\n;  |      | no\n;  |      V\n;  |  +-------+\n;  |  | p<-*  |\n;  |  +-------+\n;  |      |\n;  |      V\n;  |  +-------+\n;  |  | c++   |\n;  |  +-------+\n;  |      |\n;  +------+\n;\n; Note that if you get the order of the two instructions in the loop wrong,\n; the controller diagram would be wrong.\n"
  },
  {
    "path": "scheme/sicp/05/02.scm",
    "content": "; SICP exercise 5.02\n;\n; Use the register machine language to describe the iterative factorial\n; machine of exercise 5.1.\n\n(define factorial-machine\n  (make-machine\n    '(c p n)\n    (list (list '+ +) (list '* *) (list '> >))\n    '(\n        (assign c (const 1))\n        (assign p (const 1))\n      test->\n        (test (op >) (reg c) (reg n))\n        (branch (label factorial-done))\n        (assign p (op *) (reg c) (reg p))\n        (assign c (op +) (reg c) (const 1))\n        (goto (label test->))\n      factorial-done)))\n"
  },
  {
    "path": "scheme/sicp/05/03.scm",
    "content": "; SICP exercise 5.03\n;\n; Design a machine to compute square roots using Newton's method, as described\n; in section 1.1.7:\n;\n; (define (sqrt x)\n;   (define (good-enough? guess)\n;     (< (abs (- (square guess) x)) 0.001))\n;   (define (improve guess)\n;     (average guess (/ x guess)))\n;   (define (sqrt-iter guess)\n;     (if (good-enough? guess)\n;         guess\n;         (sqrt-iter (improve guess))))\n;   (sqrt-iter 1.0))\n;\n; Begin by assuming that good-enough? and improve operations are available as\n; primitives. Then show how to expand these in terms of arithmetic operations.\n; Describe each version of the sqrt machine design by a data-path diagram and\n; writing a controller definition in the register machine language.\n\n; Here's a bunch of helper functions:\n\n(define (square x)\n  (* x x))\n\n(define (average x y)\n  (/ (+ x y) 2))\n\n(define (good-enough? guess x)\n  (< (abs (- (square guess) x)) 0.001))\n\n(define (improve guess x)\n  (average guess (/ x guess)))\n\n; Now comes the \"simple\" version.\n;\n; The data-path diagram is fairly simple:\n;\n;                 +-->(  ge?  )<--+\n;                 |               |\n;   +---+        +-----+     +-----+\n;  / 1.0 \\--(x)->|  g  |     |  x  |\n; +-------+      +-----+     +-----+\n;                 ^   |       |\n;                 |  +---------+\n;                 |   \\  imp  /\n;                 |    +-----+\n;                (x)      |\n;                 +-------+\n\n(define simple-sqrt-machine\n  (make-machine\n    '(g x)\n    (list (list 'ge? good-enough?) (list 'imp improve))\n    '(\n        (assign g (const 1.0))\n      test-ge?\n        (test (op ge?) (reg g) (reg x))\n        (branch (label sqrt-done))\n        (assign g (op imp) (reg g) (reg x))\n        (goto (label test-ge?))\n      sqrt-done)))\n\n; This is the second version, where all we use is arithmetic operations. This\n; gets a bit more involved. Let's note a few things.\n;\n; * I've designed the data paths to operate exclusively on register a. All\n;   arithmetic operations have a as the first operand. I did that because I\n;   wanted to get closer to a traditional processor. Note that some of the\n;   instructions have g as the second operand, some have x, and some have a\n;   constant. I did this because I don't want to overcomplicate the\n;   controller.\n; * Before jumping to test-good-enough?, a is already assigned the contents of\n;   register g. That's why test-good-enough? comes after the a <- g\n;   assignment.\n; * There are, in total, ten instructions and two tests. They can be reduced\n;   if we introduce some new operations (and memory), but it's not yet the\n;   time for that.\n;\n; And now follows some ASCII art:\n;\n;     +-+                                +-----+\n;    / 0 \\---(  <  )---+  +---(  <  )---/ 0.001 \\\n;   +-----+            |  |            +---------+\n;                      |  |\n;                      |  |             +---+\n;                      |  |            / 1.0 \\\n;                      |  |           +-------+\n;                      |  |               |\n;                      |  |              (x)\n;                      |  |               |\n;                      |  |               V\n; +-------------------------+         +-------+   +-------+\n; |                     a   | --(x)-> |   g   |   |   x   |\n; +-------------------------+         +-------+   +-------+\n;      |   |           ^  |               |           |\n;      |   |    +-+    |  +----+     +----+           |\n;      |   |   / 2 \\   |  |    |     |    |           |\n;      |   |  +-----+  |  |   +-------+   |           |\n;      |   |     |     |  |    \\  +  /    |           |\n;      |  +-------+    |  |     +---+     |           |\n;      |   \\  /  /     |  |       |       |           |\n;      |    +---+      +-----(x)--+       |           |\n;      |      |        |  |               |           |\n;  +-------+  +--(x)---+  +----+     +----+           |\n;   \\  -  /            |  |    |     |    |           |\n;    +---+             |  |   +-------+   |           |\n;      |               |  |    \\  *  /    |           |\n;      +---------(x)---+  |     +---+     |           |\n;                      |  |       |       |           |\n;                      +-----(x)--+       |           |\n;                      |  |               |           |\n;                      |  +----+     +----+           |\n;                      |  |    |     |    |           |\n;                      |  |   +-------+   |           |\n;                      |  |    \\  /  /    |           |\n;                      |  |     +---+     |           |\n;                      |  |       |       |           |\n;                      +-----(x)--+       |           |\n;                      |  |               |           |\n;                      +-----(x)----------+           |\n;                      |  |                           |\n;                      |  +----+     +----------------+\n;                      |       |     |                |\n;                      |      +-------+               |\n;                      |       \\  -  /                |\n;                      |        +---+                 |\n;                      |          |                   |\n;                      +-----(x)--+                   |\n;                      |                              |\n;                      +-----(x)----------------------+\n\n(define complex-sqrt-machine\n  (make-machine\n    '(g x a)\n    (list (list '+ +) (list '- -) (list '* *) (list '/ /) (list '< <))\n    '(\n        (assign g (const 1.0))\n        (assign a (reg g))\n      test-good-enough?\n        (assign a (op *) (reg a) (reg g))\n        (assign a (op -) (reg a) (reg x))\n        (test (op <) (const 0) (reg a))\n        (branch (label after-abs-a))\n        (assign a (op -) (reg a))\n      after-abs-a\n        (test (op <) (reg a) (const 0.001))\n        (branch (label sqrt-done))\n        (assign a (reg x))\n        (assign a (op /) (reg a) (reg g))\n        (assign a (op +) (reg a) (reg g))\n        (assign a (op /) (reg a) (const 2))\n        (assign g (reg a))\n        (goto (label test-good-enough?))\n      sqrt-done)))\n"
  },
  {
    "path": "scheme/sicp/05/04.scm",
    "content": "; SICP exercise 5.04\n;\n; Specify register machines that implement each of the following procedures.\n; For each machine, write a controller instruction sequence and draw a diagram\n; showing the data paths.\n;\n; a. Recursive exponentiation\n;\n; (define (expt b n)\n;   (if (= n 0)\n;       1\n;       (* b (expt b (- n 1)))))\n;\n; b. Iterative exponentiation\n;\n; (define (expt b n)\n;   (define (expt-iter counter product)\n;     (if (= counter 0)\n;         product\n;         (expt-iter (- counter 1) (* b product))))\n;   (expt-iter n 1))\n\n; a. This is the data path diagram:\n;\n;                       +-+                       +---------+\n;      +--->(  =  )<---/ 0 \\                      |  stack  |\n;      |              +-----+                     +---------+\n;   +-----+     +-+           +-----+   +-----+     |     ^\n;   |  n  |    / 1 \\---(x)--->| val |   |  b  |    (x)    |\n;   +-----+   +-----+         +-----+   +-----+     |    (x)\n;    ^   |     |               ^   |     |          V     |\n;    |  +-------+              |  +-------+     +------------+\n;    |   \\  -  /               |   \\  *  /      |  continue  |----> controller\n;   (x)   +---+               (x)   +---+       +------------+\n;    |      |                  |      |           ^        ^\n;    +------+                  +------+           |        |\n;                                                (x)      (x)\n;                                                 |        |\n;                                        +---------+      +----------+\n;                                       / expt-done \\    / after-expt \\\n;                                      +-------------+  +--------------+\n\n(define recursive-expt-machine\n  (make-machine\n    '(b n val continue)\n    (list (list '= =) (list '- -) (list '* *))\n    '(\n        (assign continue (label expt-done))\n      expt-loop\n        (test (op =) (reg n) (const 0))\n        (branch (label base-case))\n        (save continue)\n        (assign n (op -) (reg n) (const 1))\n        (assign continue (label after-expt))\n        (goto (label expt-loop))\n      after-expt\n        (assign val (op *) (reg val) (reg b))\n        (restore continue)\n        (goto (reg continue))\n      base-case\n        (assign val (const 1))\n        (goto (reg continue))\n      expt-done)))\n\n; b. This is the iterative data path. Notice that it is simpler.\n;\n;                     +-+\n;      +-->(  =  )<--/ 0 \\\n;      |            +-----+\n;      |\n;   +-----+   +-+         +-----+ +-----+\n;   |  n  |  / 1 \\--(x)-->| val | |  b  |\n;   +-----+ +-----+       +-----+ +-----+\n;    ^   |     |           ^   |     |\n;    |  +-------+          |  +-------+\n;    |   \\  -  /           |   \\  *  /\n;   (x)   +---+           (x)   +---+\n;    |      |              |      |\n;    +------+              +------+\n\n(define iterative-expt-machine\n  (make-machine\n    '(b n val continue)\n    (list (list '= =) (list '- -) (list '* *))\n    '(\n        (assign val (const 1))\n      expt-loop\n        (test (op =) (reg n) (const 0))\n        (branch (label expt-done))\n        (assign val (op *) (reg val) (reg b))\n        (assign n (op -) (reg n) (const 1))\n        (goto (label expt-loop))\n      expt-done)))\n\n\n"
  },
  {
    "path": "scheme/sicp/05/05.scm",
    "content": "; SICP exercise 5.05\n;\n; Hand-simulate the factorial and Fibonacci machines, using some nontrivial\n; input (requiring execution of at least one recursive call). Show the\n; contents of the stack at each significant point in the execution.\n\n; I did that on a piece of paper. It's fairly tricky to find a way to write it\n; down in this file, so I will just show the state of the stacks after various\n; saves and restores.\n;\n; First, the factorial machine. Let's say we're calculating it for 3.\n;\n; Initially n is 3 and the stack is empty.\n;\n; 1. +-------------+  n: 3\n;    |   <empty>   |  continue: fact-done\n;    +-------------+  val: ?\n;\n; 2. +-------------+  n: 2\n;    |      3      |  continue: after-fact\n;    +-------------+  val: ?\n;    |  fact-done  |\n;    +-------------+\n;\n; 3. +-------------+  n: 1\n;    |      2      |  continue: after-fact\n;    +-------------+  val: ?\n;    | after-fact  |\n;    +-------------+\n;    |      3      |\n;    +-------------+\n;    |  fact-done  |\n;    +-------------+\n;\n; 4. +-------------+  n: 1\n;    |      2      |  continue: after-fact\n;    +-------------+  val: 1\n;    | after-fact  |\n;    +-------------+\n;    |      3      |\n;    +-------------+\n;    |  fact-done  |\n;    +-------------+\n;\n; 5. +-------------+  n: 2\n;    |      3      |  continue: after-fact\n;    +-------------+  val: 2\n;    |  fact-done  |\n;    +-------------+\n;\n; 6. +-------------+  n: 3\n;    |   <empty>   |  continue: fact-done\n;    +-------------+  val: 6\n;\n;\n;\n; The Fibonacci machine is a bit more intricate:\n;\n;  1. +---------------+  n: 3\n;     |    <empty>    |  continue: fib-done\n;     +---------------+  val: ?\n;\n;  2. +---------------+  n: 2\n;     |       3       |  continue: after-fib-n-1\n;     +---------------+  val: ?\n;     |   fib-done    |\n;     +---------------+\n;\n;  3. +---------------+  n: 1\n;     |       2       |  continue: after-fib-n-1\n;     +---------------+  val: ?\n;     | after-fib-n-1 |\n;     +---------------+\n;     |       3       |\n;     +---------------+\n;     |   fib-done    |\n;     +---------------+\n;\n;  4. +---------------+  n: 1\n;     |       2       |  continue: after-fib-n-1\n;     +---------------+  val: 1\n;     | after-fib-n-1 |\n;     +---------------+\n;     |       3       |\n;     +---------------+\n;     |   fib-done    |\n;     +---------------+\n;\n;  5. +---------------+  n: 0\n;     |       1       |  continue: after-fib-n-2\n;     +---------------+  val: 1\n;     | after-fib-n-1 |\n;     +---------------+\n;     |       3       |\n;     +---------------+\n;     |   fib-done    |\n;     +---------------+\n;\n;  6. +---------------+  n: 0\n;     |       1       |  continue: after-fib-n-2\n;     +---------------+  val: 0\n;     | after-fib-n-1 |\n;     +---------------+\n;     |       3       |\n;     +---------------+\n;     |   fib-done    |\n;     +---------------+\n;\n;  7. +---------------+  n: 0\n;     |       3       |  continue: after-fib-n-1\n;     +---------------+  val: 1\n;     |   fib-done    |\n;     +---------------+\n;\n;  8. +---------------+  n: 1\n;     |       1       |  continue: after-fib-n-2\n;     +---------------+  val: 1\n;     |   fib-done    |\n;     +---------------+\n;\n;  9. +---------------+  n: 1\n;     |       1       |  continue: after-fib-n-2\n;     +---------------+  val: 1\n;     |   fib-done    |\n;     +---------------+\n;\n; 10. +---------------+  n: 1\n;     |    <empty>    |  continue: fib-done\n;     +---------------+  val: 2\n"
  },
  {
    "path": "scheme/sicp/05/06.scm",
    "content": "; SICP exercise 5.06\n;\n; Ben Bitdiddle observes that the Fibonacci machine's controller sequence has\n; an extra save and an extra restore, which can be removed to make a faster\n; machine. Where are these instructions?\n\n; They are below, commented out:\n\n(define fibonacci-machine\n  (make-machine\n    '(n val continue)\n    (list (list '< <) (list '- -) (list '+ +))\n    '(\n        (assign continue (label fib-done))\n      fib-loop\n        (test (op <) (reg n) (const 2))\n        (branch (label immediate-answer))\n        (save continue)\n        (assign continue (label after-fib-n-1))\n        (save n)\n        (assign n (op -) (reg n) (const 1))\n        (goto (label fib-loop))\n      after-fib-n-1\n        (restore n)\n;       (restore continue)\n        (assign n (op -) (reg n) (const 2))\n;       (save continue)\n        (assign continue (label after-fib-n-2))\n        (save val)\n        (goto (label fib-loop))\n      after-fib-n-2\n        (assign n (reg val))\n        (restore val)\n        (restore continue)\n        (assign val (op +) (reg val) (reg n))\n        (goto (reg continue))\n      immediate-answer\n        (assign val (reg n))\n        (goto (reg continue))\n      fib-done)))\n\n"
  },
  {
    "path": "scheme/sicp/05/07.scm",
    "content": "; SICP exercise 5.07\n;\n; Use the simulator to test the machines you designed in exercise 5.4.\n\n; How? At this point in the book, we haven't yet completed it.\n;\n; Anyway, I already did in the tests of exercise 5.4\n"
  },
  {
    "path": "scheme/sicp/05/08.scm",
    "content": "; SICP exercise 5.08\n;\n; The following register-machine code is ambiguous, because the label here is\n; defined more than once:\n;\n; start\n;   (goto (label here))\n; here\n;   (assign a (const 3))\n;   (goto (label there))\n; here\n;   (assign a (const 4))\n;   (goto (label there))\n; there\n;\n; With the simulator as written, what will the contents of register a be when\n; control reaches there? Modify the extract-labels procedure so that the\n; assembler will signal an error if the same label name is used to indicate\n; two different locations.\n\n; The result will be 3. Since the associative list of labels retains the order\n; in which they are defined, goto will jump to the first label.\n;\n; Here's the modification:\n\n(define (extract-labels text receive)\n  (if (null? text)\n      (receive '() '())\n      (extract-labels (cdr text)\n        (lambda (insts labels)\n          (let ((next-inst (car text)))\n            (if (symbol? next-inst)\n                (if (assoc next-inst labels)\n                    (error \"Duplicate label:\" next-inst)\n                    (receive insts\n                             (cons (make-label-entry next-inst insts)\n                                   labels)))\n                (receive (cons (make-instruction next-inst)\n                               insts)\n                         labels)))))))\n"
  },
  {
    "path": "scheme/sicp/05/09.scm",
    "content": "; SICP exercise 5.09\n;\n; The treatment of machine operations above permits them to operate on labels\n; as well as on constants and the contents of registers. Modify the\n; expression-processing procedures to enforce the condition that operations\n; can be used only with registers and constants.\n\n(define (make-operation-exp exp machine labels operations)\n  (if (ormap label-exp? (operation-exp-operands exp))\n      (error \"Operations are not applicable to labels\" exp)\n      (let ((op (lookup-prim (operation-exp-op exp) operations))\n            (aprocs (map (lambda (e) (make-primitive-exp e machine labels))\n                         (operation-exp-operands exp))))\n        (lambda ()\n          (apply op (map (lambda (p) (p)) aprocs))))))\n"
  },
  {
    "path": "scheme/sicp/05/10.scm",
    "content": "; SICP exercise 5.10\n;\n; Design a new syntax for register-machine instructions and modify the\n; simulator to use your new syntax. Can you implement your new syntax without\n; changing any part of the simulator except procedures in this section?\n\n; Sure.\n;\n; Registers will be prefixed with @ and labels will be prefixed with :.\n; Numbers will be constants. Everything else is an operation.\n\n(define (symbol-starting-with? symbol prefix)\n  (and (symbol? symbol)\n       (equal? (substring (symbol->string symbol) 0 (string-length prefix))\n               prefix)))\n\n(define (symbol-without-prefix symbol)\n  (string->symbol (substring (symbol->string symbol) 1)))\n\n(define (register-exp? exp) (symbol-starting-with? exp \"@\"))\n(define (register-exp-reg exp) (symbol-without-prefix exp))\n(define (constant-exp? exp) (number? exp))\n(define (constant-exp-value exp) exp)\n(define (label-exp? exp) (symbol-starting-with? exp \":\"))\n(define (label-exp-label exp) (symbol-without-prefix exp))\n(define (operation-exp? exp)\n  (and (pair? exp)\n       (not (register-exp? (car exp)))\n       (not (constant-exp? (car exp)))\n       (not (label-exp? (car exp)))))\n(define (operation-exp-op operation-exp) (car operation-exp))\n(define (operation-exp-operands operation-exp) (cdr operation-exp))\n\n(define fibonacci-machine\n  (make-machine\n    '(n val continue)\n    (list (list '< <) (list '- -) (list '+ +))\n    '(\n        (assign continue :fib-done)\n      fib-loop\n        (test < @n 2)\n        (branch :immediate-answer)\n        (save continue)\n        (assign continue :after-fib-n-1)\n        (save n)\n        (assign n - @n 1)\n        (goto :fib-loop)\n      after-fib-n-1\n        (restore n)\n        (restore continue)\n        (assign n - @n 2)\n        (save continue)\n        (assign continue :after-fib-n-2)\n        (save val)\n        (goto :fib-loop)\n      after-fib-n-2\n        (assign n @val)\n        (restore val)\n        (restore continue)\n        (assign val + @val @n)\n        (goto @continue)\n      immediate-answer\n        (assign val @n)\n        (goto @continue)\n      fib-done)))\n"
  },
  {
    "path": "scheme/sicp/05/11.scm",
    "content": "; SICP exercise 5.11\n;\n; When we introduced save and restore in section 5.1.4, we didn't specify what\n; would happen if you tried to restore a register that was not the last one\n; saved, as in the sequence\n;\n; (save x)\n; (save x)\n; (restore y)\n;\n; There are several reasonable possibilities for the meaning of restore.\n;\n; a. (restore y) puts into y the last value saved on the stack, regardless of\n; what register that value came from. This is the way our simulator behaves.\n; Show how to take advantage of this behavior to eliminate one instruction\n; from the Fibonacci machine of section 5.1.4 (figure 5.12).\n;\n; b. (restore y) puts into y the last value saved on the stack, but only if\n; that value was saved from y; otherwise, it signals an error. Modify the\n; simulator to behave this way. You will have to change save to put the\n; register name on the stack along with the value.\n;\n; c. (restore y) puts into y the last value saved from y, regardless of what\n; other registers were saved after y and not restored. Modify the simulator to\n; behave this way. You will have to associate a separate stack with each\n; register. You should make the initialize-stack operation initialize all the\n; register stacks.\n\n; Some code to allow all variants to coexist.\n\n(define table (make-hash))\n\n(define (make-save inst machine stack pc)\n  ((hash-ref table 'make-save) inst machine stack pc))\n\n(define (make-restore inst machine stack pc)\n  ((hash-ref table 'make-restore) inst machine stack pc))\n\n(define original-make-register make-register)\n\n(define (make-register name)\n  ((hash-ref table 'make-register) name))\n\n(define (get-contents register)\n  ((hash-ref table 'get-contents) register))\n\n(define (set-contents! register value)\n  ((hash-ref table 'set-contents!) register value))\n\n(define (use-traditional-registers!)\n  (define (get-contents register) (register 'get))\n  (define (set-contents! register value) ((register 'set) value))\n\n  (hash-set! table 'make-register original-make-register)\n  (hash-set! table 'get-contents get-contents)\n  (hash-set! table 'set-contents! set-contents!))\n\n; a. Here are the modified procedures:\n\n(define (use-version-a!)\n  (define (make-save inst machine stack pc)\n    (let ((reg (get-register machine (stack-inst-reg-name inst))))\n      (lambda ()\n        (push stack (get-contents reg))\n        (advance-pc pc))))\n\n  (define (make-restore inst machine stack pc)\n    (let ((reg (get-register machine (stack-inst-reg-name inst))))\n      (lambda ()\n        (set-contents! reg (pop stack))\n        (advance-pc pc))))\n\n  (use-traditional-registers!)\n  (hash-set! table 'make-save make-save)\n  (hash-set! table 'make-restore make-restore))\n\n; And this is the shorter Fibonacci machine:\n\n(define (make-shorter-fibonacci-machine)\n  (make-machine\n    '(n val continue)\n    (list (list '< <) (list '- -) (list '+ +))\n    '(\n        (assign continue (label fib-done))\n      fib-loop\n        (test (op <) (reg n) (const 2))\n        (branch (label immediate-answer))\n        (save continue)\n        (assign continue (label after-fib-n-1))\n        (save n)\n        (assign n (op -) (reg n) (const 1))\n        (goto (label fib-loop))\n      after-fib-n-1\n        (restore n)\n        (restore continue)\n        (assign n (op -) (reg n) (const 2))\n        (save continue)\n        (assign continue (label after-fib-n-2))\n        (save val)\n        (goto (label fib-loop))\n      after-fib-n-2\n        (restore n) ; The modification is here\n        (restore continue)\n        (assign val (op +) (reg val) (reg n))\n        (goto (reg continue))\n      immediate-answer\n        (assign val (reg n))\n        (goto (reg continue))\n      fib-done)))\n\n; b. Erroring out when registers don't match\n\n(define (use-version-b!)\n  (define (make-save inst machine stack pc)\n    (let ((reg-name (stack-inst-reg-name inst)))\n      (let ((reg (get-register machine reg-name)))\n        (lambda ()\n          (push stack (cons reg-name (get-contents reg)))\n          (advance-pc pc)))))\n\n  (define (make-restore inst machine stack pc)\n    (let ((reg-name (stack-inst-reg-name inst)))\n      (let ((reg (get-register machine reg-name)))\n        (lambda ()\n          (let ((saved-value (pop stack)))\n            (if (eq? reg-name (car saved-value))\n                (begin\n                  (set-contents! reg (cdr saved-value))\n                  (advance-pc pc))\n                (error \"Mismatching registers:\" (car saved-value) inst)))))))\n\n  (use-traditional-registers!)\n  (hash-set! table 'make-save make-save)\n  (hash-set! table 'make-restore make-restore))\n\n; c. A stack per each register\n;\n; I'm not going to modify the initialize stack operation. I can (and I\n; should), but it is simpler if I don't modify the original code. I will store\n; the stack in each register, since I don't want to modify make-machine. I'm\n; doing this solely to have a compact exercise solution.\n\n(define (use-version-c!)\n  (define (make-register name)\n    (let ((register (original-make-register name)))\n      ((register 'set) (mcons '() (make-stack)))\n      register))\n\n  (define (get-contents register) (mcar (register 'get)))\n  (define (set-contents! register value) (set-mcar! (register 'get) value))\n  (define (push-register register value) (push (mcdr (register 'get)) value))\n  (define (pop-register register) (pop (mcdr (register 'get))))\n\n  (define (make-save inst machine stack pc)\n    (let ((reg (get-register machine (stack-inst-reg-name inst))))\n      (lambda ()\n        (push-register reg (get-contents reg))\n        (advance-pc pc))))\n\n  (define (make-restore inst machine stack pc)\n    (let ((reg (get-register machine (stack-inst-reg-name inst))))\n      (lambda ()\n        (set-contents! reg (pop-register reg))\n        (advance-pc pc))))\n\n  (hash-set! table 'make-register make-register)\n  (hash-set! table 'get-contents get-contents)\n  (hash-set! table 'set-contents! set-contents!)\n  (hash-set! table 'make-save make-save)\n  (hash-set! table 'make-restore make-restore))\n"
  },
  {
    "path": "scheme/sicp/05/12.scm",
    "content": "; SICP exercise 5.12\n;\n; The simulator can be used to help determine the data paths required for\n; implementing a machine with a given controller. Extend the assembler to\n; store the following information in the machine model:\n;\n; * a list of all instructions, with duplicates removed, sorted by instruction\n;   type (assign, goto, and so on);\n; * a list (without duplicates) of the registers used to hold entry points\n;   (these are the registers referenced by goto instructions);\n; * a list (without duplicates) of the registers that are saved or restored;\n; * for each register, a list (without duplicates) of the sources from which\n;   it is assigned (for example, the sources for register val in the factorial\n;   of figure 5.11 are (const 1) and ((op *) (reg n) (reg val))).\n;\n; Extend the message-passing interface to the machine to provide access to\n; this new information. To test your analyzer, define the Fibonacci machine\n; from figure 5.12 and examine the lists you constructed.\n\n(define (extract-data-path-info controller-text)\n  (list (list 'instructions (data-path-instructions controller-text))\n        (list 'entry-point-registers (data-path-entry-point-registers controller-text))\n        (list 'stack-registers (data-path-stack-registers controller-text))\n        (list 'register-sources (data-path-register-sources controller-text))))\n\n(define (data-path-instructions controller-text)\n  (process-text controller-text\n                (lambda (inst) #t)\n                (lambda (inst) inst)))\n\n(define (data-path-entry-point-registers controller-text)\n  (process-text controller-text\n                (lambda (inst) (and (eq? (car inst) 'goto)\n                                    (register-exp? (goto-dest inst))))\n                (compose goto-dest register-exp-reg)))\n\n(define (data-path-stack-registers controller-text)\n  (process-text controller-text\n                (lambda (inst) (or (eq? (car inst) 'save)\n                                   (eq? (car inst) 'restore)))\n                stack-inst-reg-name))\n\n(define (data-path-register-sources controller-text)\n  (define (to-alist items result)\n    (cond ((null? items) (list result))\n          ((null? result)\n           (to-alist (cdr items) (car items)))\n          ((eq? (caar items) (car result))\n           (to-alist (cdr items) (cons (car result)\n                                      (append (cdr result)\n                                              (list (cadar items))))))\n          (else (cons result (to-alist items '())))))\n\n  (to-alist\n    (process-text controller-text\n                  (lambda (inst) (eq? (car inst) 'assign))\n                  (lambda (inst) (list (assign-reg-name inst)\n                                       (if (operation-exp? (assign-value-exp inst))\n                                           (assign-value-exp inst)\n                                           (car (assign-value-exp inst))))))\n\n    '()))\n\n(define (process-text controller-text predicate proc)\n  (sort (remove-duplicates (map proc\n                                (filter predicate\n                                        (filter pair?\n                                                controller-text))))\n\n        string<?\n        #:key (lambda (inst) (format \"~a\" inst))\n        #:cache-keys? #f))\n\n; Tweaks for make-machine and make-new-machine:\n\n(define (make-machine register-names ops controller-text)\n  (let ((machine (make-new-machine)))\n    (for-each (lambda (register-name)\n                ((machine 'allocate-register) register-name))\n              register-names)\n    ((machine 'install-operations) ops)\n    ((machine 'install-instruction-sequence)\n     (assemble controller-text machine))\n    ((machine 'install-data-path-info)\n     (extract-data-path-info controller-text))\n    machine))\n\n(define (make-new-machine)\n  (let ((pc (make-register 'pc))\n        (flag (make-register 'flag))\n        (stack (make-stack))\n        (the-instruction-sequence '())\n        (data-path-info '()))\n    (let ((the-ops (list (list 'initialize-stack\n                               (lambda () (stack 'initialize)))))\n          (register-table (list (list 'pc pc) (list 'flag flag))))\n      (define (allocate-register name)\n        (if (assoc name register-table)\n            (error \"Multiply defined register: \" name)\n            (set! register-table (cons (list name (make-register name))\n                                       register-table)))\n        'register-allocated)\n      (define (lookup-register name)\n        (let ((val (assoc name register-table)))\n          (if val\n              (cadr val)\n              (error \"Unknown register: \" name))))\n      (define (execute)\n        (let ((insts (get-contents pc)))\n          (if (null? insts)\n              'done\n              (begin\n                ((instruction-execution-proc (car insts)))\n                (execute)))))\n      (define (dispatch message)\n        (cond ((eq? message 'start)\n               (set-contents! pc the-instruction-sequence)\n               (execute))\n              ((eq? message 'install-instruction-sequence)\n               (lambda (seq) (set! the-instruction-sequence seq)))\n              ((eq? message 'allocate-register) allocate-register)\n              ((eq? message 'get-register) lookup-register)\n              ((eq? message 'install-operations)\n               (lambda (ops) (set! the-ops (append the-ops ops))))\n              ((eq? message 'stack) stack)\n              ((eq? message 'operations) the-ops)\n              ((eq? message 'install-data-path-info)\n               (lambda (info) (set! data-path-info info)))\n              ((eq? message 'data-path-instructions)\n               (cadr (assoc 'instructions data-path-info)))\n              ((eq? message 'data-path-entry-point-registers)\n               (cadr (assoc 'entry-point-registers data-path-info)))\n              ((eq? message 'data-path-stack-registers)\n               (cadr (assoc 'stack-registers data-path-info)))\n              ((eq? message 'data-path-register-sources)\n               (cadr (assoc 'register-sources data-path-info)))\n              (else (error \"Unknown request -- MACHINE\" message))))\n      dispatch)))\n"
  },
  {
    "path": "scheme/sicp/05/13.scm",
    "content": "; SICP exercise 5.13\n;\n; Modify the simulator so that it uses the controller sequence to determine\n; what registers the machine has rather than requiring a list of registers as\n; an argument to make-machine. Instead of pre-allocating the registers in\n; make-machine, you can allocate them one at a time when they are first seen\n; during assembly of the instructions.\n\n(define (make-machine ops controller-text)\n  (let ((machine (make-new-machine)))\n    ((machine 'install-operations) ops)\n    ((machine 'install-instruction-sequence)\n     (assemble controller-text machine))\n    machine))\n\n(define (make-new-machine)\n  (let ((pc (make-register 'pc))\n        (flag (make-register 'flag))\n        (stack (make-stack))\n        (the-instruction-sequence '()))\n    (let ((the-ops (list (list 'initialize-stack\n                               (lambda () (stack 'initialize)))))\n          (register-table (list (list 'pc pc) (list 'flag flag))))\n      (define (allocate-register name)\n        (if (assoc name register-table)\n            (error \"Multiply defined register: \" name)\n            (let ((register (make-register name)))\n              (set! register-table (cons (list name register)\n                                         register-table))\n              register)))\n      (define (lookup-register name)\n        (let ((val (assoc name register-table)))\n          (if val\n              (cadr val)\n              (allocate-register name))))\n      (define (execute)\n        (let ((insts (get-contents pc)))\n          (if (null? insts)\n              'done\n              (begin\n                ((instruction-execution-proc (car insts)))\n                (execute)))))\n      (define (dispatch message)\n        (cond ((eq? message 'start)\n               (set-contents! pc the-instruction-sequence)\n               (execute))\n              ((eq? message 'install-instruction-sequence)\n               (lambda (seq) (set! the-instruction-sequence seq)))\n              ((eq? message 'allocate-register) allocate-register)\n              ((eq? message 'get-register) lookup-register)\n              ((eq? message 'install-operations)\n               (lambda (ops) (set! the-ops (append the-ops ops))))\n              ((eq? message 'stack) stack)\n              ((eq? message 'operations) the-ops)\n              (else (error \"Unknown request -- MACHINE\" message))))\n      dispatch)))\n"
  },
  {
    "path": "scheme/sicp/05/14.scm",
    "content": "; SICP exercise 5.14\n;\n; Measure the number of pushes and the maximum stack depth required to compute\n; n! for various small values of n using the factorial machine shown in figure\n; 5.11. From your data determine formulas in terms of n for the total number\n; of push operations and the maximum stack depth used in computing n! for any\n; n > 1. Note that each of these is a linear function of n and is thus\n; determined by two constants. In order to get the statistics printed, you\n; will have to augment the factorial machine with instructions to initialize\n; the stack and print the statistics. You may want to also modify the machine\n; so that it repeatedly reads a value for n, computes the factorial, and\n; prints the result (as we did for the GCD machine in figure 5.4), so that you\n; will not have to repeatedly invoke get-register-contents,\n; set-register-contents!, and start.\n\n; The results are:\n;\n;   Running 1!: (total-pushes = 0 maximum-depth = 0)\n;   Running 2!: (total-pushes = 2 maximum-depth = 2)\n;   Running 3!: (total-pushes = 4 maximum-depth = 4)\n;   Running 4!: (total-pushes = 6 maximum-depth = 6)\n;   Running 5!: (total-pushes = 8 maximum-depth = 8)\n;   Running 6!: (total-pushes = 10 maximum-depth = 10)\n;   Running 7!: (total-pushes = 12 maximum-depth = 12)\n;   Running 8!: (total-pushes = 14 maximum-depth = 14)\n;   Running 9!: (total-pushes = 16 maximum-depth = 16)\n;\n; This implies that for computing n!, there are in total 2(n - 1) pushes. This\n; number is equal to the maximum depth too.\n\n(load-relative \"tests/helpers/simulator.scm\")\n\n; The modified procedures:\n\n(define (make-stack)\n  (let ((s '())\n       (number-pushes 0)\n       (max-depth 0)\n       (current-depth 0))\n    (define (push x)\n      (set! s (cons x s))\n      (set! number-pushes (+ 1 number-pushes))\n      (set! current-depth (+ 1 current-depth))\n      (set! max-depth (max current-depth max-depth)))\n    (define (pop)\n      (if (null? s)\n          (error \"Empty stack -- POP\")\n          (let ((top (car s)))\n            (set! s (cdr s))\n            (set! current-depth (- current-depth 1))\n            top)))\n    (define (initialize)\n      (set! s '())\n      (set! number-pushes 0)\n      (set! max-depth 0)\n      (set! current-depth 0)\n      'done)\n    (define (print-statistics)\n      (display (list 'total-pushes '= number-pushes\n                     'maximum-depth '= max-depth))\n      (newline))\n    (define (dispatch message)\n      (cond ((eq? message 'push) push)\n            ((eq? message 'pop) (pop))\n            ((eq? message 'initialize) (initialize))\n            ((eq? message 'print-statistics) (print-statistics))\n            (else (error \"Unknown request -- STACK\" message))))\n    dispatch))\n\n(define (make-new-machine)\n  (let ((pc (make-register 'pc))\n        (flag (make-register 'flag))\n        (stack (make-stack))\n        (the-instruction-sequence '()))\n    (let ((the-ops (list (list 'initialize-stack\n                               (lambda () (stack 'initialize)))\n                         (list 'print-stack-statistics\n                               (lambda () (stack 'print-statistics)))))\n          (register-table (list (list 'pc pc) (list 'flag flag))))\n      (define (allocate-register name)\n        (if (assoc name register-table)\n            (error \"Multiply defined register: \" name)\n            (set! register-table (cons (list name (make-register name))\n                                       register-table)))\n        'register-allocated)\n      (define (lookup-register name)\n        (let ((val (assoc name register-table)))\n          (if val\n              (cadr val)\n              (error \"Unknown register: \" name))))\n      (define (execute)\n        (let ((insts (get-contents pc)))\n          (if (null? insts)\n              'done\n              (begin\n                ((instruction-execution-proc (car insts)))\n                (execute)))))\n      (define (dispatch message)\n        (cond ((eq? message 'start)\n               (set-contents! pc the-instruction-sequence)\n               (execute))\n              ((eq? message 'install-instruction-sequence)\n               (lambda (seq) (set! the-instruction-sequence seq)))\n              ((eq? message 'allocate-register) allocate-register)\n              ((eq? message 'get-register) lookup-register)\n              ((eq? message 'install-operations)\n               (lambda (ops) (set! the-ops (append the-ops ops))))\n              ((eq? message 'stack) stack)\n              ((eq? message 'operations) the-ops)\n              (else (error \"Unknown request -- MACHINE\" message))))\n      dispatch)))\n\n(define factorial-machine\n  (make-machine\n    '(n val continue)\n    (list (list '= =) (list '- -) (list '* *))\n    '(\n        (perform (op initialize-stack))\n        (assign continue (label fact-done))\n      fact-loop\n        (test (op =) (reg n) (const 1))\n        (branch (label base-case))\n        (save continue)\n        (save n)\n        (assign n (op -) (reg n) (const 1))\n        (assign continue (label after-fact))\n        (goto (label fact-loop))\n      after-fact\n        (restore n)\n        (restore continue)\n        (assign val (op *) (reg n) (reg val))\n        (goto (reg continue))\n      base-case\n        (assign val (const 1))\n        (goto (reg continue))\n      fact-done\n        (perform (op print-stack-statistics)))))\n\n(define (measure-factorial n)\n  (set-register-contents! factorial-machine 'n n)\n  (display \"Running \")\n  (display n)\n  (display \"!: \")\n  (start factorial-machine))\n\n(for ([n (in-range 1 10)])\n  (measure-factorial n))\n"
  },
  {
    "path": "scheme/sicp/05/15.scm",
    "content": "; SICP exercise 5.15\n;\n; Add instruction counting to the register machine simulation. That is, have\n; the machine model keep track of the number of instructions executed. Extend\n; the machine model's interface to accept a new message that prints the value\n; of the instruction count and resets the count to zero.\n\n(define (make-new-machine)\n  (let ((pc (make-register 'pc))\n        (flag (make-register 'flag))\n        (stack (make-stack))\n        (the-instruction-sequence '())\n        (instruction-count 0))\n    (let ((the-ops (list (list 'initialize-stack\n                               (lambda () (stack 'initialize)))))\n          (register-table (list (list 'pc pc) (list 'flag flag))))\n      (define (allocate-register name)\n        (if (assoc name register-table)\n            (error \"Multiply defined register: \" name)\n            (set! register-table (cons (list name (make-register name))\n                                       register-table)))\n        'register-allocated)\n      (define (lookup-register name)\n        (let ((val (assoc name register-table)))\n          (if val\n              (cadr val)\n              (error \"Unknown register: \" name))))\n      (define (execute)\n        (let ((insts (get-contents pc)))\n          (if (null? insts)\n              'done\n              (begin\n                ((instruction-execution-proc (car insts)))\n                (set! instruction-count (+ instruction-count 1))\n                (execute)))))\n      (define (get-instruction-count)\n        (let ((count instruction-count))\n          (set! instruction-count 0)\n          count))\n      (define (dispatch message)\n        (cond ((eq? message 'start)\n               (set-contents! pc the-instruction-sequence)\n               (execute))\n              ((eq? message 'install-instruction-sequence)\n               (lambda (seq) (set! the-instruction-sequence seq)))\n              ((eq? message 'allocate-register) allocate-register)\n              ((eq? message 'get-register) lookup-register)\n              ((eq? message 'install-operations)\n               (lambda (ops) (set! the-ops (append the-ops ops))))\n              ((eq? message 'stack) stack)\n              ((eq? message 'operations) the-ops)\n              ((eq? message 'instruction-count) (get-instruction-count))\n              (else (error \"Unknown request -- MACHINE\" message))))\n      dispatch)))\n"
  },
  {
    "path": "scheme/sicp/05/16.scm",
    "content": "; SICP exercise 5.16\n;\n; Augment the simulator to provide for instruction tracing. That is, before\n; each instruction is executed, the simulator should print the text of the\n; instruction. Make the machine model accept trace-on and trace-off messages\n; to turn tracing on and off.\n\n; I will base this on the solution of the previous exercise, since I'm going\n; to need both instruction counting and tracing for the next one. Instead of\n; printing the instructions, I will allow providing a trace procedure so\n; testing can be easier.\n\n(define (make-new-machine)\n  (let ((pc (make-register 'pc))\n        (flag (make-register 'flag))\n        (stack (make-stack))\n        (the-instruction-sequence '())\n        (trace-proc (lambda (inst) (void)))\n        (tracing #f)\n        (instruction-count 0))\n    (let ((the-ops (list (list 'initialize-stack\n                               (lambda () (stack 'initialize)))))\n          (register-table (list (list 'pc pc) (list 'flag flag))))\n      (define (allocate-register name)\n        (if (assoc name register-table)\n            (error \"Multiply defined register: \" name)\n            (set! register-table (cons (list name (make-register name))\n                                       register-table)))\n        'register-allocated)\n      (define (lookup-register name)\n        (let ((val (assoc name register-table)))\n          (if val\n              (cadr val)\n              (error \"Unknown register: \" name))))\n      (define (execute)\n        (let ((insts (get-contents pc)))\n          (if (null? insts)\n              'done\n              (let ((inst (car insts)))\n                (when tracing (trace-proc (instruction-text inst)))\n                ((instruction-execution-proc inst))\n                (set! instruction-count (+ instruction-count 1))\n                (execute)))))\n      (define (get-instruction-count)\n        (let ((count instruction-count))\n          (set! instruction-count 0)\n          count))\n      (define (dispatch message)\n        (cond ((eq? message 'start)\n               (set-contents! pc the-instruction-sequence)\n               (execute))\n              ((eq? message 'install-instruction-sequence)\n               (lambda (seq) (set! the-instruction-sequence seq)))\n              ((eq? message 'allocate-register) allocate-register)\n              ((eq? message 'get-register) lookup-register)\n              ((eq? message 'install-operations)\n               (lambda (ops) (set! the-ops (append the-ops ops))))\n              ((eq? message 'stack) stack)\n              ((eq? message 'operations) the-ops)\n              ((eq? message 'instruction-count) (get-instruction-count))\n              ((eq? message 'install-trace-proc)\n               (lambda (proc) (set! trace-proc proc)))\n              ((eq? message 'trace-on) (set! tracing #t))\n              ((eq? message 'trace-off) (set! tracing #f))\n              (else (error \"Unknown request -- MACHINE\" message))))\n      dispatch)))\n"
  },
  {
    "path": "scheme/sicp/05/17.scm",
    "content": "; SICP exercise 5.17\n;\n; Extend the instruction tracing of exercise 5.16 so that before printing an\n; instruction, the simulator prints any labels that immediately precede that\n; instruction in the controller sequence. Be careful to do this in a way that\n; does not interfere with instruction counting (exercise 5.15). You will have\n; to make the simulator retain the necessary label information.\n\n(define (extract-labels text receive)\n  (if (null? text)\n      (receive '() '())\n      (extract-labels (cdr text)\n        (lambda (insts labels)\n          (let ((next-inst (car text)))\n            (if (symbol? next-inst)\n                (begin\n                  (when (not (null? insts))\n                    (set-instruction-label! (car insts) next-inst))\n                  (receive insts\n                           (cons (make-label-entry next-inst insts)\n                                 labels)))\n                (receive (cons (make-instruction next-inst)\n                               insts)\n                         labels)))))))\n\n(define (make-instruction text)\n  (mcons text (mcons '() (mcons '() '()))))\n(define (instruction-text inst)\n  (mcar inst))\n(define (instruction-execution-proc inst)\n  (mcar (mcdr inst)))\n(define (instruction-label inst)\n  (mcar (mcdr (mcdr inst))))\n(define (instruction-labeled? inst)\n  (not (null? (instruction-label inst))))\n(define (set-instruction-execution-proc! inst proc)\n  (set-mcar! (mcdr inst) proc))\n(define (set-instruction-label! inst label)\n  (set-mcar! (mcdr (mcdr inst)) label))\n\n\n(define (make-new-machine)\n  (let ((pc (make-register 'pc))\n        (flag (make-register 'flag))\n        (stack (make-stack))\n        (the-instruction-sequence '())\n        (trace-proc (lambda (inst) (void)))\n        (tracing #f)\n        (instruction-count 0))\n    (let ((the-ops (list (list 'initialize-stack\n                               (lambda () (stack 'initialize)))))\n          (register-table (list (list 'pc pc) (list 'flag flag))))\n      (define (allocate-register name)\n        (if (assoc name register-table)\n            (error \"Multiply defined register: \" name)\n            (set! register-table (cons (list name (make-register name))\n                                       register-table)))\n        'register-allocated)\n      (define (lookup-register name)\n        (let ((val (assoc name register-table)))\n          (if val\n              (cadr val)\n              (error \"Unknown register: \" name))))\n      (define (execute)\n        (let ((insts (get-contents pc)))\n          (if (null? insts)\n              'done\n              (let ((inst (car insts)))\n                (cond ((and tracing (instruction-labeled? inst))\n                       (trace-proc (instruction-label inst))\n                       (trace-proc (instruction-text inst)))\n                      (tracing\n                       (trace-proc (instruction-text inst))))\n                ((instruction-execution-proc inst))\n                (set! instruction-count (+ instruction-count 1))\n                (execute)))))\n      (define (get-instruction-count)\n        (let ((count instruction-count))\n          (set! instruction-count 0)\n          count))\n      (define (dispatch message)\n        (cond ((eq? message 'start)\n               (set-contents! pc the-instruction-sequence)\n               (execute))\n              ((eq? message 'install-instruction-sequence)\n               (lambda (seq) (set! the-instruction-sequence seq)))\n              ((eq? message 'allocate-register) allocate-register)\n              ((eq? message 'get-register) lookup-register)\n              ((eq? message 'install-operations)\n               (lambda (ops) (set! the-ops (append the-ops ops))))\n              ((eq? message 'stack) stack)\n              ((eq? message 'operations) the-ops)\n              ((eq? message 'instruction-count) (get-instruction-count))\n              ((eq? message 'install-trace-proc)\n               (lambda (proc) (set! trace-proc proc)))\n              ((eq? message 'trace-on) (set! tracing #t))\n              ((eq? message 'trace-off) (set! tracing #f))\n              (else (error \"Unknown request -- MACHINE\" message))))\n      dispatch)))\n"
  },
  {
    "path": "scheme/sicp/05/18.scm",
    "content": "; SICP exercise 5.18\n;\n; Modify the make-register procedure of section 5.2.1 so that registers can be\n; traced. Registers should accept messages that turn tracing on and off. When\n; a register is traced, assigning a value to the register should print the\n; name of the register, the old contents of the register, and the new contents\n; being assigned. Extend the interface to the machine model to permit you to\n; turn tracing on and off for designated machine registers.\n\n(define (make-register name trace)\n  (let ((contents '*unassigned*)\n        (tracing #f))\n    (define (dispatch message)\n      (cond ((eq? message 'get) contents)\n            ((eq? message 'set)\n             (lambda (value)\n               (when tracing\n                 (trace name contents value))\n               (set! contents value)))\n            ((eq? message 'trace-off)\n             (set! tracing #f))\n            ((eq? message 'trace-on)\n             (set! tracing #t))\n            (else\n             (error \"Unknown request -- REGISTER\" message))))\n    dispatch))\n\n(define (make-new-machine)\n  (define register-trace-proc (lambda (name old new) (void)))\n  (define (trace name old new)\n    (register-trace-proc name old new))\n  (let ((pc (make-register 'pc trace))\n        (flag (make-register 'flag trace))\n        (stack (make-stack))\n        (the-instruction-sequence '()))\n    (let ((the-ops (list (list 'initialize-stack\n                               (lambda () (stack 'initialize)))))\n          (register-table (list (list 'pc pc) (list 'flag flag))))\n      (define (allocate-register name)\n        (if (assoc name register-table)\n            (error \"Multiply defined register: \" name)\n            (set! register-table (cons (list name (make-register name trace))\n                                       register-table)))\n        'register-allocated)\n      (define (lookup-register name)\n        (let ((val (assoc name register-table)))\n          (if val\n              (cadr val)\n              (error \"Unknown register: \" name))))\n      (define (execute)\n        (let ((insts (get-contents pc)))\n          (if (null? insts)\n              'done\n              (begin\n                ((instruction-execution-proc (car insts)))\n                (execute)))))\n      (define (dispatch message)\n        (cond ((eq? message 'start)\n               (set-contents! pc the-instruction-sequence)\n               (execute))\n              ((eq? message 'install-instruction-sequence)\n               (lambda (seq) (set! the-instruction-sequence seq)))\n              ((eq? message 'allocate-register) allocate-register)\n              ((eq? message 'get-register) lookup-register)\n              ((eq? message 'install-operations)\n               (lambda (ops) (set! the-ops (append the-ops ops))))\n              ((eq? message 'stack) stack)\n              ((eq? message 'operations) the-ops)\n              ((eq? message 'install-register-trace-proc)\n               (lambda (proc) (set! register-trace-proc proc)))\n              ((eq? message 'register-trace-off)\n               (lambda (reg-name) ((lookup-register reg-name) 'trace-off)))\n              ((eq? message 'register-trace-on)\n               (lambda (reg-name) ((lookup-register reg-name) 'trace-on)))\n              (else (error \"Unknown request -- MACHINE\" message))))\n      dispatch)))\n"
  },
  {
    "path": "scheme/sicp/05/19.scm",
    "content": "; SICP exercise 5.19\n;\n; Allysa P. Hacker wants a breakpoint feature in the simulator to help her\n; debug her machine designs. You have been hired to install this feature for\n; her. She wants to be able to specify a place in the controller sequence\n; where the simulator will stop and allow her to examine the state of the\n; machine. You are to implement a procedure\n;\n; (set-breakpoint <machine> <label> <n>)\n;\n; that sets a breakpoint just before the nth instruction after the given\n; label. For example,\n;\n; (set-breakpoint gcd-machine 'test-b 4)\n;\n; installs a breakpoint in the gcd-machine just before the assignment to\n; register a. When the simulator reaches the breakpoint it should print the\n; label and the offset of the breakpoint and stop executing instructions.\n; Alyssa can then use get-register-contents and set-register-contents! to\n; manipulate the state of the simulated machine. She should then be able to\n; continue execution by saying\n;\n; (proceed-machine <machine>)\n;\n; She should also be able to remove a specific breakpoint by means of\n;\n; (cancel-breakpoint <machine> <label> <n>)\n;\n; or to remove all breakpoints by means of\n;\n; (cancel-all-breakpoints machine)\n\n; I will ignore the printing, since it is not that interesting. It can be\n; implemented by storing (cons label offset) instead of #t in the mcaddr of\n; thet instruction.\n;\n; Our interface for the breakpoints:\n\n(define (set-breakpoint machine label offset)\n  ((machine 'set-breakpoint) label offset))\n\n(define (cancel-breakpoint machine label offset)\n  ((machine 'cancel-breakpoint) label offset))\n\n(define (cancel-all-breakpoints machine)\n  (machine 'cancel-all-breakpoints))\n\n(define (proceed-machine machine)\n  (machine 'proceed))\n\n; The assmebler is modified to save the labels in the machine\n\n(define (assemble controller-text machine)\n  (extract-labels controller-text\n    (lambda (insts labels)\n      (update-insts! insts labels machine)\n      (update-labels! labels machine)\n      insts)))\n\n(define (update-labels! labels machine)\n  ((machine 'install-labels) labels))\n\n; The instruction representation stores whether there is a breakpoint on the\n; instruction\n\n(define (make-instruction text)\n  (mcons text (mcons '() (mcons #f '()))))\n(define (instruction-text inst)\n  (mcar inst))\n(define (instruction-execution-proc inst)\n  (mcar (mcdr inst)))\n(define (instruction-breakpoint? inst)\n  (mcar (mcdr (mcdr inst))))\n(define (set-instruction-execution-proc! inst proc)\n  (set-mcar! (mcdr inst) proc))\n(define (set-instruction-breakpoint! inst active?)\n  (set-mcar! (mcdr (mcdr inst)) active?))\n\n; The modified machine constructor\n\n(define (make-new-machine)\n  (let ((pc (make-register 'pc))\n        (flag (make-register 'flag))\n        (stack (make-stack))\n        (the-instruction-sequence '())\n        (the-labels '()))\n    (let ((the-ops (list (list 'initialize-stack\n                               (lambda () (stack 'initialize)))))\n          (register-table (list (list 'pc pc) (list 'flag flag))))\n      (define (allocate-register name)\n        (if (assoc name register-table)\n            (error \"Multiply defined register: \" name)\n            (set! register-table (cons (list name (make-register name))\n                                       register-table)))\n        'register-allocated)\n      (define (lookup-register name)\n        (let ((val (assoc name register-table)))\n          (if val\n              (cadr val)\n              (error \"Unknown register: \" name))))\n      (define (execute)\n        (let ((insts (get-contents pc)))\n          (if (null? insts)\n              'done\n              (begin\n                ((instruction-execution-proc (car insts)))\n                (if (and (not (null? (get-contents pc)))\n                         (instruction-breakpoint? (car (get-contents pc))))\n                    'breakpoint\n                    (execute))))))\n      (define (set-breakpoint label offset)\n        (set-instruction-breakpoint!\n          (list-ref (lookup-label the-labels label) (- offset 1))\n          #t))\n      (define (cancel-breakpoint label offset)\n        (set-instruction-breakpoint!\n          (list-ref (lookup-label the-labels label) (- offset 1))\n          #f))\n      (define (cancel-all-breakpoints)\n        (for-each (lambda (inst) (set-instruction-breakpoint! inst #f))\n                  the-instruction-sequence))\n      (define (dispatch message)\n        (cond ((eq? message 'start)\n               (set-contents! pc the-instruction-sequence)\n               (execute))\n              ((eq? message 'proceed)\n               (execute))\n              ((eq? message 'install-instruction-sequence)\n               (lambda (seq) (set! the-instruction-sequence seq)))\n              ((eq? message 'install-labels)\n               (lambda (labels) (set! the-labels labels)))\n              ((eq? message 'allocate-register) allocate-register)\n              ((eq? message 'get-register) lookup-register)\n              ((eq? message 'install-operations)\n               (lambda (ops) (set! the-ops (append the-ops ops))))\n              ((eq? message 'set-breakpoint) set-breakpoint)\n              ((eq? message 'cancel-breakpoint) cancel-breakpoint)\n              ((eq? message 'cancel-all-breakpoints) (cancel-all-breakpoints))\n              ((eq? message 'stack) stack)\n              ((eq? message 'operations) the-ops)\n              (else (error \"Unknown request -- MACHINE\" message))))\n      dispatch)))\n"
  },
  {
    "path": "scheme/sicp/05/20.scm",
    "content": "; SICP exercise 5.20\n;\n; Draw the box-and-pointer representation and the memory-vector representation\n; (as in figure 5.14) of the list structure produced by\n;\n; (define x (cons 1 2))\n; (define y (list x x))\n;\n; with the free pointer initially p1. What is the final value of free? What\n; pointers represent the values of x and y?\n\n; The final value of free will be n4. Here are the drawings:\n;\n;             +---+---+       +---+---+\n; (x x) ----> | o | o ------->| o | / |\n;           1 +-|-+---+     2 +-|-+---+\n;               |               |\n;               |               V\n;               |             +---+---+\n;               +------------>| o | o |\n;                           3 +-|-+-|-+\n;                               |   |\n;                               V   V\n;                            +---+ +---+\n;                            | 1 | | 2 |\n;                            +---+ +---+\n;\n;    Index   0    1    2    3    4    ...\n;          +----+----+----+----+----+----\n; the-cars |    | p3 | p3 | n1 |    | ...\n;          +----+----+----+----+----+----\n; the-csrs |    | p2 | e0 | n2 |    | ...\n;          +----+----+----+----+----+----\n;                                ^\n;                                |\n;                               free\n"
  },
  {
    "path": "scheme/sicp/05/21.scm",
    "content": "; SICP exercise 5.21\n;\n; Implement register machines for the following procedures. Assume that the\n; list-structure memory operations are available as machine primitives.\n;\n; a. Recursive count-leaves\n;\n; (define (count-leaves tree)\n;   (cond ((null? tree) 0)\n;         ((not (pair? tree)) 1)\n;         (else (+ (count-leaves (car tree))\n;                  (count-leaves (cdr tree))))))\n;\n; b. Recursive count-leaves with explicit counter\n;\n; (define (count-leaves tree)\n;   (define (count-iter tree n)\n;     (cond ((null? tree) n)\n;           ((not (pair? tree)) (+ n 1))\n;           (else (count-iter (cdr tree)\n;                             (count-iter (car tree) n)))))\n;   (count-iter tree 0))\n\n; I have defined the necessary-to-run code in helpers/memory.scm.\n;\n; a. Recursive count-leaves\n\n(define count-leaves-machine\n  (make-machine-with-memory '(result n tree continue)\n                            '(\n                                (assign continue (label count-done))\n                              count-leaves\n                                (test (op null?) (reg tree))\n                                (branch (label tree-null))\n                                (test (op pair?) (reg tree))\n                                (branch (label tree-pair))\n                                (goto (label tree-number))\n                              tree-null\n                                (assign result (const (n 0)))\n                                (goto (reg continue))\n                              tree-number\n                                (assign result (const (n 1)))\n                                (goto (reg continue))\n                              tree-pair\n                                (save continue)\n                                (save tree)\n                                (assign tree (op vector-ref) (reg the-cars) (reg tree))\n                                (assign continue (label tree-pair-after-car))\n                                (goto (label count-leaves))\n                              tree-pair-after-car\n                                (restore tree)\n                                (assign n (reg result))\n                                (save n)\n                                (assign tree (op vector-ref) (reg the-cdrs) (reg tree))\n                                (assign continue (label tree-pair-after-cdr))\n                                (goto (label count-leaves))\n                              tree-pair-after-cdr\n                                (restore n)\n                                (restore continue)\n                                (assign result (op +) (reg result) (reg n))\n                                (goto (reg continue))\n                              count-done)))\n\n; b. Recursive count-leaves with explicit counter\n\n(define count-leaves-explicit-counter-machine\n  (make-machine-with-memory '(result n tree continue)\n                            '(\n                                (assign n (const (n 0)))\n                                (assign continue (label count-done))\n                              count-iter\n                                (test (op null?) (reg tree))\n                                (branch (label null-tree))\n                                (test (op pair?) (reg tree))\n                                (branch (label pair-tree))\n                                (goto (label number-tree))\n                              null-tree\n                                (assign result (reg n))\n                                (goto (reg continue))\n                              number-tree\n                                (assign result (op +) (reg n) (const (n 1)))\n                                (goto (reg continue))\n                              pair-tree\n                                (save tree)\n                                (save continue)\n                                (assign tree (op vector-ref) (reg the-cars) (reg tree))\n                                (assign continue (label after-car))\n                                (goto (label count-iter))\n                              after-car\n                                (restore continue)\n                                (restore tree)\n                                (assign n (reg result))\n                                (assign tree (op vector-ref) (reg the-cdrs) (reg tree))\n                                (goto (label count-iter))\n                              count-done)))\n"
  },
  {
    "path": "scheme/sicp/05/22.scm",
    "content": "; SICP exercise 5.22\n;\n; Exercise 3.12 of section 3.3.1 presented an append procedure that appends\n; two lists to form a new list and an append! procedure that splices two lists\n; together. Design a register machine to implement each of these procedures.\n; Assume that the list-structure memory operations are available as primitive\n; operations.\n\n;   (define (append x y)\n;     (if (null? x)\n;         y\n;         (cons (car x) (append (cdr x) y))))\n\n(define append-machine\n  (make-machine-with-memory '(x y val result continue)\n                            '(\n                                (assign continue (label append-done))\n                              append\n                                (test (op null?) (reg x))\n                                (branch (label x-empty))\n                                (assign val (op vector-ref) (reg the-cars) (reg x))\n                                (perform (op vector-set!) (reg the-cars) (reg free) (reg val))\n                                (assign val (reg free))\n                                (save val)\n                                (assign free (op +) (reg free) (const (p 1)))\n                                (save continue)\n                                (assign continue (label after-append))\n                                (assign x (op vector-ref) (reg the-cdrs) (reg x))\n                                (goto (label append))\n                              after-append\n                                (restore continue)\n                                (restore val)\n                                (perform (op vector-set!) (reg the-cdrs) (reg val) (reg result))\n                                (assign result (reg val))\n                                (goto (reg continue))\n                              x-empty\n                                (assign result (reg y))\n                                (goto (reg continue))\n                              append-done\n                              )))\n\n(define append!-machine\n  (make-machine-with-memory '(x y val)\n                            '(append!\n                                (assign val (op vector-ref) (reg the-cdrs) (reg x))\n                                (test (op null?) (reg val))\n                                (branch (label last-pair))\n                                (assign x (op vector-ref) (reg the-cdrs) (reg x))\n                                (goto (label append!))\n                              last-pair\n                                (perform (op vector-set!) (reg the-cdrs) (reg x) (reg y))\n                              )))\n"
  },
  {
    "path": "scheme/sicp/05/23.scm",
    "content": "; SICP exercise 5.23\n;\n; Extend the evaluator to handle derived expressions such as cond, let and so\n; on (section 4.1.2). You may \"cheat\" and assume that the syntax transformers\n; as cond->if are available as machine operations.\n\n; For starters, we can just lif cond->if and let->combination from the\n; previous exercises.\n\n(define (make-begin seq) (cons 'begin seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause) (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp) (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (let? exp) (tagged-list? exp 'let))\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n; Here are the extra operations\n\n(define extra-operations\n  (list (list 'cond? cond?)\n        (list 'cond->if cond->if)\n        (list 'let? let?)\n        (list 'let->combination let->combination)))\n\n; We also need to modify the controller text. Alas, I need to have the whole\n; thing here.\n\n(define ec-cond-and-let\n  '(\n      (assign continue (label done))\n    eval-dispatch\n      (test (op self-evaluating?) (reg exp))\n      (branch (label ev-self-eval))\n      (test (op variable?) (reg exp))\n      (branch (label ev-variable))\n      (test (op quoted?) (reg exp))\n      (branch (label ev-quoted))\n      (test (op assignment?) (reg exp))\n      (branch (label ev-assignment))\n      (test (op definition?) (reg exp))\n      (branch (label ev-definition))\n      (test (op if?) (reg exp))\n      (branch (label ev-if))\n      (test (op lambda?) (reg exp))\n      (branch (label ev-lambda))\n      (test (op begin?) (reg exp))\n      (branch (label ev-begin))\n      (test (op cond?) (reg exp))\n      (branch (label ev-cond))\n      (test (op let?) (reg exp))\n      (branch (label ev-let))\n      (test (op application?) (reg exp))\n      (branch (label ev-application))\n      (goto (label unknown-expression-type))\n\n    ; Cond and Let\n\n    ev-cond\n      (assign exp (op cond->if) (reg exp))\n      (goto (label eval-dispatch))\n    ev-let\n      (assign exp (op let->combination) (reg exp))\n      (goto (label eval-dispatch))\n\n    ; Evaluating simple expressions\n\n    ev-self-eval\n      (assign val (reg exp))\n      (goto (reg continue))\n    ev-variable\n      (assign val (op lookup-variable-value) (reg exp) (reg env))\n      (goto (reg continue))\n    ev-quoted\n      (assign val (op text-of-quotation) (reg exp))\n      (goto (reg continue))\n    ev-lambda\n      (assign unev (op lambda-parameters) (reg exp))\n      (assign exp (op lambda-body) (reg exp))\n      (assign val (op make-procedure) (reg unev) (reg exp) (reg env))\n      (goto (reg continue))\n\n    ; Evaluating procedure applications\n\n    ev-application\n      (save continue)\n      (save env)\n      (assign unev (op operands) (reg exp))\n      (save unev)\n      (assign exp (op operator) (reg exp))\n      (assign continue (label ev-appl-did-operator))\n      (goto (label eval-dispatch))\n    ev-appl-did-operator\n      (restore unev)\n      (restore env)\n      (assign argl (op empty-arglist))\n      (assign proc (reg val))\n      (test (op no-operands?) (reg unev))\n      (branch (label apply-dispatch))\n      (save proc)\n    ev-appl-operand-loop\n      (save argl)\n      (assign exp (op first-operand) (reg unev))\n      (test (op last-operand?) (reg unev))\n      (branch (label ev-appl-last-arg))\n      (save env)\n      (save unev)\n      (assign continue (label ev-appl-accumulate-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accumulate-arg\n      (restore unev)\n      (restore env)\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (assign unev (op rest-operands) (reg unev))\n      (goto (label ev-appl-operand-loop))\n    ev-appl-last-arg\n      (assign continue (label ev-appl-accum-last-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accum-last-arg\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (restore proc)\n      (goto (label apply-dispatch))\n\n    ; Procedure application\n\n    apply-dispatch\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-apply))\n      (test (op compound-procedure?) (reg proc))\n      (branch (label compound-apply))\n      (goto (label unknown-procedure-type))\n    primitive-apply\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n      (restore continue)\n      (goto (reg continue))\n    compound-apply\n      (assign unev (op procedure-parameters) (reg proc))\n      (assign env (op procedure-environment) (reg proc))\n      (assign env (op extend-environment) (reg unev) (reg argl) (reg env))\n      (assign unev (op procedure-body) (reg proc))\n      (goto (label ev-sequence))\n\n    ; Sequence evaluation\n\n    ev-begin\n      (assign unev (op begin-actions) (reg exp))\n      (save continue)\n      (goto (label ev-sequence))\n    ev-sequence\n      (assign exp (op first-exp) (reg unev))\n      (test (op last-exp?) (reg unev))\n      (branch (label ev-sequence-last-exp))\n      (save unev)\n      (save env)\n      (assign continue (label ev-sequence-continue))\n      (goto (label eval-dispatch))\n    ev-sequence-continue\n      (restore env)\n      (restore unev)\n      (assign unev (op rest-exps) (reg unev))\n      (goto (label ev-sequence))\n    ev-sequence-last-exp\n      (restore continue)\n      (goto (label eval-dispatch))\n\n    ; Conditionals\n\n    ev-if\n      (save exp)\n      (save env)\n      (save continue)\n      (assign continue (label ev-if-decide))\n      (assign exp (op if-predicate) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-decide\n      (restore continue)\n      (restore env)\n      (restore exp)\n      (test (op true?) (reg val))\n      (branch (label ev-if-consequent))\n    ev-if-alternative\n      (assign exp (op if-alternative) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-consequent\n      (assign exp (op if-consequent) (reg exp))\n      (goto (label eval-dispatch))\n\n    ; Assignments and definitions\n\n    ev-assignment\n      (assign unev (op assignment-variable) (reg exp))\n      (save unev)\n      (assign exp (op assignment-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-assignment-1))\n      (goto (label eval-dispatch))\n    ev-assignment-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op set-variable-value!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n\n    ev-definition\n      (assign unev (op definition-variable) (reg exp))\n      (save unev)\n      (assign exp (op definition-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-definition-1))\n      (goto (label eval-dispatch))\n    ev-definition-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op define-variable!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n    unknown-expression-type\n    unknown-procedure-type\n    done))\n"
  },
  {
    "path": "scheme/sicp/05/24.scm",
    "content": "; SICP exercise 5.24\n;\n; Implement cond as a new basic special form without reducing it to if. You\n; will have to construct a loop that tests the predicates of successive cond\n; clauses until you find one that is true, and then use ev-sequence to\n; evaluate the actions of the clause.\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause) (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (no-clauses? clauses) (null? clauses))\n(define (first-clause clauses) (car clauses))\n(define (rest-clauses clauses) (cdr clauses))\n\n(define extra-operations\n  (list (list 'cond? cond?)\n        (list 'cond-clauses cond-clauses)\n        (list 'no-clauses? no-clauses?)\n        (list 'first-clause first-clause)\n        (list 'cond-else-clause? cond-else-clause?)\n        (list 'cond-predicate cond-predicate)\n        (list 'rest-clauses rest-clauses)\n        (list 'cond-actions cond-actions)))\n\n(define ec-cond\n  '(\n      (assign continue (label done))\n    eval-dispatch\n      (test (op self-evaluating?) (reg exp))\n      (branch (label ev-self-eval))\n      (test (op variable?) (reg exp))\n      (branch (label ev-variable))\n      (test (op quoted?) (reg exp))\n      (branch (label ev-quoted))\n      (test (op assignment?) (reg exp))\n      (branch (label ev-assignment))\n      (test (op definition?) (reg exp))\n      (branch (label ev-definition))\n      (test (op if?) (reg exp))\n      (branch (label ev-if))\n      (test (op lambda?) (reg exp))\n      (branch (label ev-lambda))\n      (test (op begin?) (reg exp))\n      (branch (label ev-begin))\n      (test (op cond?) (reg exp))\n      (branch (label ev-cond))\n      (test (op application?) (reg exp))\n      (branch (label ev-application))\n      (goto (label unknown-expression-type))\n\n    ; Cond\n\n    ev-cond\n      (assign unev (op cond-clauses) (reg exp))\n      (save continue)\n    ev-cond-loop\n      (test (op no-clauses?) (reg unev))\n      (branch (label ev-cond-no-clauses))\n      (assign exp (op first-clause) (reg unev))\n      (test (op cond-else-clause?) (reg exp))\n      (branch (label ev-cond-else-clause))\n      (save unev)\n      (save env)\n      (assign exp (op cond-predicate) (reg exp))\n      (assign continue (label ev-cond-after-eval-predicate))\n      (goto (label eval-dispatch))\n    ev-cond-after-eval-predicate\n      (restore env)\n      (restore unev)\n      (test (op true?) (reg val))\n      (branch (label ev-cond-run-clause))\n      (assign unev (op rest-clauses) (reg unev))\n      (goto (label ev-cond-loop))\n    ev-cond-run-clause\n      (assign unev (op first-clause) (reg unev))\n      (assign unev (op cond-actions) (reg unev))\n      (goto (label ev-sequence))\n    ev-cond-else-clause\n      (assign unev (op cond-actions) (reg exp))\n      (goto (label ev-sequence))\n    ev-cond-no-clauses\n      (assign val (const #f))\n      (restore continue)\n      (goto (reg continue))\n\n    ; Evaluating simple expressions\n\n    ev-self-eval\n      (assign val (reg exp))\n      (goto (reg continue))\n    ev-variable\n      (assign val (op lookup-variable-value) (reg exp) (reg env))\n      (goto (reg continue))\n    ev-quoted\n      (assign val (op text-of-quotation) (reg exp))\n      (goto (reg continue))\n    ev-lambda\n      (assign unev (op lambda-parameters) (reg exp))\n      (assign exp (op lambda-body) (reg exp))\n      (assign val (op make-procedure) (reg unev) (reg exp) (reg env))\n      (goto (reg continue))\n\n    ; Evaluating procedure applications\n\n    ev-application\n      (save continue)\n      (save env)\n      (assign unev (op operands) (reg exp))\n      (save unev)\n      (assign exp (op operator) (reg exp))\n      (assign continue (label ev-appl-did-operator))\n      (goto (label eval-dispatch))\n    ev-appl-did-operator\n      (restore unev)\n      (restore env)\n      (assign argl (op empty-arglist))\n      (assign proc (reg val))\n      (test (op no-operands?) (reg unev))\n      (branch (label apply-dispatch))\n      (save proc)\n    ev-appl-operand-loop\n      (save argl)\n      (assign exp (op first-operand) (reg unev))\n      (test (op last-operand?) (reg unev))\n      (branch (label ev-appl-last-arg))\n      (save env)\n      (save unev)\n      (assign continue (label ev-appl-accumulate-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accumulate-arg\n      (restore unev)\n      (restore env)\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (assign unev (op rest-operands) (reg unev))\n      (goto (label ev-appl-operand-loop))\n    ev-appl-last-arg\n      (assign continue (label ev-appl-accum-last-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accum-last-arg\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (restore proc)\n      (goto (label apply-dispatch))\n\n    ; Procedure application\n\n    apply-dispatch\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-apply))\n      (test (op compound-procedure?) (reg proc))\n      (branch (label compound-apply))\n      (goto (label unknown-procedure-type))\n    primitive-apply\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n      (restore continue)\n      (goto (reg continue))\n    compound-apply\n      (assign unev (op procedure-parameters) (reg proc))\n      (assign env (op procedure-environment) (reg proc))\n      (assign env (op extend-environment) (reg unev) (reg argl) (reg env))\n      (assign unev (op procedure-body) (reg proc))\n      (goto (label ev-sequence))\n\n    ; Sequence evaluation\n\n    ev-begin\n      (assign unev (op begin-actions) (reg exp))\n      (save continue)\n      (goto (label ev-sequence))\n    ev-sequence\n      (assign exp (op first-exp) (reg unev))\n      (test (op last-exp?) (reg unev))\n      (branch (label ev-sequence-last-exp))\n      (save unev)\n      (save env)\n      (assign continue (label ev-sequence-continue))\n      (goto (label eval-dispatch))\n    ev-sequence-continue\n      (restore env)\n      (restore unev)\n      (assign unev (op rest-exps) (reg unev))\n      (goto (label ev-sequence))\n    ev-sequence-last-exp\n      (restore continue)\n      (goto (label eval-dispatch))\n\n    ; Conditionals\n\n    ev-if\n      (save exp)\n      (save env)\n      (save continue)\n      (assign continue (label ev-if-decide))\n      (assign exp (op if-predicate) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-decide\n      (restore continue)\n      (restore env)\n      (restore exp)\n      (test (op true?) (reg val))\n      (branch (label ev-if-consequent))\n    ev-if-alternative\n      (assign exp (op if-alternative) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-consequent\n      (assign exp (op if-consequent) (reg exp))\n      (goto (label eval-dispatch))\n\n    ; Assignments and definitions\n\n    ev-assignment\n      (assign unev (op assignment-variable) (reg exp))\n      (save unev)\n      (assign exp (op assignment-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-assignment-1))\n      (goto (label eval-dispatch))\n    ev-assignment-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op set-variable-value!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n\n    ev-definition\n      (assign unev (op definition-variable) (reg exp))\n      (save unev)\n      (assign exp (op definition-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-definition-1))\n      (goto (label eval-dispatch))\n    ev-definition-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op define-variable!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n    unknown-expression-type\n    unknown-procedure-type\n    done))\n"
  },
  {
    "path": "scheme/sicp/05/25.scm",
    "content": "; SICP exercise 5.25\n;\n; Modify the evaluator so that it uses normal-order evaluation, based on the\n; lazy evaluator of section 4.2.\n\n; This is tricky.\n;\n; First, in order to do normal-order evaluation, we should not cache thunk\n; values. That would beat the purpose of normal-order.\n;\n; Second, we will accomplish this with a more general procedure called\n; ev-map-operands, that will apply the procedure in the exp register to each\n; argument in unev. It is used by primitive-apply with actual-value and\n; compound-apply with delay-it.\n;\n; We will also modify ev-if to use actual-value.\n\n(define (delay-it exp env) (list 'thunk exp env))\n(define (thunk? obj) (tagged-list? obj 'thunk))\n(define (thunk-exp thunk) (cadr thunk))\n(define (thunk-env thunk) (caddr thunk))\n\n(define extra-operations\n  (list (list 'delay-it delay-it)\n        (list 'thunk? thunk?)\n        (list 'thunk-env thunk-env)\n        (list 'thunk-exp thunk-exp)))\n\n(define ec-core\n  '(\n      (assign continue (label done))\n    eval-dispatch\n      (test (op self-evaluating?) (reg exp))\n      (branch (label ev-self-eval))\n      (test (op variable?) (reg exp))\n      (branch (label ev-variable))\n      (test (op quoted?) (reg exp))\n      (branch (label ev-quoted))\n      (test (op assignment?) (reg exp))\n      (branch (label ev-assignment))\n      (test (op definition?) (reg exp))\n      (branch (label ev-definition))\n      (test (op if?) (reg exp))\n      (branch (label ev-if))\n      (test (op lambda?) (reg exp))\n      (branch (label ev-lambda))\n      (test (op begin?) (reg exp))\n      (branch (label ev-begin))\n      (test (op application?) (reg exp))\n      (branch (label ev-application))\n      (goto (label unknown-expression-type))\n\n    ; Delaying expressions\n\n    delay-it\n      (assign val (op delay-it) (reg exp) (reg env))\n      (goto (reg continue))\n\n    actual-value\n      (save continue)\n      (assign continue (label actual-value-after-eval))\n      (goto (label eval-dispatch))\n    actual-value-after-eval\n      (restore continue)\n      (assign exp (reg val))\n      (goto (label force-it))\n\n    force-it\n      (test (op thunk?) (reg exp))\n      (branch (label force-it-thunk))\n      (goto (reg continue))\n    force-it-thunk\n      (assign env (op thunk-env) (reg exp))\n      (assign exp (op thunk-exp) (reg exp))\n      (goto (label actual-value))\n\n    ; Evaluating simple expressions\n\n    ev-self-eval\n      (assign val (reg exp))\n      (goto (reg continue))\n    ev-variable\n      (assign val (op lookup-variable-value) (reg exp) (reg env))\n      (goto (reg continue))\n    ev-quoted\n      (assign val (op text-of-quotation) (reg exp))\n      (goto (reg continue))\n    ev-lambda\n      (assign unev (op lambda-parameters) (reg exp))\n      (assign exp (op lambda-body) (reg exp))\n      (assign val (op make-procedure) (reg unev) (reg exp) (reg env))\n      (goto (reg continue))\n\n    ; Evaluating procedure applications\n\n    ev-application\n      (save continue)\n      (save env)\n      (assign unev (op operands) (reg exp))\n      (save unev)\n      (assign exp (op operator) (reg exp))\n      (assign continue (label ev-appl-did-operator))\n      (goto (label eval-dispatch))\n    ev-appl-did-operator\n      (restore unev)\n      (restore env)\n      (assign proc (reg val))\n      (goto (label apply-dispatch))\n\n    ; Procedure application\n\n    apply-dispatch\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-apply))\n      (test (op compound-procedure?) (reg proc))\n      (branch (label compound-apply))\n      (goto (label unknown-procedure-type))\n    primitive-apply\n      (assign exp (label actual-value))\n      (assign continue (label primitive-apply-after-args))\n      (goto (label ev-map-operands))\n    primitive-apply-after-args\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n      (restore continue)\n      (goto (reg continue))\n    compound-apply\n      (save continue)\n      (assign exp (label delay-it))\n      (assign continue (label compound-apply-after-args))\n      (goto (label ev-map-operands))\n    compound-apply-after-args\n      (restore continue)\n      (assign unev (op procedure-parameters) (reg proc))\n      (assign env (op procedure-environment) (reg proc))\n      (assign env (op extend-environment) (reg unev) (reg argl) (reg env))\n      (assign unev (op procedure-body) (reg proc))\n      (goto (label ev-sequence))\n\n    ev-map-operands\n      (assign argl (op empty-arglist))\n      (test (op no-operands?) (reg unev))\n      (branch (label ev-map-no-args))\n      (save continue)\n      (save proc)\n      (assign proc (reg exp))\n      (save proc)\n    ev-map-operand-loop\n      (restore proc)\n      (assign exp (op first-operand) (reg unev))\n      (test (op last-operand?) (reg unev))\n      (branch (label ev-map-last-arg))\n      (save proc)\n      (save argl)\n      (save env)\n      (save unev)\n      (assign continue (label ev-map-accumulate-arg))\n      (goto (reg proc))\n    ev-map-accumulate-arg\n      (restore unev)\n      (restore env)\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (assign unev (op rest-operands) (reg unev))\n      (goto (label ev-map-operand-loop))\n    ev-map-last-arg\n      (save argl)\n      (assign continue (label ev-map-accumulate-last-arg))\n      (goto (reg proc))\n    ev-map-accumulate-last-arg\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (restore proc)\n      (restore continue)\n      (goto (reg continue))\n    ev-map-no-args\n      (goto (reg continue))\n\n    ; Sequence evaluation\n\n    ev-begin\n      (assign unev (op begin-actions) (reg exp))\n      (save continue)\n      (goto (label ev-sequence))\n    ev-sequence\n      (assign exp (op first-exp) (reg unev))\n      (test (op last-exp?) (reg unev))\n      (branch (label ev-sequence-last-exp))\n      (save unev)\n      (save env)\n      (assign continue (label ev-sequence-continue))\n      (goto (label eval-dispatch))\n    ev-sequence-continue\n      (restore env)\n      (restore unev)\n      (assign unev (op rest-exps) (reg unev))\n      (goto (label ev-sequence))\n    ev-sequence-last-exp\n      (restore continue)\n      (goto (label eval-dispatch))\n\n    ; Conditionals\n\n    ev-if\n      (save exp)\n      (save env)\n      (save continue)\n      (assign continue (label ev-if-decide))\n      (assign exp (op if-predicate) (reg exp))\n      (goto (label actual-value))\n    ev-if-decide\n      (restore continue)\n      (restore env)\n      (restore exp)\n      (test (op true?) (reg val))\n      (branch (label ev-if-consequent))\n    ev-if-alternative\n      (assign exp (op if-alternative) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-consequent\n      (assign exp (op if-consequent) (reg exp))\n      (goto (label eval-dispatch))\n\n    ; Assignments and definitions\n\n    ev-assignment\n      (assign unev (op assignment-variable) (reg exp))\n      (save unev)\n      (assign exp (op assignment-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-assignment-1))\n      (goto (label eval-dispatch))\n    ev-assignment-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op set-variable-value!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n\n    ev-definition\n      (assign unev (op definition-variable) (reg exp))\n      (save unev)\n      (assign exp (op definition-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-definition-1))\n      (goto (label eval-dispatch))\n    ev-definition-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op define-variable!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n    unknown-expression-type\n    unknown-procedure-type\n    done))\n"
  },
  {
    "path": "scheme/sicp/05/26.scm",
    "content": "; SICP exercise 5.26\n;\n; Use the monitored stack to explore the tail-recursive property of the\n; evaluator (section 5.4.2). Start the evaluator and define the iterative\n; factorial procedure from section 1.2.1:\n;\n; (define (factorial n)\n;   (define (iter product counter)\n;     (if (> counter n)\n;         product\n;         (iter (* counter product)\n;               (+ counter 1))))\n;   (iter 1 1))\n;\n; Run the procedure with some small values of n. Record the maximum stack\n; depth and the number of pushes required to compute n! for each of these\n; values.\n;\n; a. You will find that the maximum depth required to evaluate n! is\n; independent of n. What is the depth?\n;\n; b. Determine from your data a formula in terms of n for the total number of\n; push operations used in evaluating n! for any n ≥ 1. Note that the number of\n; operations used is a linear function of n and is thus determined by two\n; constants.\n\n\n; The results are:\n;\n; 1! takes (total-pushes = 64 maximum-depth = 10)\n; 2! takes (total-pushes = 99 maximum-depth = 10)\n; 3! takes (total-pushes = 134 maximum-depth = 10)\n; 4! takes (total-pushes = 169 maximum-depth = 10)\n; 5! takes (total-pushes = 204 maximum-depth = 10)\n; 6! takes (total-pushes = 239 maximum-depth = 10)\n; 7! takes (total-pushes = 274 maximum-depth = 10)\n; 8! takes (total-pushes = 309 maximum-depth = 10)\n; 9! takes (total-pushes = 344 maximum-depth = 10)\n;\n; The maximum depth is 10.\n;\n; The linear function is 35n + 29.\n;\n; The code that extracts it is below\n\n(load-relative \"tests/helpers/evaluator.scm\")\n(load-relative \"tests/helpers/monitored-stack.scm\")\n\n(define code\n  '(define (factorial n)\n     (define (iter product counter)\n       (if (> counter n)\n         product\n         (iter (* counter product)\n               (+ counter 1))))\n     (iter 1 1)))\n\n(define machine (make-explicit-control-machine))\n\n(set-register-contents! machine 'env the-global-environment)\n\n(set-register-contents! machine 'exp code)\n(start machine)\n\n(for ([n (in-range 1 10)])\n  (printf \"~a! takes ~a\\n\" n (stack-stats-for machine (list 'factorial n))))\n"
  },
  {
    "path": "scheme/sicp/05/27.scm",
    "content": "; SICP exercise 5.27\n;\n; For comparison with exercise 5.26, explore the behavior of the following\n; procedure for computing factorials recursively:\n;\n; (define (factorial n)\n;   (if (= n 1)\n;       1\n;       (* (factorial (- n 1)) n)))\n;\n; By running this procedure with the monitored stack, determine, as a function\n; of n, the maximum depth of the stack and the total number of pushes used in\n; evaluating n! for n ≥ 1. (Again, these functions will be linear). Summarize\n; your experiments by filling in the following table with the appropriate\n; expressions in terms of n:\n;\n; <table>\n;\n; The maximum depth is a measure of the amount of space used by the evaluator\n; in carrying out the computation, and the number of pushes correlates well\n; with the time required.\n\n; The results are:\n;\n; 1! takes (total-pushes = 16 maximum-depth = 8)\n; 2! takes (total-pushes = 48 maximum-depth = 13)\n; 3! takes (total-pushes = 80 maximum-depth = 18)\n; 4! takes (total-pushes = 112 maximum-depth = 23)\n; 5! takes (total-pushes = 144 maximum-depth = 28)\n; 6! takes (total-pushes = 176 maximum-depth = 33)\n; 7! takes (total-pushes = 208 maximum-depth = 38)\n; 8! takes (total-pushes = 240 maximum-depth = 43)\n; 9! takes (total-pushes = 272 maximum-depth = 48)\n;\n; This implies that the maximum depth is 5n + 3 and the total pushes are\n; 32n - 16.\n;\n;                     | Maximum depth | Number of pushes\n; --------------------+---------------+-----------------\n; Recursive factorial |        5n + 3 |         32n - 16\n; --------------------+---------------+-----------------\n; Iterative factorial |            10 |         35n + 29\n; --------------------+---------------+-----------------\n\n(load-relative \"tests/helpers/evaluator.scm\")\n(load-relative \"tests/helpers/monitored-stack.scm\")\n\n(define code\n  '(define (factorial n)\n     (if (= n 1)\n       1\n       (* (factorial (- n 1)) n))))\n\n(define machine (make-explicit-control-machine))\n\n(set-register-contents! machine 'env the-global-environment)\n\n(set-register-contents! machine 'exp code)\n(start machine)\n\n(for ([n (in-range 1 10)])\n  (printf \"~a! takes ~a\\n\" n (stack-stats-for machine (list 'factorial n))))\n"
  },
  {
    "path": "scheme/sicp/05/28.scm",
    "content": "; SICP exercise 5.28\n;\n; Modify the definition of the evaluator by changing eval-sequence as\n; described in section 5.4.2 so that the evaluator is no longer\n; tail-recursive. Rerun your experiments from exercise 5.26 to 5.27 to\n; demonstrate that both versions of the factorial procedure now require space\n; that grows linearly with their input.\n\n; The results are:\n;\n; Iterative factorial:\n;   1! takes (total-pushes = 70 maximum-depth = 17)\n;   2! takes (total-pushes = 107 maximum-depth = 20)\n;   3! takes (total-pushes = 144 maximum-depth = 23)\n;   4! takes (total-pushes = 181 maximum-depth = 26)\n;   5! takes (total-pushes = 218 maximum-depth = 29)\n;   6! takes (total-pushes = 255 maximum-depth = 32)\n;   7! takes (total-pushes = 292 maximum-depth = 35)\n;   8! takes (total-pushes = 329 maximum-depth = 38)\n;   9! takes (total-pushes = 366 maximum-depth = 41)\n; Recursive factorial:\n;   1! takes (total-pushes = 18 maximum-depth = 11)\n;   2! takes (total-pushes = 52 maximum-depth = 19)\n;   3! takes (total-pushes = 86 maximum-depth = 27)\n;   4! takes (total-pushes = 120 maximum-depth = 35)\n;   5! takes (total-pushes = 154 maximum-depth = 43)\n;   6! takes (total-pushes = 188 maximum-depth = 51)\n;   7! takes (total-pushes = 222 maximum-depth = 59)\n;   8! takes (total-pushes = 256 maximum-depth = 67)\n;   9! takes (total-pushes = 290 maximum-depth = 75)\n;\n; One can see that both versions are not bound on stack space. The code to\n; reproduce the results is below:\n\n(load-relative \"tests/helpers/evaluator.scm\")\n(load-relative \"tests/helpers/monitored-stack.scm\")\n\n(define ec-no-tail\n  '(\n      (assign continue (label done))\n    eval-dispatch\n      (test (op self-evaluating?) (reg exp))\n      (branch (label ev-self-eval))\n      (test (op variable?) (reg exp))\n      (branch (label ev-variable))\n      (test (op quoted?) (reg exp))\n      (branch (label ev-quoted))\n      (test (op assignment?) (reg exp))\n      (branch (label ev-assignment))\n      (test (op definition?) (reg exp))\n      (branch (label ev-definition))\n      (test (op if?) (reg exp))\n      (branch (label ev-if))\n      (test (op lambda?) (reg exp))\n      (branch (label ev-lambda))\n      (test (op begin?) (reg exp))\n      (branch (label ev-begin))\n      (test (op application?) (reg exp))\n      (branch (label ev-application))\n      (goto (label unknown-expression-type))\n\n    ; Evaluating simple expressions\n\n    ev-self-eval\n      (assign val (reg exp))\n      (goto (reg continue))\n    ev-variable\n      (assign val (op lookup-variable-value) (reg exp) (reg env))\n      (goto (reg continue))\n    ev-quoted\n      (assign val (op text-of-quotation) (reg exp))\n      (goto (reg continue))\n    ev-lambda\n      (assign unev (op lambda-parameters) (reg exp))\n      (assign exp (op lambda-body) (reg exp))\n      (assign val (op make-procedure) (reg unev) (reg exp) (reg env))\n      (goto (reg continue))\n\n    ; Evaluating procedure applications\n\n    ev-application\n      (save continue)\n      (save env)\n      (assign unev (op operands) (reg exp))\n      (save unev)\n      (assign exp (op operator) (reg exp))\n      (assign continue (label ev-appl-did-operator))\n      (goto (label eval-dispatch))\n    ev-appl-did-operator\n      (restore unev)\n      (restore env)\n      (assign argl (op empty-arglist))\n      (assign proc (reg val))\n      (test (op no-operands?) (reg unev))\n      (branch (label apply-dispatch))\n      (save proc)\n    ev-appl-operand-loop\n      (save argl)\n      (assign exp (op first-operand) (reg unev))\n      (test (op last-operand?) (reg unev))\n      (branch (label ev-appl-last-arg))\n      (save env)\n      (save unev)\n      (assign continue (label ev-appl-accumulate-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accumulate-arg\n      (restore unev)\n      (restore env)\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (assign unev (op rest-operands) (reg unev))\n      (goto (label ev-appl-operand-loop))\n    ev-appl-last-arg\n      (assign continue (label ev-appl-accum-last-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accum-last-arg\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (restore proc)\n      (goto (label apply-dispatch))\n\n    ; Procedure application\n\n    apply-dispatch\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-apply))\n      (test (op compound-procedure?) (reg proc))\n      (branch (label compound-apply))\n      (goto (label unknown-procedure-type))\n    primitive-apply\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n      (restore continue)\n      (goto (reg continue))\n    compound-apply\n      (assign unev (op procedure-parameters) (reg proc))\n      (assign env (op procedure-environment) (reg proc))\n      (assign env (op extend-environment) (reg unev) (reg argl) (reg env))\n      (assign unev (op procedure-body) (reg proc))\n      (goto (label ev-sequence))\n\n    ; Sequence evaluation\n\n    ev-begin\n      (assign unev (op begin-actions) (reg exp))\n      (save continue)\n      (goto (label ev-sequence))\n    ev-sequence\n      (test (op no-more-exps?) (reg unev))\n      (branch (label ev-sequence-end))\n      (assign exp (op first-exp) (reg unev))\n      (save unev)\n      (save env)\n      (assign continue (label ev-sequence-continue))\n      (goto (label eval-dispatch))\n    ev-sequence-continue\n      (restore env)\n      (restore unev)\n      (assign unev (op rest-exps) (reg unev))\n      (goto (label ev-sequence))\n    ev-sequence-end\n      (restore continue)\n      (goto (reg continue))\n\n    ; Conditionals\n\n    ev-if\n      (save exp)\n      (save env)\n      (save continue)\n      (assign continue (label ev-if-decide))\n      (assign exp (op if-predicate) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-decide\n      (restore continue)\n      (restore env)\n      (restore exp)\n      (test (op true?) (reg val))\n      (branch (label ev-if-consequent))\n    ev-if-alternative\n      (assign exp (op if-alternative) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-consequent\n      (assign exp (op if-consequent) (reg exp))\n      (goto (label eval-dispatch))\n\n    ; Assignments and definitions\n\n    ev-assignment\n      (assign unev (op assignment-variable) (reg exp))\n      (save unev)\n      (assign exp (op assignment-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-assignment-1))\n      (goto (label eval-dispatch))\n    ev-assignment-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op set-variable-value!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n\n    ev-definition\n      (assign unev (op definition-variable) (reg exp))\n      (save unev)\n      (assign exp (op definition-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-definition-1))\n      (goto (label eval-dispatch))\n    ev-definition-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op define-variable!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n    unknown-procedure-type\n    unknown-expression-type\n    done))\n\n(define iterative-code\n  '(define (factorial-iterative n)\n     (define (iter product counter)\n       (if (> counter n)\n         product\n         (iter (* counter product)\n               (+ counter 1))))\n     (iter 1 1)))\n\n(define recursive-code\n  '(define (factorial-recursive n)\n     (if (= n 1)\n       1\n       (* (factorial-recursive (- n 1)) n))))\n\n(define machine (make-explicit-machine ec-no-tail `((no-more-exps? ,null?))))\n\n(set-register-contents! machine 'env the-global-environment)\n\n(set-register-contents! machine 'exp iterative-code)\n(start machine)\n\n(set-register-contents! machine 'exp recursive-code)\n(start machine)\n\n(define (print-stats-for function name)\n  (printf \"~a:\\n\" name)\n  (for ([n (in-range 1 10)])\n    (printf \"  ~a! takes ~a\\n\" n (stack-stats-for machine (list function n)))))\n\n(print-stats-for 'factorial-iterative \"Iterative factorial\")\n(print-stats-for 'factorial-recursive \"Recursive factorial\")\n"
  },
  {
    "path": "scheme/sicp/05/29.scm",
    "content": "; SICP exercise 5.29\n;\n; Monitor the stack operations in the tree-recursive Fibonacci computation:\n;\n; (define (fib n)\n;   (if (< n 2)\n;       n\n;       (+ (fib (- n 1)) (fib (- n 2)))))\n;\n; a. Give a formula in terms of n for the maximum depth of the stack required\n; to compute Fib(n) for n ≥ 2. Hint: In section 1.2.2 we argued that the space\n; used by this process grows linearly with n.\n;\n; b. Give a formula for the total number of pushes used to compute Fib(n) for\n; n ≥ 2. You should find that the number of pushes (which correlates well with\n; the time used) grows exponentially with n. Hint: Let S(n) be the number of\n; pushes used in computing Fib(n). You should be able to argue that there is a\n; formulate that expresses S(n) in terms of S(n - 1), S(n - 2), and some fixed\n; \"overhead\" constant k that is independent of n. Give the formula, and say\n; what k is. Then show that S(n) can be expressed as a.Fib(n + 1) + b and give\n; the values of a and b.\n\n; The results are:\n;\n; fib(0) takes (total-pushes = 16 maximum-depth = 8)\n; fib(1) takes (total-pushes = 16 maximum-depth = 8)\n; fib(2) takes (total-pushes = 72 maximum-depth = 13)\n; fib(3) takes (total-pushes = 128 maximum-depth = 18)\n; fib(4) takes (total-pushes = 240 maximum-depth = 23)\n; fib(5) takes (total-pushes = 408 maximum-depth = 28)\n; fib(6) takes (total-pushes = 688 maximum-depth = 33)\n; fib(7) takes (total-pushes = 1136 maximum-depth = 38)\n; fib(8) takes (total-pushes = 1864 maximum-depth = 43)\n; fib(9) takes (total-pushes = 3040 maximum-depth = 48)\n;\n; a. The maximum stack depth for any n is\n;\n;   5n + 3\n;\n; b. The number of pushes is\n;\n;   S(n) = S(n - 1) + S(n - 2) + 40\n;\n; or\n;\n;   S(n) = 56.Fib(n + 1) - 40\n\n(load-relative \"tests/helpers/evaluator.scm\")\n(load-relative \"tests/helpers/monitored-stack.scm\")\n\n(define code\n  '(define (fib n)\n     (if (< n 2)\n       n\n       (+ (fib (- n 1)) (fib (- n 2))))))\n\n(define machine (make-explicit-control-machine))\n\n(set-register-contents! machine 'env the-global-environment)\n\n(set-register-contents! machine 'exp code)\n(start machine)\n\n(for ([n (in-range 0 10)])\n  (printf \"fib(~a) takes ~a\\n\" n (stack-stats-for machine (list 'fib n))))\n"
  },
  {
    "path": "scheme/sicp/05/30.scm",
    "content": "; SICP exercise 5.30\n;\n; Our evaluator currently catches and signals only two kind of errors --\n; unknown expression types and unknown procedure types. Other errors will take\n; us out of the evaluator read-eval-print-loop. When we run the evaluator\n; using the register machine simulator, these errors are caught by the\n; underlying Scheme system. It is a large project to make a real error system\n; work, but it is well worth the effort to understand what is involved here.\n;\n; a. Errors that occur in the evaluation process, such as an attempt to access\n; an unbound variable, could be caught by changing the lookup operation to\n; make it return a distinguished condition code, which cannot be a possible\n; value of any user variable. The evaluator can test for this condition code\n; and then do what is necessary to signal error. Find all the places in the\n; evaluator where such a change is necessary and fix them. This is lots of\n; work.\n;\n; b. Much worse is the problem of handling errors that are signaled by\n; applying primitive procedures, such as an attempt to divide by zero or an\n; attempt to extract the car of a symbol. In a professionally written\n; high-quality system, each primitive application is checked for safety as\n; part of the primitive. For example, every call to car could first check that\n; the argument is a pair. If the argument is not a pair, the application would\n; return a distinguished condition code to the evaluator, which would then\n; report the failure. We could arrange for this in our register-machine\n; simulator by making each primitive procedure check of applicability and\n; returning an appropriate distinguished condition code on failure. Then the\n; primitive-apply code in the evaluator can check for the condition code and\n; go to signal-error in necessary. Build this structure and make it work. This\n; is a major project.\n\n; You know, I'm going to do both on the same pass.\n;\n; I am going to change things a bit. First, since I don't want to test in the\n; REPL, I will have the machine return the error code itself in val when an\n; error has occured. Second, I'm going to ignore unrolling the stack -- this\n; topic is not covered in the book anyway.\n;\n; Also, I'm only going to implement the examples given. I could implement a\n; few other errors (bad function call arity, setting an undefined variable,\n; redefining a variable, etc.), but I don't think I need to.\n;\n; That way, it actually isn't that much work.\n\n; Error codes\n\n(define (error-code code debug) (vector 'error code debug))\n(define (error-code? obj) (and (vector? obj) (eq? (vector-ref obj 0) 'error)))\n(define (error-code-sym code) (vector-ref code 1))\n(define (error-code-debug code) (vector-ref code 2))\n\n; The new operations required\n\n(define (lookup-variable-value-e var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (mcar vals))\n            (else (scan (cdr vars) (mcdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error-code 'unbound-variable var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n\n; New versions of the primitive procedures\n\n(define (car-e lst)\n  (cond ((null? lst) (error-code 'car-on-null '()))\n        ((not (pair? lst)) (error-code 'car-on-non-pair lst))\n        (else (car lst))))\n\n(define (/-e a b)\n  (if (zero? b)\n      (error-code 'zero-division-error a)\n      (/ a b)))\n\n(define primitive-procedures\n  (list (list 'car car-e)\n        (list '/ /-e)\n        (list '+ +)))\n\n; Additional operations\n\n(define extra-operations\n  (list (list 'lookup-variable-value-e lookup-variable-value-e)\n        (list 'error-code? error-code?)\n        (list 'error-code-sym error-code-sym)))\n\n; The controller text\n\n(define ec-error-support\n  '(\n      (assign continue (label done))\n    eval-dispatch\n      (test (op self-evaluating?) (reg exp))\n      (branch (label ev-self-eval))\n      (test (op variable?) (reg exp))\n      (branch (label ev-variable))\n      (test (op quoted?) (reg exp))\n      (branch (label ev-quoted))\n      (test (op assignment?) (reg exp))\n      (branch (label ev-assignment))\n      (test (op definition?) (reg exp))\n      (branch (label ev-definition))\n      (test (op if?) (reg exp))\n      (branch (label ev-if))\n      (test (op lambda?) (reg exp))\n      (branch (label ev-lambda))\n      (test (op begin?) (reg exp))\n      (branch (label ev-begin))\n      (test (op application?) (reg exp))\n      (branch (label ev-application))\n      (goto (label unknown-expression-type))\n\n    ; Evaluating simple expressions\n\n    ev-self-eval\n      (assign val (reg exp))\n      (goto (reg continue))\n    ev-variable\n      (assign val (op lookup-variable-value-e) (reg exp) (reg env))\n      (test (op error-code?) (reg val))\n      (branch (label undefined-variable))\n      (goto (reg continue))\n    ev-quoted\n      (assign val (op text-of-quotation) (reg exp))\n      (goto (reg continue))\n    ev-lambda\n      (assign unev (op lambda-parameters) (reg exp))\n      (assign exp (op lambda-body) (reg exp))\n      (assign val (op make-procedure) (reg unev) (reg exp) (reg env))\n      (goto (reg continue))\n\n    ; Evaluating procedure applications\n\n    ev-application\n      (save continue)\n      (save env)\n      (assign unev (op operands) (reg exp))\n      (save unev)\n      (assign exp (op operator) (reg exp))\n      (assign continue (label ev-appl-did-operator))\n      (goto (label eval-dispatch))\n    ev-appl-did-operator\n      (restore unev)\n      (restore env)\n      (assign argl (op empty-arglist))\n      (assign proc (reg val))\n      (test (op no-operands?) (reg unev))\n      (branch (label apply-dispatch))\n      (save proc)\n    ev-appl-operand-loop\n      (save argl)\n      (assign exp (op first-operand) (reg unev))\n      (test (op last-operand?) (reg unev))\n      (branch (label ev-appl-last-arg))\n      (save env)\n      (save unev)\n      (assign continue (label ev-appl-accumulate-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accumulate-arg\n      (restore unev)\n      (restore env)\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (assign unev (op rest-operands) (reg unev))\n      (goto (label ev-appl-operand-loop))\n    ev-appl-last-arg\n      (assign continue (label ev-appl-accum-last-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accum-last-arg\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (restore proc)\n      (goto (label apply-dispatch))\n\n    ; Procedure application\n\n    apply-dispatch\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-apply))\n      (test (op compound-procedure?) (reg proc))\n      (branch (label compound-apply))\n      (goto (label unknown-procedure-type))\n    primitive-apply\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n      (test (op error-code?) (reg val))\n      (branch (label primitive-apply-error))\n      (restore continue)\n      (goto (reg continue))\n    compound-apply\n      (assign unev (op procedure-parameters) (reg proc))\n      (assign env (op procedure-environment) (reg proc))\n      (assign env (op extend-environment) (reg unev) (reg argl) (reg env))\n      (assign unev (op procedure-body) (reg proc))\n      (goto (label ev-sequence))\n\n    ; Sequence evaluation\n\n    ev-begin\n      (assign unev (op begin-actions) (reg exp))\n      (save continue)\n      (goto (label ev-sequence))\n    ev-sequence\n      (assign exp (op first-exp) (reg unev))\n      (test (op last-exp?) (reg unev))\n      (branch (label ev-sequence-last-exp))\n      (save unev)\n      (save env)\n      (assign continue (label ev-sequence-continue))\n      (goto (label eval-dispatch))\n    ev-sequence-continue\n      (restore env)\n      (restore unev)\n      (assign unev (op rest-exps) (reg unev))\n      (goto (label ev-sequence))\n    ev-sequence-last-exp\n      (restore continue)\n      (goto (label eval-dispatch))\n\n    ; Conditionals\n\n    ev-if\n      (save exp)\n      (save env)\n      (save continue)\n      (assign continue (label ev-if-decide))\n      (assign exp (op if-predicate) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-decide\n      (restore continue)\n      (restore env)\n      (restore exp)\n      (test (op true?) (reg val))\n      (branch (label ev-if-consequent))\n    ev-if-alternative\n      (assign exp (op if-alternative) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-consequent\n      (assign exp (op if-consequent) (reg exp))\n      (goto (label eval-dispatch))\n\n    ; Assignments and definitions\n\n    ev-assignment\n      (assign unev (op assignment-variable) (reg exp))\n      (save unev)\n      (assign exp (op assignment-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-assignment-1))\n      (goto (label eval-dispatch))\n    ev-assignment-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op set-variable-value!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n\n    ev-definition\n      (assign unev (op definition-variable) (reg exp))\n      (save unev)\n      (assign exp (op definition-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-definition-1))\n      (goto (label eval-dispatch))\n    ev-definition-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op define-variable!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n    undefined-variable\n      (assign val (op error-code-sym) (reg val))\n      (goto (label done))\n    primitive-apply-error\n      (assign val (op error-code-sym) (reg val))\n      (goto (label done))\n\n    unknown-procedure-type\n    unknown-expression-type\n    done))\n"
  },
  {
    "path": "scheme/sicp/05/31.scm",
    "content": "; SICP exercise 5.31\n;\n; In evaluating a procedure application, the explicit-control evaluator always\n; saves and restores the env register around the evaluation of the operator,\n; saves and restores env around the evaluation of each operand (except the\n; final one), saves and restores argl around the evalutaion of each operand,\n; and saves and restores proc around the evaluation of the operand sequence.\n; For each of the following combinations, say which of these save and restore\n; operations are superfluous and thus could be eliminated by the compiler's\n; preserving mechanism.\n;\n; (f 'x 'y)\n;\n; ((f) 'x 'y)\n;\n; (f (g 'x) y)\n;\n; (f (g 'x) 'y)\n\n; (f 'x 'y)\n;\n; There is no need to save and restore anything.\n;\n; ((f) 'x 'y)\n;\n; Again, there is no need to save/restore anything. Once the operator is\n; evaluated, all the operands are fine, since they don't depend on the\n; environment.\n;\n; (f (g 'x) y)\n;\n; * proc needs to be saved and restored around the evaluation of the first\n;   operand\n; * env needs to be saved and restored around the evaluation of the first\n;   operand, if operands are evaluated left to right. Otherwise, if they are\n;   evaluated right to left (as in the compiler), there is no need to save\n;   env.\n; * argl needs to be saved\n; * All other are superfluous\n;\n; (f (g 'x) 'y)\n;\n; * proc needs to be saved and restored around the evaluation of the first\n;   operand\n; * argl needs to be saved\n; * All other are superflous\n"
  },
  {
    "path": "scheme/sicp/05/32.scm",
    "content": "; SICP exercise 5.32\n;\n; Using the preserving mechanism, the compiler will avoid saving and restoring\n; env around the evaluation of the operator of a combination in the case where\n; the operator is a symbol. We could also build such optimizations into the\n; evalutor. Indeed, the explicit-control evaluator of section 5.4 already\n; performs a similar optimization, by treating combinations with no operands\n; as a special case.\n;\n; a. Extend the explicit control evaluator to recognize as a separate class of\n; expressions combinations whose operator is a symbol, and to take advantage\n; of this fact in evaluating such expressions.\n;\n; b. Alyssa P. Hacker suggests that by extending the evaluator to recognize\n; more and mroe special cases we could incorporate all the compiler's\n; optimizations, and this would eliminate the advantage of compilation\n; altogether. What do you think of this idea?\n\n; a. The code is below.\n;\n; b. I don't think Alyssa is right. The compiler would still can perform\n; optimizations that the interpreter can't. For example the interpreter still\n; needs to look at the expressions and determine how to dispatch. The compiler\n; already does that, making those tests superfluous\n\n(define (simple-application? exp)\n  (and (pair? exp)\n       (symbol? (car exp))))\n\n(define extra-operations\n  (list (list 'simple-application? simple-application?)\n        ))\n\n(define ec-core-optimized\n  '(\n      (assign continue (label done))\n    eval-dispatch\n      (test (op self-evaluating?) (reg exp))\n      (branch (label ev-self-eval))\n      (test (op variable?) (reg exp))\n      (branch (label ev-variable))\n      (test (op quoted?) (reg exp))\n      (branch (label ev-quoted))\n      (test (op assignment?) (reg exp))\n      (branch (label ev-assignment))\n      (test (op definition?) (reg exp))\n      (branch (label ev-definition))\n      (test (op if?) (reg exp))\n      (branch (label ev-if))\n      (test (op lambda?) (reg exp))\n      (branch (label ev-lambda))\n      (test (op begin?) (reg exp))\n      (branch (label ev-begin))\n      (test (op simple-application?) (reg exp))\n      (branch (label ev-simple-application))\n      (test (op application?) (reg exp))\n      (branch (label ev-application))\n      (goto (label unknown-expression-type))\n\n    ; Evaluating simple expressions\n\n    ev-self-eval\n      (assign val (reg exp))\n      (goto (reg continue))\n    ev-variable\n      (assign val (op lookup-variable-value) (reg exp) (reg env))\n      (goto (reg continue))\n    ev-quoted\n      (assign val (op text-of-quotation) (reg exp))\n      (goto (reg continue))\n    ev-lambda\n      (assign unev (op lambda-parameters) (reg exp))\n      (assign exp (op lambda-body) (reg exp))\n      (assign val (op make-procedure) (reg unev) (reg exp) (reg env))\n      (goto (reg continue))\n\n    ; Evaluating simple applications (operator is a symbol)\n\n    ev-simple-application\n      (save continue)\n      (assign unev (op operands) (reg exp))\n      (assign proc (op operator) (reg exp))\n      (assign proc (op lookup-variable-value) (reg proc) (reg env))\n      (assign argl (op empty-arglist))\n      (test (op no-operands?) (reg unev))\n      (branch (label apply-dispatch))\n      (save proc)\n      (goto (label ev-appl-operand-loop))\n\n    ; Evaluating procedure applications\n\n    ev-application\n      (save continue)\n      (save env)\n      (assign unev (op operands) (reg exp))\n      (save unev)\n      (assign exp (op operator) (reg exp))\n      (assign continue (label ev-appl-did-operator))\n      (goto (label eval-dispatch))\n    ev-appl-did-operator\n      (restore unev)\n      (restore env)\n      (assign argl (op empty-arglist))\n      (assign proc (reg val))\n      (test (op no-operands?) (reg unev))\n      (branch (label apply-dispatch))\n      (save proc)\n    ev-appl-operand-loop\n      (save argl)\n      (assign exp (op first-operand) (reg unev))\n      (test (op last-operand?) (reg unev))\n      (branch (label ev-appl-last-arg))\n      (save env)\n      (save unev)\n      (assign continue (label ev-appl-accumulate-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accumulate-arg\n      (restore unev)\n      (restore env)\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (assign unev (op rest-operands) (reg unev))\n      (goto (label ev-appl-operand-loop))\n    ev-appl-last-arg\n      (assign continue (label ev-appl-accum-last-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accum-last-arg\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (restore proc)\n      (goto (label apply-dispatch))\n\n    ; Procedure application\n\n    apply-dispatch\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-apply))\n      (test (op compound-procedure?) (reg proc))\n      (branch (label compound-apply))\n      (goto (label unknown-procedure-type))\n    primitive-apply\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n      (restore continue)\n      (goto (reg continue))\n    compound-apply\n      (assign unev (op procedure-parameters) (reg proc))\n      (assign env (op procedure-environment) (reg proc))\n      (assign env (op extend-environment) (reg unev) (reg argl) (reg env))\n      (assign unev (op procedure-body) (reg proc))\n      (goto (label ev-sequence))\n\n    ; Sequence evaluation\n\n    ev-begin\n      (assign unev (op begin-actions) (reg exp))\n      (save continue)\n      (goto (label ev-sequence))\n    ev-sequence\n      (assign exp (op first-exp) (reg unev))\n      (test (op last-exp?) (reg unev))\n      (branch (label ev-sequence-last-exp))\n      (save unev)\n      (save env)\n      (assign continue (label ev-sequence-continue))\n      (goto (label eval-dispatch))\n    ev-sequence-continue\n      (restore env)\n      (restore unev)\n      (assign unev (op rest-exps) (reg unev))\n      (goto (label ev-sequence))\n    ev-sequence-last-exp\n      (restore continue)\n      (goto (label eval-dispatch))\n\n    ; Conditionals\n\n    ev-if\n      (save exp)\n      (save env)\n      (save continue)\n      (assign continue (label ev-if-decide))\n      (assign exp (op if-predicate) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-decide\n      (restore continue)\n      (restore env)\n      (restore exp)\n      (test (op true?) (reg val))\n      (branch (label ev-if-consequent))\n    ev-if-alternative\n      (assign exp (op if-alternative) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-consequent\n      (assign exp (op if-consequent) (reg exp))\n      (goto (label eval-dispatch))\n\n    ; Assignments and definitions\n\n    ev-assignment\n      (assign unev (op assignment-variable) (reg exp))\n      (save unev)\n      (assign exp (op assignment-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-assignment-1))\n      (goto (label eval-dispatch))\n    ev-assignment-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op set-variable-value!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n\n    ev-definition\n      (assign unev (op definition-variable) (reg exp))\n      (save unev)\n      (assign exp (op definition-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-definition-1))\n      (goto (label eval-dispatch))\n    ev-definition-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op define-variable!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n    unknown-expression-type\n    unknown-procedure-type\n    done))\n"
  },
  {
    "path": "scheme/sicp/05/33.scm",
    "content": "; SICP exercise 5.33\n;\n; Consider the following definition of a factorial procedure, which is\n; slightly different frmo the one given above:\n;\n; (define (factorial-alt n)\n;   (if (= n 1)\n;       1\n;       (* n (factorial-alt (- n 1)))))\n;\n; Compile this procedure and compare the resulting code with that produced for\n; factorial. Explain the differences you find. Does either program execute\n; more efficiently?\n\n; This is the diff:\n;\n; 33c33,35\n; <   (save env)\n; ---\n; >   (assign val (op lookup-variable-value) (const n) (reg env))\n; >   (assign argl (op list) (reg val))\n; >   (save argl)\n; 61,63c63\n; <   (assign argl (op list) (reg val))\n; <   (restore env)\n; <   (assign val (op lookup-variable-value) (const n) (reg env))\n; ---\n; >   (restore argl)\n;\n; The new version of factorial needs to save and restore env (in order to\n; evaluate n after the recursive call), while the original needs to save and\n; restore argl (in order to put in it the value of the recursive call). Apart\n; from that, the instructions are pretty much the same. There is no difference\n; in efficiency.\n\n(load-relative \"showcase/compiler/helpers.scm\")\n\n(define factorial-alt-code\n  '(define (factorial-alt n)\n     (if (= n 1)\n       1\n       (* n (factorial-alt (- n 1))))))\n\n(pretty-print (compiled-instructions factorial-alt-code))\n"
  },
  {
    "path": "scheme/sicp/05/34.scm",
    "content": "; SICP exercise 5.34\n;\n; Compile the iterative factorial procedure\n;\n; (define (factorial n)\n;   (define (iter product counter)\n;     (if (> counter n)\n;         product\n;         (iter (* counter product)\n;               (+ counter 1))))\n;   (iter 1))\n;\n; Annotate the resulting code, showing the essential difference between the\n; code for iterative and recursive versions of factorial that makes one\n; process build up stack space and the other run in constant stack space.\n\n(define compiled-factorial-iter\n  '(\n      (assign val (op make-compiled-procedure) (label entry1) (reg env))\n      (goto (label after-lambda2))\n    entry1\n      ; (define (factorial n) ...\n      (assign env (op compiled-procedure-env) (reg proc))\n      (assign env (op extend-environment) (const (n)) (reg argl) (reg env))\n      (assign val (op make-compiled-procedure) (label entry3) (reg env))\n      (goto (label after-lambda4))\n    entry3\n      ; (define (iter product counter)\n      (assign env (op compiled-procedure-env) (reg proc))\n      (assign env (op extend-environment) (const (product counter)) (reg argl) (reg env))\n      (save continue)\n      (save env)\n      ; (> counter n)\n      (assign proc (op lookup-variable-value) (const >) (reg env))\n      (assign val (op lookup-variable-value) (const n) (reg env))\n      (assign argl (op list) (reg val))\n      (assign val (op lookup-variable-value) (const counter) (reg env))\n      (assign argl (op cons) (reg val) (reg argl))\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-branch8))\n    compiled-branch9\n      (assign continue (label after-call10))\n      (assign val (op compiled-procedure-entry) (reg proc))\n      (goto (reg val))\n    primitive-branch8\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n    after-call10\n      (restore env)\n      (restore continue)\n      ; (if ...\n      (test (op false?) (reg val))\n      (branch (label false-branch6))\n    true-branch5\n      ; The base case. Here we return product\n      (assign val (op lookup-variable-value) (const product) (reg env))\n      (goto (reg continue))\n    false-branch6\n      (assign proc (op lookup-variable-value) (const iter) (reg env))\n      (save continue)\n      (save proc)\n      (save env)\n      ; (+ counter 1)\n      (assign proc (op lookup-variable-value) (const +) (reg env))\n      (assign val (const 1))\n      (assign argl (op list) (reg val))\n      (assign val (op lookup-variable-value) (const counter) (reg env))\n      (assign argl (op cons) (reg val) (reg argl))\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-branch14))\n    compiled-branch15\n      (assign continue (label after-call16))\n      (assign val (op compiled-procedure-entry) (reg proc))\n      (goto (reg val))\n    primitive-branch14\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n    after-call16\n      (assign argl (op list) (reg val))\n      (restore env)\n      (save argl)\n      ; (* counter product)\n      (assign proc (op lookup-variable-value) (const *) (reg env))\n      (assign val (op lookup-variable-value) (const product) (reg env))\n      (assign argl (op list) (reg val))\n      (assign val (op lookup-variable-value) (const counter) (reg env))\n      (assign argl (op cons) (reg val) (reg argl))\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-branch11))\n    compiled-branch12\n      (assign continue (label after-call13))\n      (assign val (op compiled-procedure-entry) (reg proc))\n      (goto (reg val))\n    primitive-branch11\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n    after-call13\n      ; Here we actually execute the recursive call to iter. iter is already\n      ; stored in proc\n      (restore argl)\n      (assign argl (op cons) (reg val) (reg argl))\n      (restore proc)\n      (restore continue)\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-branch17))\n    compiled-branch18\n      ; This is the tail recursive part. Nothing is saved, instead the\n      ; computation proceeds with the next first instruction in iter. This\n      ; makes it not use up stack space.\n      (assign val (op compiled-procedure-entry) (reg proc))\n      (goto (reg val))\n    primitive-branch17\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n      (goto (reg continue))\n    after-call19\n    after-if7\n    after-lambda4\n      (perform (op define-variable!) (const iter) (reg val) (reg env))\n      (assign val (const ok))\n      (assign proc (op lookup-variable-value) (const iter) (reg env))\n      (assign val (const 1))\n      (assign argl (op list) (reg val))\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-branch20))\n    compiled-branch21\n      (assign val (op compiled-procedure-entry) (reg proc))\n      (goto (reg val))\n    primitive-branch20\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n      (goto (reg continue))\n    after-call22\n    after-lambda2\n      (perform (op define-variable!) (const factorial) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))))\n\n; Here we generate the compiled version.\n\n(load-relative \"showcase/compiler/helpers.scm\")\n\n(define factorial-iter-code\n  '(define (factorial n)\n     (define (iter product counter)\n       (if (> counter n)\n           product\n           (iter (* counter product)\n                 (+ counter 1))))\n     (iter 1)))\n\n(pretty-print (compiled-instructions factorial-iter-code))\n"
  },
  {
    "path": "scheme/sicp/05/35.scm",
    "content": "; SICP exercise 5.35\n;\n; What expression was compiled to produce the code shown in figure 5.18?\n\n(define figure-5-18\n  '(\n      (assign val (op make-compiled-procedure) (label entry16) (reg env))\n      (goto (label after-lambda15))\n    entry16\n      (assign env (op compiled-procedure-env) (reg proc))\n      (assign env (op extend-environment) (const (x)) (reg argl) (reg env))\n      (assign proc (op lookup-variable-value) (const +) (reg env))\n      (save continue)\n      (save proc)\n      (save env)\n      (assing proc (op lookup-variable-value) (const g) (reg env))\n      (save proc)\n      (assign proc (op lookup-variable-value) (const +) (reg env))\n      (assign val (const 2))\n      (assign argl (op list) (reg val))\n      (assign val (op lookup-variable-value) (const x) (reg env))\n      (assign argl (op cons) (reg val) (reg argl))\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-branch19))\n    compiled-branch18\n      (assign continue (label after-call17))\n      (assign val (op compiled-procedure-entry) (reg proc))\n      (goto (reg val))\n    primitive-branch19\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n    after-call17\n      (assign argl (op list) (reg val))\n      (restore proc)\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-branch22))\n    compiled-branch21\n      (assign continue (label after-call20))\n      (assign val (op compiled-procedure-entry) (reg proc))\n      (goto (reg val))\n    primitive-branch22\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n    after-call20\n      (assign argl (op list) (reg val))\n      (restore env)\n      (assign val (lookup-variable-value (const x) (reg env)))\n      (assign argl (op cons) (reg val) (reg argl))\n      (restore proc)\n      (restore continue)\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-branch25))\n    compiled-branch24\n      (assign val (op compiled-procedure-entry) (reg proc))\n      (goto (reg val))\n    primitive-branch25\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n      (goto (reg continue))\n    after-call23\n    after-lambda15\n      (perform (op define-variable!) (const f) (reg val) (reg env))\n      (assign val (const ok))))\n\n(define expression-to-be-compiled\n  '(define (f x)\n     (+ x (g (+ x 2)))))\n"
  },
  {
    "path": "scheme/sicp/05/36.scm",
    "content": "; SICP exercise 5.36\n;\n; What order of evaluation does our compiler produce for operands of a\n; combination? Is it left-to-right, right-to-left, or some other order? Where\n; in the compiler is this order determined? Modify the compiler so that it\n; produces some other order of evaluation. (See the discussion of order of\n; evaluation for the explicit-control evaluator in section 5.4.1). How does\n; changing the order of operand evaluation affect the efficiency of the code\n; that constructs the argument list?\n\n; The compiler evaluates right-to-left. We can modify it by not reversing in\n; construct-arglist and reverse argl instead, once we've accumulated all the\n; arguments in it. This is less efficient, since we're doing the reverse\n; run-time instead of compile-time.\n\n(define extra-operations\n  (list (list 'reverse reverse)))\n\n(define (construct-arglist operand-codes)\n  (let ((operand-codes operand-codes))\n    (if (null? operand-codes)\n        (make-instruction-sequence '() '(argl)\n                                   '((assign argl (const ()))))\n        (let ((code-to-get-last-arg\n               (append-instruction-sequences\n                (car operand-codes)\n                (make-instruction-sequence '(val) '(argl)\n                 '((assign argl (op list) (reg val)))))))\n          (if (null? (cdr operand-codes))\n              code-to-get-last-arg\n              (preserving '(env)\n                          code-to-get-last-arg\n                          (append-instruction-sequences\n                            (code-to-get-rest-args (cdr operand-codes))\n                            (make-instruction-sequence '(argl) '()\n                             '((assign argl (op reverse) (reg argl)))))))))))\n"
  },
  {
    "path": "scheme/sicp/05/37.scm",
    "content": "; SICP exercise 5.37\n;\n; One way to understand the compiler's preserving mechanism for optimizing\n; stack usage is to see what extra operations would be generated if we did not\n; use this idea. Modify preserving so that it always generates the save and\n; restore operations. Compile some simple expressions and identify the\n; unnecessary stack operations that are generated. Compare the code to that\n; generated with the preserving mechanism intact.\n\n; For the simple expression\n\n(define simple-if '(if true 1 0))\n\n; There are 10 additional saves and restores:\n\n(define annotated-unoptimized-code\n  '(\n      (save continue)         ; extra\n      (save env)              ; extra\n      (save continue)         ; extra\n      (assign val (op lookup-variable-value) (const true) (reg env))\n      (restore continue)      ; extra\n      (restore env)           ; extra\n      (restore continue)      ; extra\n      (test (op false?) (reg val))\n      (branch (label false-branch5))\n    true-branch4\n      (save continue)         ; extra\n      (assign val (const 1))\n      (restore continue)      ; extra\n      (goto (reg continue))\n    false-branch5\n      (save continue)         ; extra\n      (assign val (const 0))\n      (restore continue)      ; extra\n      (goto (reg continue))\n    after-if6))\n\n; In the original code there are no saves and restores. Here is how to\n; generate it:\n\n(load-relative \"showcase/compiler/helpers.scm\")\n\n(define with-optimization (compiled-instructions simple-if))\n\n(define (preserving regs seq1 seq2)\n  (if (null? regs)\n      (append-instruction-sequences seq1 seq2)\n      (let ((first-reg (car regs)))\n        (preserving (cdr regs)\n         (make-instruction-sequence\n          (list-union (list first-reg) (registers-needed seq1))\n          (list-difference (registers-modified seq1) (list first-reg))\n          (append `((save ,first-reg))\n                  (statements seq1)\n                  `((restore ,first-reg))))\n         seq2))))\n\n(define without-optimization (compiled-instructions simple-if))\n\n(printf \"With optimization:\\n\")\n(pretty-print with-optimization)\n(printf \"\\n\\nWithout optimization:\\n\")\n(pretty-print without-optimization)\n"
  },
  {
    "path": "scheme/sicp/05/38.scm",
    "content": "; SICP exercise 5.38\n;\n; Our compiler is clever about avoiding unnecessary stack operations, but it\n; is not clever at all when it comes to compiling calls to the primitive\n; procedures of the language in terms of the primitive operations supplied by\n; the machine. For example, consider how much code is compiled to compute\n; (+ a 1): The code sets up an argument list in argl, puts the primitive\n; addition procedure (which it finds by lookup up the symbol + in the\n; environment) into proc, and tests whether the procedure is primitive or\n; compound. The compiler always generates code to perform the test, as well as\n; code for primitive and compound branches (only one of which will be\n; executed). We have not shown the part of the controller that implements\n; primitives, but we presume that these instructions make use of primitive\n; arithmetic operations in the machine's data path. Consider how much less\n; code would be generated if the compiler could open-code primitives -- that\n; is, if it could generate code to directly use these primitive machine\n; operations. The expression (+ a 1) might be compiled into something as\n; simple as\n;\n; (assign val (op lookup-variable-value) (const a) (reg env))\n; (assign val (op +) (reg val) (const 1))\n;\n; In this exercise, we will extend our compiler to support open coding of\n; selected primitives. Special-purpose code will be generated fo calls to\n; these primitive procedures instead of the general proedure-application code.\n; In order to support this, we will augment our machine with special argument\n; registers arg1 and arg2. The primitive arithmetic operations of the machine\n; will take their inputs from arg1 and arg2. The results may be put into val,\n; arg1, or arg2.\n;\n; The compiler must be able to recognize the application of an open-coded\n; primitive in the source program. We will augment the dispatch in the compile\n; procedure to recognize the names of these primitives in addition to the\n; reserved words (the special forms) it currently recognizes. For each special\n; form our compiler has a code generator. In this exercise we will construct a\n; family of code generators for the open-coded primitives.\n;\n; a. The open-coded primitives, unlike the special forms, all need their\n; operands evaluated. Write a code generator spread-arguments for use by all\n; the open-coding code generators. spread-arguments should take an operand\n; list and compile the given operands targeted to successive argument\n; registers. Note that an operand may contain a call to an open-coded\n; primitive, so argument registers will have to be preserved during operand\n; evaluation.\n;\n; b. For each of the primitive procedures =, *, -, and +, write a code\n; generator that takes a combination with that operator, together with a\n; target and a linkage descriptor, and produces code to spread the arguments\n; into the registers and then performs the operation targeted to the given\n; target with the given linkage. You need only handle expressions with two\n; operands. Make compile dispatch to these code generators.\n;\n; c. Try your new compiler on the factorial example. Compare the resulting\n; code with the result produced without open coding.\n;\n; d. Extend your code generators for + and * so that they can handle\n; expressions with arbitrary numbers of operands. An expression with more\n; than two operands will have to be compiled into a sequence of operations,\n; each with only two inputs.\n\n; I will just ignore the spread-arguments nonsense, since I cannot figure out\n; how to get it working with the results I want.\n;\n; What I want is the expression (+ 1 2 3) to be compiled to:\n;\n;   (assign arg1 (const 1))\n;   (assign arg2 (const 2))\n;   (assign arg1 (op +) (reg arg1) (reg arg2))\n;   (assign arg2 (const 3))\n;   (assign val (op +) (reg arg1) (reg arg2))\n;\n; That is, the first operand gets assign to arg1 and every other gets assigned\n; to arg2 and subsequently added to arg1.\n\n; The compiled factorial is below. The differences are highlighted.\n\n(define compiled-factorial\n  '(  (assign val (op make-compiled-procedure) (label entry1) (reg env))\n      (goto (label after-lambda2))\n    entry1\n      (assign env (op compiled-procedure-env) (reg proc))\n      (assign env (op extend-environment) (const (n)) (reg argl) (reg env))\n\n      ; <changed>\n      ; We don't need to do a call here, which removes a bunch of instructions\n      ; and a save/restore of continue and env\n      (assign arg1 (op lookup-variable-value) (const n) (reg env))\n      (assign arg2 (const 1))\n      (assign val (op =) (reg arg1) (reg arg2))\n      ; </changed>\n\n      (test (op false?) (reg val))\n      (branch (label false-branch4))\n    true-branch3\n      (assign val (const 1))\n      (goto (reg continue))\n    false-branch4\n\n      ; <changed>\n      ; We skip another call, which saves a save/restore of proc and argl and\n      ; another bunch of instruction\n      (save continue)\n      (save env) ; Saving env happens here, instead of when entering the procedure\n      (assign proc (op lookup-variable-value) (const factorial) (reg env))\n      (assign arg1 (op lookup-variable-value) (const n) (reg env))\n      (assign arg2 (const 1))\n      (assign val (op -) (reg arg1) (reg arg2))\n      ; </changed>\n\n      (assign argl (op list) (reg val))\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-branch6))\n    compiled-branch7\n      (assign continue (label proc-return9)) ; Different return label\n      (assign val (op compiled-procedure-entry) (reg proc))\n      (goto (reg val))\n\n    proc-return9\n      ; This is different, since we store result in arg1, not val.\n      (assign arg1 (reg val))\n      (goto (label after-call8))\n\n    primitive-branch6\n      (assign arg1 (op apply-primitive-procedure) (reg proc) (reg argl))\n    after-call8\n\n      ; <changed>\n      ; We save another call, including a save/restore of argl.\n      (restore env)\n      (restore continue)\n      (assign arg2 (op lookup-variable-value) (const n) (reg env))\n      (assign val (op *) (reg arg1) (reg arg2))\n      ; </changed>\n\n      (goto (reg continue))\n    after-if5\n    after-lambda2\n      (perform (op define-variable!) (const factorial) (reg val) (reg env))\n      (assign val (const ok))))\n\n; I need to modify compile-exp to check if an operation should be open-coded.\n\n(define (compile-exp exp target linkage)\n  (cond ((self-evaluating? exp)\n         (compile-self-evaluating exp target linkage))\n        ((quoted? exp) (compile-quoted exp target linkage))\n        ((variable? exp)\n         (compile-variable exp target linkage))\n        ((assignment? exp)\n         (compile-assignment exp target linkage))\n        ((definition? exp)\n         (compile-definition exp target linkage))\n        ((if? exp) (compile-if exp target linkage))\n        ((lambda? exp) (compile-lambda exp target linkage))\n        ((begin? exp)\n         (compile-sequence (begin-actions exp) target linkage))\n        ((cond? exp) (compile-exp (cond->if exp) target linkage))\n        ((open-coded? exp) (compile-open-coded exp target linkage))\n        ((application? exp)\n         (compile-application exp target linkage))\n        (else\n         (error \"Unknown expression type -- COMPILE\" exp))))\n\n; I need to add arg1 and arg2 to all-regs, so they will be preserved when\n; there is a function call.\n\n(define all-regs (append '(arg1 arg2) all-regs))\n\n; Methods to check open coding\n\n(define (open-coded? exp)\n  (and (pair? exp)\n       (memq (car exp) '(+ * - =))))\n\n(define (vararg-open-coded-exp? exp)\n  (and (pair? exp)\n       (memq (car exp) '(+ *))))\n\n; The real work\n\n(define (compile-open-coded exp target linkage)\n  (when (and (not (vararg-open-coded-exp? exp))\n           (not (= (length exp) 3)))\n        (error \"Expression should be binary\" exp))\n  (let ((code (car exp))\n        (first-operand (cadr exp))\n        (rest-operands (cddr exp)))\n    (preserving '(env continue)\n      (compile-exp first-operand 'arg1 'next)\n      (compile-open-coded-rest-args code rest-operands target linkage))))\n\n(define (compile-open-coded-rest-args code operands target linkage)\n  (if (null? (cdr operands))\n      (preserving '(arg1 continue)\n        (compile-exp (car operands) 'arg2 'next)\n        (end-with-linkage linkage\n          (make-instruction-sequence '(arg1 arg2) (list target)\n            `((assign ,target (op ,code) (reg arg1) (reg arg2))))))\n      (preserving '(env continue)\n        (preserving '(arg1)\n          (compile-exp (car operands) 'arg2 'next)\n          (make-instruction-sequence '(arg1 arg2) '(arg1)\n            `((assign arg1 (op ,code) (reg arg1) (reg arg2)))))\n        (compile-open-coded-rest-args code (cdr operands) target linkage))))\n\n(define factorial-code\n  '(define (factorial n)\n     (if (= n 1)\n         1\n         (* (factorial (- n 1)) n))))\n\n;(pretty-print (statements (compile-exp factorial-code 'val 'next)))\n"
  },
  {
    "path": "scheme/sicp/05/39.scm",
    "content": "; SICP exercise 5.39\n;\n; Write a procedure lexical-address-lookup that implements the new lookup\n; operation. It should take two arguments -- a lexical address and a run-time\n; environment -- and return the value of the variable stored at the specified\n; lexical address. lexical-address-lookup should signal an error if the value\n; of the variable is the symbol *unassigned*. Also, write a procedure\n; lexical-address-set! that implements the operation that changes the value of\n; the variable at a specified lexical address.\n\n(define (lexical-address-lookup address env)\n  (define (env-ref offset env)\n    (if (= offset 0)\n        (frame-values (first-frame env))\n        (env-ref (- offset 1) (enclosing-environment env))))\n\n  (define (frame-ref offset vals)\n    (if (= offset 0)\n        (mcar vals)\n        (frame-ref (- offset 1) (mcdr vals))))\n\n  (let ((result (frame-ref (cadr address)\n                           (env-ref (car address) env))))\n    (if (eq? result '*unassigned*)\n        (error \"Unassigned variable\" address)\n        result)))\n\n\n(define (lexical-address-set! address val env)\n  (define (env-ref offset env)\n    (if (= offset 0)\n        (frame-values (first-frame env))\n        (env-ref (- offset 1) (enclosing-environment env))))\n\n  (define (frame-set! offset vals)\n    (if (= offset 0)\n        (set-mcar! vals val)\n        (frame-set! (- offset 1) (mcdr vals))))\n\n  (frame-set! (cadr address)\n              (env-ref (car address) env)))\n"
  },
  {
    "path": "scheme/sicp/05/40.scm",
    "content": "; SICP exercise 5.40\n;\n; Modify the compiler to maintain the compile-time environment as described\n; above. That is, add a compile-time-environment argument to compile and the\n; various code-generators, and extend it in compile-lambda-body\n\n(load-relative \"39.scm\")\n\n; Construction of the compile-time environment\n\n(define (empty-compile-time-env) '())\n(define (extend-compile-time-environment formals env) (cons formals env))\n\n; The modifications of the compiler\n\n(define (compile-exp exp target linkage env)\n  (cond ((self-evaluating? exp)\n         (compile-self-evaluating exp target linkage))\n        ((quoted? exp) (compile-quoted exp target linkage))\n        ((variable? exp)\n         (compile-variable exp target linkage env))\n        ((assignment? exp)\n         (compile-assignment exp target linkage env))\n        ((definition? exp)\n         (compile-definition exp target linkage env))\n        ((if? exp) (compile-if exp target linkage env))\n        ((lambda? exp) (compile-lambda exp target linkage env))\n        ((begin? exp)\n         (compile-sequence (begin-actions exp) target linkage env))\n        ((cond? exp) (compile-exp (cond->if exp) target linkage env))\n        ((application? exp)\n         (compile-application exp target linkage env))\n        (else\n         (error \"Unknown expression type -- COMPILE\" exp))))\n\n(define (compile-variable exp target linkage env)\n  (end-with-linkage linkage\n   (make-instruction-sequence '(env) (list target)\n    `((assign ,target (op lookup-variable-value) (const ,exp) (reg env))))))\n\n(define (compile-assignment exp target linkage env)\n  (let ((var (assignment-variable exp))\n        (get-value-code (compile-exp (assignment-value exp) 'val 'next env)))\n    (end-with-linkage linkage\n     (preserving '(env)\n      get-value-code\n      (make-instruction-sequence '(env val) (list target)\n       `((perform (op set-variable-value!)\n                  (const ,var)\n                  (reg val)\n                  (reg env))\n         (assign ,target (const ok))))))))\n\n(define (compile-definition exp target linkage env)\n  (let ((var (definition-variable exp))\n        (get-value-code (compile-exp (definition-value exp) 'val 'next env)))\n    (end-with-linkage linkage\n     (preserving '(env)\n      get-value-code\n      (make-instruction-sequence '(env val) (list target)\n       `((perform (op define-variable!)\n                  (const ,var)\n                  (reg val)\n                  (reg env))\n         (assign ,target (const ok))))))))\n\n(define (compile-if exp target linkage env)\n  (let ((t-branch (make-label 'true-branch))\n        (f-branch (make-label 'false-branch))\n        (after-if (make-label 'after-if)))\n    (let ((consequent-linkage (if (eq? linkage 'next) after-if linkage)))\n      (let ((p-code (compile-exp (if-predicate exp) 'val 'next env))\n            (c-code (compile-exp (if-consequent exp) target consequent-linkage env))\n            (a-code (compile-exp (if-alternative exp) target linkage env)))\n        (preserving '(env continue)\n         p-code\n         (append-instruction-sequences\n          (make-instruction-sequence '(val) '()\n           `((test (op false?) (reg val))\n             (branch (label ,f-branch))))\n          (parallel-instruction-sequences\n           (append-instruction-sequences t-branch c-code)\n           (append-instruction-sequences f-branch a-code))\n          after-if))))))\n\n(define (compile-sequence seq target linkage env)\n  (if (last-exp? seq)\n      (compile-exp (first-exp seq) target linkage env)\n      (preserving '(env continue)\n       (compile-exp (first-exp seq) target 'next env)\n       (compile-sequence (rest-exps seq) target linkage env))))\n\n(define (compile-lambda exp target linkage env)\n  (let ((proc-entry (make-label 'entry))\n        (after-lambda (make-label 'after-lambda)))\n    (let ((lambda-linkage (if (eq? linkage 'next) after-lambda linkage)))\n      (append-instruction-sequences\n       (tack-on-instruction-sequence\n        (end-with-linkage lambda-linkage\n         (make-instruction-sequence '(env) (list target)\n          `((assign ,target\n                    (op make-compiled-procedure)\n                    (label ,proc-entry)\n                    (reg env)))))\n        (compile-lambda-body exp proc-entry env))\n       after-lambda))))\n\n(define (compile-lambda-body exp proc-entry env)\n  (let ((formals (lambda-parameters exp)))\n    (append-instruction-sequences\n     (make-instruction-sequence '(env proc argl) '(env)\n      `(,proc-entry\n         (assign env (op compiled-procedure-env) (reg proc))\n         (assign env\n                 (op extend-environment)\n                 (const ,formals)\n                 (reg argl)\n                 (reg env))))\n     (compile-sequence (lambda-body exp)\n                       'val\n                       'return\n                       (extend-compile-time-environment formals env)))))\n\n(define (compile-application exp target linkage env)\n  (let ((proc-code (compile-exp (operator exp) 'proc 'next env))\n        (operand-codes (map (lambda (operand) (compile-exp operand 'val 'next env))\n                            (operands exp))))\n    (preserving '(env continue)\n     proc-code\n     (preserving '(proc continue)\n      (construct-arglist operand-codes)\n      (compile-procedure-call target linkage env)))))\n\n(define (compile-procedure-call target linkage env)\n  (let ((primitive-branch (make-label 'primitive-branch))\n        (compiled-branch (make-label 'compiled-branch))\n        (after-call (make-label 'after-call)))\n    (let ((compiled-linkage (if (eq? linkage 'next) after-call linkage)))\n      (append-instruction-sequences\n       (make-instruction-sequence '(proc) '()\n        `((test (op primitive-procedure?) (reg proc))\n          (branch (label ,primitive-branch))))\n       (parallel-instruction-sequences\n        (append-instruction-sequences\n         compiled-branch\n         (compile-proc-appl target compiled-linkage env))\n        (append-instruction-sequences\n         primitive-branch\n         (end-with-linkage linkage\n          (make-instruction-sequence '(proc argl) (list target)\n           `((assign ,target\n                     (op apply-primitive-procedure)\n                     (reg proc)\n                     (reg argl)))))))\n       after-call))))\n\n(define (compile-proc-appl target linkage env)\n  (cond ((and (eq? target 'val) (not (eq? linkage 'return)))\n         (make-instruction-sequence '(proc) all-regs\n          `((assign continue (label ,linkage))\n            (assign val (op compiled-procedure-entry) (reg proc))\n            (goto (reg val)))))\n        ((and (not (eq? target 'val)) (not (eq? linkage 'return)))\n         (let ((proc-return (make-label 'proc-return)))\n           (make-instruction-sequence '(proc) all-regs\n            `((assign continue (label ,proc-return))\n              (assign val (op compiled-procedure-entry) (reg proc))\n              (goto (reg val))\n              ,proc-return\n              (assign ,target (reg val))\n              (goto (label ,linkage))))))\n        ((and (eq? target 'val) (eq? linkage 'return))\n         (make-instruction-sequence '(proc continue) all-regs\n          `((assign val (op compiled-procedure-entry) (reg proc))\n            (goto (reg val)))))\n        ((and (not (eq? target 'val)) (eq? linkage 'return))\n         (error \"return linkage, target not val -- COMPILE-EXP\" target))\n        (else (error \"How did we get here?\"))))\n\n; Some of the helpers, needed in subsequent exercises\n\n(define extra-operations\n  (list (list 'lexical-address-lookup lexical-address-lookup)\n        (list 'lexical-address-set! lexical-address-set!)\n        (list 'the-global-environment get-global-environment)))\n\n(define extra-registers '())\n\n(define (make-explicit+compile-machine)\n  (make-machine (append ec-registers extra-registers)\n                (append cm-operations extra-operations)\n                explicit+compile-text))\n\n(define (compile-in-machine machine expression)\n  (let ((instructions (assemble (statements (compile-exp expression\n                                                         'val\n                                                         'return\n                                                         (empty-compile-time-env)))\n                                machine)))\n    (set-register-contents! machine 'env the-global-environment)\n    (set-register-contents! machine 'val instructions)\n    (set-register-contents! machine 'flag true)\n\n    (start machine)))\n\n(define (compiled-instructions expression)\n  (statements (compile-exp expression 'val 'return (empty-compile-time-env))))\n"
  },
  {
    "path": "scheme/sicp/05/41.scm",
    "content": "; SICP exercise 5.41\n;\n; Write a procedure find-variable that takes as arguments a variable and a\n; compile-time environment and returns the lexical address of the variable\n; with respect to that environment. For example, in the program fragment shown\n; above, the compile-time environment during the compilation of expression\n; <e1> is ((y z) (a b c d e) (x y)). find-variable should produce\n;\n; (find-variable 'c '((y z) (a b c d e) (x y)))\n; (1 2)\n;\n; (find-variable 'x '((y z) (a b c d e) (x y)))\n; (2 0)\n;\n; (find-variable 'w '((y z) (a b c d e) (x y)))\n; not-found\n\n(define (find-variable var env)\n  (define (loop frame position vars env)\n    (cond ((and (null? vars) (null? (cdr env))) 'not-found)\n          ((null? vars) (loop (+ frame 1) 0 (cadr env) (cdr env)))\n          ((eq? (car vars) var) (list frame position))\n          (else (loop frame (+ position 1) (cdr vars) env))))\n  (if (null? env)\n      'not-found\n      (loop 0 0 (car env) env)))\n"
  },
  {
    "path": "scheme/sicp/05/42.scm",
    "content": "; SICP exercise 5.42\n;\n; Using find-variable from exercise 5.41, rewrite compile-variable and\n; compile-assignment to output lexical address instructions. In cases where\n; find-variable returns not-found (that is, where the variable is not in the\n; compile-time environment), you should have the code generators use the\n; evaluator operations, as before, to search for the binding. (The only place\n; a variable that is not found at compile time can be is the global\n; environment, which is part of the run-time environment but is not part of\n; the compile-time environment. Thus, if you wish, you may have the evaluator\n; operations look directly in the global environment, which can be obtained\n; with the operation (op get-global-environment), instead of having them\n; search the whole run-time environment found in env.) Test the modified\n; compiler of a few simple cases, such as the nested lambda combination at the\n; beginning of this section.\n\n(load-relative \"40.scm\")\n(load-relative \"41.scm\")\n\n(define (compile-variable exp target linkage env)\n  (let ((address (find-variable exp env)))\n    (if (eq? address 'not-found)\n        (end-with-linkage linkage\n         (make-instruction-sequence '(env) (list target 'env)\n          `((assign env (op the-global-environment))\n            (assign ,target (op lookup-variable-value) (const ,exp) (reg env)))))\n        (end-with-linkage linkage\n         (make-instruction-sequence '(env) (list target)\n          `((assign ,target (op lexical-address-lookup) (const ,address) (reg env))))))))\n\n(define (compile-assignment exp target linkage env)\n  (let ((var (assignment-variable exp))\n        (get-value-code (compile-exp (assignment-value exp) 'val 'next env)))\n    (let ((address (find-variable var env)))\n      (if (eq? address 'not-found)\n          (end-with-linkage linkage\n           (preserving '(env)\n            get-value-code\n            (make-instruction-sequence '(env val) (list target 'env)\n             `((assign env (op the-global-environment))\n               (perform (op set-variable-value!) (const ,var) (reg val) (reg env))\n               (assign ,target (const ok))))))\n          (end-with-linkage linkage\n           (preserving '(env)\n            get-value-code\n            (make-instruction-sequence '(env val) (list target)\n             `((perform (op lexical-address-set!) (const ,address) (reg val) (reg env))\n               (assign ,target (const ok))))))))))\n"
  },
  {
    "path": "scheme/sicp/05/43.scm",
    "content": "; SICP exercise 5.43\n;\n; We argued in section 4.1.6 that internal definitions for block structure\n; should not be considered \"real\" defines. Rather, a procedure body should be\n; interpreted as if the internal variables being defined were installed as\n; ordinary lambda variables initialized to their correct values using set!.\n; Section 4.1.6 and exercise 4.16 showed how to modify the metacircular\n; interpreter to accomplish this by scanning out internal definitions. Modify\n; the compiler to perform the same transformations before it compiles a\n; procedure body.\n\n(load-relative \"42.scm\")\n\n; First, here is the support for let.\n\n(define (let? exp) (tagged-list? exp 'let))\n\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n; Second, here is scan-out-defines.\n\n(define (scan-out-defines body)\n  (define (definitions-in body)\n    (cond ((null? body)\n           '())\n          ((definition? (car body))\n           (cons (car body) (definitions-in (cdr body))))\n          (else\n           (definitions-in (cdr body)))))\n  (define (body-without-definitions body)\n    (cond ((null? body)\n           '())\n          ((definition? (car body))\n           (body-without-definitions (cdr body)))\n          (else\n           (cons (car body) (body-without-definitions (cdr body))))))\n  (define (definition->unassigned-pair definition)\n    (list (definition-variable definition) ''*unassigned*))\n  (define (definition->set! definition)\n    (list 'set! (definition-variable definition) (definition-value definition)))\n  (define (defines->let definitions body)\n    (list\n      (cons 'let\n            (cons (map definition->unassigned-pair definitions)\n                  (append (map definition->set! definitions) body)))))\n\n  (let ((internal-definitions (definitions-in body)))\n    (if (null? internal-definitions)\n        body\n        (defines->let internal-definitions (body-without-definitions body)))))\n\n; This time we hook it to lambda-body\n\n(define (lambda-body exp) (scan-out-defines (cddr exp)))\n\n; We also need to modify compile in order to pick up lets\n\n(define (compile-exp exp target linkage env)\n  (cond ((self-evaluating? exp)\n         (compile-self-evaluating exp target linkage))\n        ((quoted? exp) (compile-quoted exp target linkage))\n        ((variable? exp)\n         (compile-variable exp target linkage env))\n        ((assignment? exp)\n         (compile-assignment exp target linkage env))\n        ((definition? exp)\n         (compile-definition exp target linkage env))\n        ((if? exp) (compile-if exp target linkage env))\n        ((lambda? exp) (compile-lambda exp target linkage env))\n        ((let? exp) (compile-exp (let->combination exp) target linkage env))\n        ((begin? exp)\n         (compile-sequence (begin-actions exp) target linkage env))\n        ((cond? exp) (compile-exp (cond->if exp) target linkage env))\n        ((application? exp)\n         (compile-application exp target linkage env))\n        (else\n         (error \"Unknown expression type -- COMPILE\" exp))))\n"
  },
  {
    "path": "scheme/sicp/05/44.scm",
    "content": "; SICP exercise 5.44\n;\n; In this section we have focused on the use of the compile-time environment\n; to produce lexical addresses. But there are other uses for compile-time\n; environments. For instance, in exercise 5.38 we increased the efficiency of\n; compiled code by open-coding primitive procedures. Our implementation\n; treated the names of open-coded procedures as reserved words. If a program\n; were to rebind such a name, the mechanism described in exercise 5.38 would\n; still open-code it as a primitive, ignoring the new binding. For example,\n; consider the procedure\n;\n; (lambda (+ * a b x y)\n;   (+ (* a x) (* b y)))\n;\n; which computes a linear combination of x and y. We might call it with\n; arguments +matrix, *matrix, and four matrices, but the open-coded compiler\n; would still open-code the + and the * in (+ (* a x) (* b y)) as primitive +\n; and *. Modify the open-coding compiler to consult the compile-time\n; environment in order to compile the correct code for expressions involving\n; the names of primitive procedures. (The code will work correctly as long as\n; the program does not define or set! these names.)\n\n(load-relative \"43.scm\")\n\n; We just lift the code from 4.38 and modify it:\n\n(define extra-registers '(arg1 arg2))\n(define extra-operations (append extra-operations `((+ ,+) (- ,-) (* ,*) (= ,=))))\n(define all-regs (append '(arg1 arg2) all-regs))\n\n(define (open-coded? exp env)\n  (and (pair? exp)\n       (memq (car exp) '(+ * - =))\n       (eq? (find-variable (car exp) env) 'not-found)))\n\n(define (vararg-open-coded-exp? exp)\n  (and (pair? exp)\n       (memq (car exp) '(+ *))))\n\n(define (compile-open-coded exp target linkage env)\n  (when (and (not (vararg-open-coded-exp? exp))\n           (not (= (length exp) 3)))\n        (error \"Expression should be binary\" exp))\n  (let ((code (car exp))\n        (first-operand (cadr exp))\n        (rest-operands (cddr exp)))\n    (preserving '(env continue)\n      (compile-exp first-operand 'arg1 'next env)\n      (compile-open-coded-rest-args code rest-operands target linkage env))))\n\n(define (compile-open-coded-rest-args code operands target linkage env)\n  (if (null? (cdr operands))\n      (preserving '(arg1 continue)\n        (compile-exp (car operands) 'arg2 'next env)\n        (end-with-linkage linkage\n          (make-instruction-sequence '(arg1 arg2) (list target)\n            `((assign ,target (op ,code) (reg arg1) (reg arg2))))))\n      (preserving '(env continue)\n        (preserving '(arg1)\n          (compile-exp (car operands) 'arg2 'next env)\n          (make-instruction-sequence '(arg1 arg2) '(arg1)\n            `((assign arg1 (op ,code) (reg arg1) (reg arg2)))))\n        (compile-open-coded-rest-args code (cdr operands) target linkage env))))\n\n; We also need to modify compile from 4.43\n\n(define (compile-exp exp target linkage env)\n  (cond ((self-evaluating? exp)\n         (compile-self-evaluating exp target linkage))\n        ((quoted? exp) (compile-quoted exp target linkage))\n        ((variable? exp)\n         (compile-variable exp target linkage env))\n        ((assignment? exp)\n         (compile-assignment exp target linkage env))\n        ((definition? exp)\n         (compile-definition exp target linkage env))\n        ((if? exp) (compile-if exp target linkage env))\n        ((lambda? exp) (compile-lambda exp target linkage env))\n        ((let? exp) (compile-exp (let->combination exp) target linkage env))\n        ((begin? exp)\n         (compile-sequence (begin-actions exp) target linkage env))\n        ((cond? exp) (compile-exp (cond->if exp) target linkage env))\n        ((open-coded? exp env) (compile-open-coded exp target linkage env))\n        ((application? exp)\n         (compile-application exp target linkage env))\n        (else\n         (error \"Unknown expression type -- COMPILE\" exp))))\n"
  },
  {
    "path": "scheme/sicp/05/45.scm",
    "content": "; SICP exercise 5.45\n;\n; By comparing the stack operations used by compiled code to the stack\n; operations used by the evaluator for the same computation, we can determine\n; the extent to which the compiler optimizes use of the stack, both in speed\n; (reducing the total number of stack operations) and in space (reducing the\n; maximum stack depth). Comparing this optimized stack use to performance of a\n; special-purpose machine for the same computation gives some indication of\n; the quality of the compiler.\n;\n; a. Exercise 5.27 asked you to determine, as a function of n, the number of\n; pushes and the number of maximum stack depth needed by the evaluator to\n; compute n! using the recursive factorial procedure given above. Exercise\n; 5.14 asked you to do the same measurements for the special-purpose factorial\n; machine shown in figure 5.11. Now perform the same analysis using the\n; compiled factorial procedure.\n;\n; Take the ratio of the number of pushes in the compiled version to the number\n; of pushes in the interpreted version, and do the same for the maximum stack\n; depth. Since the number of operations and the stack depth used to compute n!\n; are linear in n, these ratios should approach constants as n becomes large.\n; What are these constants? Similarly, find the ratios of the stack usage in a\n; special-purpose machine to the usage in the interpreted version.\n;\n; Compare the ratios for the special-purpose versus interpreted code to the\n; ratios for compiled versus interpreted code. You should find that the\n; special-purpose machine does much better than the compiled code, since the\n; hand-tailored controller code should be much better than what is produced by\n; our rudimentary general-purpose compiler.\n;\n; b. Can you suggest improvements to the compiler that would help it generate\n; code that would come closer in performance to the hand-tailored version?\n\n; a. Let's compare both the open-coding compiler and the simpler one.\n;\n; Without open-coding optimizations:\n;   1! takes (total-pushes = 7 maximum-depth = 3)\n;   2! takes (total-pushes = 13 maximum-depth = 5)\n;   3! takes (total-pushes = 19 maximum-depth = 8)\n;   4! takes (total-pushes = 25 maximum-depth = 11)\n;   5! takes (total-pushes = 31 maximum-depth = 14)\n;   6! takes (total-pushes = 37 maximum-depth = 17)\n;   7! takes (total-pushes = 43 maximum-depth = 20)\n;   8! takes (total-pushes = 49 maximum-depth = 23)\n;   9! takes (total-pushes = 55 maximum-depth = 26)\n; With open-coding optimizations:\n;   1! takes (total-pushes = 5 maximum-depth = 3)\n;   2! takes (total-pushes = 7 maximum-depth = 3)\n;   3! takes (total-pushes = 9 maximum-depth = 4)\n;   4! takes (total-pushes = 11 maximum-depth = 6)\n;   5! takes (total-pushes = 13 maximum-depth = 8)\n;   6! takes (total-pushes = 15 maximum-depth = 10)\n;   7! takes (total-pushes = 17 maximum-depth = 12)\n;   8! takes (total-pushes = 19 maximum-depth = 14)\n;   9! takes (total-pushes = 21 maximum-depth = 16)\n;\n; As usual, code to reproduce is below.\n;\n; Now we can do a table\n; +----+-----------------------+-----------------------+\n; |    |      total-pushes     |     maximum-depth     |\n; |    +-----+-----+-----+-----+-----+-----+-----+-----+\n; |    | int | cmp | opc | sht | int | cmp | opc | sht |\n; +----+-----+-----+-----+-----+-----+-----+-----+-----+\n; | 1! |  16 |   7 |   5 |   0 |   8 |   3 |   3 |   0 |\n; | 2! |  48 |  13 |   7 |   2 |  13 |   5 |   3 |   2 |\n; | 3! |  80 |  19 |   9 |   4 |  18 |   8 |   4 |   4 |\n; | 4! | 112 |  25 |  11 |   6 |  23 |  11 |   6 |   6 |\n; | 5! | 144 |  31 |  13 |   8 |  28 |  14 |   8 |   8 |\n; | 6! | 176 |  37 |  15 |  10 |  33 |  17 |  10 |  10 |\n; | 7! | 208 |  43 |  17 |  12 |  38 |  20 |  12 |  12 |\n; | 8! | 240 |  49 |  19 |  14 |  43 |  23 |  14 |  14 |\n; | 9! | 272 |  55 |  21 |  16 |  48 |  26 |  16 |  16 |\n; +----+-----+-----+-----+-----+-----+-----+-----+-----+\n; Legend: * int - interpreted\n;         * cmp - compiled with the 5.5 compiler\n;         * opc - compiled with open-coding primitives\n;         * sht - special hand-tailored version\n;\n; We can compare ratios by comparing the ratio of the differences between\n; computing n! and (n + 1)!\n;\n; total pushes:\n;  int / cmp is 32 / 6 ≈ 5.333\n;  int / opc is 32 / 2 = 16.0\n;  cmp / sht is  6 / 2 = 3.0\n;  opc / sht is  2 / 2 = 1.0\n;\n; That is, the compiled code is 5.3 times faster than the interpreted (16\n; times if open-coding instructions) and the hand-tailored version is 3 times\n; faster than the copmiled (or as fast with the hand-tailored version).\n;\n; maximum-depth\n;   int / cmp is 5 / 3 ≈ 1.666\n;   int / opc is 5 / 2 = 2.5\n;   cmp / sht is 3 / 2 = 1.5\n;   opc / sht is 2 / 2 = 1.0\n;\n; That is, the compiled code uses 1.66 less space than the interpreted (2.5\n; times less if open-coding instructions) and the hand-tailored version uses\n; 1.5 less space than the compiled (or as much if open-coding instructions).\n;\n; Note that we're speaking asymptotically and we're ignoring the number of\n; performed instructions as opposed to checking stack pushes.\n;\n; b. Open-coding comes pretty near. Of course, this assumes that the\n; instruction count does not matter. There are two thinks we can do to get\n; even closer.\n;\n; First, we can do away with storing variables in environments and just use\n; the registers. That way we will eliminate environment lookup for n and\n; factorial.\n;\n; Second, we can replace the check if factorial is a primitive procedure with\n; a jump to the beginning of the function.\n;\n; Those two along with open-coding will come to pretty much the same code as\n; the hand-tailored version.\n\n(load-relative \"showcase/compiler/helpers.scm\")\n(load-relative \"tests/helpers/monitored-stack.scm\")\n\n(define code\n  '(define (factorial n)\n     (if (= n 1)\n       1\n       (* (factorial (- n 1)) n))))\n\n(define (report-stats)\n  (define machine (make-machine (append '(arg1 arg2) ec-registers)\n                                (append `((+ ,+) (- ,-) (* ,*) (= ,=)) cm-operations)\n                                explicit+compile-text))\n\n  (compile-in-machine machine code)\n\n  (for ([n (in-range 1 10)])\n    (set-register-contents! machine 'flag false)\n    (printf \"  ~a! takes ~a\\n\" n (stack-stats-for machine (list 'factorial n)))))\n\n(printf \"Without open-coding optimizations:\\n\")\n(report-stats)\n\n(load-relative \"38.scm\")\n(printf \"With open-coding optimizations:\\n\")\n(report-stats)\n"
  },
  {
    "path": "scheme/sicp/05/46.scm",
    "content": "; SICP exercise 5.46\n;\n; Carry out an analysis like the one in exercise 5.45 to determine the\n; effectiveness of compiling the tree-recursive Fibonacci procedure\n;\n; (define (fib n)\n;   (if (< n 2)\n;       n\n;       (+ (fib (- n 1)) (fib (- n 2)))))\n;\n; compared to the effectiveness of using the special-purpose Fibonacci machine\n; of figure 5.12. (For measurement of the interpreted performance, see\n; exercise 5.29). For Fibonacci, the time resource used is not linear in n;\n; hence the ratios of stack operations will not approach a limiting value that\n; is independent of n.\n\n; Here are the results in a table (this time generated with Racket):\n;\n; +--------+------------------------+-----------------------+\n; |        |       total-pushes     |     maximum-depth     |\n; |        +------+-----+-----+-----+-----+-----+-----+-----+\n; |        | int  | cmp | opc | sh  | int | cmp | opc | sht |\n; +--------+------+-----+-----+-----+-----+-----+-----+-----+\n; | fib(1) |   16 |   7 |   7 |   0 |   8 |   3 |   3 |   0 |\n; | fib(2) |   72 |  17 |  15 |   3 |  13 |   5 |   4 |   2 |\n; | fib(3) |  128 |  27 |  23 |   6 |  18 |   8 |   6 |   4 |\n; | fib(4) |  240 |  47 |  39 |  12 |  23 |  11 |   8 |   6 |\n; | fib(5) |  408 |  77 |  63 |  21 |  28 |  14 |  10 |   8 |\n; | fib(6) |  688 | 127 | 103 |  36 |  33 |  17 |  12 |  10 |\n; | fib(7) | 1136 | 207 | 167 |  60 |  38 |  20 |  14 |  12 |\n; | fib(8) | 1864 | 337 | 271 |  99 |  43 |  23 |  16 |  14 |\n; | fib(9) | 3040 | 547 | 439 | 162 |  48 |  26 |  18 |  16 |\n; +--------+------+-----+-----+-----+-----+-----+-----+-----+\n; Legend: * int - interpreted\n;         * cmp - compiled with the 5.5 compiler\n;         * opc - compiled with open-coding primitives\n;         * sht - special hand-tailored version\n;\n; If we stare at the total pushes for a while, we figure out that:\n; - int grows with 56 * fib(n) on each iteration\n; - cmp grows with 10 * fib(n) on each iteration\n; - opc grows with  8 * fib(n) on each iteration\n; - sht grows with  3 * fib(n) on each iteration\n;\n; As for the maximum-depth:\n; - int takes 5n + 3\n; - cmp takes 3n - 1 (except for 1 and 2)\n; - opc takes 2n     (except for 1 and 2)\n; - sht takes 2n - 2\n;\n; It is worth noting that this time opc is around 2.66 slower than sht (in\n; comparison to the previous exercise) because the exponential growth of the\n; function makes those extra saves and restores really count.\n\n(require (prefix-in srfi: srfi/48))\n(load-relative \"showcase/compiler/helpers.scm\")\n(load-relative \"tests/helpers/monitored-stack.scm\")\n\n; This is the recursive procedure:\n\n(define code\n  '(define (fib n)\n     (if (< n 2)\n       n\n       (+ (fib (- n 1)) (fib (- n 2))))))\n\n; Let's use the 5.06 version of the Fibonacci machine\n\n(define sht-machine\n  (make-machine\n    '(n val continue)\n    (list (list '< <) (list '- -) (list '+ +))\n    '(\n        (assign continue (label fib-done))\n      fib-loop\n        (test (op <) (reg n) (const 2))\n        (branch (label immediate-answer))\n        (save continue)\n        (assign continue (label after-fib-n-1))\n        (save n)\n        (assign n (op -) (reg n) (const 1))\n        (goto (label fib-loop))\n      after-fib-n-1\n        (restore n)\n        (assign n (op -) (reg n) (const 2))\n        (assign continue (label after-fib-n-2))\n        (save val)\n        (goto (label fib-loop))\n      after-fib-n-2\n        (assign n (reg val))\n        (restore val)\n        (restore continue)\n        (assign val (op +) (reg val) (reg n))\n        (goto (reg continue))\n      immediate-answer\n        (assign val (reg n))\n        (goto (reg continue))\n      fib-done)))\n\n; Code that gathers stats\n\n(define (gather-stats machine name callback)\n  (printf \"~a:\\n\" name)\n  (for/list ([n (in-range 1 10)])\n    (set-register-contents! machine 'flag false)\n    (let ((stats (callback n)))\n      (printf \"  fib(~a) takes ~a\\n\" n stats)\n      (list (third stats) (sixth stats)))))\n\n(define (build-machine)\n  (make-machine (append '(arg1 arg2) ec-registers)\n                (append `((+ ,+) (- ,-) (* ,*) (= ,=)) cm-operations)\n                explicit+compile-text))\n\n; Stats for interpretation\n\n(define int-machine (build-machine))\n(eval-in-machine int-machine code)\n(define int-stats\n  (gather-stats int-machine\n                \"Interpreted code\"\n                (lambda (n) (stack-stats-for int-machine (list 'fib n)))))\n\n; Stats for compilation\n\n(define cmp-machine (build-machine))\n(compile-in-machine cmp-machine code)\n(define cmp-stats\n  (gather-stats cmp-machine\n                \"Compiled code\"\n                (lambda (n) (stack-stats-for cmp-machine (list 'fib n)))))\n\n; Stats for compilation with open-coding primitives\n\n(load-relative \"38.scm\")\n(define opc-machine (build-machine))\n(compile-in-machine opc-machine code)\n(define opc-stats\n  (gather-stats opc-machine\n                \"Compiled code with open-coding\"\n                (lambda (n) (stack-stats-for opc-machine (list 'fib n)))))\n\n; Stats for the special hand-tailored version\n\n(define sht-stats\n  (gather-stats sht-machine\n                \"Special hand-tailored version\"\n                (lambda (n)\n                  (set-register-contents! sht-machine 'n n)\n                  ((sht-machine 'stack) 'initialize)\n                  (start sht-machine)\n                  ((sht-machine 'stack) 'statistics))))\n\n; Printing the results in a nice table\n\n(define (pad n . args)\n  (srfi:format \"~3F\" n))\n\n(newline)\n(printf \"The final results:\\n\")\n(printf \"+--------+------------------------+-----------------------+\\n\")\n(printf \"|        |       total-pushes     |     maximum-depth     |\\n\")\n(printf \"|        +------+-----+-----+-----+-----+-----+-----+-----+\\n\")\n(printf \"|        | int  | cmp | opc | sh  | int | cmp | opc | sht |\\n\")\n(printf \"+--------+------+-----+-----+-----+-----+-----+-----+-----+\\n\")\n(for ([n (in-range 1 10)]\n      [int int-stats]\n      [cmp cmp-stats]\n      [opc opc-stats]\n      [sht sht-stats])\n     (printf \"| fib(~a) | ~a | ~a | ~a | ~a | ~a | ~a | ~a | ~a |\\n\"\n             n\n             (srfi:format \"~4F\" (first int)) (pad (first cmp)) (pad (first opc)) (pad (first sht))\n             (pad (second int)) (pad (second cmp)) (pad (second opc)) (pad (second sht))))\n(printf \"+--------+------+-----+-----+-----+-----+-----+-----+-----+\\n\")\n"
  },
  {
    "path": "scheme/sicp/05/47.scm",
    "content": "; SICP exercise 5.47\n;\n; This section described how to modify the explicit-control evaluator so that\n; interpreted code can call compiled procedures. Show how to modify the\n; compiler so that compiled procedures can call not only primitive procedures\n; and compiled procedures, but interpreted procedures as well. This requires\n; modifying compile-procedure-call to handle the case of compound\n; (interpreted) procedures. Be sure to handle all the same target and linkage\n; combinations as in compile-proc-argl. To do the actual procedure\n; application, the code needs to jump to the evaluator's compound-apply entry\n; point. This label cannot be directly referenced in object code (since the\n; assmebler requires that all labels referenced by the code it is assembling\n; be defined there), so we will add a register called compapp to the evaluator\n; machine to hold this entry point, and add an instruction to initialize it:\n;\n;   (assign compapp (label compound-apply))\n;   (branch (label external-entry))\n; read-eval-print-loop\n;   ...\n;\n; To test your code, start by defining a proceudre f that calls a procedure g.\n; Use compile-and-go to compile the definition of f and start the evaluator.\n; Now, typing at the evalutor, define g and try to call f.\n\n; Yeah, typing in the evalutor. Right.\n\n(define ec-registers (cons 'compapp ec-registers))\n\n(define explicit+compile-text\n  (append '((assign compapp (label compound-apply)))\n          explicit+compile-text))\n\n(define (compile-procedure-call target linkage)\n  (let ((primitive-branch (make-label 'primitive-branch))\n        (compiled-branch (make-label 'compiled-branch))\n        (compound-branch (make-label 'compound-branch))\n        (after-call (make-label 'after-call)))\n    (let ((compiled-linkage (if (eq? linkage 'next) after-call linkage)))\n      (append-instruction-sequences\n       (make-instruction-sequence '(proc) '()\n        `((test (op primitive-procedure?) (reg proc))\n          (branch (label ,primitive-branch))\n          (test (op compound-procedure?) (reg proc))\n          (branch (label ,compound-branch))))\n       (parallel-instruction-sequences\n        (append-instruction-sequences\n         compiled-branch\n         (compile-proc-appl target compiled-linkage))\n        (parallel-instruction-sequences\n          (append-instruction-sequences\n           compound-branch\n           (compile-compound-appl target compiled-linkage))\n          (append-instruction-sequences\n           primitive-branch\n           (end-with-linkage linkage\n            (make-instruction-sequence '(proc argl) (list target)\n             `((assign ,target\n                       (op apply-primitive-procedure)\n                       (reg proc)\n                       (reg argl))))))))\n       after-call))))\n\n(define (compile-compound-appl target linkage)\n  (cond ((and (eq? target 'val) (not (eq? linkage 'return)))\n         (make-instruction-sequence '(proc) all-regs\n          `((assign continue (label ,linkage))\n            (save continue)\n            (goto (reg compapp)))))\n        ((and (not (eq? target 'val)) (not (eq? linkage 'return)))\n         (let ((proc-return (make-label 'proc-return)))\n           (make-instruction-sequence '(proc) all-regs\n            `((assign continue (label ,proc-return))\n              (save continue)\n              (goto (reg compapp))\n              ,proc-return\n              (assign ,target (reg val))\n              (goto (label ,linkage))))))\n        ((and (eq? target 'val) (eq? linkage 'return))\n         (make-instruction-sequence '(proc continue) all-regs\n          `((save continue)\n            (goto (reg compapp)))))\n        ((and (not (eq? target 'val)) (eq? linkage 'return))\n         (error \"return linkage, target not val -- COMPILE-EXP\" target))\n        (else (error \"How did we get here?\"))))\n"
  },
  {
    "path": "scheme/sicp/05/48.scm",
    "content": "; SICP exercise 5.48\n;\n; The compile-and-go interface implemented in this section is awkward, since\n; the compile cna be called only once (when the evaluator machine is started).\n; Augment the compiler-interpreter interface by providing a compile-and-run\n; primitive that can be called form within the explicit-control evaluator as\n; follows:\n;\n; ;;; EC-Eval input;\n; (compile-and-run\n;   '(define (factorial n)\n;      (if (= n 1)\n;          1\n;          (* (factorial (- n 1)) n))))\n; ;;; EC-Eval value:\n; ok\n; ;;; EC-Eval input:\n; (factorial 5)\n; ;;; EC-Eval value:\n; 120\n\n(load-relative \"showcase/compiler/helpers.scm\")\n\n(define (compile-and-run? exp) (tagged-list? exp 'compile-and-run))\n(define (compile-and-run-body exp) (cadadr exp))\n(define (compile-in-machine exp)\n  (assemble (statements (compile-exp exp 'val 'return)) eceval))\n\n(define cm-operations\n  (append cm-operations `((compile-and-run? ,compile-and-run?)\n                          (compile-and-run-body ,compile-and-run-body)\n                          (compile ,compile-in-machine))))\n\n(define explicit+compile-text\n  '(read-eval-print-loop\n      (perform (op initialize-stack))\n      (perform (op prompt-for-input) (const \";;; EC-Eval input:\"))\n      (assign exp (op read))\n      (assign env (op get-global-environment))\n      (assign continue (label print-result))\n      (goto (label eval-dispatch))\n    print-result\n      (perform (op announce-output) (const \";;; EC-Eval value:\"))\n      (perform (op user-print) (reg val))\n      (goto (label read-eval-print-loop))\n    unknown-expression-type\n      (assign val (const unknown-expression-type-error))\n      (goto (label signal-error))\n    unknown-procedure-type\n      (restore continue)\n      (assign val (const unknown-procedure-type-error))\n      (goto (label signal-error))\n    signal-error\n      (perform (op user-print) (reg val))\n      (goto (label read-eval-print-loop))\n\n    eval-dispatch\n      (test (op self-evaluating?) (reg exp))\n      (branch (label ev-self-eval))\n      (test (op variable?) (reg exp))\n      (branch (label ev-variable))\n      (test (op quoted?) (reg exp))\n      (branch (label ev-quoted))\n      (test (op assignment?) (reg exp))\n      (branch (label ev-assignment))\n      (test (op definition?) (reg exp))\n      (branch (label ev-definition))\n      (test (op if?) (reg exp))\n      (branch (label ev-if))\n      (test (op lambda?) (reg exp))\n      (branch (label ev-lambda))\n      (test (op begin?) (reg exp))\n      (branch (label ev-begin))\n      (test (op compile-and-run?) (reg exp))\n      (branch (label ev-compile-and-run))\n      (test (op application?) (reg exp))\n      (branch (label ev-application))\n      (goto (label unknown-expression-type))\n\n    ; Compile and run\n\n    ev-compile-and-run\n      (save continue)\n      (assign exp (op compile-and-run-body) (reg exp))\n      (assign val (op compile) (reg exp))\n      (goto (reg val))\n\n    ; Evaluating simple expressions\n\n    ev-self-eval\n      (assign val (reg exp))\n      (goto (reg continue))\n    ev-variable\n      (assign val (op lookup-variable-value) (reg exp) (reg env))\n      (goto (reg continue))\n    ev-quoted\n      (assign val (op text-of-quotation) (reg exp))\n      (goto (reg continue))\n    ev-lambda\n      (assign unev (op lambda-parameters) (reg exp))\n      (assign exp (op lambda-body) (reg exp))\n      (assign val (op make-procedure) (reg unev) (reg exp) (reg env))\n      (goto (reg continue))\n\n    ; Evaluating procedure applications\n\n    ev-application\n      (save continue)\n      (save env)\n      (assign unev (op operands) (reg exp))\n      (save unev)\n      (assign exp (op operator) (reg exp))\n      (assign continue (label ev-appl-did-operator))\n      (goto (label eval-dispatch))\n    ev-appl-did-operator\n      (restore unev)\n      (restore env)\n      (assign argl (op empty-arglist))\n      (assign proc (reg val))\n      (test (op no-operands?) (reg unev))\n      (branch (label apply-dispatch))\n      (save proc)\n    ev-appl-operand-loop\n      (save argl)\n      (assign exp (op first-operand) (reg unev))\n      (test (op last-operand?) (reg unev))\n      (branch (label ev-appl-last-arg))\n      (save env)\n      (save unev)\n      (assign continue (label ev-appl-accumulate-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accumulate-arg\n      (restore unev)\n      (restore env)\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (assign unev (op rest-operands) (reg unev))\n      (goto (label ev-appl-operand-loop))\n    ev-appl-last-arg\n      (assign continue (label ev-appl-accum-last-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accum-last-arg\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (restore proc)\n      (goto (label apply-dispatch))\n\n    ; Procedure application\n\n    apply-dispatch\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-apply))\n      (test (op compound-procedure?) (reg proc))\n      (branch (label compound-apply))\n      (test (op compiled-procedure?) (reg proc))\n      (branch (label compiled-apply))\n      (goto (label unknown-procedure-type))\n    primitive-apply\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n      (restore continue)\n      (goto (reg continue))\n    compound-apply\n      (assign unev (op procedure-parameters) (reg proc))\n      (assign env (op procedure-environment) (reg proc))\n      (assign env (op extend-environment) (reg unev) (reg argl) (reg env))\n      (assign unev (op procedure-body) (reg proc))\n      (goto (label ev-sequence))\n    compiled-apply\n      (restore continue)\n      (assign val (op compiled-procedure-entry) (reg proc))\n      (goto (reg val))\n\n    ; Sequence evaluation\n\n    ev-begin\n      (assign unev (op begin-actions) (reg exp))\n      (save continue)\n      (goto (label ev-sequence))\n    ev-sequence\n      (assign exp (op first-exp) (reg unev))\n      (test (op last-exp?) (reg unev))\n      (branch (label ev-sequence-last-exp))\n      (save unev)\n      (save env)\n      (assign continue (label ev-sequence-continue))\n      (goto (label eval-dispatch))\n    ev-sequence-continue\n      (restore env)\n      (restore unev)\n      (assign unev (op rest-exps) (reg unev))\n      (goto (label ev-sequence))\n    ev-sequence-last-exp\n      (restore continue)\n      (goto (label eval-dispatch))\n\n    ; Conditionals\n\n    ev-if\n      (save exp)\n      (save env)\n      (save continue)\n      (assign continue (label ev-if-decide))\n      (assign exp (op if-predicate) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-decide\n      (restore continue)\n      (restore env)\n      (restore exp)\n      (test (op true?) (reg val))\n      (branch (label ev-if-consequent))\n    ev-if-alternative\n      (assign exp (op if-alternative) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-consequent\n      (assign exp (op if-consequent) (reg exp))\n      (goto (label eval-dispatch))\n\n    ; Assignments and definitions\n\n    ev-assignment\n      (assign unev (op assignment-variable) (reg exp))\n      (save unev)\n      (assign exp (op assignment-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-assignment-1))\n      (goto (label eval-dispatch))\n    ev-assignment-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op set-variable-value!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n\n    ev-definition\n      (assign unev (op definition-variable) (reg exp))\n      (save unev)\n      (assign exp (op definition-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-definition-1))\n      (goto (label eval-dispatch))\n    ev-definition-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op define-variable!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n\n    ; Error handling\n\n    unknown-expression-type\n      (perform (op error) (const \"Unknown expression type\") (reg exp))\n    unknown-procedure-type\n      (perform (op error) (const \"Unknown procedure type\") (reg proc))\n\n    ; External entries\n\n    external-entry\n      (perform (op initialize-stack))\n      (assign env (op get-global-environment))\n      (assign continue (label done))\n      (goto (reg val))\n\n    done))\n\n(define eceval (make-explicit+compile-machine))\n(set-register-contents! eceval 'env the-global-environment)\n\n(start eceval)\n"
  },
  {
    "path": "scheme/sicp/05/49.scm",
    "content": "; SICP exercise 5.49\n;\n; As an alternative to using the explicit-control evaluator's read-eval-print\n; loop, design a register machine that performs a read-compile-execute-print\n; loop. That is, the machine should run a loop that reads an expression,\n; compiles it, assembles and executes the resulting code, and prints the\n; result. This is easy to run in our simulated setup, wince we can arrange to\n; call the procedures compile and assemble as \"register-machine operations\".\n\n(load-relative \"showcase/compiler/helpers.scm\")\n\n(define (compile-in-machine exp)\n  (assemble (statements (compile-exp exp 'val 'return)) eceval))\n\n(define cm-operations\n  (append cm-operations `((compile ,compile-in-machine))))\n\n(define explicit+compile-text\n  '(read-eval-print-loop\n      (perform (op initialize-stack))\n      (perform (op prompt-for-input) (const \";;; EC-Eval input:\"))\n      (assign exp (op read))\n      (assign env (op get-global-environment))\n      (assign continue (label print-result))\n      (assign val (op compile) (reg exp))\n      (goto (reg val))\n    print-result\n      (perform (op announce-output) (const \";;; EC-Eval value:\"))\n      (perform (op user-print) (reg val))\n      (goto (label read-eval-print-loop))\n    unknown-expression-type\n      (assign val (const unknown-expression-type-error))\n      (goto (label signal-error))\n    unknown-procedure-type\n      (restore continue)\n      (assign val (const unknown-procedure-type-error))\n      (goto (label signal-error))\n    signal-error\n      (perform (op user-print) (reg val))\n      (goto (label read-eval-print-loop))\n    unknown-expression-type\n      (perform (op error) (const \"Unknown expression type\") (reg exp))\n    unknown-procedure-type\n      (perform (op error) (const \"Unknown procedure type\") (reg proc))))\n\n(define eceval (make-explicit+compile-machine))\n(set-register-contents! eceval 'env the-global-environment)\n\n(start eceval)\n"
  },
  {
    "path": "scheme/sicp/05/50.scm",
    "content": "; SICP exercise 5.50\n;\n; Use the compiler to compile the metacircular evaluator of section 4.1 and\n; run this program using the register-machine simulator. (To compile more than\n; one definition at a time, you can package the definitions in a begin.) The\n; resulting interpreter will run very slowly because of the multiple levels of\n; interpretation, but getting all the details to work is an instructive\n; exercise.\n\n; Oh boy. This is going to be so much fun!\n;\n; r5rs makes a return. It is required in the tests. I can probably work it out\n; of this, but it will be too much work.\n;\n; Running the tests of the evaluator results in a whooping amount of 215 524\n; instructions, 8036 pushes and a maximum stack depth of 22. If that is not\n; cool, I don't know what is.\n;\n; Let's start with using the open-coding compiler, just because it's cooler\n; that way.\n\n(load-relative \"tests/helpers/monitored-stack.scm\")\n(load-relative \"38.scm\")\n\n; This is the code of the metacircular evaluator. Note that it has some\n; modifications. They are at the end of the code and are highlighted.\n\n(define metacircular-evaluator\n  '(begin\n     (define (evaluate exp env)\n       (cond ((self-evaluating? exp) exp)\n             ((variable? exp) (lookup-variable-value exp env))\n             ((quoted? exp) (text-of-quotation exp))\n             ((assignment? exp) (eval-assignment exp env))\n             ((definition? exp) (eval-definition exp env))\n             ((if? exp) (eval-if exp env))\n             ((lambda? exp)\n              (make-procedure (lambda-parameters exp)\n                              (lambda-body exp)\n                              env))\n             ((begin? exp)\n              (eval-sequence (begin-actions exp) env))\n             ((cond? exp) (evaluate (cond->if exp) env))\n             ((application? exp)\n              (apply-procedure (evaluate (operator exp) env)\n                               (list-of-values (operands exp) env)))\n             (else\n              (error \"Unknown expression type - EVALUATE\" exp))))\n\n     (define (apply-procedure procedure arguments)\n       (cond ((primitive-procedure? procedure)\n              (apply-primitive-procedure procedure arguments))\n             ((compound-procedure? procedure)\n              (eval-sequence\n                (procedure-body procedure)\n                (extend-environment\n                  (procedure-parameters procedure)\n                  arguments\n                  (procedure-environment procedure))))\n             (else\n              (error \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n     (define (list-of-values exps env)\n       (if (no-operands? exps)\n           '()\n           (cons (evaluate (first-operand exps) env)\n                 (list-of-values (rest-operands exps) env))))\n\n     (define (eval-if exp env)\n       (if (true? (evaluate (if-predicate exp) env))\n           (evaluate (if-consequent exp) env)\n           (evaluate (if-alternative exp) env)))\n\n     (define (eval-sequence exps env)\n       (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n             (else (evaluate (first-exp exps) env)\n                   (eval-sequence (rest-exps exps) env))))\n\n     (define (eval-assignment exp env)\n       (set-variable-value! (assignment-variable exp)\n                            (evaluate (assignment-value exp) env)\n                            env)\n       'ok)\n\n     (define (eval-definition exp env)\n       (define-variable! (definition-variable exp)\n                         (evaluate (definition-value exp) env)\n                         env)\n       'ok)\n\n     (define (self-evaluating? exp)\n       (cond ((number? exp) true)\n             ((string? exp) true)\n             (else false)))\n\n     (define (variable? exp) (symbol? exp))\n\n     (define (quoted? exp)\n       (tagged-list? exp 'quote))\n\n     (define (text-of-quotation exp) (cadr exp))\n\n     (define (tagged-list? exp tag)\n       (if (pair? exp)\n           (eq? (car exp) tag)\n           false))\n\n     (define (assignment? exp) (tagged-list? exp 'set!))\n     (define (assignment-variable exp) (cadr exp))\n     (define (assignment-value exp) (caddr exp))\n\n     (define (definition? exp)\n       (tagged-list? exp 'define))\n     (define (definition-variable exp)\n       (if (symbol? (cadr exp))\n         (cadr exp)\n         (caadr exp)))\n     (define (definition-value exp)\n       (if (symbol? (cadr exp))\n           (caddr exp)\n           (make-lambda (cdadr exp)\n                        (cddr exp))))\n\n     (define (lambda? exp) (tagged-list? exp 'lambda))\n     (define (lambda-parameters exp) (cadr exp))\n     (define (lambda-body exp) (cddr exp))\n     (define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n     (define (if? exp) (tagged-list? exp 'if))\n     (define (if-predicate exp) (cadr exp))\n     (define (if-consequent exp) (caddr exp))\n     (define (if-alternative exp)\n       (if (not (null? (cdddr exp)))\n           (cadddr exp)\n           'false))\n\n     (define (make-if predicate consequent alternative)\n       (list 'if predicate consequent alternative))\n\n     (define (begin? exp) (tagged-list? exp 'begin))\n     (define (begin-actions exp) (cdr exp))\n     (define (last-exp? seq) (null? (cdr seq)))\n     (define (first-exp seq) (car seq))\n     (define (rest-exps seq) (cdr seq))\n     (define (sequence->exp seq)\n       (cond ((null? seq) seq)\n             ((last-exp? seq) (first-exp seq))\n             (else (make-begin seq))))\n     (define (make-begin seq) (cons 'begin seq))\n\n     (define (application? exp) (pair? exp))\n     (define (operator exp) (car exp))\n     (define (operands exp) (cdr exp))\n     (define (no-operands? ops) (null? ops))\n     (define (first-operand ops) (car ops))\n     (define (rest-operands ops) (cdr ops))\n\n     (define (cond? exp) (tagged-list? exp 'cond))\n     (define (cond-clauses exp) (cdr exp))\n     (define (cond-else-clause? clause)\n       (eq? (cond-predicate clause) 'else))\n     (define (cond-predicate clause) (car clause))\n     (define (cond-actions clause) (cdr clause))\n     (define (cond->if exp)\n       (expand-clauses (cond-clauses exp)))\n     (define (expand-clauses clauses)\n       (if (null? clauses)\n           'false\n           (let ((first (car clauses))\n                 (rest (cdr clauses)))\n             (if (cond-else-clause? first)\n                 (if (null? rest)\n                     (sequence->exp (cond-actions first))\n                     (error \"ELSE clause isn't last - COND->IF\" clauses))\n                 (make-if (cond-predicate first)\n                          (sequence->exp (cond-actions first))\n                          (expand-clauses rest))))))\n\n     (define (true? x) (not (eq? x false)))\n     (define (false? x) (eq? x false))\n\n     (define (make-procedure parameters body env)\n       (list 'procedure parameters body env))\n     (define (compound-procedure? p)\n       (tagged-list? p 'procedure))\n     (define (procedure-parameters p) (cadr p))\n     (define (procedure-body p) (caddr p))\n     (define (procedure-environment p) (cadddr p))\n\n     (define (enclosing-environment env) (cdr env))\n     (define (first-frame env) (car env))\n     (define the-empty-environment '())\n\n     (define (make-frame variables values)\n       (cons variables values))\n     (define (frame-variables frame) (car frame))\n     (define (frame-values frame) (cdr frame))\n     (define (add-binding-to-frame! var val frame)\n       (set-car! frame (cons var (car frame)))\n       (set-cdr! frame (cons val (cdr frame))))\n     (define (extend-environment vars vals base-env)\n       (if (= (length vars) (length vals))\n           (cons (make-frame vars vals) base-env)\n           (if (< (length vars) (length vals))\n               (error \"Too many arguments supplied\" vars vals)\n               (error \"Too few arguments supplied\" vars vals))))\n     (define (lookup-variable-value var env)\n       (define (env-loop env)\n         (define (scan vars vals)\n           (cond ((null? vars)\n                  (env-loop (enclosing-environment env)))\n                 ((eq? var (car vars))\n                  (car vals))\n                 (else (scan (cdr vars) (cdr vals)))))\n         (if (eq? env the-empty-environment)\n             (error \"Unbound variable\" var)\n             (let ((frame (first-frame env)))\n               (scan (frame-variables frame)\n                     (frame-values frame)))))\n       (env-loop env))\n     (define (set-variable-value! var val env)\n       (define (env-loop env)\n         (define (scan vars vals)\n           (cond ((null? vars)\n                  (env-loop (enclosing-environment env)))\n                 ((eq? var (car vars))\n                  (set-car! vals val))\n                 (else (scan (cdr vars) (cdr vals)))))\n         (if (eq? env the-empty-environment)\n             (error \"Unbound variable - SET!\" var)\n             (let ((frame (first-frame env)))\n               (scan (frame-variables frame)\n                     (frame-values frame)))))\n       (env-loop env))\n     (define (define-variable! var val env)\n       (let ((frame (first-frame env)))\n         (define (scan vars vals)\n           (cond ((null? vars)\n                  (add-binding-to-frame! var val frame))\n                 ((eq? var (car vars))\n                  (set-car! vals val))\n                 (else (scan (cdr vars) (cdr vals)))))\n         (scan (frame-variables frame)\n               (frame-values frame))))\n\n     (define (primitive-procedure? proc)\n       (tagged-list? proc 'evaluator-primitive))\n     (define (primitive-implementation proc) (cadr proc))\n\n     (define primitive-procedures\n       (list (list 'car car)\n             (list 'cdr cdr)\n             (list 'cons cons)\n             (list 'null? null?)\n             (list 'pair? pair?)\n             (list '= =)\n             (list '+ +)\n             (list '- -)\n             (list '* *)\n             (list '/ /)\n             (list '< <)))\n\n     (define (primitive-procedure-names)\n       (map car primitive-procedures))\n     (define (primitive-procedure-objects)\n       (map (lambda (proc) (list 'evaluator-primitive (cadr proc)))\n            primitive-procedures))\n\n     (define (apply-primitive-procedure proc args)\n       (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n     (define (setup-environment)\n       (let ((initial-env\n               (extend-environment (primitive-procedure-names)\n                                   (primitive-procedure-objects)\n                                   the-empty-environment)))\n         (define-variable! 'true true initial-env)\n         (define-variable! 'false false initial-env)\n         initial-env))\n\n     ; These are the additions. Those procedures are used by the evaluator.\n     ; Instead of adding them as primitives, I have implemented them here for\n     ; additional fun.\n\n     (define (map proc lst)\n       (if (null? lst)\n           '()\n           (cons (proc (car lst))\n                 (map proc (cdr lst)))))\n\n     (define (cadr lst) (car (cdr lst)))\n     (define (cddr lst) (cdr (cdr lst)))\n     (define (caadr lst) (car (car (cdr lst))))\n     (define (caddr lst) (car (cdr (cdr lst))))\n     (define (cdadr lst) (cdr (car (cdr lst))))\n     (define (cdddr lst) (cdr (cdr (cdr lst))))\n     (define (cadddr lst) (car (cdr (cdr (cdr lst)))))\n\n     (define (not x) (if x false true))\n\n     (define (length lst)\n       (if (null? lst)\n           0\n           (+ 1 (length (cdr lst)))))\n\n     (define the-global-environment (setup-environment))))\n\n; The compiler also needs some modifications.\n;\n; First, it needs to understand let expressions.\n\n(define (let? exp) (tagged-list? exp 'let))\n\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n; Here is the modified compile-exp. It just has let\n\n(define (compile-exp exp target linkage)\n  (cond ((self-evaluating? exp)\n         (compile-self-evaluating exp target linkage))\n        ((quoted? exp) (compile-quoted exp target linkage))\n        ((variable? exp)\n         (compile-variable exp target linkage))\n        ((assignment? exp)\n         (compile-assignment exp target linkage))\n        ((definition? exp)\n         (compile-definition exp target linkage))\n        ((if? exp) (compile-if exp target linkage))\n        ((lambda? exp) (compile-lambda exp target linkage))\n        ((let? exp) (compile-exp (let->combination exp) target linkage))\n        ((begin? exp)\n         (compile-sequence (begin-actions exp) target linkage))\n        ((cond? exp) (compile-exp (cond->if exp) target linkage))\n        ((open-coded? exp) (compile-open-coded exp target linkage))\n        ((application? exp)\n         (compile-application exp target linkage))\n        (else\n         (error \"Unknown expression type -- COMPILE\" exp))))\n\n; The compiler requires a bunch of additional primitive procedures.\n\n(define (apply-primitive proc args)\n  (apply (car (cdr proc)) args))\n\n(define extra-primitives\n  `((number? ,number?)\n    (string? ,string?)\n    (symbol? ,symbol?)\n    (< ,<)\n    (error ,error)\n    (eq? ,eq?)\n    (list ,list)\n    (set-car! ,set-car!)\n    (set-cdr! ,set-cdr!)\n    (apply-in-underlying-scheme ,apply-primitive)))\n\n(set! primitive-procedures (append extra-primitives primitive-procedures))\n(set! the-global-environment (setup-environment))\n\n; Since we're using the open-coding compiler, we need some additional\n; operations too:\n\n(define extra-operations `((= ,=) (+ ,+) (- ,-) (* ,*)))\n\n; This is a little trick to count the number of instructions.\n; instruction-execution-proc gets called only when the instruction is about to\n; be executed, the count is genuine.\n\n(define total-instructions 0)\n(define (instruction-execution-proc inst)\n  (set! total-instructions (+ total-instructions 1))\n  (cdr inst))\n\n; This is our machine:\n\n(define machine\n  (make-machine\n    '(arg1 arg2 val env exp continue proc argl unev)\n    (append cm-operations extra-operations)\n    explicit+compile-text))\n\n; Finally, let's compile the evaluator in it.\n\n(compile-in-machine machine metacircular-evaluator)\n"
  },
  {
    "path": "scheme/sicp/05/51.scm",
    "content": "; SICP exercise 5.51\n;\n; Develop a rudimentary implementation of Scheme in C (or some other low-level\n; language of your choice) by translating the explicit-control evaluator of\n; section 5.4 into C. In order to run this code, you will need to also provide\n; appropriate storage-allocation routines and other run-time support.\n\n; That was a journey. It took me three days to implement this fully. More\n; commentary can be found in 05/support/51/evaluator.c, which contains the\n; actual C code to do it.\n;\n; This file provides with some necessary code in order to compile and run the\n; interpreter. Note that it depends on cc --std=c99.\n\n(require racket/runtime-path)\n\n(define-runtime-path base-path \".\")\n\n(define (relative-path path)\n  (find-relative-path\n    (current-directory)\n    (simplify-path (build-path base-path path))))\n\n(define source-path (relative-path \"support/51/evaluator.c\"))\n(define tests-path (relative-path \"support/51/tests.scm\"))\n(define target-path (relative-path \"support/bin/51\"))\n\n(define compile-call\n  (format \"cc --std=c99 ~a -o ~a\"\n          (path->string source-path)\n          (path->string target-path)))\n\n(define run-tests-call\n  (format \"~a ~a\"\n          (path->string target-path)\n          (path->string tests-path)))\n\n(define (compile-interpreter)\n  (let ((exit-code (system/exit-code compile-call)))\n    (when (not (zero? exit-code))\n          (error \"Failed to compile the interpreter ;(\"))))\n\n(define (run-interpreter-tests)\n  (system run-tests-call))\n\n(define (interpreter-test-results)\n  (with-output-to-string run-interpreter-tests))\n"
  },
  {
    "path": "scheme/sicp/05/52.scm",
    "content": "; SICP exercise 5.52\n;\n; As a counterpoint to exercise 5.51, modify the compiler so that it compiles\n; Scheme procedures into sequences of C instructions. Compile the metacircular\n; evaluator of section 4.1 to produce a Scheme written in C.\n\n; This exercise marks and end of a long journey. It uses an approach similar\n; to the previous one. The code used to compile everything is in build.scm.\n; There are modified versions of the metacircular evaluator and the compiler\n; too (but noting noteworthy).\n;\n; Let's bring up some Racket-fu and use pattern matching.\n\n(load-relative \"support/52/metacircular-evaluator.scm\")\n(load-relative \"support/52/compiler.scm\")\n(load-relative \"support/52/syntax.scm\")\n(load-relative \"support/52/build.scm\")\n\n; Some utility string transformation functions.\n\n(define (dash-to-underscore str) (regexp-replace* (regexp \"-\") str \"_\"))\n(define (question-mark-to-p str) (regexp-replace* (regexp \"\\\\?$\") str \"_p\"))\n(define (exclamation-mark-to-bang str) (regexp-replace* (regexp \"!\") str \"_bang\"))\n\n; Translates an instruction to a single line of C.\n\n(define (translate inst)\n  (match inst\n    ; Assign\n    [`(assign ,reg (op ,op) . ,args)\n      (format \"~a = ~a(~a);\" (c-reg reg) (c-func-name op) (c-args args))]\n    [`(assign ,reg ,val)\n      (format \"~a = ~a;\" (c-reg reg) (c-val val))]\n\n    ; Perform\n    [`(perform (op ,op) . ,args)\n      (format \"~a(~a);\" (c-func-name op) (c-args args))]\n\n    ; Save\n    [`(save ,reg)\n      (format \"push(~a);\" (c-reg reg))]\n\n    ; Restore\n    [`(restore ,reg)\n      (format \"~a = pop();\" (c-reg reg))]\n\n    ; Test\n    [`(test (op ,op) . ,args)\n      (format \"test = ~a(~a);\" (c-func-name op) (c-args args))]\n\n    ; Branch\n    [`(branch (label ,label))\n      (format \"if (test) goto ~a;\" (c-label-name label))]\n\n    ; Goto\n    [`(goto (label ,reg))\n      (format \"goto ~a;\" (c-label-name reg))]\n    [`(goto (reg ,reg))\n      (format \"goto *value_to_label(~a);\" (c-reg reg))]\n\n    ; Labels\n    [(app symbol? #t)\n     (format \"~a:\" (c-label-name inst))]\n\n    [else (error \"Unrecognized instruction:\" inst)]))\n\n; A bunch of utility procedures that know how to convert different fragments\n; into the C code required.\n\n(define (c-val val)\n  (match val\n    [`(reg ,reg) (c-reg reg)]\n    [`(const ,const) (c-const const)]\n    [`(label ,label) (format \"label(&&~a)\" (c-label-name label))]\n    [else (error \"Unknown c-val\" val)]))\n\n(define (c-const const)\n  (cond ((symbol? const) (format \"sym(\\\"~a\\\")\" const))\n        ((string? const) (format \"str(~s)\" const))\n        ((number? const) (format \"num(~a)\" const))\n        ((pair? const) (format \"cons(~a, ~a)\" (c-const (car const)) (c-const (cdr const))))\n        ((null? const) (format \"null()\"))\n        (else (error \"Unknown c-const\" const))))\n\n(define (c-reg reg)\n  (match reg\n    ['continue \"cont\"]\n    [else (symbol->string reg)]))\n\n(define c-label-name\n  (compose dash-to-underscore symbol->string))\n\n(define c-func-name\n  (compose exclamation-mark-to-bang\n           dash-to-underscore\n           question-mark-to-p\n           symbol->string))\n\n(define (c-args args)\n  (string-join (map c-val args) \", \"))\n\n; Indents everything but the labels, so the compiled C code can look nicer.\n\n(define (ident text)\n  (if (regexp-match (regexp \":$\") text)\n      text\n      (string-append \"  \" text)))\n\n; Finally, the C code for the interpreter.\n\n(define interpreter-in-c\n  (let* ((instructions (compile-exp metacircular-evaluator 'val 'next))\n         (statements (statements instructions))\n         (lines (map (compose ident translate) statements)))\n    (string-join lines \"\\n\")))\n"
  },
  {
    "path": "scheme/sicp/05/showcase/compiler/compiler.scm",
    "content": "; The procedure compile is renamed to compile-exp, because it is\n; already defined in Racket.\n\n; The compile procedure\n\n(define (compile-exp exp target linkage)\n  (cond ((self-evaluating? exp)\n         (compile-self-evaluating exp target linkage))\n        ((quoted? exp) (compile-quoted exp target linkage))\n        ((variable? exp)\n         (compile-variable exp target linkage))\n        ((assignment? exp)\n         (compile-assignment exp target linkage))\n        ((definition? exp)\n         (compile-definition exp target linkage))\n        ((if? exp) (compile-if exp target linkage))\n        ((lambda? exp) (compile-lambda exp target linkage))\n        ((begin? exp)\n         (compile-sequence (begin-actions exp) target linkage))\n        ((cond? exp) (compile-exp (cond->if exp) target linkage))\n        ((application? exp)\n         (compile-application exp target linkage))\n        (else\n         (error \"Unknown expression type -- COMPILE\" exp))))\n\n; Compiling linkage code\n\n(define (compile-linkage linkage)\n  (cond ((eq? linkage 'return)\n         (make-instruction-sequence '(continue) '()\n          '((goto (reg continue)))))\n        ((eq? linkage 'next)\n         (empty-instruction-sequence))\n        (else\n         (make-instruction-sequence '() '()\n          `((goto (label ,linkage)))))))\n\n(define (end-with-linkage linkage instruction-sequence)\n  (preserving '(continue)\n              instruction-sequence\n              (compile-linkage linkage)))\n\n; Compiling simple expressions\n\n(define (compile-self-evaluating exp target linkage)\n  (end-with-linkage linkage\n   (make-instruction-sequence '() (list target)\n    `((assign ,target (const ,exp))))))\n\n(define (compile-quoted exp target linkage)\n  (end-with-linkage linkage\n   (make-instruction-sequence '() (list target)\n    `((assign ,target (const ,(text-of-quotation exp)))))))\n\n(define (compile-variable exp target linkage)\n  (end-with-linkage linkage\n   (make-instruction-sequence '(env) (list target)\n    `((assign ,target (op lookup-variable-value) (const ,exp) (reg env))))))\n\n(define (compile-assignment exp target linkage)\n  (let ((var (assignment-variable exp))\n        (get-value-code (compile-exp (assignment-value exp) 'val 'next)))\n    (end-with-linkage linkage\n     (preserving '(env)\n      get-value-code\n      (make-instruction-sequence '(env val) (list target)\n       `((perform (op set-variable-value!)\n                  (const ,var)\n                  (reg val)\n                  (reg env))\n         (assign ,target (const ok))))))))\n\n(define (compile-definition exp target linkage)\n  (let ((var (definition-variable exp))\n        (get-value-code (compile-exp (definition-value exp) 'val 'next)))\n    (end-with-linkage linkage\n     (preserving '(env)\n      get-value-code\n      (make-instruction-sequence '(env val) (list target)\n       `((perform (op define-variable!)\n                  (const ,var)\n                  (reg val)\n                  (reg env))\n         (assign ,target (const ok))))))))\n\n; Compiling conditional expressions\n\n(define (compile-if exp target linkage)\n  (let ((t-branch (make-label 'true-branch))\n        (f-branch (make-label 'false-branch))\n        (after-if (make-label 'after-if)))\n    (let ((consequent-linkage (if (eq? linkage 'next) after-if linkage)))\n      (let ((p-code (compile-exp (if-predicate exp) 'val 'next))\n            (c-code (compile-exp (if-consequent exp) target consequent-linkage))\n            (a-code (compile-exp (if-alternative exp) target linkage)))\n        (preserving '(env continue)\n         p-code\n         (append-instruction-sequences\n          (make-instruction-sequence '(val) '()\n           `((test (op false?) (reg val))\n             (branch (label ,f-branch))))\n          (parallel-instruction-sequences\n           (append-instruction-sequences t-branch c-code)\n           (append-instruction-sequences f-branch a-code))\n          after-if))))))\n\n; Compiling sequences\n\n(define (compile-sequence seq target linkage)\n  (if (last-exp? seq)\n      (compile-exp (first-exp seq) target linkage)\n      (preserving '(env continue)\n       (compile-exp (first-exp seq) target 'next)\n       (compile-sequence (rest-exps seq) target linkage))))\n\n; Compiling lambda expressions\n\n(define (compile-lambda exp target linkage)\n  (let ((proc-entry (make-label 'entry))\n        (after-lambda (make-label 'after-lambda)))\n    (let ((lambda-linkage (if (eq? linkage 'next) after-lambda linkage)))\n      (append-instruction-sequences\n       (tack-on-instruction-sequence\n        (end-with-linkage lambda-linkage\n         (make-instruction-sequence '(env) (list target)\n          `((assign ,target\n                    (op make-compiled-procedure)\n                    (label ,proc-entry)\n                    (reg env)))))\n        (compile-lambda-body exp proc-entry))\n       after-lambda))))\n\n(define (compile-lambda-body exp proc-entry)\n  (let ((formals (lambda-parameters exp)))\n    (append-instruction-sequences\n     (make-instruction-sequence '(env proc argl) '(env)\n      `(,proc-entry\n         (assign env (op compiled-procedure-env) (reg proc))\n         (assign env\n                 (op extend-environment)\n                 (const ,formals)\n                 (reg argl)\n                 (reg env))))\n     (compile-sequence (lambda-body exp) 'val 'return))))\n\n; Compiling combinations\n\n(define (compile-application exp target linkage)\n  (let ((proc-code (compile-exp (operator exp) 'proc 'next))\n        (operand-codes (map (lambda (operand) (compile-exp operand 'val 'next))\n                            (operands exp))))\n    (preserving '(env continue)\n     proc-code\n     (preserving '(proc continue)\n      (construct-arglist operand-codes)\n      (compile-procedure-call target linkage)))))\n\n(define (construct-arglist operand-codes)\n  (let ((operand-codes (reverse operand-codes)))\n    (if (null? operand-codes)\n        (make-instruction-sequence '() '(argl)\n                                   '((assign argl (const ()))))\n        (let ((code-to-get-last-arg\n               (append-instruction-sequences\n                (car operand-codes)\n                (make-instruction-sequence '(val) '(argl)\n                 '((assign argl (op list) (reg val)))))))\n          (if (null? (cdr operand-codes))\n              code-to-get-last-arg\n              (preserving '(env)\n                          code-to-get-last-arg\n                          (code-to-get-rest-args (cdr operand-codes))))))))\n\n(define (code-to-get-rest-args operand-codes)\n  (let ((code-for-next-arg (preserving '(argl)\n                                       (car operand-codes)\n                                       (make-instruction-sequence '(val argl) '(argl)\n                                        '((assign argl (op cons) (reg val) (reg argl)))))))\n    (if (null? (cdr operand-codes))\n        code-for-next-arg\n        (preserving '(env)\n                    code-for-next-arg\n                    (code-to-get-rest-args (cdr operand-codes))))))\n\n; Applying procedures\n\n(define (compile-procedure-call target linkage)\n  (let ((primitive-branch (make-label 'primitive-branch))\n        (compiled-branch (make-label 'compiled-branch))\n        (after-call (make-label 'after-call)))\n    (let ((compiled-linkage (if (eq? linkage 'next) after-call linkage)))\n      (append-instruction-sequences\n       (make-instruction-sequence '(proc) '()\n        `((test (op primitive-procedure?) (reg proc))\n          (branch (label ,primitive-branch))))\n       (parallel-instruction-sequences\n        (append-instruction-sequences\n         compiled-branch\n         (compile-proc-appl target compiled-linkage))\n        (append-instruction-sequences\n         primitive-branch\n         (end-with-linkage linkage\n          (make-instruction-sequence '(proc argl) (list target)\n           `((assign ,target\n                     (op apply-primitive-procedure)\n                     (reg proc)\n                     (reg argl)))))))\n       after-call))))\n\n; Applying compiled procedures\n\n(define all-regs '(env proc val argl continue))\n\n(define (compile-proc-appl target linkage)\n  (cond ((and (eq? target 'val) (not (eq? linkage 'return)))\n         (make-instruction-sequence '(proc) all-regs\n          `((assign continue (label ,linkage))\n            (assign val (op compiled-procedure-entry) (reg proc))\n            (goto (reg val)))))\n        ((and (not (eq? target 'val)) (not (eq? linkage 'return)))\n         (let ((proc-return (make-label 'proc-return)))\n           (make-instruction-sequence '(proc) all-regs\n            `((assign continue (label ,proc-return))\n              (assign val (op compiled-procedure-entry) (reg proc))\n              (goto (reg val))\n              ,proc-return\n              (assign ,target (reg val))\n              (goto (label ,linkage))))))\n        ((and (eq? target 'val) (eq? linkage 'return))\n         (make-instruction-sequence '(proc continue) all-regs\n          `((assign val (op compiled-procedure-entry) (reg proc))\n            (goto (reg val)))))\n        ((and (not (eq? target 'val)) (eq? linkage 'return))\n         (error \"return linkage, target not val -- COMPILE-EXP\" target))\n        (else (error \"How did we get here?\"))))\n\n; Combining Instruction Sequences\n\n(define (registers-needed s) (if (symbol? s) '() (car s)))\n(define (registers-modified s) (if (symbol? s) '() (cadr s)))\n(define (statements s) (if (symbol? s) (list s) (caddr s)))\n(define (needs-register? seq reg) (memq reg (registers-needed seq)))\n(define (modifies-register? seq reg) (memq reg (registers-modified seq)))\n\n(define (append-instruction-sequences . seqs)\n  (define (append-2-sequences seq1 seq2)\n    (make-instruction-sequence\n      (list-union (registers-needed seq1)\n                  (list-difference (registers-needed seq2)\n                                   (registers-modified seq1)))\n      (list-union (registers-modified seq1)\n                  (registers-modified seq2))\n      (append (statements seq1) (statements seq2))))\n  (define (append-seq-list seqs)\n    (if (null? seqs)\n        (empty-instruction-sequence)\n        (append-2-sequences (car seqs)\n                            (append-seq-list (cdr seqs)))))\n  (append-seq-list seqs))\n\n(define (list-union s1 s2)\n  (cond ((null? s1) s2)\n        ((memq (car s1) s2) (list-union (cdr s1) s2))\n        (else (cons (car s1) (list-union (cdr s1) s2)))))\n\n(define (list-difference s1 s2)\n  (cond ((null? s1) '())\n        ((memq (car s1) s2) (list-difference (cdr s1) s2))\n        (else (cons (car s1) (list-difference (cdr s1) s2)))))\n\n(define (preserving regs seq1 seq2)\n  (if (null? regs)\n      (append-instruction-sequences seq1 seq2)\n      (let ((first-reg (car regs)))\n        (if (and (needs-register? seq2 first-reg)\n                 (modifies-register? seq1 first-reg))\n            (preserving (cdr regs)\n             (make-instruction-sequence\n              (list-union (list first-reg) (registers-needed seq1))\n              (list-difference (registers-modified seq1) (list first-reg))\n              (append `((save ,first-reg))\n                      (statements seq1)\n                      `((restore ,first-reg))))\n             seq2)\n            (preserving (cdr regs) seq1 seq2)))))\n\n(define (tack-on-instruction-sequence seq body-seq)\n  (make-instruction-sequence (registers-needed seq)\n                             (registers-modified seq)\n                             (append (statements seq)\n                                     (statements body-seq))))\n\n(define (parallel-instruction-sequences seq1 seq2)\n  (make-instruction-sequence\n    (list-union (registers-needed seq1)\n                (registers-needed seq2))\n    (list-union (registers-modified seq1)\n                (registers-modified seq2))\n    (append (statements seq1) (statements seq2))))\n\n; Instruction sequences\n\n(define (make-instruction-sequence needs modifies statements)\n  (list needs modifies statements))\n\n(define (empty-instruction-sequence)\n  (make-instruction-sequence '() '() '()))\n\n; Make label\n\n(define label-counter 0)\n\n(define (new-label-number)\n  (set! label-counter (+ 1 label-counter))\n  label-counter)\n\n(define (make-label name)\n  (string->symbol\n    (string-append (symbol->string name)\n                   (number->string (new-label-number)))))\n\n; Compiled procedure operations\n\n(define (make-compiled-procedure entry env) (list 'compiled-procedure entry env))\n(define (compiled-procedure? proc) (tagged-list? proc 'compiled-procedure))\n(define (compiled-procedure-entry c-proc) (cadr c-proc))\n(define (compiled-procedure-env c-proc) (caddr c-proc))\n"
  },
  {
    "path": "scheme/sicp/05/showcase/compiler/explicit-evaluator-text.scm",
    "content": "(define explicit+compile-text\n  '(\n      (branch (label external-entry))\n      (assign continue (label done))\n    eval-dispatch\n      (test (op self-evaluating?) (reg exp))\n      (branch (label ev-self-eval))\n      (test (op variable?) (reg exp))\n      (branch (label ev-variable))\n      (test (op quoted?) (reg exp))\n      (branch (label ev-quoted))\n      (test (op assignment?) (reg exp))\n      (branch (label ev-assignment))\n      (test (op definition?) (reg exp))\n      (branch (label ev-definition))\n      (test (op if?) (reg exp))\n      (branch (label ev-if))\n      (test (op lambda?) (reg exp))\n      (branch (label ev-lambda))\n      (test (op begin?) (reg exp))\n      (branch (label ev-begin))\n      (test (op application?) (reg exp))\n      (branch (label ev-application))\n      (goto (label unknown-expression-type))\n\n    ; Evaluating simple expressions\n\n    ev-self-eval\n      (assign val (reg exp))\n      (goto (reg continue))\n    ev-variable\n      (assign val (op lookup-variable-value) (reg exp) (reg env))\n      (goto (reg continue))\n    ev-quoted\n      (assign val (op text-of-quotation) (reg exp))\n      (goto (reg continue))\n    ev-lambda\n      (assign unev (op lambda-parameters) (reg exp))\n      (assign exp (op lambda-body) (reg exp))\n      (assign val (op make-procedure) (reg unev) (reg exp) (reg env))\n      (goto (reg continue))\n\n    ; Evaluating procedure applications\n\n    ev-application\n      (save continue)\n      (save env)\n      (assign unev (op operands) (reg exp))\n      (save unev)\n      (assign exp (op operator) (reg exp))\n      (assign continue (label ev-appl-did-operator))\n      (goto (label eval-dispatch))\n    ev-appl-did-operator\n      (restore unev)\n      (restore env)\n      (assign argl (op empty-arglist))\n      (assign proc (reg val))\n      (test (op no-operands?) (reg unev))\n      (branch (label apply-dispatch))\n      (save proc)\n    ev-appl-operand-loop\n      (save argl)\n      (assign exp (op first-operand) (reg unev))\n      (test (op last-operand?) (reg unev))\n      (branch (label ev-appl-last-arg))\n      (save env)\n      (save unev)\n      (assign continue (label ev-appl-accumulate-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accumulate-arg\n      (restore unev)\n      (restore env)\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (assign unev (op rest-operands) (reg unev))\n      (goto (label ev-appl-operand-loop))\n    ev-appl-last-arg\n      (assign continue (label ev-appl-accum-last-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accum-last-arg\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (restore proc)\n      (goto (label apply-dispatch))\n\n    ; Procedure application\n\n    apply-dispatch\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-apply))\n      (test (op compound-procedure?) (reg proc))\n      (branch (label compound-apply))\n      (test (op compiled-procedure?) (reg proc))\n      (branch (label compiled-apply))\n      (goto (label unknown-procedure-type))\n    primitive-apply\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n      (restore continue)\n      (goto (reg continue))\n    compound-apply\n      (assign unev (op procedure-parameters) (reg proc))\n      (assign env (op procedure-environment) (reg proc))\n      (assign env (op extend-environment) (reg unev) (reg argl) (reg env))\n      (assign unev (op procedure-body) (reg proc))\n      (goto (label ev-sequence))\n    compiled-apply\n      (restore continue)\n      (assign val (op compiled-procedure-entry) (reg proc))\n      (goto (reg val))\n\n    ; Sequence evaluation\n\n    ev-begin\n      (assign unev (op begin-actions) (reg exp))\n      (save continue)\n      (goto (label ev-sequence))\n    ev-sequence\n      (assign exp (op first-exp) (reg unev))\n      (test (op last-exp?) (reg unev))\n      (branch (label ev-sequence-last-exp))\n      (save unev)\n      (save env)\n      (assign continue (label ev-sequence-continue))\n      (goto (label eval-dispatch))\n    ev-sequence-continue\n      (restore env)\n      (restore unev)\n      (assign unev (op rest-exps) (reg unev))\n      (goto (label ev-sequence))\n    ev-sequence-last-exp\n      (restore continue)\n      (goto (label eval-dispatch))\n\n    ; Conditionals\n\n    ev-if\n      (save exp)\n      (save env)\n      (save continue)\n      (assign continue (label ev-if-decide))\n      (assign exp (op if-predicate) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-decide\n      (restore continue)\n      (restore env)\n      (restore exp)\n      (test (op true?) (reg val))\n      (branch (label ev-if-consequent))\n    ev-if-alternative\n      (assign exp (op if-alternative) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-consequent\n      (assign exp (op if-consequent) (reg exp))\n      (goto (label eval-dispatch))\n\n    ; Assignments and definitions\n\n    ev-assignment\n      (assign unev (op assignment-variable) (reg exp))\n      (save unev)\n      (assign exp (op assignment-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-assignment-1))\n      (goto (label eval-dispatch))\n    ev-assignment-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op set-variable-value!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n\n    ev-definition\n      (assign unev (op definition-variable) (reg exp))\n      (save unev)\n      (assign exp (op definition-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-definition-1))\n      (goto (label eval-dispatch))\n    ev-definition-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op define-variable!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n\n    ; Error handling\n\n    unknown-expression-type\n      (perform (op error) (const \"Unknown expression type\") (reg exp))\n    unknown-procedure-type\n      (perform (op error) (const \"Unknown procedure type\") (reg proc))\n\n    ; External entries\n\n    external-entry\n      (perform (op initialize-stack))\n      (assign env (op get-global-environment))\n      (assign continue (label done))\n      (goto (reg val))\n\n    done))\n"
  },
  {
    "path": "scheme/sicp/05/showcase/compiler/helpers.scm",
    "content": "(load-relative \"syntax.scm\")\n(load-relative \"operations.scm\")\n(load-relative \"compiler.scm\")\n(load-relative \"explicit-evaluator-text.scm\")\n(load-relative \"../simulator/simulator.scm\")\n(load-relative \"../explicit/controller-text.scm\")\n\n(define (make-explicit+compile-machine)\n  (make-machine ec-registers cm-operations explicit+compile-text))\n\n(define (compile-in-machine machine expression)\n  (let ((instructions (assemble (statements (compile-exp expression 'val 'return))\n                                machine)))\n    (set-register-contents! machine 'env the-global-environment)\n    (set-register-contents! machine 'val instructions)\n    (set-register-contents! machine 'flag true)\n\n    (start machine)))\n\n(define (eval-in-machine machine expression)\n  (set-register-contents! machine 'env the-global-environment)\n  (set-register-contents! machine 'exp expression)\n  (set-register-contents! machine 'flag false)\n\n  (start machine))\n\n(define (compiled-instructions expression)\n  (statements (compile-exp expression 'val 'return)))\n\n"
  },
  {
    "path": "scheme/sicp/05/showcase/compiler/main.scm",
    "content": "(display \"There is no executable for this showcase.\")\n(newline)\n(display \"Just use the compiler as you see fit.\")\n(newline)\n"
  },
  {
    "path": "scheme/sicp/05/showcase/compiler/operations.scm",
    "content": "(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (list->mlist lst)\n  (if (null? lst)\n      '()\n      (mcons (car lst) (list->mlist (cdr lst)))))\n\n(define (text-of-quotation exp) (cadr exp))\n\n\n(define (last-operand? ops) (null? (cdr ops)))\n\n(define (make-procedure parameters body env) (list 'procedure parameters body env))\n(define (compound-procedure? p) (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (empty-arglist) '())\n(define (adjoin-arg arg arglist) (append arglist (list arg)))\n\n(define (true? x) (not (eq? x false)))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (mcons variables values))\n(define (frame-variables frame) (mcar frame))\n(define (frame-values frame) (mcdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-mcar! frame (cons var (mcar frame)))\n  (set-mcdr! frame (mcons val (mcdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars (list->mlist vals)) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (mcar vals))\n            (else (scan (cdr vars) (mcdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-mcar! vals val))\n            (else (scan (cdr vars) (mcdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-mcar! vals val))\n            (else (scan (cdr vars) (mcdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '> >)\n        (list '< <)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n\n(define the-global-environment (setup-environment))\n(define (get-global-environment) the-global-environment)\n\n(define (reset-the-global-environment!)\n  (set! the-global-environment (setup-environment)))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n\n(define (make-compiled-procedure entry env) (list 'compiled-procedure entry env))\n(define (compiled-procedure? proc) (tagged-list? proc 'compiled-procedure))\n(define (compiled-procedure-entry c-proc) (cadr c-proc))\n(define (compiled-procedure-env c-proc) (caddr c-proc))\n\n; The list of registers\n\n(define cm-registers '(exp env val proc argl continue unev))\n\n; The list of all operations\n\n(define cm-operations\n  (list (list 'self-evaluating? self-evaluating?)\n        (list 'variable? variable?)\n\n        (list 'quoted? quoted?)\n        (list 'text-of-quotation text-of-quotation)\n\n        (list 'assignment? assignment?)\n        (list 'assignment-value assignment-value)\n        (list 'assignment-variable assignment-variable)\n\n        (list 'definition? definition?)\n        (list 'definition-variable definition-variable)\n        (list 'definition-value definition-value)\n\n        (list 'if? if?)\n        (list 'if-predicate if-predicate)\n        (list 'if-consequent if-consequent)\n        (list 'if-alternative if-alternative)\n\n        (list 'lambda? lambda?)\n        (list 'lambda-parameters lambda-parameters)\n        (list 'lambda-body lambda-body)\n\n        (list 'begin? begin?)\n        (list 'begin-actions begin-actions)\n        (list 'first-exp first-exp)\n        (list 'last-exp? last-exp?)\n        (list 'rest-exps rest-exps)\n\n        (list 'application? application?)\n        (list 'operands operands)\n        (list 'operator operator)\n        (list 'no-operands? no-operands?)\n        (list 'last-operand? last-operand?)\n        (list 'first-operand first-operand)\n        (list 'rest-operands rest-operands)\n\n        (list 'lookup-variable-value lookup-variable-value)\n        (list 'define-variable! define-variable!)\n        (list 'set-variable-value! set-variable-value!)\n        (list 'extend-environment extend-environment)\n\n        (list 'primitive-procedure? primitive-procedure?)\n        (list 'apply-primitive-procedure apply-primitive-procedure)\n\n        (list 'compound-procedure? compound-procedure?)\n        (list 'procedure-parameters procedure-parameters)\n        (list 'procedure-environment procedure-environment)\n        (list 'procedure-body procedure-body)\n\n        (list 'make-procedure make-procedure)\n\n        (list 'empty-arglist empty-arglist)\n        (list 'adjoin-arg adjoin-arg)\n\n        (list 'true? true?)\n        (list 'false? false?)\n\n        (list 'list list)\n        (list 'cons cons)\n\n        (list 'compiled-procedure? compiled-procedure?)\n        (list 'make-compiled-procedure make-compiled-procedure)\n        (list 'compiled-procedure-env compiled-procedure-env)\n        (list 'compiled-procedure-entry compiled-procedure-entry)\n\n        (list 'prompt-for-input prompt-for-input)\n        (list 'read read)\n        (list 'get-global-environment get-global-environment)\n        (list 'announce-output announce-output)\n        (list 'user-print user-print)\n\n        (list 'error error)))\n"
  },
  {
    "path": "scheme/sicp/05/showcase/compiler/syntax.scm",
    "content": "(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n\n(define (variable? exp) (symbol? exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp) (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n"
  },
  {
    "path": "scheme/sicp/05/showcase/compiler/tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n\n(load \"helpers.scm\")\n\n(define (run exp)\n  (let ((machine (make-explicit+compile-machine)))\n    (compile-in-machine machine exp)\n    (get-register-contents machine 'val)))\n\n(define evaluator-tests\n  (test-suite\n    \"Tests for the metacircular evaluator\"\n\n    (test-suite \"Self-evaluating expressions\"\n      (check-equal? (run '1) 1)\n      (check-equal? (run '\"something\") \"something\"))\n\n    (test-suite \"Quotation\"\n      (check-equal? (run '(quote foo)) 'foo))\n\n    (test-suite \"Begin\"\n      (check-equal? (run '(begin 1 2)) 2))\n\n    (test-suite \"Define\"\n      (check-equal? (run '(define x 1)) 'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 x))\n                    1)\n      (check-equal? (run '(define (x) 1)) 'ok)\n      (check-equal? (run '(begin (define (x) 1)\n                                 (x)))\n                    1))\n\n    (test-suite \"Set!\"\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)))\n                    'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)\n                                 x))\n                    2))\n\n    (test-suite \"If\"\n      (check-equal? (run '(if true 1 2)) 1)\n      (check-equal? (run '(if false 1 2)) 2)\n      (check-equal? (run '(if true 1)) 1)\n      (check-equal? (run '(if false 1)) false))\n\n    (test-suite \"Lambda\"\n      (check-equal? (run '((lambda () 1))) 1)\n      (check-equal? (run '((lambda (x) x) 1)) 1)\n      (check-equal? (run '((lambda (a b) (cons a b)) 1 2)) '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 ((lambda (a) (cons a b)) 3)))\n                    '(3 . 2)))\n\n    (test-suite \"Cond\"\n      (check-equal? (run '(cond (true 1))) 1)\n      (check-equal? (run '(cond (false 1) (true 2))) 2)\n      (check-equal? (run '(cond (false 1) (else 2))) 2)\n      (check-exn exn? (lambda () (run '(cond (else 1) (true 2))))))\n\n    (test-suite \"Procedure application\"\n      (check-equal? (run '(begin (define (a) 1)\n                                 (a)))\n                    1)\n      (check-equal? (run '(begin (define (pair a b) (cons a b))\n                                 (pair 1 2)))\n                    '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define (pair b) (cons a b))\n                                 (pair 2)))\n                    '(1 . 2)))\n\n    (test-suite \"Defining append\"\n      (check-equal? (run '(begin (define (append x y)\n                                   (if (null? x)\n                                       y\n                                       (cons (car x)\n                                             (append (cdr x) y))))\n                                 (append '(a b c) '(d e f))))\n                    '(a b c d e f)))\n\n    (test-suite \"Factorial\"\n      (check-equal? (run '(begin (define (factorial n)\n                                   (if (= n 1)\n                                       1\n                                       (* n (factorial (- n 1)))))\n                                 (factorial 5)))\n                    120)\n      (check-equal? (run '(begin (define (factorial n)\n                                   (define (iter n result)\n                                     (if (= n 0)\n                                         result\n                                         (iter (- n 1) (* result n))))\n                                   (iter n 1))\n                                 (factorial 5)))\n                    120)) \n))\n\n(run-tests evaluator-tests)\n"
  },
  {
    "path": "scheme/sicp/05/showcase/explicit/controller-text.scm",
    "content": "(define ec-registers '(exp env val proc argl continue unev))\n\n(define ec-core\n  '(eval-dispatch\n      (test (op self-evaluating?) (reg exp))\n      (branch (label ev-self-eval))\n      (test (op variable?) (reg exp))\n      (branch (label ev-variable))\n      (test (op quoted?) (reg exp))\n      (branch (label ev-quoted))\n      (test (op assignment?) (reg exp))\n      (branch (label ev-assignment))\n      (test (op definition?) (reg exp))\n      (branch (label ev-definition))\n      (test (op if?) (reg exp))\n      (branch (label ev-if))\n      (test (op lambda?) (reg exp))\n      (branch (label ev-lambda))\n      (test (op begin?) (reg exp))\n      (branch (label ev-begin))\n      (test (op application?) (reg exp))\n      (branch (label ev-application))\n      (goto (label unknown-expression-type))\n\n    ; Evaluating simple expressions\n\n    ev-self-eval\n      (assign val (reg exp))\n      (goto (reg continue))\n    ev-variable\n      (assign val (op lookup-variable-value) (reg exp) (reg env))\n      (goto (reg continue))\n    ev-quoted\n      (assign val (op text-of-quotation) (reg exp))\n      (goto (reg continue))\n    ev-lambda\n      (assign unev (op lambda-parameters) (reg exp))\n      (assign exp (op lambda-body) (reg exp))\n      (assign val (op make-procedure) (reg unev) (reg exp) (reg env))\n      (goto (reg continue))\n\n    ; Evaluating procedure applications\n\n    ev-application\n      (save continue)\n      (save env)\n      (assign unev (op operands) (reg exp))\n      (save unev)\n      (assign exp (op operator) (reg exp))\n      (assign continue (label ev-appl-did-operator))\n      (goto (label eval-dispatch))\n    ev-appl-did-operator\n      (restore unev)\n      (restore env)\n      (assign argl (op empty-arglist))\n      (assign proc (reg val))\n      (test (op no-operands?) (reg unev))\n      (branch (label apply-dispatch))\n      (save proc)\n    ev-appl-operand-loop\n      (save argl)\n      (assign exp (op first-operand) (reg unev))\n      (test (op last-operand?) (reg unev))\n      (branch (label ev-appl-last-arg))\n      (save env)\n      (save unev)\n      (assign continue (label ev-appl-accumulate-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accumulate-arg\n      (restore unev)\n      (restore env)\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (assign unev (op rest-operands) (reg unev))\n      (goto (label ev-appl-operand-loop))\n    ev-appl-last-arg\n      (assign continue (label ev-appl-accum-last-arg))\n      (goto (label eval-dispatch))\n    ev-appl-accum-last-arg\n      (restore argl)\n      (assign argl (op adjoin-arg) (reg val) (reg argl))\n      (restore proc)\n      (goto (label apply-dispatch))\n\n    ; Procedure application\n\n    apply-dispatch\n      (test (op primitive-procedure?) (reg proc))\n      (branch (label primitive-apply))\n      (test (op compound-procedure?) (reg proc))\n      (branch (label compound-apply))\n      (goto (label unknown-procedure-type))\n    primitive-apply\n      (assign val (op apply-primitive-procedure) (reg proc) (reg argl))\n      (restore continue)\n      (goto (reg continue))\n    compound-apply\n      (assign unev (op procedure-parameters) (reg proc))\n      (assign env (op procedure-environment) (reg proc))\n      (assign env (op extend-environment) (reg unev) (reg argl) (reg env))\n      (assign unev (op procedure-body) (reg proc))\n      (goto (label ev-sequence))\n\n    ; Sequence evaluation\n\n    ev-begin\n      (assign unev (op begin-actions) (reg exp))\n      (save continue)\n      (goto (label ev-sequence))\n    ev-sequence\n      (assign exp (op first-exp) (reg unev))\n      (test (op last-exp?) (reg unev))\n      (branch (label ev-sequence-last-exp))\n      (save unev)\n      (save env)\n      (assign continue (label ev-sequence-continue))\n      (goto (label eval-dispatch))\n    ev-sequence-continue\n      (restore env)\n      (restore unev)\n      (assign unev (op rest-exps) (reg unev))\n      (goto (label ev-sequence))\n    ev-sequence-last-exp\n      (restore continue)\n      (goto (label eval-dispatch))\n\n    ; Conditionals\n\n    ev-if\n      (save exp)\n      (save env)\n      (save continue)\n      (assign continue (label ev-if-decide))\n      (assign exp (op if-predicate) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-decide\n      (restore continue)\n      (restore env)\n      (restore exp)\n      (test (op true?) (reg val))\n      (branch (label ev-if-consequent))\n    ev-if-alternative\n      (assign exp (op if-alternative) (reg exp))\n      (goto (label eval-dispatch))\n    ev-if-consequent\n      (assign exp (op if-consequent) (reg exp))\n      (goto (label eval-dispatch))\n\n    ; Assignments and definitions\n\n    ev-assignment\n      (assign unev (op assignment-variable) (reg exp))\n      (save unev)\n      (assign exp (op assignment-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-assignment-1))\n      (goto (label eval-dispatch))\n    ev-assignment-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op set-variable-value!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))\n\n    ev-definition\n      (assign unev (op definition-variable) (reg exp))\n      (save unev)\n      (assign exp (op definition-value) (reg exp))\n      (save env)\n      (save continue)\n      (assign continue (label ev-definition-1))\n      (goto (label eval-dispatch))\n    ev-definition-1\n      (restore continue)\n      (restore env)\n      (restore unev)\n      (perform (op define-variable!) (reg unev) (reg val) (reg env))\n      (assign val (const ok))\n      (goto (reg continue))))\n\n(define ec-repl-head\n  '(read-eval-print-loop\n      (perform (op initialize-stack))\n      (perform (op prompt-for-input) (const \";;; EC-Eval input:\"))\n      (assign exp (op read))\n      (assign env (op get-global-environment))\n      (assign continue (label print-result))\n      (goto (label eval-dispatch))\n    print-result\n      (perform (op announce-output) (const \";;; EC-Eval value:\"))\n      (perform (op user-print) (reg val))\n      (goto (label read-eval-print-loop))\n    unknown-expression-type\n      (assign val (const unknown-expression-type-error))\n      (goto (label signal-error))\n    unknown-procedure-type\n      (restore continue)\n      (assign val (const unknown-procedure-type-error))\n      (goto (label signal-error))\n    signal-error\n      (perform (op user-print) (reg val))\n      (goto (label read-eval-print-loop))))\n\n(define ec-controller-text\n  (append '((assign continue (label done)))\n          ec-core\n          '(unknown-expression-type unknown-procedure-type done)))\n\n(define ec-repl-controller-text\n  (append ec-repl-head ec-core))\n"
  },
  {
    "path": "scheme/sicp/05/showcase/explicit/evaluator.scm",
    "content": "(load-relative \"../simulator/simulator.scm\")\n(load-relative \"controller-text.scm\")\n(load-relative \"operations.scm\")\n\n(define (make-explicit-control-machine)\n  (make-machine ec-registers ec-operations ec-controller-text))\n\n(define (make-explicit-control-repl-machine)\n  (make-machine ec-registers ec-operations ec-repl-controller-text))\n"
  },
  {
    "path": "scheme/sicp/05/showcase/explicit/main.scm",
    "content": "(load-relative \"evaluator.scm\")\n\n(define ec-repl-machine (make-explicit-control-repl-machine))\n(start ec-repl-machine)\n"
  },
  {
    "path": "scheme/sicp/05/showcase/explicit/operations.scm",
    "content": "; This file contains all the \"primitive\" operations required by the explicit\n; control evaluator. They are lifted from the metacircular evaluator, with the\n; addition that it is converted to use Racket instead of R5RS.\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (list->mlist lst)\n  (if (null? lst)\n      '()\n      (mcons (car lst) (list->mlist (cdr lst)))))\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (variable? exp) (symbol? exp))\n\n(define (quoted? exp) (tagged-list? exp 'quote))\n(define (text-of-quotation exp) (cadr exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp)\n  (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (cddr exp))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (last-operand? ops) (null? (cdr ops)))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (make-procedure parameters body env)\n  (list 'procedure parameters body env))\n(define (compound-procedure? p)\n  (tagged-list? p 'procedure))\n(define (procedure-parameters p) (cadr p))\n(define (procedure-body p) (caddr p))\n(define (procedure-environment p) (cadddr p))\n\n(define (empty-arglist) '())\n(define (adjoin-arg arg arglist) (append arglist (list arg)))\n\n(define (true? x) (not (eq? x false)))\n\n(define (enclosing-environment env) (cdr env))\n(define (first-frame env) (car env))\n(define the-empty-environment '())\n\n(define (make-frame variables values)\n  (mcons variables values))\n(define (frame-variables frame) (mcar frame))\n(define (frame-values frame) (mcdr frame))\n(define (add-binding-to-frame! var val frame)\n  (set-mcar! frame (cons var (mcar frame)))\n  (set-mcdr! frame (mcons val (mcdr frame))))\n(define (extend-environment vars vals base-env)\n  (if (= (length vars) (length vals))\n      (cons (make-frame vars (list->mlist vals)) base-env)\n      (if (< (length vars) (length vals))\n          (error \"Too many arguments supplied\" vars vals)\n          (error \"Too few arguments supplied\" vars vals))))\n(define (lookup-variable-value var env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (mcar vals))\n            (else (scan (cdr vars) (mcdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (set-variable-value! var val env)\n  (define (env-loop env)\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (env-loop (enclosing-environment env)))\n            ((eq? var (car vars))\n             (set-mcar! vals val))\n            (else (scan (cdr vars) (mcdr vals)))))\n    (if (eq? env the-empty-environment)\n        (error \"Unbound variable - SET!\" var)\n        (let ((frame (first-frame env)))\n          (scan (frame-variables frame)\n                (frame-values frame)))))\n  (env-loop env))\n(define (define-variable! var val env)\n  (let ((frame (first-frame env)))\n    (define (scan vars vals)\n      (cond ((null? vars)\n             (add-binding-to-frame! var val frame))\n            ((eq? var (car vars))\n             (set-mcar! vals val))\n            (else (scan (cdr vars) (mcdr vals)))))\n    (scan (frame-variables frame)\n          (frame-values frame))))\n\n(define (primitive-procedure? proc)\n  (tagged-list? proc 'primitive))\n(define (primitive-implementation proc) (cadr proc))\n\n(define primitive-procedures\n  (list (list 'car car)\n        (list 'cdr cdr)\n        (list 'cons cons)\n        (list 'null? null?)\n        (list 'pair? pair?)\n        (list '= =)\n        (list '> >)\n        (list '< <)\n        (list '+ +)\n        (list '- -)\n        (list '* *)\n        (list '/ /)))\n\n(define (primitive-procedure-names)\n  (map car primitive-procedures))\n(define (primitive-procedure-objects)\n  (map (lambda (proc) (list 'primitive (cadr proc)))\n       primitive-procedures))\n\n(define apply-in-underlying-scheme apply)\n\n(define (apply-primitive-procedure proc args)\n  (apply-in-underlying-scheme (primitive-implementation proc) args))\n\n(define (setup-environment)\n  (let ((initial-env\n          (extend-environment (primitive-procedure-names)\n                              (primitive-procedure-objects)\n                              the-empty-environment)))\n    (define-variable! 'true true initial-env)\n    (define-variable! 'false false initial-env)\n    initial-env))\n\n(define the-global-environment (setup-environment))\n(define (get-global-environment) the-global-environment)\n\n(define (reset-the-global-environment!)\n  (set! the-global-environment (setup-environment)))\n\n(define (prompt-for-input string)\n  (newline) (newline) (display string) (newline))\n\n(define (announce-output string)\n  (newline) (display string) (newline))\n\n(define (user-print object)\n  (if (compound-procedure? object)\n      (display (list 'compound-procedure\n                     (procedure-parameters object)\n                     (procedure-body object)\n                     '<procedure-env>))\n      (display object)))\n\n; The list of all operations\n\n(define ec-operations\n  (list (list 'self-evaluating? self-evaluating?)\n        (list 'variable? variable?)\n\n        (list 'quoted? quoted?)\n        (list 'text-of-quotation text-of-quotation)\n\n        (list 'assignment? assignment?)\n        (list 'assignment-value assignment-value)\n        (list 'assignment-variable assignment-variable)\n\n        (list 'definition? definition?)\n        (list 'definition-variable definition-variable)\n        (list 'definition-value definition-value)\n\n        (list 'if? if?)\n        (list 'if-predicate if-predicate)\n        (list 'if-consequent if-consequent)\n        (list 'if-alternative if-alternative)\n\n        (list 'lambda? lambda?)\n        (list 'lambda-parameters lambda-parameters)\n        (list 'lambda-body lambda-body)\n\n        (list 'begin? begin?)\n        (list 'begin-actions begin-actions)\n        (list 'first-exp first-exp)\n        (list 'last-exp? last-exp?)\n        (list 'rest-exps rest-exps)\n\n        (list 'application? application?)\n        (list 'operands operands)\n        (list 'operator operator)\n        (list 'no-operands? no-operands?)\n        (list 'last-operand? last-operand?)\n        (list 'first-operand first-operand)\n        (list 'rest-operands rest-operands)\n\n        (list 'lookup-variable-value lookup-variable-value)\n        (list 'define-variable! define-variable!)\n        (list 'set-variable-value! set-variable-value!)\n        (list 'extend-environment extend-environment)\n\n        (list 'primitive-procedure? primitive-procedure?)\n        (list 'apply-primitive-procedure apply-primitive-procedure)\n\n        (list 'compound-procedure? compound-procedure?)\n        (list 'procedure-parameters procedure-parameters)\n        (list 'procedure-environment procedure-environment)\n        (list 'procedure-body procedure-body)\n\n        (list 'make-procedure make-procedure)\n\n        (list 'empty-arglist empty-arglist)\n        (list 'adjoin-arg adjoin-arg)\n\n        (list 'true? true?)\n        (list 'prompt-for-input prompt-for-input)\n        (list 'read read)\n        (list 'get-global-environment get-global-environment)\n        (list 'announce-output announce-output)\n        (list 'user-print user-print)\n        ))\n"
  },
  {
    "path": "scheme/sicp/05/showcase/explicit/tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n\n(load-relative \"evaluator.scm\")\n\n(define ec-machine (make-explicit-control-machine))\n\n(define (run exp)\n  (set-register-contents! ec-machine 'env (setup-environment))\n  (set-register-contents! ec-machine 'exp exp)\n\n  (start ec-machine)\n\n  (get-register-contents ec-machine 'val))\n\n(define evaluator-tests\n  (test-suite\n    \"Tests for the explicit control evaluator\"\n\n    (test-suite \"Self-evaluating expressions\"\n      (check-equal? (run '1) 1)\n      (check-equal? (run '\"something\") \"something\"))\n\n    (test-suite \"Quotation\"\n      (check-equal? (run '(quote foo)) 'foo))\n\n    (test-suite \"Begin\"\n      (check-equal? (run '(begin 1 2)) 2))\n\n    (test-suite \"Define\"\n      (check-equal? (run '(define x 1)) 'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 x))\n                    1)\n      (check-equal? (run '(define (x) 1)) 'ok)\n      (check-equal? (run '(begin (define (x) 1)\n                                 (x)))\n                    1))\n\n    (test-suite \"Set!\"\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)))\n                    'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)\n                                 x))\n                    2))\n\n    (test-suite \"If\"\n      (check-equal? (run '(if true 1 2)) 1)\n      (check-equal? (run '(if false 1 2)) 2)\n      (check-equal? (run '(if true 1)) 1)\n      (check-equal? (run '(if false 1)) false))\n\n    (test-suite \"Lambda\"\n      (check-equal? (run '((lambda () 1))) 1)\n      (check-equal? (run '((lambda (x) x) 1)) 1)\n      (check-equal? (run '((lambda (a b) (cons a b)) 1 2)) '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 ((lambda (a) (cons a b)) 3)))\n                    '(3 . 2)))\n\n    (test-suite \"Procedure application\"\n      (check-equal? (run '(begin (define (a) 1)\n                                 (a)))\n                    1)\n      (check-equal? (run '(begin (define (pair a b) (cons a b))\n                                 (pair 1 2)))\n                    '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define (pair b) (cons a b))\n                                 (pair 2)))\n                    '(1 . 2)))\n\n    (test-suite \"Defining append\"\n      (check-equal? (run '(begin (define (append x y)\n                                   (if (null? x)\n                                       y\n                                       (cons (car x)\n                                             (append (cdr x) y))))\n                                 (append '(a b c) '(d e f))))\n                    '(a b c d e f)))\n\n    (test-suite \"Factorial\"\n      (check-equal? (run '(begin (define (factorial n)\n                                   (if (= n 1)\n                                       1\n                                       (* n (factorial (- n 1)))))\n                                 (factorial 5)))\n                    120)\n      (check-equal? (run '(begin (define (factorial n)\n                                   (define (iter n result)\n                                     (if (= n 0)\n                                         result\n                                         (iter (- n 1) (* result n))))\n                                   (iter n 1))\n                                 (factorial 5)))\n                    120))\n))\n\n(run-tests evaluator-tests)\n"
  },
  {
    "path": "scheme/sicp/05/showcase/simulator/sample-machines.scm",
    "content": "(define gcd-machine\n  (make-machine\n    '(a b t)\n    (list (list 'rem remainder) (list '= =))\n    '(test-b\n        (test (op =) (reg b) (const 0))\n        (branch (label gcd-done))\n        (assign t (op rem) (reg a) (reg b))\n        (assign a (reg b))\n        (assign b (reg t))\n        (goto (label test-b))\n      gcd-done)))\n\n(define factorial-machine\n  (make-machine\n    '(n val continue)\n    (list (list '= =) (list '- -) (list '* *))\n    '(\n        (assign continue (label fact-done))\n      fact-loop\n        (test (op =) (reg n) (const 1))\n        (branch (label base-case))\n        (save continue)\n        (save n)\n        (assign n (op -) (reg n) (const 1))\n        (assign continue (label after-fact))\n        (goto (label fact-loop))\n      after-fact\n        (restore n)\n        (restore continue)\n        (assign val (op *) (reg n) (reg val))\n        (goto (reg continue))\n      base-case\n        (assign val (const 1))\n        (goto (reg continue))\n      fact-done)))\n\n(define fibonacci-machine\n  (make-machine\n    '(n val continue)\n    (list (list '< <) (list '- -) (list '+ +))\n    '(\n        (assign continue (label fib-done))\n      fib-loop\n        (test (op <) (reg n) (const 2))\n        (branch (label immediate-answer))\n        (save continue)\n        (assign continue (label after-fib-n-1))\n        (save n)\n        (assign n (op -) (reg n) (const 1))\n        (goto (label fib-loop))\n      after-fib-n-1\n        (restore n)\n        (restore continue)\n        (assign n (op -) (reg n) (const 2))\n        (save continue)\n        (assign continue (label after-fib-n-2))\n        (save val)\n        (goto (label fib-loop))\n      after-fib-n-2\n        (assign n (reg val))\n        (restore val)\n        (restore continue)\n        (assign val (op +) (reg val) (reg n))\n        (goto (reg continue))\n      immediate-answer\n        (assign val (reg n))\n        (goto (reg continue))\n      fib-done)))\n\n"
  },
  {
    "path": "scheme/sicp/05/showcase/simulator/simulator.scm",
    "content": "; The simulator from section 5.2.\n;\n; Notes:\n; * There are small variations - I don't want to use r5rs, so I'm using mcons\n;   to be able to do set-car\n\n(define (make-machine register-names ops controller-text)\n  (let ((machine (make-new-machine)))\n    (for-each (lambda (register-name)\n                ((machine 'allocate-register) register-name))\n              register-names)\n    ((machine 'install-operations) ops)\n    ((machine 'install-instruction-sequence)\n     (assemble controller-text machine))\n    machine))\n\n; Registers\n\n(define (make-register name)\n  (let ((contents '*unassigned*))\n    (define (dispatch message)\n      (cond ((eq? message 'get) contents)\n            ((eq? message 'set)\n             (lambda (value) (set! contents value)))\n            (else\n             (error \"Unknown request -- REGISTER\" message))))\n    dispatch))\n\n(define (get-contents register)\n  (register 'get))\n\n(define (set-contents! register value)\n  ((register 'set) value))\n\n; The stack\n\n(define (make-stack)\n  (let ((s '()))\n    (define (push x)\n      (set! s (cons x s)))\n    (define (pop)\n      (if (null? s)\n          (error \"Empty stack -- POP\")\n          (let ((top (car s)))\n            (set! s (cdr s))\n            top)))\n    (define (initialize)\n      (set! s '())\n      'done)\n    (define (dispatch message)\n      (cond ((eq? message 'push) push)\n            ((eq? message 'pop) (pop))\n            ((eq? message 'initialize) (initialize))\n            (else (error \"Unknown request -- STACK\" message))))\n    dispatch))\n\n(define (pop stack)\n  (stack 'pop))\n\n(define (push stack value)\n  ((stack 'push) value))\n\n; The basic machine\n\n(define (make-new-machine)\n  (let ((pc (make-register 'pc))\n        (flag (make-register 'flag))\n        (stack (make-stack))\n        (the-instruction-sequence '()))\n    (let ((the-ops (list (list 'initialize-stack\n                               (lambda () (stack 'initialize)))))\n          (register-table (list (list 'pc pc) (list 'flag flag))))\n      (define (allocate-register name)\n        (if (assoc name register-table)\n            (error \"Multiply defined register: \" name)\n            (set! register-table (cons (list name (make-register name))\n                                       register-table)))\n        'register-allocated)\n      (define (lookup-register name)\n        (let ((val (assoc name register-table)))\n          (if val\n              (cadr val)\n              (error \"Unknown register: \" name))))\n      (define (execute)\n        (let ((insts (get-contents pc)))\n          (if (null? insts)\n              'done\n              (begin\n                ((instruction-execution-proc (car insts)))\n                (execute)))))\n      (define (dispatch message)\n        (cond ((eq? message 'start)\n               (set-contents! pc the-instruction-sequence)\n               (execute))\n              ((eq? message 'install-instruction-sequence)\n               (lambda (seq) (set! the-instruction-sequence seq)))\n              ((eq? message 'allocate-register) allocate-register)\n              ((eq? message 'get-register) lookup-register)\n              ((eq? message 'install-operations)\n               (lambda (ops) (set! the-ops (append the-ops ops))))\n              ((eq? message 'stack) stack)\n              ((eq? message 'operations) the-ops)\n              (else (error \"Unknown request -- MACHINE\" message))))\n      dispatch)))\n\n(define (start machine)\n  (machine 'start))\n\n(define (get-register-contents machine register-name)\n  (get-contents (get-register machine register-name)))\n\n(define (set-register-contents! machine register-name value)\n  (set-contents! (get-register machine register-name) value)\n  'done)\n\n(define (get-register machine reg-name)\n  ((machine 'get-register) reg-name))\n\n; The Assembler\n\n(define (assemble controller-text machine)\n  (extract-labels controller-text\n    (lambda (insts labels)\n      (update-insts! insts labels machine)\n      insts)))\n\n(define (extract-labels text receive)\n  (if (null? text)\n      (receive '() '())\n      (extract-labels (cdr text)\n        (lambda (insts labels)\n          (let ((next-inst (car text)))\n            (if (symbol? next-inst)\n                (receive insts\n                         (cons (make-label-entry next-inst insts)\n                               labels))\n                (receive (cons (make-instruction next-inst)\n                               insts)\n                         labels)))))))\n\n(define (update-insts! insts labels machine)\n  (let ((pc (get-register machine 'pc))\n        (flag (get-register machine 'flag))\n        (stack (machine 'stack))\n        (ops (machine 'operations)))\n    (for-each\n      (lambda (inst)\n        (set-instruction-execution-proc!\n          inst\n          (make-execution-procedure (instruction-text inst) labels machine\n                                    pc flag stack ops)))\n      insts)))\n\n(define (make-instruction text)\n  (mcons text '()))\n(define (instruction-text inst)\n  (mcar inst))\n(define (instruction-execution-proc inst)\n  (mcdr inst))\n(define (set-instruction-execution-proc! inst proc)\n  (set-mcdr! inst proc))\n\n(define (make-label-entry label-name insts)\n  (cons label-name insts))\n\n(define (lookup-label labels label-name)\n  (let ((val (assoc label-name labels)))\n    (if val\n        (cdr val)\n        (error \"Undefined label -- ASSEMBLE\" label-name))))\n\n; Generating Execution Procedures for Instructions\n\n(define (make-execution-procedure inst labels machine\n                                  pc flag stack ops)\n  (cond ((eq? (car inst) 'assign)\n         (make-assign inst machine labels ops pc))\n        ((eq? (car inst) 'test)\n         (make-test inst machine labels ops flag pc))\n        ((eq? (car inst) 'branch)\n         (make-branch inst machine labels flag pc))\n        ((eq? (car inst) 'goto)\n         (make-goto inst machine labels pc))\n        ((eq? (car inst) 'save)\n         (make-save inst machine stack pc))\n        ((eq? (car inst) 'restore)\n         (make-restore inst machine stack pc))\n        ((eq? (car inst) 'perform)\n         (make-perform inst machine labels ops pc))\n        (else (error \"Unknown instruction type -- ASSEMBLE\" inst))))\n\n; Assign instructions\n\n(define (make-assign inst machine labels operations pc)\n  (let ((target (get-register machine (assign-reg-name inst)))\n        (value-exp (assign-value-exp inst)))\n    (let ((value-proc (if (operation-exp? value-exp)\n                          (make-operation-exp value-exp machine labels operations)\n                          (make-primitive-exp (car value-exp) machine labels))))\n      (lambda ()\n        (set-contents! target (value-proc))\n        (advance-pc pc)))))\n\n(define (assign-reg-name assign-instruction)\n  (cadr assign-instruction))\n(define (assign-value-exp assign-instruction)\n  (cddr assign-instruction))\n\n(define (advance-pc pc)\n  (set-contents! pc (cdr (get-contents pc))))\n\n; Test, branch, and goto instructions\n\n(define (make-test inst machine labels operations flag pc)\n  (let ((condition (test-condition inst)))\n    (if (operation-exp? condition)\n        (let ((condition-proc (make-operation-exp condition machine labels operations)))\n          (lambda ()\n            (set-contents! flag (condition-proc))\n            (advance-pc pc)))\n        (error \"Bad TEST instruction -- ASSEMBLE\" inst))))\n\n(define (test-condition test-instruction)\n  (cdr test-instruction))\n\n(define (make-branch inst machine labels flag pc)\n  (let ((dest (branch-dest inst)))\n    (if (label-exp? dest)\n        (let ((insts (lookup-label labels (label-exp-label dest))))\n          (lambda ()\n            (if (get-contents flag)\n                (set-contents! pc insts)\n                (advance-pc pc))))\n        (error \"Bad BRANCH instruction -- ASSEMBLE\" inst))))\n\n(define (branch-dest branch-instruction)\n  (cadr branch-instruction))\n\n(define (make-goto inst machine labels pc)\n  (let ((dest (goto-dest inst)))\n    (cond ((label-exp? dest)\n           (let ((insts (lookup-label labels (label-exp-label dest))))\n             (lambda () (set-contents! pc insts))))\n          ((register-exp? dest)\n           (let ((reg (get-register machine (register-exp-reg dest))))\n             (lambda () (set-contents! pc (get-contents reg)))))\n          (error (error \"Bad GOTO instruction -- ASSEMBLE\" inst)))))\n\n(define (goto-dest goto-instruction)\n  (cadr goto-instruction))\n\n; Other instructions\n\n(define (make-save inst machine stack pc)\n  (let ((reg (get-register machine (stack-inst-reg-name inst))))\n    (lambda ()\n      (push stack (get-contents reg))\n      (advance-pc pc))))\n\n(define (make-restore inst machine stack pc)\n  (let ((reg (get-register machine (stack-inst-reg-name inst))))\n    (lambda ()\n      (set-contents! reg (pop stack))\n      (advance-pc pc))))\n\n(define (stack-inst-reg-name stack-instruction)\n  (cadr stack-instruction))\n\n(define (make-perform inst machine labels operations pc)\n  (let ((action (perform-action inst)))\n    (if (operation-exp? action)\n        (let ((action-proc (make-operation-exp action machine labels operations)))\n          (lambda ()\n            (action-proc)\n            (advance-pc pc)))\n        (error \"Bad PERFORM instruction -- ASSEMBLE\" inst))))\n\n(define (perform-action inst)\n  (cdr inst))\n\n; Execution procedures for subexpressions\n\n(define (make-primitive-exp exp machine labels)\n  (cond ((constant-exp? exp)\n         (let ((c (constant-exp-value exp)))\n           (lambda () c)))\n        ((label-exp? exp)\n         (let ((insts (lookup-label labels (label-exp-label exp))))\n           (lambda () insts)))\n        ((register-exp? exp)\n         (let ((r (get-register machine (register-exp-reg exp))))\n           (lambda () (get-contents r))))\n        (else\n         (error \"Unknown expression type -- ASSEMBLE\" exp))))\n\n(define (register-exp? exp) (tagged-list? exp 'reg))\n(define (register-exp-reg exp) (cadr exp))\n(define (constant-exp? exp) (tagged-list? exp 'const))\n(define (constant-exp-value exp) (cadr exp))\n(define (label-exp? exp) (tagged-list? exp 'label))\n(define (label-exp-label exp) (cadr exp))\n\n(define (make-operation-exp exp machine labels operations)\n  (let ((op (lookup-prim (operation-exp-op exp) operations))\n        (aprocs (map (lambda (e) (make-primitive-exp e machine labels))\n                     (operation-exp-operands exp))))\n    (lambda ()\n      (apply op (map (lambda (p) (p)) aprocs)))))\n\n(define (operation-exp? exp)\n  (and (pair? exp) (tagged-list? (car exp) 'op)))\n(define (operation-exp-op operation-exp)\n  (cadr (car operation-exp)))\n(define (operation-exp-operands operation-exp)\n  (cdr operation-exp))\n\n(define (lookup-prim symbol operations)\n  (let ((val (assoc symbol operations)))\n    (if val\n        (cadr val)\n        (error \"Unknown operation -- ASSEMBLE\" symbol))))\n\n(define (tagged-list? exp tag)\n  (and (pair? exp)\n       (eq? (car exp) tag)))\n"
  },
  {
    "path": "scheme/sicp/05/showcase/simulator/tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n\n(load \"simulator.scm\")\n(load \"sample-machines.scm\")\n\n(define simulator-tests\n  (test-suite \"Register machine simulator tests\"\n\n    (test-case \"(gcd 206 40)\"\n      (set-register-contents! gcd-machine 'a 206)\n      (set-register-contents! gcd-machine 'b 40)\n      (start gcd-machine)\n\n      (check-eq? (get-register-contents gcd-machine 'a)\n                 2))\n\n    (test-case \"(gcd 54 24)\"\n      (set-register-contents! gcd-machine 'a 54)\n      (set-register-contents! gcd-machine 'b 24)\n      (start gcd-machine)\n\n      (check-eq? (get-register-contents gcd-machine 'a)\n                 6))\n\n    (test-case \"(gcd 13 7)\"\n      (set-register-contents! gcd-machine 'a 13)\n      (set-register-contents! gcd-machine 'b 7)\n      (start gcd-machine)\n\n      (check-eq? (get-register-contents gcd-machine 'a)\n                 1))\n\n    (test-case \"(factorial 5)\"\n      (set-register-contents! factorial-machine 'n 5)\n      (start factorial-machine)\n\n      (check-eq? (get-register-contents factorial-machine 'val)\n                 120))\n\n    (test-case \"(fibonacci 8)\"\n      (set-register-contents! fibonacci-machine 'n 8)\n      (start fibonacci-machine)\n\n      (check-eq? (get-register-contents fibonacci-machine 'val)\n                 21))\n))\n\n(run-tests simulator-tests)\n"
  },
  {
    "path": "scheme/sicp/05/support/51/evaluator.c",
    "content": "/*\n * This is the rudimentary scheme interpreter, I had to write for exercise\n * 5.51. This is very exciting for me for several reasons.\n *\n * For starters, it is the first actual C code I have written since school. I\n * had a very different memory of the language and it certainly is contrasted\n * by using Vim and gcc (or clang). It is very far from the best C code that\n * I'm able to produce, but I wanted to keep it simple and rudimentary.\n *\n * Second, it includes know-how from every part of Structure and\n * Interpretation of Computer Programs, excluding 5.5 Compilation, which is\n * the next exercise.\n *\n * Finally, it was just tons of fun writing it. I did not use my usual method\n * and I did not use a debugger to make up for it, which made it way harder.\n * More reflections can be found in the notes.\n *\n * As for what this is, it a Scheme evaluator based on the explicit-control\n * evaluator (translated line-by-line) with a garbage collector (based on the\n * one in section 5.3). It supports the functionality of the explicit-control\n * evaluator (no conds) and has tail recursion. It has a hand-written parser\n * that I care not to classify and a memory implementation like the one in\n * section 5.3. It memory leaks symbols and strings, but apart from that,\n * everything is (supposed to be) nicely collected.\n *\n * More details and commentary are intermingled with the code in comments.\n */\n\n#include <stdlib.h>\n#include <string.h>\n#include <stdio.h>\n#include <stdbool.h>\n#include <errno.h>\n\n/*\n * Some constants that set up the boundaries of the interpreter.\n */\n\n#define MAX_FILE_SIZE 10000\n#define MAX_LINE_LENGTH 1024\n#define MAX_TOKEN_LENGTH 128\n#define MEMORY_SIZE 512\n#define MEMORY_WIGGLE_ROOM 20\n#define STACK_SIZE 100\n\n/*\n * Various typedefs for all the types we're using. There are special\n * structures for the symbol table and the memory. Everything else is stored\n * in pairs.\n */\n\ntypedef enum p_type p_type;\ntypedef struct symbol_node symbol_node;\ntypedef struct pairs memory;\ntypedef struct value value;\ntypedef const char* symbol;\ntypedef value (*primitive_function)(value);\n\n/*\n * Definitions for values and memory.\n *\n * They need to be up here in order to get the file to compile. The different\n * types of values are represented by p_type. A value is a pair of a type and\n * a long. Depending on the value, the long can contain a pointer, a number or\n * some other value.\n */\n\nenum p_type {\n  p_null,\n  p_boolean,\n  p_number,\n  p_symbol,\n  p_string,\n  p_pair,\n  p_procedure,\n  p_primitive,\n  p_label,\n  p_broken_heart\n};\n\nstruct value {\n  p_type type;\n  unsigned long value;\n};\n\n/*\n * Memory declarations\n *\n * Since we use stop and copy garbage collection, modelled after section 5.3,\n * we allocate two segments of memory for the working memory and the free\n * memory. Each segment contains space for the cars and cdrs of the pairs\n * stored.\n */\n\nstruct pairs {\n  value cars[MEMORY_SIZE];\n  value cdrs[MEMORY_SIZE];\n};\n\nunsigned int free_ptr = 0;\n\nmemory *working_mem;\nmemory *free_mem;\n\nmemory block1;\nmemory block2;\n\n/*\n * The main interface\n *\n * Those functions are the C interface to the evaluator. They are used to\n * build the read-eval-print loop\n */\n\nvalue read(const char *);\nvalue eval(value);\nvoid print(value);\n\n/*\n * The number of times the garbage collector has run\n *\n * This is declared up here, since it is tricky to organize the code the way I\n * want it and not have it declared first.\n */\n\nint gc_runs = 0;\n\n/*\n * Error reporting\n *\n * A couple of functions used to report errors. They are not that much to look\n * at.\n */\n\nvoid error(const char *message) {\n  printf(\"%s\\n\", message);\n  exit(0);\n}\n\nvoid errorc(const char *message, char c) {\n  printf(\"%s: %c\\n\", message, c);\n  exit(0);\n}\n\nvoid errorv(const char *message, value val) {\n  printf(\"%s: \", message);\n  print(val);\n  printf(\"\\n\");\n  exit(0);\n}\n\nvoid errort(const char *message, char *token) {\n  token[MAX_TOKEN_LENGTH] = '\\0';\n  printf(\"%s: %s\\n\", message, token);\n  exit(0);\n}\n\nvoid errors(const char *message, symbol sym) {\n  printf(\"%s: %s\\n\", message, sym);\n  exit(0);\n}\n\n/*\n * Symbols\n *\n * The interpreter maintains a symbole table (more like a symbol linked list)\n * in order to intern symbols so they can be compared with == (and also take\n * less memory). intern() checks if the passed symbol is already allocated and\n * returns it if so. If not, it allocated a new one, copies the symbol in it\n * and returns the copy.\n */\n\nsymbol_node *symbol_table_head;\n\nstruct symbol_node {\n  symbol symbol;\n  symbol_node* next;\n};\n\nsymbol_node* allocate_symbol_node(const char *name) {\n  char *copy = calloc(sizeof(char), 1 + strlen(name));\n  strcpy(copy, name);\n\n  symbol_node *node = malloc(sizeof(node));\n  node->symbol = copy;\n  node->next = NULL;\n\n  return node;\n}\n\nsymbol intern(const char *name) {\n  if (!symbol_table_head) {\n    symbol_table_head = allocate_symbol_node(name);\n    return symbol_table_head->symbol;\n  }\n\n  symbol_node* current = symbol_table_head;\n\n  while (true) {\n    if (strcmp(name, current->symbol) == 0)\n      return current->symbol;\n    if (!current->next) {\n      symbol_node *new = allocate_symbol_node(name);\n      current->next = new;\n      return new->symbol;\n    }\n    current = current->next;\n  }\n}\n\n/*\n * Preallocated symbols\n *\n * Some symbols that we will preallocate to avoid looking up the symbol table\n * every time\n */\n\nsymbol s_quote;\nsymbol s_begin;\nsymbol s_if;\nsymbol s_define;\nsymbol s_set_bang;\nsymbol s_lambda;\nsymbol s_ok;\n\nvoid initialize_symbols() {\n  s_quote    = intern(\"quote\");\n  s_begin    = intern(\"begin\");\n  s_if       = intern(\"if\");\n  s_define   = intern(\"define\");\n  s_set_bang = intern(\"set!\");\n  s_lambda   = intern(\"lambda\");\n  s_ok       = intern(\"ok\");\n}\n\n/*\n * Values\n *\n * This section defines the values that the interpreter works with. They can\n * be pointers to memory (in the case of pairs), self contained (in the case\n * of booleans and numbers) or have a C pointer to some address in the heap\n * (in the case of primitive procedures and strings).\n *\n * Procedures are implemented as a special case of pairs. They are essentially\n * the same, but with a different type. I've chosen to go that way in order to\n * have the procedures (and environments they generate) garbage collected.\n *\n * Strings, symbols and primitives are implemented as pointers to the C\n * memory. That causes a memory leak for unneeded strings. Symbols don't\n * really need to be garbage collected and primitive procedures don't allocate\n * extra memory.\n *\n * Broken hearts are something that is used when garbage collecting.\n *\n * This section contains all the basic constructors and selectors for the\n * primitives. There are other selectors, implemented in terms of them, that\n * are defined later.\n */\n\n// Type predicates\n\nbool null_p(value val)         { return val.type == p_null;         }\nbool boolean_p(value val)      { return val.type == p_boolean;      }\nbool number_p(value val)       { return val.type == p_number;       }\nbool symbol_p(value val)       { return val.type == p_symbol;       }\nbool string_p(value val)       { return val.type == p_string;       }\nbool pair_p(value val)         { return val.type == p_pair;         }\nbool procedure_p(value val)    { return val.type == p_procedure;    }\nbool primitive_p(value val)    { return val.type == p_primitive;    }\nbool label_p(value val)        { return val.type == p_label;        }\nbool broken_heart_p(value val) { return val.type == p_broken_heart; }\n\n// Null\n\nvalue null() {\n  return (value) { p_null, 0 };\n}\n\n// Booleans\n\nvalue truev() {\n  return (value) { p_boolean, 1 };\n}\n\nvalue falsev() {\n  return (value) { p_boolean, 0 };\n}\n\nvalue booleanv(bool val) {\n  return val ? truev() : falsev();\n}\n\n// Numbers\n\nvalue num(long n) {\n  return (value) { p_number, n };\n}\n\nlong value_to_long(value val) {\n  if (val.type != p_number)\n    errorv(\"Expected a number\", val);\n\n  return (long) val.value;\n}\n\n// Symbols\n\nvalue sym(const char *s) {\n  return (value) { p_symbol, (unsigned long) intern(s) };\n}\n\nsymbol value_to_sym(value val) {\n  if (val.type != p_symbol)\n    errorv(\"Expected a symbol\", val);\n\n  return (symbol) val.value;\n}\n\n// Strings\n\nvalue str(const char *s) {\n  char *copy = calloc(sizeof(char), strlen(s) + 1);\n  strcpy(copy, s);\n  return (value) { p_string, (unsigned long) copy };\n}\n\n// Pairs\n\nvalue cons(value car, value cdr) {\n  if (free_ptr == MEMORY_SIZE) {\n    error(\"Ran out of memory\");\n  }\n\n  working_mem->cars[free_ptr] = car;\n  working_mem->cdrs[free_ptr] = cdr;\n\n  value pair = (value) { p_pair, free_ptr };\n\n  free_ptr++;\n\n  return pair;\n}\n\nvalue car(value pair) {\n  if (pair.type != p_pair)\n    errorv(\"Expected carable value\", pair);\n\n  return working_mem->cars[pair.value];\n}\n\nvalue cdr(value pair) {\n  if (pair.type != p_pair)\n    errorv(\"Expected cdrable value\", pair);\n\n  return working_mem->cdrs[pair.value];\n}\n\nvoid set_car(value pair, value val) {\n  if (pair.type != p_pair)\n    errorv(\"set_car expects a pair\", pair);\n\n  unsigned int offset = (unsigned int) pair.value;\n  working_mem->cars[offset] = val;\n}\n\nvoid set_cdr(value pair, value val) {\n  if (pair.type != p_pair)\n    errorv(\"set_cdr expects a pair\", pair);\n\n  unsigned int offset = (unsigned int) pair.value;\n  working_mem->cdrs[offset] = val;\n}\n\n// Procedures\n\nvalue pcons(value car, value cdr) {\n  value pair = cons(car, cdr);\n\n  // A little hack to reuse the cons() code.\n  pair.type = p_procedure;\n\n  return pair;\n}\n\nvalue pcdr(value proc) {\n  if (proc.type != p_procedure)\n    errorv(\"Expected a pcdrable value\", proc);\n\n  return working_mem->cdrs[proc.value];\n}\n\nvalue pcar(value proc) {\n  if (proc.type != p_procedure)\n    errorv(\"Expected a pcarable value\", proc);\n\n  return working_mem->cars[proc.value];\n}\n\n// Primitives\n\nvalue primitive(primitive_function function) {\n  return (value) { p_primitive, (unsigned long) function };\n}\n\n// Labels\n\nvalue label(void *label) {\n  return (value) { p_label, (unsigned long) label };\n}\n\nvoid *value_to_label(value label) {\n  if (!label_p(label))\n    errorv(\"Expected a label\", label);\n\n  return (void *) label.value;\n}\n\n// Broken heart\n\nvalue broken_heart() {\n  return (value) { p_broken_heart };\n}\n\n/*\n * Memory initialization\n *\n * Memory is organized as in chapter 5.3. A struct represents two arrays of\n * cars and cdrs. There are two such structs that get rotated with a\n * stop-and-copy garbage collector.\n */\n\nvoid wipe_memory(memory *memory) {\n  for (int i = 0; i < MEMORY_SIZE; i++) {\n    memory->cars[i] = (value) { p_null, 0 };\n  }\n}\n\nvoid initialize_memory() {\n  wipe_memory(&block1);\n  wipe_memory(&block2);\n\n  working_mem = &block1;\n  free_mem    = &block2;\n}\n\n/*\n * The stack\n *\n * This is a straightforward implementation of a stack.\n */\n\nint stack_ptr = 0;\nvalue stack[STACK_SIZE];\n\nvoid push(value v) {\n  if (stack_ptr == STACK_SIZE)\n    error(\"Stack overflow\");\n\n  stack[stack_ptr++] = v;\n}\n\nvalue pop() {\n  if (!stack_ptr)\n    error(\"Stack is empty\");\n\n  return stack[--stack_ptr];\n}\n\n/*\n * The registers\n *\n * Those are the registers that the explicit-control evaluator uses.\n */\n\nvalue cont;\nvalue val;\nvalue expr;\nvalue unev;\nvalue proc;\nvalue argl;\nvalue env;\n\nvoid initialize_registers() {\n  cont = null();\n  val  = null();\n  expr = null();\n  unev = null();\n  proc = null();\n  argl = null();\n  env  = null();\n}\n\n/*\n * Utility functions for working with lists\n *\n * Simle convenience functions, used in C.\n */\n\nvalue first(value pair)  { return car(pair);                }\nvalue second(value pair) { return car(cdr(pair));           }\nvalue third(value pair)  { return car(cdr(cdr(pair)));      }\nvalue fourth(value pair) { return car(cdr(cdr(cdr(pair)))); }\n\n/*\n * Standard functions\n *\n * Some of the standard Scheme functions, implemented in C. They are wrapped\n * as primitives to be available to the evaluator.\n */\n\nint length(value list) {\n  int result = 0;\n\n  while (!null_p(list)) {\n    list = cdr(list);\n    result++;\n  }\n\n  return result;\n}\n\nbool eq(value v1, value v2) {\n  return v1.type == v2.type && v1.value == v2.value;\n}\n\nbool equal(value v1, value v2) {\n  if (v1.type != v2.type)\n    return false;\n\n  if (eq(v1, v2))\n    return true;\n\n  switch (v1.type) {\n    case p_string:\n      return strcmp((char *) v1.value, (char *) v2.value) == 0;\n\n    case p_pair:\n      return equal(car(v1), car(v2)) && equal(cdr(v1), cdr(v2));\n\n    default:\n      return false;\n  }\n}\n\n/*\n * Environments\n *\n * Environments are implemented simply as lists, using the same structure as\n * the metacircular evaluator. This way they get to be garbage collected, even\n * if they are not optimal in variable lookup.\n *\n * Environments cannot be obtained with Scheme code, since they get\n * constructed only in the explicit-evaluator and are stored in registers or\n * stack. The only case when environments are stored in memory is when there\n * is a procedure in memory, but the environment cannot be obtained from\n * within the interpreter.\n */\n\nvalue empty_environment() {\n  return cons(cons(null(), cons(null(), null())), null());\n}\n\nvalue extend_environment(value vars, value vals, value enclosing) {\n  if (length(vars) != length(vals))\n    errorv(\"Argument count mismatch\", cons(vars, cons(vals, null())));\n\n  value frame = cons(vars, cons(vals, null()));\n  return cons(frame, enclosing);\n}\n\nvalue lookup_variable(symbol name, value env) {\n  while (!null_p(env)) {\n    value frame = car(env);\n    value vars  = car(frame);\n    value vals  = car(cdr(frame));\n\n    while (!null_p(vars)) {\n      if (value_to_sym(car(vars)) == name)\n        return car(vals);\n\n      vars = cdr(vars);\n      vals = cdr(vals);\n    }\n\n    env = cdr(env);\n  }\n\n  errors(\"Variable not found\", name);\n  exit(0);\n}\n\nvoid define_variable(symbol name, value val, value env) {\n  value frame = car(env);\n  value vars  = car(frame);\n  value vals  = car(cdr(frame));\n\n  set_car(frame, cons(sym(name), vars));\n  set_car(cdr(frame), cons(val, vals));\n}\n\nvoid set_variable_value(symbol name, value val, value env) {\n  while (!null_p(env)) {\n    value frame = car(env);\n    value vars  = car(frame);\n    value vals  = car(cdr(frame));\n\n    while (!null_p(vars)) {\n      if (value_to_sym(car(vars)) == name) {\n        set_car(vals, val);\n        return;\n      }\n\n      vars = cdr(vars);\n      vals = cdr(vals);\n    }\n\n    env = cdr(env);\n  }\n\n  errors(\"Variable not set\", name);\n  exit(0);\n}\n\n/*\n * The functions used by the explicit control evaluator.\n *\n * Those functions are used in the explicit control evaluator.\n */\n\nbool true_p(value val) {\n  return !boolean_p(val) || val.value != 0;\n}\n\nvalue make_procedure(value params, value body, value env) {\n  return pcons(params, cons(body, cons(env, null())));\n}\n\nvalue procedure_parameters(value proc)  { return pcar(proc);         }\nvalue procedure_body(value proc)        { return first(pcdr(proc));  }\nvalue procedure_environment(value proc) { return second(pcdr(proc)); }\n\nvalue empty_arglist() {\n  return null();\n}\n\nvalue adjoin_arg(value arg, value arglist) {\n  if (null_p(arglist))\n    return cons(arg, null());\n  else\n    return cons(car(arglist), adjoin_arg(arg, cdr(arglist)));\n}\n\nvalue apply_primitive_procedure(value proc, value args) {\n  if (!primitive_p(proc))\n    errorv(\"Trying to apply a non-primitive procedure\", proc);\n\n  primitive_function function = (primitive_function) proc.value;\n\n  return function(args);\n}\n\n/*\n * The primitive procedures\n *\n * Below are the C functions that represent all the primitive procedures in\n * the language\n */\n\nvalue prim_add(value args) {\n  long result = 0;\n\n  while (!null_p(args)) {\n    result += value_to_long(car(args));\n    args = cdr(args);\n  }\n\n  return num(result);\n}\n\nvalue prim_sub(value args) {\n  long result = value_to_long(car(args));\n  args = cdr(args);\n\n  if (null_p(args))\n    return num(-result);\n\n  while (!null_p(args)) {\n    result -= value_to_long(car(args));\n    args = cdr(args);\n  }\n\n  return num(result);\n}\n\nvalue prim_mul(value args) {\n  long result = 1;\n\n  while (!null_p(args)) {\n    result *= value_to_long(car(args));\n    args = cdr(args);\n  }\n\n  return num(result);\n}\n\nvalue prim_equal_sign(value args) {\n  long num1 = value_to_long(first(args));\n  long num2 = value_to_long(second(args));\n\n  return booleanv(num1 == num2);\n}\n\nvalue prim_less_than_sign(value args) {\n  long num1 = value_to_long(first(args));\n  long num2 = value_to_long(second(args));\n\n  return booleanv(num1 < num2);\n}\n\nvalue prim_eq_p(value args) {\n  return booleanv(eq(first(args), second(args)));\n}\n\nvalue prim_equal_p(value args) {\n  return booleanv(equal(first(args), second(args)));\n}\n\nvalue prim_number_p(value args) {\n  return booleanv(number_p(first(args)));\n}\n\nvalue prim_string_p(value args) {\n  return booleanv(string_p(first(args)));\n}\n\nvalue prim_symbol_p(value args) {\n  return booleanv(symbol_p(first(args)));\n}\n\nvalue prim_pair_p(value args) {\n  return booleanv(pair_p(first(args)));\n}\n\nvalue prim_null_p(value args) {\n  return booleanv(null_p(first(args)));\n}\n\nvalue prim_car(value args) {\n  return car(first(args));\n}\n\nvalue prim_cdr(value args) {\n  return cdr(first(args));\n}\n\nvalue prim_cons(value args) {\n  return cons(first(args), second(args));\n}\n\nvalue prim_list(value args) {\n  return args;\n}\n\nvalue prim_set_car_bang(value args) {\n  set_car(first(args), second(args));\n  return sym(s_ok);\n}\n\nvalue prim_set_cdr_bang(value args) {\n  set_cdr(first(args), second(args));\n  return sym(s_ok);\n}\n\nvalue prim_display(value args) {\n  print(first(args));\n\n  return sym(s_ok);\n}\n\nvalue prim_newline(value args) {\n  printf(\"\\n\");\n\n  return sym(s_ok);\n}\n\nvalue prim_gc_runs(value args) {\n  return num(gc_runs);\n}\n\nvalue prim_stack_max_depth(value args) {\n  return num(STACK_SIZE);\n}\n\n/*\n * The global environment\n *\n * The code below initializes the global environment\n */\n\nvalue global_env;\n\nvoid add_primitive_to_env(value env, const char *name, primitive_function function) {\n  define_variable(intern(name), primitive(function), env);\n}\n\nvoid initialize_global_environment() {\n  global_env = empty_environment();\n\n  define_variable(intern(\"true\"),  truev(),  global_env);\n  define_variable(intern(\"false\"), falsev(), global_env);\n\n  add_primitive_to_env(global_env, \"+\", prim_add);\n  add_primitive_to_env(global_env, \"-\", prim_sub);\n  add_primitive_to_env(global_env, \"*\", prim_mul);\n  add_primitive_to_env(global_env, \"=\", prim_equal_sign);\n  add_primitive_to_env(global_env, \"<\", prim_less_than_sign);\n\n  add_primitive_to_env(global_env, \"eq?\", prim_eq_p);\n  add_primitive_to_env(global_env, \"equal?\", prim_equal_p);\n\n  add_primitive_to_env(global_env, \"number?\", prim_number_p);\n  add_primitive_to_env(global_env, \"string?\", prim_string_p);\n  add_primitive_to_env(global_env, \"symbol?\", prim_symbol_p);\n  add_primitive_to_env(global_env, \"pair?\", prim_pair_p);\n  add_primitive_to_env(global_env, \"null?\", prim_null_p);\n\n  add_primitive_to_env(global_env, \"car\", prim_car);\n  add_primitive_to_env(global_env, \"cdr\", prim_cdr);\n  add_primitive_to_env(global_env, \"cons\", prim_cons);\n  add_primitive_to_env(global_env, \"list\", prim_list);\n\n  add_primitive_to_env(global_env, \"set-car!\", prim_set_car_bang);\n  add_primitive_to_env(global_env, \"set-cdr!\", prim_set_cdr_bang);\n\n  add_primitive_to_env(global_env, \"display\", prim_display);\n  add_primitive_to_env(global_env, \"newline\", prim_newline);\n\n  add_primitive_to_env(global_env, \"gc-runs\", prim_gc_runs);\n  add_primitive_to_env(global_env, \"stack-max-depth\", prim_stack_max_depth);\n}\n\n/*\n * The garbage collector\n *\n * This is based on the stop-and-copy garbage collector of section 5.3. It\n * uses a few modifications, namely how root is handled.\n *\n * Instead of having a root, we start by relocating all the registers and\n * stack. Afterwards, we run the garbage collection as usual. When it scan\n * overtakes free, we update the registers and stack pointers before flipping\n * the memory. If there are pairs in the stack or registers, they point to an\n * address in the old memory. Since it is already relocated, it will contain\n * broken hearts and forwarding addresses. All those pairs get updated with\n * the forwarding address.\n *\n * Note that procedures are treated as pairs for the purpose of garbage\n * collection.\n *\n * There is a fine point when the garbage collector is run. Before evaluating\n * an expressing, the explicit-control evaluator checks to see if there is\n * enough free memory (where \"enough\" is defined by MEMORY_WIGGLE_ROOM). If\n * not, garbage collection is triggered.\n *\n * The alternative approach will be to do that in the cons() call when we're\n * running out of memory. While that would be better, it poses two problems.\n *\n * First, the car and cdr passed to cons will contain addresses to the old\n * memory. This can be solved simply by pushing them on the stack, garbage\n * collecting and poping. That would solve the problem.\n *\n * The second is more subtle. Since the C code calls cons(), that might\n * trigger garbage collection. Let's say there is a call like this:\n *\n * cons(cons(num(1), num(2)), cons(num(3), num(4)))\n *\n * The third call to cons takes two pairs as arguments - (1 . 2) and (3 . 4).\n * If the second call triggers garbage collection, the result will be an\n * address in the new memory (provided we solved the first problem), but the\n * first pair will still have the old address. That will result to an invalid\n * pair.\n *\n * A solution I can think of is if the C cons function does not take its\n * arguments directly, but from the Scheme stack instead. That way if a cons\n * triggers garbage collection, all the intermediate pairs will be in the\n * stack and relocated from the garbage collecter.\n *\n * This is an interesting change to the code that I might revisit some day.\n * Until then, there is a preemptive check if garbage collection needs to run\n * on each evaluation of an expression.\n *\n * Garbage collection is triggered by the gc() function. I've always wanted to\n * write a function called \"gc\";\n */\n\nint gc_scan;\nint gc_free;\n\nvoid relocate(value);\nvoid update(value *);\nvoid relocate_registers_and_stack();\nvoid update_registers_and_stack();\nvoid update_value_from_old_memory(value *);\n\nvoid gc() {\n  gc_scan = 0;\n  gc_free = 0;\n\n  relocate_registers_and_stack();\n\n  while (gc_scan < gc_free) {\n    update(&free_mem->cars[gc_scan]);\n    update(&free_mem->cdrs[gc_scan]);\n\n    gc_scan++;\n  }\n\n  update_registers_and_stack();\n\n  memory *tmp = working_mem;\n  working_mem = free_mem;\n  free_mem    = tmp;\n\n  free_ptr = gc_free;\n  gc_runs  += 1;\n}\n\nvoid relocate(value val) {\n  if (!pair_p(val) && !procedure_p(val))\n    return;\n\n  int old_address = val.value;\n\n  if (broken_heart_p(working_mem->cars[old_address]))\n    return;\n\n  free_mem->cars[gc_free] = working_mem->cars[old_address];\n  free_mem->cdrs[gc_free] = working_mem->cdrs[old_address];\n\n  working_mem->cars[old_address] = broken_heart();\n  working_mem->cdrs[old_address] = num(gc_free);\n\n  gc_free++;\n}\n\nvoid update(value *val) {\n  if (!pair_p(*val) && !procedure_p(*val))\n    return;\n\n  relocate(*val);\n\n  int old_address = val->value;\n  int new_address = working_mem->cdrs[old_address].value;\n\n  val->value = new_address;\n}\n\nvoid relocate_registers_and_stack() {\n  relocate(val);\n  relocate(expr);\n  relocate(unev);\n  relocate(proc);\n  relocate(argl);\n  relocate(env);\n  relocate(cont);\n  relocate(global_env);\n\n  for(int i = 0; i < stack_ptr; i++) {\n    relocate(stack[i]);\n  }\n}\n\nvoid update_registers_and_stack() {\n  update_value_from_old_memory(&val);\n  update_value_from_old_memory(&expr);\n  update_value_from_old_memory(&unev);\n  update_value_from_old_memory(&proc);\n  update_value_from_old_memory(&argl);\n  update_value_from_old_memory(&env);\n  update_value_from_old_memory(&cont);\n  update_value_from_old_memory(&global_env);\n\n  for(int i = 0; i < stack_ptr; i++) {\n    update_value_from_old_memory(&stack[i]);\n  }\n}\n\nvoid update_value_from_old_memory(value *val) {\n  if (!pair_p(*val) && !procedure_p(*val))\n    return;\n\n  val->value = working_mem->cdrs[val->value].value;\n}\n\nvoid gc_if_necessary() {\n  if (MEMORY_SIZE - free_ptr < MEMORY_WIGGLE_ROOM) {\n    gc();\n  }\n}\n\n/*\n * The printer\n *\n * This is based on the code in exercise 4.34. It was nice to be able to reuse\n * an algorithm I though about on a piece of paper.\n */\n\nvoid print_cdr(value v) {\n  switch (v.type) {\n    case p_null:\n      printf(\")\");\n      break;\n    case p_pair:\n      printf(\" \");\n      print(car(v));\n      print_cdr(cdr(v));\n      break;\n    default:\n      printf(\" . \");\n      print(v);\n      printf(\")\");\n  }\n}\n\nvoid print(value v) {\n  switch (v.type) {\n    case p_null:\n      printf(\"()\");\n      break;\n    case p_boolean:\n      if (v.value)\n        printf(\"#t\");\n      else\n        printf(\"#f\");\n      break;\n    case p_number:\n      printf(\"%ld\", (long) v.value);\n      break;\n    case p_symbol:\n      printf(\"%s\", (symbol) v.value);\n      break;\n    case p_string:\n      printf(\"%s\", (const char *) v.value);\n      break;\n    case p_pair:\n      printf(\"(\");\n      print(car(v));\n      print_cdr(cdr(v));\n      break;\n    case p_procedure:\n      printf(\"<procedure:%d>\", (int) v.value);\n      break;\n    case p_primitive:\n      printf(\"<primitive:%ld>\", (long) v.value);\n      break;\n    case p_label:\n      printf(\"<label:%ld>\", (unsigned long) v.value);\n      break;\n    case p_broken_heart:\n      printf(\"<broken-heart>\");\n      break;\n  }\n}\n\n/*\n * The parser\n *\n * It is a simple, hand-written parser. I managed to whip it up why almost\n * asleep and without consulting the Dragon Book. I'm not extremely proud, so\n * I will gloss over details.\n *\n * It calls sym() and str(), which makes it allocate strings and symbols\n * freely. If pointers to those strings are garbage collected, this will\n * result to memory leaks.\n */\n\nconst char *input;\nchar lookahead;\nint pos = 0;\n\nvalue parse_sexp();\n\nvalue read(const char *string) {\n  input     = string;\n  pos       = 0;\n  lookahead = input[pos];\n\n  return parse_sexp();\n}\n\nchar advance() {\n  if (lookahead == '\\0')\n    error(\"Unexpected end of input\");\n\n  char result = input[pos];\n  lookahead = input[++pos];\n\n  return result;\n}\n\nvoid match(char c) {\n  if (lookahead != c)\n    errorc(\"Expected character\", c);\n  advance();\n}\n\nvoid whitespace() {\n  while (lookahead == ' ' || lookahead == '\\n' || lookahead == ';') {\n    if (lookahead == ';') {\n      match(';');\n      while (lookahead != '\\n') advance();\n      match('\\n');\n    } else {\n      advance();\n    }\n  }\n}\n\nvalue parse_symbol() {\n  char buffer[MAX_TOKEN_LENGTH + 1];\n  int i = 0;\n\n  while (lookahead != ' ' && lookahead != '\\n' && lookahead != ')' && lookahead != '\\0') {\n    buffer[i++] = advance();\n\n    if (i > MAX_TOKEN_LENGTH)\n      errort(\"Parser encountered a token that is too long\", buffer);\n  }\n\n  buffer[i] = '\\0';\n\n  return sym(buffer);\n}\n\nvalue parse_number() {\n  char buffer[MAX_TOKEN_LENGTH + 1];\n  int i = 0;\n\n  while ('0' <= lookahead && lookahead <= '9') {\n    buffer[i++] = advance();\n\n    if (i > MAX_TOKEN_LENGTH)\n      errort(\"Parser encountered a token that is too long\", buffer);\n  }\n\n  buffer[i] = '\\0';\n\n  return num(atoi(buffer));\n}\n\nvalue parse_string() {\n  char buffer[MAX_TOKEN_LENGTH + 1];\n  int i = 0;\n\n  match('\"');\n\n  while (lookahead != '\"') {\n    buffer[i++] = advance();\n\n    if (i > MAX_TOKEN_LENGTH)\n      errort(\"Parser encountered a token that is too long...\", buffer);\n  }\n\n  match('\"');\n\n  buffer[i] = '\\0';\n\n  return str(buffer);\n}\n\nvalue parse_quote() {\n  match('\\'');\n  value quoted = parse_sexp();\n\n  return cons(sym(\"quote\"),\n              cons(quoted, null()));\n}\n\nvalue parse_list() {\n  whitespace();\n\n  if (lookahead == ')') {\n    match(')');\n    return null();\n  } else if (lookahead == '.') {\n    match('.');\n    value sexp = parse_sexp();\n    whitespace();\n    match(')');\n    return sexp;\n  } else {\n    value car = parse_sexp();\n    whitespace();\n    value cdr = parse_list();\n    return cons(car, cdr);\n  }\n}\n\nvalue parse_sexp() {\n  whitespace();\n  if (lookahead == '(') {\n    match('(');\n    return parse_list();\n  } else if (lookahead == '\\'') {\n    return parse_quote();\n  } else if ('0' <= lookahead && lookahead <= '9') {\n    return parse_number();\n  } else if (lookahead == '\"') {\n    return parse_string();\n  } else {\n    return parse_symbol();\n  }\n}\n\n/*\n * Syntax functions\n *\n * The familiar syntax functions that are used to figure out what to evaluate.\n */\n\nbool tagged_list_p(value expr, symbol tag) {\n  if (expr.type == p_pair) {\n    value head = car(expr);\n    return head.type == p_symbol && ((const char *) head.value) == tag;\n  } else {\n    return false;\n  }\n}\n\nbool self_evaluating_p(value expr) { return number_p(expr) || string_p(expr); }\nbool variable_p(value expr)        { return symbol_p(expr);                   }\nbool quoted_p(value expr)          { return tagged_list_p(expr, s_quote);     }\nbool begin_p(value expr)           { return tagged_list_p(expr, s_begin);     }\nbool if_p(value expr)              { return tagged_list_p(expr, s_if);        }\nbool definition_p(value expr)      { return tagged_list_p(expr, s_define);    }\nbool assignment_p(value expr)      { return tagged_list_p(expr, s_set_bang);  }\nbool lambda_p(value expr)          { return tagged_list_p(expr, s_lambda);    }\nbool application_p(value expr)     { return pair_p(expr);                     }\n\nvalue text_of_quotation(value expr) { return car(cdr(expr)); }\n\nvalue if_predicate(value expr)   { return second(expr); }\nvalue if_consequent(value expr)  { return third(expr);  }\nvalue if_alternative(value expr) { return fourth(expr); }\n\nvalue operator(value expr)     { return car(expr);    }\nvalue operands(value expr)     { return cdr(expr);    }\nbool no_operands_p(value expr) { return null_p(expr); }\n\nvalue lambda_parameters(value expr) { return car(cdr(expr)); }\nvalue lambda_body(value expr)       { return cdr(cdr(expr)); }\n\nvalue assignment_variable(value expr) { return second(expr); }\nvalue assignment_value(value expr)    { return third(expr);  }\n\nvalue make_lambda(value parameters, value body) {\n  return cons(sym(s_lambda), cons(parameters, body));\n}\n\nvalue definition_variable(value expr) {\n  if (symbol_p(car(cdr(expr))))\n    return car(cdr(expr));\n  else\n    return car(car(cdr(expr)));\n}\n\nvalue definition_value(value expr) {\n  if (symbol_p(car(cdr(expr))))\n    return car(cdr(cdr(expr)));\n  else\n    return make_lambda(cdr(car(cdr(expr))),\n                       cdr(cdr(expr)));\n}\n\nvalue begin_actions(value expr) { return cdr(expr); }\nvalue first_exp(value expr)     { return car(expr); }\nvalue rest_exps(value expr)     { return cdr(expr); }\nint last_exp_p(value expr)      { return pair_p(expr) && null_p(cdr(expr)); }\n\nvalue first_operand(value expr) { return car(expr); }\nvalue rest_operands(value expr) { return cdr(expr); }\nint last_operand_p(value expr)  { return pair_p(expr) && null_p(cdr(expr)); }\n\n/*\n * The explicit-control evaluator\n *\n * I've chosen to translate this line-by-line for two reasons. First, I get\n * one more chance to write the explicit evaluator, using C this time, which\n * was an interesting exercise. Second, this gives me tail-call optimizations\n * for free, which is way better than figuring out a way to implement them\n * myself.\n *\n * As a fun note, we're storing pointers to labels, which I did not know was\n * possible.\n */\n\nvalue start() {\n  cont = label(&&done);\n\neval_dispatch:\n  gc_if_necessary();\n  if (self_evaluating_p(expr))\n    goto ev_self_eval;\n  if (variable_p(expr))\n    goto ev_variable;\n  if (quoted_p(expr))\n    goto ev_quoted;\n  if (assignment_p(expr))\n    goto ev_assignment;\n  if (if_p(expr))\n    goto ev_if;\n  if (definition_p(expr))\n    goto ev_definition;\n  if (begin_p(expr))\n    goto ev_begin;\n  if (lambda_p(expr))\n    goto ev_lambda;\n  if (application_p(expr))\n    goto ev_application;\n  errorv(\"Unrecognized expression\", expr);\n\nev_self_eval:\n  val = expr;\n  goto *value_to_label(cont);\nev_variable:\n  val = lookup_variable(value_to_sym(expr), env);\n  goto *value_to_label(cont);\nev_quoted:\n  val = text_of_quotation(expr);\n  goto *value_to_label(cont);\nev_lambda:\n  unev = lambda_parameters(expr);\n  expr = lambda_body(expr);\n  val  = make_procedure(unev, expr, env);\n  goto *value_to_label(cont);\n\nev_application:\n  push(cont);\n  push(env);\n  unev = operands(expr);\n  push(unev);\n  expr = operator(expr);\n  cont = label(&&ev_appl_did_operator);\n  goto eval_dispatch;\nev_appl_did_operator:\n  unev = pop();\n  env  = pop();\n  argl = empty_arglist();\n  proc = val;\n  if (no_operands_p(unev))\n    goto apply_dispatch;\n  push(proc);\nev_appl_operand_loop:\n  push(argl);\n  expr = first_operand(unev);\n  if (last_operand_p(unev))\n    goto ev_appl_last_arg;\n  push(env);\n  push(unev);\n  cont = label(&&ev_appl_accumulate_arg);\n  goto eval_dispatch;\nev_appl_accumulate_arg:\n  unev = pop();\n  env  = pop();\n  argl = pop();\n  argl = adjoin_arg(val, argl);\n  unev = rest_operands(unev);\n  goto ev_appl_operand_loop;\nev_appl_last_arg:\n  cont = label(&&ev_appl_accum_last_arg);\n  goto eval_dispatch;\nev_appl_accum_last_arg:\n  argl = pop();\n  argl = adjoin_arg(val, argl);\n  proc = pop();\n  goto apply_dispatch;\n\napply_dispatch:\n  if (primitive_p(proc))\n    goto primitive_apply;\n  if (procedure_p(proc))\n    goto compound_apply;\n  errorv(\"Unknown procedure type\", proc);\nprimitive_apply:\n  val  = apply_primitive_procedure(proc, argl);\n  cont = pop();\n  goto *value_to_label(cont);\ncompound_apply:\n  unev = procedure_parameters(proc);\n  env  = procedure_environment(proc);\n  env  = extend_environment(unev, argl, env);\n  unev = procedure_body(proc);\n  goto ev_sequence;\n\nev_begin:\n  unev = begin_actions(expr);\n  push(cont);\nev_sequence:\n  expr = first_exp(unev);\n  if (last_exp_p(unev))\n    goto ev_sequence_last_exp;\n  push(unev);\n  push(env);\n  cont = label(&&ev_sequence_continue);\n  goto eval_dispatch;\nev_sequence_continue:\n  env  = pop();\n  unev = pop();\n  unev = rest_exps(unev);\n  goto ev_sequence;\nev_sequence_last_exp:\n  cont = pop();\n  goto eval_dispatch;\n\nev_if:\n  push(expr);\n  push(env);\n  push(cont);\n  cont = label(&&ev_if_decide);\n  expr = if_predicate(expr);\n  goto eval_dispatch;\nev_if_decide:\n  cont = pop();\n  env  = pop();\n  expr = pop();\n  if (true_p(val))\n    goto ev_if_consequent;\nev_if_alternative:\n  expr = if_alternative(expr);\n  goto eval_dispatch;\nev_if_consequent:\n  expr = if_consequent(expr);\n  goto eval_dispatch;\n\nev_assignment:\n  unev = assignment_variable(expr);\n  push(unev);\n  expr = assignment_value(expr);\n  push(env);\n  push(cont);\n  cont = label(&&ev_assignment_1);\n  goto eval_dispatch;\nev_assignment_1:\n  cont = pop();\n  env  = pop();\n  unev = pop();\n  set_variable_value(value_to_sym(unev), val, env);\n  val  = sym(s_ok);\n  goto *value_to_label(cont);\n\nev_definition:\n  unev = definition_variable(expr);\n  push(unev);\n  expr = definition_value(expr);\n  push(env);\n  push(cont);\n  cont = label(&&ev_definition_1);\n  goto eval_dispatch;\nev_definition_1:\n  cont = pop();\n  env  = pop();\n  unev = pop();\n  define_variable(value_to_sym(unev), val, env);\n  val  = sym(s_ok);\n  goto *value_to_label(cont);\ndone:\n  return val;\n}\n\n/*\n * The eval function\n */\n\nvalue eval(value expression) {\n  env  = global_env;\n  expr = expression;\n\n  start();\n\n  return val;\n}\n\n/*\n * Running a file\n *\n * The file is read in a buffer and then the buffer is read and evaluated. The\n * buffer has a maximum size, over which the program will error out. Of\n * course, the buffer can be allocated dynamically, but this is just simpler.\n */\n\nvoid run_file(const char *filename) {\n  int chars_read;\n  char buffer[MAX_FILE_SIZE];\n\n  FILE *file = fopen(filename, \"r\");\n\n  if (!file) {\n    printf(\"Failed to open %s: %s\\n\", filename, strerror(errno));\n    exit(0);\n  }\n\n  chars_read = fread(buffer, sizeof(char), MAX_FILE_SIZE, file);\n  fclose(file);\n\n  if (chars_read == MAX_FILE_SIZE) {\n    printf(\"File %s is too big (more than %d bytes)\\n\", filename, MAX_FILE_SIZE);\n    exit(0);\n  }\n\n  buffer[chars_read] = '\\0';\n  eval(read(buffer));\n}\n\n/*\n * The read-eval-print loop\n *\n * There is not much needed to explain here. repl() is another name I've\n * always wanted to give to a function.\n */\n\nchar line[MAX_LINE_LENGTH + 1];\n\nvalue read_line() {\n  if (!fgets(line, MAX_LINE_LENGTH, stdin))\n    error(\"Line too long\");\n\n  return read(line);\n}\n\nvoid repl() {\n  value input, result;\n\n  printf(\"Structure and Interpretation of Computer Programs\\n\");\n  printf(\"Exercise 5.51 - Scheme evaluator in C\\n\");\n\n  while (true) {\n    printf(\"> \");\n    input = read_line();\n    result = eval(input);\n    print(result);\n    printf(\"\\n\");\n  }\n}\n\n/*\n * The main function\n *\n * It initializes everything first. Afterwards, it runs any files if passed as\n * command line arguments. Otherwise, it runs the REPL.\n */\n\nint main(int argc, char *argv[]) {\n  initialize_memory();\n  initialize_symbols();\n  initialize_registers();\n  initialize_global_environment();\n\n  if (argc > 1) {\n    for (int i = 1; i < argc; i++) {\n      run_file(argv[i]);\n    }\n  } else {\n    repl();\n  }\n}\n"
  },
  {
    "path": "scheme/sicp/05/support/51/tests.scm",
    "content": "(begin\n   (define passed-tests 0)\n   (define failed-tests 0)\n   (define (test actual expected)\n     (if (equal? actual expected)\n         (set! passed-tests (+ 1 passed-tests))\n         (set! failed-tests (+ 1 failed-tests))))\n\n   (test 1 1)\n   (test \"something\" \"something\")\n   (test (quote foo) 'foo)\n   (test (begin 1 2) 2)\n   (test (define x1 1) 'ok)\n   (test (begin (define x2 1)\n                        x2)\n         1)\n   (test (define (x3) 1)\n         'ok)\n   (test (begin (define (x3) 1)\n                (x3))\n         1)\n   (test (begin (define x4 1)\n                (set! x4 2))\n         'ok)\n   (test (begin (define x5 1)\n                (set! x5 2)\n                x5)\n         2)\n\n   (test (if true 1 2) 1)\n   (test (if false 1 2) 2)\n\n   (test ((lambda () 1)) 1)\n   (test ((lambda (x) x) 1) 1)\n   (test ((lambda (a b) (cons a b)) 1 2) '(1 . 2))\n   (test (begin (define a 1)\n                (define b 2)\n                ((lambda (a) (cons a b)) 3))\n         '(3 . 2))\n\n   (test (begin (define (a) 1)\n                (a))\n         1)\n   (test (begin (define (pair1 a b) (cons a b))\n                (pair1 1 2))\n         '(1 . 2))\n   (test (begin (define a 1)\n                (define (pair2 b) (cons a b))\n                (pair2 2))\n         '(1 . 2))\n\n   (test (begin (define (append1 x y)\n                  (if (null? x)\n                      y\n                      (cons (car x)\n                            (append1 (cdr x) y))))\n                (append1 '(a b c) '(d e f)))\n         '(a b c d e f))\n\n   (test (begin (define (factorial1 n)\n                  (if (= n 1)\n                      1\n                      (* n (factorial1 (- n 1)))))\n                (factorial1 5))\n         120)\n   (test (begin (define (factorial2 n)\n                  (define (iter n result)\n                    (if (= n 0)\n                        result\n                        (iter (- n 1) (* result n))))\n                  (iter n 1))\n                (factorial2 5))\n         120)\n\n   (test (< 1 (gc-runs)) true)\n\n   (test (begin (define (countdown n)\n                  (if (= n 0)\n                      'done\n                      (countdown (- n 1))))\n                (countdown (+ 1 (stack-max-depth))))\n         'done)\n\n   (display (list 'passed '= passed-tests 'failed '= failed-tests)))\n"
  },
  {
    "path": "scheme/sicp/05/support/52/build.scm",
    "content": "; The necessary code to compile the compiled interpreter and run the tests\n; withn it\n\n(require racket/runtime-path)\n\n(define-runtime-path base-path \".\")\n\n(define (relative-path path)\n  (find-relative-path\n    (current-directory)\n    (simplify-path (build-path base-path path))))\n\n(define source-path (relative-path \"runtime.c\"))\n(define tests-path (relative-path \"tests.scm\"))\n(define compiled-code-path (relative-path \"../bin/compiled_interpreter\"))\n(define target-path (relative-path \"../bin/52\"))\n\n(define compile-call\n  (format \"cc --std=c99 ~a -o ~a\"\n          (path->string source-path)\n          (path->string target-path)))\n\n(define run-tests-call\n  (format \"~a ~a\"\n          (path->string target-path)\n          (path->string tests-path)))\n\n(define (write-interpreter c-code)\n  (with-output-to-file compiled-code-path\n     (lambda () (display c-code))\n     #:mode 'text\n     #:exists 'truncate))\n\n(define (compile-runtime)\n  (let ((exit-code (system/exit-code compile-call)))\n    (when (not (zero? exit-code))\n          (error \"Failed to compile the runtime ;(\"))))\n\n(define (run-interpreter-tests)\n  (system run-tests-call))\n\n(define (interpreter-test-results)\n  (with-output-to-string run-interpreter-tests))\n"
  },
  {
    "path": "scheme/sicp/05/support/52/compiler.scm",
    "content": "; The section 5.5 compiler.\n;\n; The only difference is the introduction of let expressions.\n\n(define (compile-exp exp target linkage)\n  (cond ((self-evaluating? exp)\n         (compile-self-evaluating exp target linkage))\n        ((quoted? exp) (compile-quoted exp target linkage))\n        ((variable? exp)\n         (compile-variable exp target linkage))\n        ((assignment? exp)\n         (compile-assignment exp target linkage))\n        ((definition? exp)\n         (compile-definition exp target linkage))\n        ((if? exp) (compile-if exp target linkage))\n        ((let? exp) (compile-exp (let->combination exp) target linkage))\n        ((lambda? exp) (compile-lambda exp target linkage))\n        ((begin? exp)\n         (compile-sequence (begin-actions exp) target linkage))\n        ((cond? exp) (compile-exp (cond->if exp) target linkage))\n        ((application? exp)\n         (compile-application exp target linkage))\n        (else\n         (error \"Unknown expression type -- COMPILE\" exp))))\n\n; Compiling linkage code\n\n(define (compile-linkage linkage)\n  (cond ((eq? linkage 'return)\n         (make-instruction-sequence '(continue) '()\n          '((goto (reg continue)))))\n        ((eq? linkage 'next)\n         (empty-instruction-sequence))\n        (else\n         (make-instruction-sequence '() '()\n          `((goto (label ,linkage)))))))\n\n(define (end-with-linkage linkage instruction-sequence)\n  (preserving '(continue)\n              instruction-sequence\n              (compile-linkage linkage)))\n\n; Compiling simple expressions\n\n(define (compile-self-evaluating exp target linkage)\n  (end-with-linkage linkage\n   (make-instruction-sequence '() (list target)\n    `((assign ,target (const ,exp))))))\n\n(define (compile-quoted exp target linkage)\n  (end-with-linkage linkage\n   (make-instruction-sequence '() (list target)\n    `((assign ,target (const ,(text-of-quotation exp)))))))\n\n(define (compile-variable exp target linkage)\n  (end-with-linkage linkage\n   (make-instruction-sequence '(env) (list target)\n    `((assign ,target (op lookup-variable-value) (const ,exp) (reg env))))))\n\n(define (compile-assignment exp target linkage)\n  (let ((var (assignment-variable exp))\n        (get-value-code (compile-exp (assignment-value exp) 'val 'next)))\n    (end-with-linkage linkage\n     (preserving '(env)\n      get-value-code\n      (make-instruction-sequence '(env val) (list target)\n       `((perform (op set-variable-value!)\n                  (const ,var)\n                  (reg val)\n                  (reg env))\n         (assign ,target (const ok))))))))\n\n(define (compile-definition exp target linkage)\n  (let ((var (definition-variable exp))\n        (get-value-code (compile-exp (definition-value exp) 'val 'next)))\n    (end-with-linkage linkage\n     (preserving '(env)\n      get-value-code\n      (make-instruction-sequence '(env val) (list target)\n       `((perform (op define-variable!)\n                  (const ,var)\n                  (reg val)\n                  (reg env))\n         (assign ,target (const ok))))))))\n\n; Compiling conditional expressions\n\n(define (compile-if exp target linkage)\n  (let ((t-branch (make-label 'true-branch))\n        (f-branch (make-label 'false-branch))\n        (after-if (make-label 'after-if)))\n    (let ((consequent-linkage (if (eq? linkage 'next) after-if linkage)))\n      (let ((p-code (compile-exp (if-predicate exp) 'val 'next))\n            (c-code (compile-exp (if-consequent exp) target consequent-linkage))\n            (a-code (compile-exp (if-alternative exp) target linkage)))\n        (preserving '(env continue)\n         p-code\n         (append-instruction-sequences\n          (make-instruction-sequence '(val) '()\n           `((test (op false?) (reg val))\n             (branch (label ,f-branch))))\n          (parallel-instruction-sequences\n           (append-instruction-sequences t-branch c-code)\n           (append-instruction-sequences f-branch a-code))\n          after-if))))))\n\n; Compiling sequences\n\n(define (compile-sequence seq target linkage)\n  (if (last-exp? seq)\n      (compile-exp (first-exp seq) target linkage)\n      (preserving '(env continue)\n       (compile-exp (first-exp seq) target 'next)\n       (compile-sequence (rest-exps seq) target linkage))))\n\n; Compiling lambda expressions\n\n(define (compile-lambda exp target linkage)\n  (let ((proc-entry (make-label 'entry))\n        (after-lambda (make-label 'after-lambda)))\n    (let ((lambda-linkage (if (eq? linkage 'next) after-lambda linkage)))\n      (append-instruction-sequences\n       (tack-on-instruction-sequence\n        (end-with-linkage lambda-linkage\n         (make-instruction-sequence '(env) (list target)\n          `((assign ,target\n                    (op make-compiled-procedure)\n                    (label ,proc-entry)\n                    (reg env)))))\n        (compile-lambda-body exp proc-entry))\n       after-lambda))))\n\n(define (compile-lambda-body exp proc-entry)\n  (let ((formals (lambda-parameters exp)))\n    (append-instruction-sequences\n     (make-instruction-sequence '(env proc argl) '(env)\n      `(,proc-entry\n         (assign env (op compiled-procedure-env) (reg proc))\n         (assign env\n                 (op extend-environment)\n                 (const ,formals)\n                 (reg argl)\n                 (reg env))))\n     (compile-sequence (lambda-body exp) 'val 'return))))\n\n; Compiling combinations\n\n(define (compile-application exp target linkage)\n  (let ((proc-code (compile-exp (operator exp) 'proc 'next))\n        (operand-codes (map (lambda (operand) (compile-exp operand 'val 'next))\n                            (operands exp))))\n    (preserving '(env continue)\n     proc-code\n     (preserving '(proc continue)\n      (construct-arglist operand-codes)\n      (compile-procedure-call target linkage)))))\n\n(define (construct-arglist operand-codes)\n  (let ((operand-codes (reverse operand-codes)))\n    (if (null? operand-codes)\n        (make-instruction-sequence '() '(argl)\n                                   '((assign argl (const ()))))\n        (let ((code-to-get-last-arg\n               (append-instruction-sequences\n                (car operand-codes)\n                (make-instruction-sequence '(val) '(argl)\n                 '((assign argl (op list) (reg val)))))))\n          (if (null? (cdr operand-codes))\n              code-to-get-last-arg\n              (preserving '(env)\n                          code-to-get-last-arg\n                          (code-to-get-rest-args (cdr operand-codes))))))))\n\n(define (code-to-get-rest-args operand-codes)\n  (let ((code-for-next-arg (preserving '(argl)\n                                       (car operand-codes)\n                                       (make-instruction-sequence '(val argl) '(argl)\n                                        '((assign argl (op cons) (reg val) (reg argl)))))))\n    (if (null? (cdr operand-codes))\n        code-for-next-arg\n        (preserving '(env)\n                    code-for-next-arg\n                    (code-to-get-rest-args (cdr operand-codes))))))\n\n; Applying procedures\n\n(define (compile-procedure-call target linkage)\n  (let ((primitive-branch (make-label 'primitive-branch))\n        (compiled-branch (make-label 'compiled-branch))\n        (after-call (make-label 'after-call)))\n    (let ((compiled-linkage (if (eq? linkage 'next) after-call linkage)))\n      (append-instruction-sequences\n       (make-instruction-sequence '(proc) '()\n        `((test (op primitive-procedure?) (reg proc))\n          (branch (label ,primitive-branch))))\n       (parallel-instruction-sequences\n        (append-instruction-sequences\n         compiled-branch\n         (compile-proc-appl target compiled-linkage))\n        (append-instruction-sequences\n         primitive-branch\n         (end-with-linkage linkage\n          (make-instruction-sequence '(proc argl) (list target)\n           `((assign ,target\n                     (op apply-primitive-procedure)\n                     (reg proc)\n                     (reg argl)))))))\n       after-call))))\n\n; Applying compiled procedures\n\n(define all-regs '(env proc val argl continue))\n\n(define (compile-proc-appl target linkage)\n  (cond ((and (eq? target 'val) (not (eq? linkage 'return)))\n         (make-instruction-sequence '(proc) all-regs\n          `((assign continue (label ,linkage))\n            (assign val (op compiled-procedure-entry) (reg proc))\n            (goto (reg val)))))\n        ((and (not (eq? target 'val)) (not (eq? linkage 'return)))\n         (let ((proc-return (make-label 'proc-return)))\n           (make-instruction-sequence '(proc) all-regs\n            `((assign continue (label ,proc-return))\n              (assign val (op compiled-procedure-entry) (reg proc))\n              (goto (reg val))\n              ,proc-return\n              (assign ,target (reg val))\n              (goto (label ,linkage))))))\n        ((and (eq? target 'val) (eq? linkage 'return))\n         (make-instruction-sequence '(proc continue) all-regs\n          `((assign val (op compiled-procedure-entry) (reg proc))\n            (goto (reg val)))))\n        ((and (not (eq? target 'val)) (eq? linkage 'return))\n         (error \"return linkage, target not val -- COMPILE-EXP\" target))\n        (else (error \"How did we get here?\"))))\n\n; Combining Instruction Sequences\n\n(define (registers-needed s) (if (symbol? s) '() (car s)))\n(define (registers-modified s) (if (symbol? s) '() (cadr s)))\n(define (statements s) (if (symbol? s) (list s) (caddr s)))\n(define (needs-register? seq reg) (memq reg (registers-needed seq)))\n(define (modifies-register? seq reg) (memq reg (registers-modified seq)))\n\n(define (append-instruction-sequences . seqs)\n  (define (append-2-sequences seq1 seq2)\n    (make-instruction-sequence\n      (list-union (registers-needed seq1)\n                  (list-difference (registers-needed seq2)\n                                   (registers-modified seq1)))\n      (list-union (registers-modified seq1)\n                  (registers-modified seq2))\n      (append (statements seq1) (statements seq2))))\n  (define (append-seq-list seqs)\n    (if (null? seqs)\n        (empty-instruction-sequence)\n        (append-2-sequences (car seqs)\n                            (append-seq-list (cdr seqs)))))\n  (append-seq-list seqs))\n\n(define (list-union s1 s2)\n  (cond ((null? s1) s2)\n        ((memq (car s1) s2) (list-union (cdr s1) s2))\n        (else (cons (car s1) (list-union (cdr s1) s2)))))\n\n(define (list-difference s1 s2)\n  (cond ((null? s1) '())\n        ((memq (car s1) s2) (list-difference (cdr s1) s2))\n        (else (cons (car s1) (list-difference (cdr s1) s2)))))\n\n(define (preserving regs seq1 seq2)\n  (if (null? regs)\n      (append-instruction-sequences seq1 seq2)\n      (let ((first-reg (car regs)))\n        (if (and (needs-register? seq2 first-reg)\n                 (modifies-register? seq1 first-reg))\n            (preserving (cdr regs)\n             (make-instruction-sequence\n              (list-union (list first-reg) (registers-needed seq1))\n              (list-difference (registers-modified seq1) (list first-reg))\n              (append `((save ,first-reg))\n                      (statements seq1)\n                      `((restore ,first-reg))))\n             seq2)\n            (preserving (cdr regs) seq1 seq2)))))\n\n(define (tack-on-instruction-sequence seq body-seq)\n  (make-instruction-sequence (registers-needed seq)\n                             (registers-modified seq)\n                             (append (statements seq)\n                                     (statements body-seq))))\n\n(define (parallel-instruction-sequences seq1 seq2)\n  (make-instruction-sequence\n    (list-union (registers-needed seq1)\n                (registers-needed seq2))\n    (list-union (registers-modified seq1)\n                (registers-modified seq2))\n    (append (statements seq1) (statements seq2))))\n\n; Instruction sequences\n\n(define (make-instruction-sequence needs modifies statements)\n  (list needs modifies statements))\n\n(define (empty-instruction-sequence)\n  (make-instruction-sequence '() '() '()))\n\n; Make label\n\n(define label-counter 0)\n\n(define (new-label-number)\n  (set! label-counter (+ 1 label-counter))\n  label-counter)\n\n(define (make-label name)\n  (string->symbol\n    (string-append (symbol->string name)\n                   (number->string (new-label-number)))))\n\n; Compiled procedure operations\n\n(define (make-compiled-procedure entry env) (list 'compiled-procedure entry env))\n(define (compiled-procedure? proc) (tagged-list? proc 'compiled-procedure))\n(define (compiled-procedure-entry c-proc) (cadr c-proc))\n(define (compiled-procedure-env c-proc) (caddr c-proc))\n"
  },
  {
    "path": "scheme/sicp/05/support/52/metacircular-evaluator.scm",
    "content": "(define metacircular-evaluator\n  '(begin\n     (define (evaluate exp env)\n       (gc-if-necessary)\n       (cond ((self-evaluating? exp) exp)\n             ((variable? exp) (lookup-variable-value exp env))\n             ((quoted? exp) (text-of-quotation exp))\n             ((assignment? exp) (eval-assignment exp env))\n             ((definition? exp) (eval-definition exp env))\n             ((if? exp) (eval-if exp env))\n             ((lambda? exp)\n              (make-procedure (lambda-parameters exp)\n                              (lambda-body exp)\n                              env))\n             ((begin? exp)\n              (eval-sequence (begin-actions exp) env))\n             ((cond? exp) (evaluate (cond->if exp) env))\n             ((application? exp)\n              (apply-procedure (evaluate (operator exp) env)\n                               (list-of-values (operands exp) env)))\n             (else\n              (error \"Unknown expression type - EVALUATE\" exp))))\n\n     (define (apply-procedure procedure arguments)\n       (cond ((primitive-procedure? procedure)\n              (apply-primitive-procedure procedure arguments))\n             ((compound-procedure? procedure)\n              (eval-sequence\n                (procedure-body procedure)\n                (extend-environment\n                  (procedure-parameters procedure)\n                  arguments\n                  (procedure-environment procedure))))\n             (else\n              (error \"Unknown procedure type - APPLY-PROCEDURE\" procedure))))\n\n     (define (list-of-values exps env)\n       (if (no-operands? exps)\n           '()\n           (cons (evaluate (first-operand exps) env)\n                 (list-of-values (rest-operands exps) env))))\n\n     (define (eval-if exp env)\n       (if (true? (evaluate (if-predicate exp) env))\n           (evaluate (if-consequent exp) env)\n           (evaluate (if-alternative exp) env)))\n\n     (define (eval-sequence exps env)\n       (cond ((last-exp? exps) (evaluate (first-exp exps) env))\n             (else (evaluate (first-exp exps) env)\n                   (eval-sequence (rest-exps exps) env))))\n\n     (define (eval-assignment exp env)\n       (set-variable-value! (assignment-variable exp)\n                            (evaluate (assignment-value exp) env)\n                            env)\n       'ok)\n\n     (define (eval-definition exp env)\n       (define-variable! (definition-variable exp)\n                         (evaluate (definition-value exp) env)\n                         env)\n       'ok)\n\n     (define (self-evaluating? exp)\n       (cond ((number? exp) true)\n             ((string? exp) true)\n             (else false)))\n\n     (define (variable? exp) (symbol? exp))\n\n     (define (quoted? exp)\n       (tagged-list? exp 'quote))\n\n     (define (text-of-quotation exp) (cadr exp))\n\n     (define (tagged-list? exp tag)\n       (if (pair? exp)\n           (eq? (car exp) tag)\n           false))\n\n     (define (assignment? exp) (tagged-list? exp 'set!))\n     (define (assignment-variable exp) (cadr exp))\n     (define (assignment-value exp) (caddr exp))\n\n     (define (definition? exp)\n       (tagged-list? exp 'define))\n     (define (definition-variable exp)\n       (if (symbol? (cadr exp))\n         (cadr exp)\n         (caadr exp)))\n     (define (definition-value exp)\n       (if (symbol? (cadr exp))\n           (caddr exp)\n           (make-lambda (cdadr exp)\n                        (cddr exp))))\n\n     (define (lambda? exp) (tagged-list? exp 'lambda))\n     (define (lambda-parameters exp) (cadr exp))\n     (define (lambda-body exp) (cddr exp))\n     (define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n     (define (if? exp) (tagged-list? exp 'if))\n     (define (if-predicate exp) (cadr exp))\n     (define (if-consequent exp) (caddr exp))\n     (define (if-alternative exp)\n       (if (not (null? (cdddr exp)))\n           (cadddr exp)\n           'false))\n\n     (define (make-if predicate consequent alternative)\n       (list 'if predicate consequent alternative))\n\n     (define (begin? exp) (tagged-list? exp 'begin))\n     (define (begin-actions exp) (cdr exp))\n     (define (last-exp? seq) (null? (cdr seq)))\n     (define (first-exp seq) (car seq))\n     (define (rest-exps seq) (cdr seq))\n     (define (sequence->exp seq)\n       (cond ((null? seq) seq)\n             ((last-exp? seq) (first-exp seq))\n             (else (make-begin seq))))\n     (define (make-begin seq) (cons 'begin seq))\n\n     (define (application? exp) (pair? exp))\n     (define (operator exp) (car exp))\n     (define (operands exp) (cdr exp))\n     (define (no-operands? ops) (null? ops))\n     (define (first-operand ops) (car ops))\n     (define (rest-operands ops) (cdr ops))\n\n     (define (cond? exp) (tagged-list? exp 'cond))\n     (define (cond-clauses exp) (cdr exp))\n     (define (cond-else-clause? clause)\n       (eq? (cond-predicate clause) 'else))\n     (define (cond-predicate clause) (car clause))\n     (define (cond-actions clause) (cdr clause))\n     (define (cond->if exp)\n       (expand-clauses (cond-clauses exp)))\n     (define (expand-clauses clauses)\n       (if (null? clauses)\n           'false\n           (let ((first (car clauses))\n                 (rest (cdr clauses)))\n             (if (cond-else-clause? first)\n                 (if (null? rest)\n                     (sequence->exp (cond-actions first))\n                     (error \"ELSE clause isn't last - COND->IF\" clauses))\n                 (make-if (cond-predicate first)\n                          (sequence->exp (cond-actions first))\n                          (expand-clauses rest))))))\n\n     (define (true? x) (not (eq? x false)))\n     (define (false? x) (eq? x false))\n\n     (define (make-procedure parameters body env)\n       (list 'procedure parameters body env))\n     (define (compound-procedure? p)\n       (tagged-list? p 'procedure))\n     (define (procedure-parameters p) (cadr p))\n     (define (procedure-body p) (caddr p))\n     (define (procedure-environment p) (cadddr p))\n\n     (define (enclosing-environment env) (cdr env))\n     (define (first-frame env) (car env))\n     (define the-empty-environment '())\n\n     (define (make-frame variables values)\n       (cons variables values))\n     (define (frame-variables frame) (car frame))\n     (define (frame-values frame) (cdr frame))\n     (define (add-binding-to-frame! var val frame)\n       (set-car! frame (cons var (car frame)))\n       (set-cdr! frame (cons val (cdr frame))))\n     (define (extend-environment vars vals base-env)\n       (if (= (length vars) (length vals))\n           (cons (make-frame vars vals) base-env)\n           (if (< (length vars) (length vals))\n               (error \"Too many arguments supplied\" vars vals)\n               (error \"Too few arguments supplied\" vars vals))))\n     (define (lookup-variable-value var env)\n       (define (env-loop env)\n         (define (scan vars vals)\n           (cond ((null? vars)\n                  (env-loop (enclosing-environment env)))\n                 ((eq? var (car vars))\n                  (car vals))\n                 (else (scan (cdr vars) (cdr vals)))))\n         (if (eq? env the-empty-environment)\n             (error \"Unbound variable\" var)\n             (let ((frame (first-frame env)))\n               (scan (frame-variables frame)\n                     (frame-values frame)))))\n       (env-loop env))\n     (define (set-variable-value! var val env)\n       (define (env-loop env)\n         (define (scan vars vals)\n           (cond ((null? vars)\n                  (env-loop (enclosing-environment env)))\n                 ((eq? var (car vars))\n                  (set-car! vals val))\n                 (else (scan (cdr vars) (cdr vals)))))\n         (if (eq? env the-empty-environment)\n             (error \"Unbound variable - SET!\" var)\n             (let ((frame (first-frame env)))\n               (scan (frame-variables frame)\n                     (frame-values frame)))))\n       (env-loop env))\n     (define (define-variable! var val env)\n       (let ((frame (first-frame env)))\n         (define (scan vars vals)\n           (cond ((null? vars)\n                  (add-binding-to-frame! var val frame))\n                 ((eq? var (car vars))\n                  (set-car! vals val))\n                 (else (scan (cdr vars) (cdr vals)))))\n         (scan (frame-variables frame)\n               (frame-values frame))))\n\n     (define (primitive-procedure? proc)\n       (tagged-list? proc 'evaluator-primitive))\n     (define (primitive-implementation proc) (cadr proc))\n\n     (define primitive-procedures\n       (list (list 'car car)\n             (list 'cdr cdr)\n             (list 'cons cons)\n             (list 'list list)\n             (list 'display display)\n             (list 'null? null?)\n             (list 'equal? equal?)\n             (list 'stack-max-depth stack-max-depth)\n             (list 'gc-runs gc-runs)\n             (list '= =)\n             (list '+ +)\n             (list '- -)\n             (list '* *)\n             (list '< <)))\n\n     (define (primitive-procedure-names)\n       (map car primitive-procedures))\n     (define (primitive-procedure-objects)\n       (map (lambda (proc) (list 'evaluator-primitive (cadr proc)))\n            primitive-procedures))\n\n     (define (apply-primitive-procedure proc args)\n       (apply-primitive (primitive-implementation proc) args))\n\n     (define (setup-environment)\n       (let ((initial-env\n               (extend-environment (primitive-procedure-names)\n                                   (primitive-procedure-objects)\n                                   the-empty-environment)))\n         (define-variable! 'true true initial-env)\n         (define-variable! 'false false initial-env)\n         initial-env))\n\n     (define (map proc lst)\n       (if (null? lst)\n           '()\n           (cons (proc (car lst))\n                 (map proc (cdr lst)))))\n\n     (define (cadr lst) (car (cdr lst)))\n     (define (cddr lst) (cdr (cdr lst)))\n     (define (caadr lst) (car (car (cdr lst))))\n     (define (caddr lst) (car (cdr (cdr lst))))\n     (define (cdadr lst) (cdr (car (cdr lst))))\n     (define (cdddr lst) (cdr (cdr (cdr lst))))\n     (define (cadddr lst) (car (cdr (cdr (cdr lst)))))\n\n     (define (not x) (if x false true))\n\n     (define (length lst)\n       (if (null? lst)\n           0\n           (+ 1 (length (cdr lst)))))\n\n     (define the-global-environment (setup-environment))\n\n     (define (eval* exp)\n       (evaluate exp the-global-environment))))\n"
  },
  {
    "path": "scheme/sicp/05/support/52/runtime.c",
    "content": "/*\n * The code for exercise 5.52.\n *\n * I wrote it by copying the code for 5.51, removing the unneeded parts and\n * adding the required primitive operations. The new code is at the end of the\n * file, after the main function.\n *\n * All this code here is necessary as a runtime for the compiled Scheme\n * interpreter.\n *\n * It's noteworthy that the call to gc_if_necessary() is triggered from the\n * interpreter. There is a primitive procedure gc-if-necessary that wraps the\n * call and it is called before evaluating an expression.\n */\n\n#include <stdlib.h>\n#include <string.h>\n#include <stdio.h>\n#include <stdbool.h>\n#include <errno.h>\n\n#define MAX_FILE_SIZE 10000\n#define MAX_LINE_LENGTH 50\n#define MAX_TOKEN_LENGTH 128\n#define MEMORY_SIZE 10000\n#define MEMORY_WIGGLE_ROOM 1000\n#define STACK_SIZE 400\n\ntypedef enum p_type p_type;\ntypedef struct symbol_node symbol_node;\ntypedef struct pairs memory;\ntypedef struct value value;\ntypedef const char* symbol;\ntypedef value (*primitive_function)(value);\n\n/*\n * Definitions for values and memory.\n */\n\nenum p_type {\n  p_null,\n  p_boolean,\n  p_number,\n  p_symbol,\n  p_string,\n  p_pair,\n  p_procedure,\n  p_primitive,\n  p_label,\n  p_broken_heart\n};\n\nstruct value {\n  p_type type;\n  unsigned long value;\n};\n\n/*\n * Memory declarations\n */\n\nstruct pairs {\n  value cars[MEMORY_SIZE];\n  value cdrs[MEMORY_SIZE];\n};\n\nunsigned int free_ptr = 0;\n\nmemory *working_mem;\nmemory *free_mem;\n\nmemory block1;\nmemory block2;\n\n/*\n * The main interface\n */\n\nvalue read(const char *);\nvalue eval(value);\nvoid print(value);\nvoid gc_if_necessary();\n\n/*\n * The number of times the garbage collector has run\n */\n\nint gc_runs = 0;\n\n/*\n * Error reporting\n */\n\nvoid error(const char *message) {\n  printf(\"%s\\n\", message);\n  exit(0);\n}\n\nvoid errorc(const char *message, char c) {\n  printf(\"%s: %c\\n\", message, c);\n  exit(0);\n}\n\nvoid errorv(const char *message, value val) {\n  printf(\"%s: \", message);\n  print(val);\n  printf(\"\\n\");\n  exit(0);\n}\n\nvoid errort(const char *message, char *token) {\n  token[MAX_TOKEN_LENGTH] = '\\0';\n  printf(\"%s: %s\\n\", message, token);\n  exit(0);\n}\n\nvoid errors(const char *message, symbol sym) {\n  printf(\"%s: %s\\n\", message, sym);\n  exit(0);\n}\n\n/*\n * Symbols\n */\n\nsymbol_node *symbol_table_head;\n\nstruct symbol_node {\n  symbol symbol;\n  symbol_node* next;\n};\n\nsymbol_node* allocate_symbol_node(const char *name) {\n  char *copy = calloc(sizeof(char), 1 + strlen(name));\n  strcpy(copy, name);\n\n  symbol_node *node = malloc(sizeof(node));\n  node->symbol = copy;\n  node->next = NULL;\n\n  return node;\n}\n\nsymbol intern(const char *name) {\n  if (!symbol_table_head) {\n    symbol_table_head = allocate_symbol_node(name);\n    return symbol_table_head->symbol;\n  }\n\n  symbol_node* current = symbol_table_head;\n\n  while (true) {\n    if (strcmp(name, current->symbol) == 0)\n      return current->symbol;\n    if (!current->next) {\n      symbol_node *new = allocate_symbol_node(name);\n      current->next = new;\n      return new->symbol;\n    }\n    current = current->next;\n  }\n}\n\n/*\n * Preallocated symbols\n */\n\nsymbol s_quote;\nsymbol s_begin;\nsymbol s_if;\nsymbol s_define;\nsymbol s_set_bang;\nsymbol s_lambda;\nsymbol s_ok;\n\nvoid initialize_symbols() {\n  s_quote    = intern(\"quote\");\n  s_begin    = intern(\"begin\");\n  s_if       = intern(\"if\");\n  s_define   = intern(\"define\");\n  s_set_bang = intern(\"set!\");\n  s_lambda   = intern(\"lambda\");\n  s_ok       = intern(\"ok\");\n}\n\n/*\n * Values\n */\n\n// Type predicates\n\nbool null_p(value val)         { return val.type == p_null;         }\nbool boolean_p(value val)      { return val.type == p_boolean;      }\nbool number_p(value val)       { return val.type == p_number;       }\nbool symbol_p(value val)       { return val.type == p_symbol;       }\nbool string_p(value val)       { return val.type == p_string;       }\nbool pair_p(value val)         { return val.type == p_pair;         }\nbool procedure_p(value val)    { return val.type == p_procedure;    }\nbool primitive_p(value val)    { return val.type == p_primitive;    }\nbool label_p(value val)        { return val.type == p_label;        }\nbool broken_heart_p(value val) { return val.type == p_broken_heart; }\n\n// Null\n\nvalue null() {\n  return (value) { p_null, 0 };\n}\n\n// Booleans\n\nvalue truev() {\n  return (value) { p_boolean, 1 };\n}\n\nvalue falsev() {\n  return (value) { p_boolean, 0 };\n}\n\nvalue booleanv(bool val) {\n  return val ? truev() : falsev();\n}\n\n// Numbers\n\nvalue num(long n) {\n  return (value) { p_number, n };\n}\n\nlong value_to_long(value val) {\n  if (val.type != p_number)\n    errorv(\"Expected a number\", val);\n\n  return (long) val.value;\n}\n\n// Symbols\n\nvalue sym(const char *s) {\n  return (value) { p_symbol, (unsigned long) intern(s) };\n}\n\nsymbol value_to_sym(value val) {\n  if (val.type != p_symbol)\n    errorv(\"Expected a symbol\", val);\n\n  return (symbol) val.value;\n}\n\n// Strings\n\nvalue str(const char *s) {\n  char *copy = calloc(sizeof(char), strlen(s) + 1);\n  strcpy(copy, s);\n  return (value) { p_string, (unsigned long) copy };\n}\n\n// Pairs\n\nvalue cons(value car, value cdr) {\n  if (free_ptr == MEMORY_SIZE) {\n    error(\"Ran out of memory\");\n  }\n\n  working_mem->cars[free_ptr] = car;\n  working_mem->cdrs[free_ptr] = cdr;\n\n  value pair = (value) { p_pair, free_ptr };\n\n  free_ptr++;\n\n  return pair;\n}\n\nvalue car(value pair) {\n  if (pair.type != p_pair)\n    errorv(\"Expected carable value\", pair);\n\n  return working_mem->cars[pair.value];\n}\n\nvalue cdr(value pair) {\n  if (pair.type != p_pair)\n    errorv(\"Expected cdrable value\", pair);\n\n  return working_mem->cdrs[pair.value];\n}\n\nvoid set_car(value pair, value val) {\n  if (pair.type != p_pair)\n    errorv(\"set_car expects a pair\", pair);\n\n  unsigned int offset = (unsigned int) pair.value;\n  working_mem->cars[offset] = val;\n}\n\nvoid set_cdr(value pair, value val) {\n  if (pair.type != p_pair)\n    errorv(\"set_cdr expects a pair\", pair);\n\n  unsigned int offset = (unsigned int) pair.value;\n  working_mem->cdrs[offset] = val;\n}\n\n// Procedures\n\nvalue pcons(value car, value cdr) {\n  value pair = cons(car, cdr);\n\n  // A little hack to reuse the cons() code.\n  pair.type = p_procedure;\n\n  return pair;\n}\n\nvalue pcdr(value proc) {\n  if (proc.type != p_procedure)\n    errorv(\"Expected a pcdrable value\", proc);\n\n  return working_mem->cdrs[proc.value];\n}\n\nvalue pcar(value proc) {\n  if (proc.type != p_procedure)\n    errorv(\"Expected a pcarable value\", proc);\n\n  return working_mem->cars[proc.value];\n}\n\n// Primitives\n\nvalue primitive(primitive_function function) {\n  return (value) { p_primitive, (unsigned long) function };\n}\n\n// Labels\n\nvalue label(void *label) {\n  return (value) { p_label, (unsigned long) label };\n}\n\nvoid *value_to_label(value label) {\n  if (!label_p(label))\n    errorv(\"Expected a label\", label);\n\n  return (void *) label.value;\n}\n\n// Broken heart\n\nvalue broken_heart() {\n  return (value) { p_broken_heart };\n}\n\n/*\n * Memory initialization\n */\n\nvoid wipe_memory(memory *memory) {\n  for (int i = 0; i < MEMORY_SIZE; i++) {\n    memory->cars[i] = (value) { p_null, 0 };\n  }\n}\n\nvoid initialize_memory() {\n  wipe_memory(&block1);\n  wipe_memory(&block2);\n\n  working_mem = &block1;\n  free_mem    = &block2;\n}\n\n/*\n * The stack\n */\n\nint stack_ptr = 0;\nvalue stack[STACK_SIZE];\n\nvoid push(value v) {\n  if (stack_ptr == STACK_SIZE)\n    error(\"Stack overflow\");\n\n  stack[stack_ptr++] = v;\n}\n\nvalue pop() {\n  if (!stack_ptr)\n    error(\"Stack is empty\");\n\n  return stack[--stack_ptr];\n}\n\n/*\n * The registers\n */\n\nbool test;\nvalue cont;\nvalue val;\nvalue proc;\nvalue argl;\nvalue env;\n\nvoid initialize_registers() {\n  cont = null();\n  val  = null();\n  proc = null();\n  argl = null();\n  env  = null();\n}\n\n/*\n * Utility functions for working with lists\n */\n\nvalue first(value pair)  { return car(pair);                }\nvalue second(value pair) { return car(cdr(pair));           }\nvalue third(value pair)  { return car(cdr(cdr(pair)));      }\nvalue fourth(value pair) { return car(cdr(cdr(cdr(pair)))); }\n\n/*\n * Standard functions\n */\n\nint length(value list) {\n  int result = 0;\n\n  while (!null_p(list)) {\n    list = cdr(list);\n    result++;\n  }\n\n  return result;\n}\n\nbool eq(value v1, value v2) {\n  return v1.type == v2.type && v1.value == v2.value;\n}\n\nbool equal(value v1, value v2) {\n  if (v1.type != v2.type)\n    return false;\n\n  if (eq(v1, v2))\n    return true;\n\n  switch (v1.type) {\n    case p_string:\n      return strcmp((char *) v1.value, (char *) v2.value) == 0;\n\n    case p_pair:\n      return equal(car(v1), car(v2)) && equal(cdr(v1), cdr(v2));\n\n    default:\n      return false;\n  }\n}\n\n/*\n * Environments\n */\n\nvalue empty_environment() {\n  return cons(cons(null(), cons(null(), null())), null());\n}\n\nvalue extend_environment(value vars, value vals, value enclosing) {\n  if (length(vars) != length(vals))\n    errorv(\"Argument count mismatch\", cons(vars, cons(vals, null())));\n\n  value frame = cons(vars, cons(vals, null()));\n  return cons(frame, enclosing);\n}\n\nvalue lookup_variable(symbol name, value env) {\n  while (!null_p(env)) {\n    value frame = car(env);\n    value vars  = car(frame);\n    value vals  = car(cdr(frame));\n\n    while (!null_p(vars)) {\n      if (value_to_sym(car(vars)) == name)\n        return car(vals);\n\n      vars = cdr(vars);\n      vals = cdr(vals);\n    }\n\n    env = cdr(env);\n  }\n\n  errors(\"Variable not found\", name);\n  exit(0);\n}\n\nvoid define_variable(symbol name, value val, value env) {\n  value frame = car(env);\n  value vars  = car(frame);\n  value vals  = car(cdr(frame));\n\n  set_car(frame, cons(sym(name), vars));\n  set_car(cdr(frame), cons(val, vals));\n}\n\nvoid set_variable_value(symbol name, value val, value env) {\n  while (!null_p(env)) {\n    value frame = car(env);\n    value vars  = car(frame);\n    value vals  = car(cdr(frame));\n\n    while (!null_p(vars)) {\n      if (value_to_sym(car(vars)) == name) {\n        set_car(vals, val);\n        return;\n      }\n\n      vars = cdr(vars);\n      vals = cdr(vals);\n    }\n\n    env = cdr(env);\n  }\n\n  errors(\"Variable not set\", name);\n  exit(0);\n}\n\n/*\n * Applying a primitive procedure\n */\n\nvalue apply_primitive_procedure(value proc, value args) {\n  if (!primitive_p(proc))\n    errorv(\"Trying to apply a non-primitive procedure\", proc);\n\n  primitive_function function = (primitive_function) proc.value;\n\n  return function(args);\n}\n\n/*\n * The primitive procedures\n */\n\nvalue prim_add(value args) {\n  long result = 0;\n\n  while (!null_p(args)) {\n    result += value_to_long(car(args));\n    args = cdr(args);\n  }\n\n  return num(result);\n}\n\nvalue prim_sub(value args) {\n  long result = value_to_long(car(args));\n  args = cdr(args);\n\n  if (null_p(args))\n    return num(-result);\n\n  while (!null_p(args)) {\n    result -= value_to_long(car(args));\n    args = cdr(args);\n  }\n\n  return num(result);\n}\n\nvalue prim_mul(value args) {\n  long result = 1;\n\n  while (!null_p(args)) {\n    result *= value_to_long(car(args));\n    args = cdr(args);\n  }\n\n  return num(result);\n}\n\nvalue prim_equal_sign(value args) {\n  long num1 = value_to_long(first(args));\n  long num2 = value_to_long(second(args));\n\n  return booleanv(num1 == num2);\n}\n\nvalue prim_less_than_sign(value args) {\n  long num1 = value_to_long(first(args));\n  long num2 = value_to_long(second(args));\n\n  return booleanv(num1 < num2);\n}\n\nvalue prim_eq_p(value args) {\n  return booleanv(eq(first(args), second(args)));\n}\n\nvalue prim_equal_p(value args) {\n  return booleanv(equal(first(args), second(args)));\n}\n\nvalue prim_number_p(value args) {\n  return booleanv(number_p(first(args)));\n}\n\nvalue prim_string_p(value args) {\n  return booleanv(string_p(first(args)));\n}\n\nvalue prim_symbol_p(value args) {\n  return booleanv(symbol_p(first(args)));\n}\n\nvalue prim_pair_p(value args) {\n  return booleanv(pair_p(first(args)));\n}\n\nvalue prim_null_p(value args) {\n  return booleanv(null_p(first(args)));\n}\n\nvalue prim_car(value args) {\n  return car(first(args));\n}\n\nvalue prim_cdr(value args) {\n  return cdr(first(args));\n}\n\nvalue prim_cons(value args) {\n  return cons(first(args), second(args));\n}\n\nvalue prim_list(value args) {\n  return args;\n}\n\nvalue prim_set_car_bang(value args) {\n  set_car(first(args), second(args));\n  return sym(s_ok);\n}\n\nvalue prim_set_cdr_bang(value args) {\n  set_cdr(first(args), second(args));\n  return sym(s_ok);\n}\n\nvalue prim_display(value args) {\n  print(first(args));\n\n  return sym(s_ok);\n}\n\nvalue prim_newline(value args) {\n  printf(\"\\n\");\n\n  return sym(s_ok);\n}\n\nvalue prim_gc_if_necessary(value args) {\n  gc_if_necessary();\n  return sym(s_ok);\n}\n\nvalue prim_gc_runs(value args) {\n  return num(gc_runs);\n}\n\nvalue prim_stack_max_depth(value args) {\n  return num(STACK_SIZE);\n}\n\nvalue prim_apply_primitive(value args) {\n  value proc      = first(args);\n  value arguments = second(args);\n\n  if (!primitive_p(proc))\n    errorv(\"Expected a primitive procedure\", proc);\n\n  return apply_primitive_procedure(proc, arguments);\n}\n\nvalue prim_error(value args) {\n  value message = car(args);\n  value info    = cdr(args);\n\n  errorv((const char *) message.value, info);\n  exit(0);\n}\n\n/*\n * The global environment\n */\n\nvalue global_env;\n\nvoid add_primitive_to_env(value env, const char *name, primitive_function function) {\n  define_variable(intern(name), primitive(function), env);\n}\n\nvoid initialize_global_environment() {\n  global_env = empty_environment();\n\n  define_variable(intern(\"true\"),  truev(),  global_env);\n  define_variable(intern(\"false\"), falsev(), global_env);\n\n  add_primitive_to_env(global_env, \"+\", prim_add);\n  add_primitive_to_env(global_env, \"-\", prim_sub);\n  add_primitive_to_env(global_env, \"*\", prim_mul);\n  add_primitive_to_env(global_env, \"=\", prim_equal_sign);\n  add_primitive_to_env(global_env, \"<\", prim_less_than_sign);\n\n  add_primitive_to_env(global_env, \"eq?\", prim_eq_p);\n  add_primitive_to_env(global_env, \"equal?\", prim_equal_p);\n\n  add_primitive_to_env(global_env, \"number?\", prim_number_p);\n  add_primitive_to_env(global_env, \"string?\", prim_string_p);\n  add_primitive_to_env(global_env, \"symbol?\", prim_symbol_p);\n  add_primitive_to_env(global_env, \"pair?\", prim_pair_p);\n  add_primitive_to_env(global_env, \"null?\", prim_null_p);\n\n  add_primitive_to_env(global_env, \"car\", prim_car);\n  add_primitive_to_env(global_env, \"cdr\", prim_cdr);\n  add_primitive_to_env(global_env, \"cons\", prim_cons);\n  add_primitive_to_env(global_env, \"list\", prim_list);\n\n  add_primitive_to_env(global_env, \"set-car!\", prim_set_car_bang);\n  add_primitive_to_env(global_env, \"set-cdr!\", prim_set_cdr_bang);\n\n  add_primitive_to_env(global_env, \"display\", prim_display);\n  add_primitive_to_env(global_env, \"newline\", prim_newline);\n\n  add_primitive_to_env(global_env, \"apply-primitive\", prim_apply_primitive);\n  add_primitive_to_env(global_env, \"error\", prim_error);\n\n  add_primitive_to_env(global_env, \"gc-runs\", prim_gc_runs);\n  add_primitive_to_env(global_env, \"gc-if-necessary\", prim_gc_if_necessary);\n  add_primitive_to_env(global_env, \"stack-max-depth\", prim_stack_max_depth);\n}\n\n/*\n * The garbage collector\n */\n\nint gc_scan;\nint gc_free;\n\nvoid relocate(value);\nvoid update(value *);\nvoid relocate_registers_and_stack();\nvoid update_registers_and_stack();\nvoid update_value_from_old_memory(value *);\n\nbool repeat = true;\n\nvoid gc() {\n  gc_scan = 0;\n  gc_free = 0;\n\n  relocate_registers_and_stack();\n\n  while (gc_scan < gc_free) {\n    update(&free_mem->cars[gc_scan]);\n    update(&free_mem->cdrs[gc_scan]);\n\n    gc_scan++;\n  }\n\n  update_registers_and_stack();\n\n  memory *tmp = working_mem;\n  working_mem = free_mem;\n  free_mem    = tmp;\n\n  free_ptr = gc_free;\n  gc_runs  += 1;\n}\n\nvoid relocate(value val) {\n  if (!pair_p(val) && !procedure_p(val))\n    return;\n\n  int old_address = val.value;\n\n  if (broken_heart_p(working_mem->cars[old_address]))\n    return;\n\n  free_mem->cars[gc_free] = working_mem->cars[old_address];\n  free_mem->cdrs[gc_free] = working_mem->cdrs[old_address];\n\n  working_mem->cars[old_address] = broken_heart();\n  working_mem->cdrs[old_address] = num(gc_free);\n\n  gc_free++;\n}\n\nvoid update(value *val) {\n  if (!pair_p(*val) && !procedure_p(*val))\n    return;\n\n  relocate(*val);\n\n  int old_address = val->value;\n  int new_address = working_mem->cdrs[old_address].value;\n\n  val->value = new_address;\n}\n\nvoid relocate_registers_and_stack() {\n  relocate(val);\n  relocate(proc);\n  relocate(argl);\n  relocate(env);\n  relocate(cont);\n  relocate(global_env);\n\n  for(int i = 0; i < stack_ptr; i++) {\n    relocate(stack[i]);\n  }\n}\n\nvoid update_registers_and_stack() {\n  update_value_from_old_memory(&val);\n  update_value_from_old_memory(&proc);\n  update_value_from_old_memory(&argl);\n  update_value_from_old_memory(&env);\n  update_value_from_old_memory(&cont);\n  update_value_from_old_memory(&global_env);\n\n  for(int i = 0; i < stack_ptr; i++) {\n    update_value_from_old_memory(&stack[i]);\n  }\n}\n\nvoid update_value_from_old_memory(value *val) {\n  if (!pair_p(*val) && !procedure_p(*val))\n    return;\n\n  val->value = working_mem->cdrs[val->value].value;\n}\n\nvoid gc_if_necessary() {\n  if (MEMORY_SIZE - free_ptr < MEMORY_WIGGLE_ROOM) {\n    repeat = true;\n    gc();\n  }\n}\n\n/*\n * The printer\n */\n\nvoid print_cdr(value v) {\n  switch (v.type) {\n    case p_null:\n      printf(\")\");\n      break;\n    case p_pair:\n      printf(\" \");\n      print(car(v));\n      print_cdr(cdr(v));\n      break;\n    default:\n      printf(\" . \");\n      print(v);\n      printf(\")\");\n  }\n}\n\nvoid print(value v) {\n  switch (v.type) {\n    case p_pair:\n      printf(\"(\");\n      print(car(v));\n      print_cdr(cdr(v));\n      break;\n    case p_null:\n      printf(\"()\");\n      break;\n    case p_symbol:\n      printf(\"%s\", (symbol) v.value);\n      break;\n    case p_number:\n      printf(\"%ld\", (long) v.value);\n      break;\n    case p_string:\n      printf(\"%s\", (const char *) v.value);\n      break;\n    case p_procedure:\n      printf(\"<procedure:%d>\", (int) v.value);\n      break;\n    case p_primitive:\n      printf(\"<primitive:%ld>\", (long) v.value);\n      break;\n    case p_label:\n      printf(\"<label:%ld>\", (unsigned long) v.value);\n      return;\n    case p_boolean:\n      if (v.value)\n        printf(\"#t\");\n      else\n        printf(\"#f\");\n      break;\n    case p_broken_heart:\n      printf(\"<broken-heart>\");\n      break;\n  }\n}\n\n/*\n * The parser\n */\n\nconst char *input;\nchar lookahead;\nint pos = 0;\n\nvalue parse_sexp();\n\nvalue read(const char *string) {\n  input     = string;\n  pos       = 0;\n  lookahead = input[pos];\n\n  return parse_sexp();\n}\n\nchar advance() {\n  if (lookahead == '\\0')\n    error(\"Unexpected end of input\");\n\n  char result = input[pos];\n  lookahead = input[++pos];\n\n  return result;\n}\n\nvoid match(char c) {\n  if (lookahead != c)\n    errorc(\"Expected character\", c);\n  advance();\n}\n\nvoid whitespace() {\n  while (lookahead == ' ' || lookahead == '\\n' || lookahead == ';') {\n    if (lookahead == ';') {\n      match(';');\n      while (lookahead != '\\n') advance();\n      match('\\n');\n    } else {\n      advance();\n    }\n  }\n}\n\nvalue parse_symbol() {\n  char buffer[MAX_TOKEN_LENGTH + 1];\n  int i = 0;\n\n  while (lookahead != ' ' && lookahead != '\\n' && lookahead != ')' && lookahead != '\\0') {\n    buffer[i++] = advance();\n\n    if (i > MAX_TOKEN_LENGTH)\n      errort(\"Parser encountered a token that is too long\", buffer);\n  }\n\n  buffer[i] = '\\0';\n\n  return sym(buffer);\n}\n\nvalue parse_number() {\n  char buffer[MAX_TOKEN_LENGTH + 1];\n  int i = 0;\n\n  while ('0' <= lookahead && lookahead <= '9') {\n    buffer[i++] = advance();\n\n    if (i > MAX_TOKEN_LENGTH)\n      errort(\"Parser encountered a token that is too long\", buffer);\n  }\n\n  buffer[i] = '\\0';\n\n  return num(atoi(buffer));\n}\n\nvalue parse_string() {\n  char buffer[MAX_TOKEN_LENGTH + 1];\n  int i = 0;\n\n  match('\"');\n\n  while (lookahead != '\"') {\n    buffer[i++] = advance();\n\n    if (i > MAX_TOKEN_LENGTH)\n      errort(\"Parser encountered a token that is too long...\", buffer);\n  }\n\n  match('\"');\n\n  buffer[i] = '\\0';\n\n  return str(buffer);\n}\n\nvalue parse_quote() {\n  match('\\'');\n  value quoted = parse_sexp();\n\n  return cons(sym(\"quote\"),\n              cons(quoted, null()));\n}\n\nvalue parse_list() {\n  whitespace();\n\n  if (lookahead == ')') {\n    match(')');\n    return null();\n  } else if (lookahead == '.') {\n    match('.');\n    value sexp = parse_sexp();\n    whitespace();\n    match(')');\n    return sexp;\n  } else {\n    value car = parse_sexp();\n    whitespace();\n    value cdr = parse_list();\n    return cons(car, cdr);\n  }\n}\n\nvalue parse_sexp() {\n  whitespace();\n  if (lookahead == '(') {\n    match('(');\n    return parse_list();\n  } else if (lookahead == '\\'') {\n    return parse_quote();\n  } else if ('0' <= lookahead && lookahead <= '9') {\n    return parse_number();\n  } else if (lookahead == '\"') {\n    return parse_string();\n  } else {\n    return parse_symbol();\n  }\n}\n\n/*\n * Running a file\n */\n\nvoid run_file(const char *filename) {\n  int chars_read;\n  char buffer[MAX_FILE_SIZE];\n\n  FILE *file = fopen(filename, \"r\");\n\n  if (!file) {\n    printf(\"Failed to open %s: %s\\n\", filename, strerror(errno));\n    exit(0);\n  }\n\n  chars_read = fread(buffer, sizeof(char), MAX_FILE_SIZE, file);\n  fclose(file);\n\n  if (chars_read == MAX_FILE_SIZE) {\n    printf(\"File %s is too big (more than %d bytes)\\n\", filename, MAX_FILE_SIZE);\n    exit(0);\n  }\n\n  buffer[chars_read] = '\\0';\n  eval(read(buffer));\n}\n\n/*\n * The read-eval-print loop\n */\n\nchar line[MAX_LINE_LENGTH + 1];\n\nvalue read_line() {\n  if (!fgets(line, MAX_LINE_LENGTH, stdin))\n    error(\"Line too long\");\n\n  return read(line);\n}\n\nvoid repl() {\n  value input, result;\n\n  printf(\"Structure and Interpretation of Computer Programs\\n\");\n  printf(\"Exercise 5.52 - (Compiled) Scheme in C\\n\");\n\n  while (true) {\n    printf(\"> \");\n    input = read_line();\n    result = eval(input);\n    print(result);\n    printf(\"\\n\");\n  }\n}\n\n/*\n * The main function\n */\n\nint main(int argc, char *argv[]) {\n  initialize_memory();\n  initialize_symbols();\n  initialize_registers();\n  initialize_global_environment();\n\n  if (argc > 1) {\n    for (int i = 1; i < argc; i++) {\n      run_file(argv[i]);\n    }\n  } else {\n    repl();\n  }\n}\n\n/*\n * Primitive operations\n *\n * Those correspond to the primitive operations that the compiler expects.\n * They are, of course, implemented in C.\n */\n\nbool primitive_procedure_p(value proc) {\n  return primitive_p(proc);\n}\n\nvalue lookup_variable_value(value name, value env) {\n  return lookup_variable(value_to_sym(name), env);\n}\n\nvalue list(value singleton) {\n  return cons(singleton, null());\n}\n\nvalue make_compiled_procedure(value entry, value env) {\n  return pcons(entry, env);\n}\n\nvalue compiled_procedure_entry(value proc) {\n  return pcar(proc);\n}\n\nvalue compiled_procedure_env(value proc) {\n  return pcdr(proc);\n}\n\nvoid set_variable_value_bang(value name, value val, value env) {\n  set_variable_value(value_to_sym(name), val, env);\n}\n\nvoid define_variable_bang(value name, value val, value env) {\n  define_variable(value_to_sym(name), val, env);\n}\n\nbool true_p(value val) {\n  return !boolean_p(val) || val.value != 0;\n}\n\nbool false_p(value val) {\n  return !true_p(val);\n}\n\n/*\n * The eval function\n *\n * The function is similar to what we do in section 5.5, except that the\n * read-eval-print loop is written in C. The first time the function is called\n * it runs the compiled interpreter in order to populate the global\n * environment. Afterwards the interpreter code is skipped and the function\n * jumps directly to evaluating the passed expression.\n *\n * The expression is evaluated in a tricky way. The C code knows that the\n * compiled interpreter defines a procedure eval* that evalutes and expression\n * in the global environment. It finds that procedure in the environment and\n * calls it. That happens by assigning it to proc, assigning its argument\n * (wrapped in a list) to argl and jumping to its entry point. Upon completion\n * the result is in val.\n */\n\nbool interpreter_loaded = false;\n\nvalue eval(value expr) {\n  push(expr);\n  env  = global_env;\n\n  if (interpreter_loaded)\n    goto evaluate_expression;\n\n#include \"../bin/compiled_interpreter\"\n  interpreter_loaded = true;\n\nevaluate_expression:\n  cont = label(&&done);\n  proc = lookup_variable(intern(\"eval*\"), env);\n  val  = compiled_procedure_entry(proc);\n  argl = list(expr);\n  goto *value_to_label(val);\n\ndone:\n  pop();\n  return val;\n}\n"
  },
  {
    "path": "scheme/sicp/05/support/52/syntax.scm",
    "content": "; The usual syntax functions.\n;\n; It's noteworthy that lambda body are scanning out defines.\n\n(define (self-evaluating? exp)\n  (cond ((number? exp) true)\n        ((string? exp) true)\n        (else false)))\n\n(define (quoted? exp)\n  (tagged-list? exp 'quote))\n(define (text-of-quotation exp) (cadr exp))\n\n(define (variable? exp) (symbol? exp))\n\n(define (assignment? exp) (tagged-list? exp 'set!))\n(define (assignment-variable exp) (cadr exp))\n(define (assignment-value exp) (caddr exp))\n\n(define (definition? exp) (tagged-list? exp 'define))\n(define (definition-variable exp)\n  (if (symbol? (cadr exp))\n    (cadr exp)\n    (caadr exp)))\n(define (definition-value exp)\n  (if (symbol? (cadr exp))\n      (caddr exp)\n      (make-lambda (cdadr exp)\n                   (cddr exp))))\n\n(define (if? exp) (tagged-list? exp 'if))\n(define (if-predicate exp) (cadr exp))\n(define (if-consequent exp) (caddr exp))\n(define (if-alternative exp)\n  (if (not (null? (cdddr exp)))\n      (cadddr exp)\n      'false))\n\n(define (make-if predicate consequent alternative)\n  (list 'if predicate consequent alternative))\n\n(define (let? exp) (tagged-list? exp 'let))\n\n(define (let->combination exp)\n  (let ((names (map car (cadr exp)))\n        (values (map cadr (cadr exp)))\n        (body (cddr exp)))\n    (cons (cons 'lambda (cons names body))\n          values)))\n\n(define (lambda? exp) (tagged-list? exp 'lambda))\n(define (lambda-parameters exp) (cadr exp))\n(define (lambda-body exp) (scan-out-defines (cddr exp)))\n(define (make-lambda parameters body) (cons 'lambda (cons parameters body)))\n\n(define (begin? exp) (tagged-list? exp 'begin))\n(define (begin-actions exp) (cdr exp))\n(define (last-exp? seq) (null? (cdr seq)))\n(define (first-exp seq) (car seq))\n(define (rest-exps seq) (cdr seq))\n(define (sequence->exp seq)\n  (cond ((null? seq) seq)\n        ((last-exp? seq) (first-exp seq))\n        (else (make-begin seq))))\n(define (make-begin seq) (cons 'begin seq))\n\n(define (cond? exp) (tagged-list? exp 'cond))\n(define (cond-clauses exp) (cdr exp))\n(define (cond-else-clause? clause)\n  (eq? (cond-predicate clause) 'else))\n(define (cond-predicate clause) (car clause))\n(define (cond-actions clause) (cdr clause))\n(define (cond->if exp)\n  (expand-clauses (cond-clauses exp)))\n(define (expand-clauses clauses)\n  (if (null? clauses)\n      'false\n      (let ((first (car clauses))\n            (rest (cdr clauses)))\n        (if (cond-else-clause? first)\n            (if (null? rest)\n                (sequence->exp (cond-actions first))\n                (error \"ELSE clause isn't last - COND->IF\" clauses))\n            (make-if (cond-predicate first)\n                     (sequence->exp (cond-actions first))\n                     (expand-clauses rest))))))\n\n(define (application? exp) (pair? exp))\n(define (operator exp) (car exp))\n(define (operands exp) (cdr exp))\n(define (no-operands? ops) (null? ops))\n(define (first-operand ops) (car ops))\n(define (rest-operands ops) (cdr ops))\n\n(define (tagged-list? exp tag)\n  (if (pair? exp)\n      (eq? (car exp) tag)\n      false))\n\n(define (scan-out-defines body)\n  (define (definitions-in body)\n    (cond ((null? body)\n           '())\n          ((definition? (car body))\n           (cons (car body) (definitions-in (cdr body))))\n          (else\n           (definitions-in (cdr body)))))\n  (define (body-without-definitions body)\n    (cond ((null? body)\n           '())\n          ((definition? (car body))\n           (body-without-definitions (cdr body)))\n          (else\n           (cons (car body) (body-without-definitions (cdr body))))))\n  (define (definition->unassigned-pair definition)\n    (list (definition-variable definition) ''*unassigned*))\n  (define (definition->set! definition)\n    (list 'set! (definition-variable definition) (definition-value definition)))\n  (define (defines->let definitions body)\n    (list\n      (cons 'let\n            (cons (map definition->unassigned-pair definitions)\n                  (append (map definition->set! definitions) body)))))\n\n  (let ((internal-definitions (definitions-in body)))\n    (if (null? internal-definitions)\n        body\n        (defines->let internal-definitions (body-without-definitions body)))))\n"
  },
  {
    "path": "scheme/sicp/05/support/52/tests.scm",
    "content": "(begin\n   (define passed-tests 0)\n   (define failed-tests 0)\n   (define (test actual expected)\n     (if (equal? actual expected)\n         (set! passed-tests (+ 1 passed-tests))\n         (set! failed-tests (+ 1 failed-tests))))\n\n   (test 1 1)\n   (test \"something\" \"something\")\n   (test (quote foo) 'foo)\n   (test (begin 1 2) 2)\n   (test (define x1 1) 'ok)\n   (test (begin (define x2 1)\n                        x2)\n         1)\n   (test (define (x3) 1)\n         'ok)\n   (test (begin (define (x3) 1)\n                (x3))\n         1)\n   (test (begin (define x4 1)\n                (set! x4 2))\n         'ok)\n   (test (begin (define x5 1)\n                (set! x5 2)\n                x5)\n         2)\n\n   (test (if true 1 2) 1)\n   (test (if false 1 2) 2)\n\n   (test ((lambda () 1)) 1)\n   (test ((lambda (x) x) 1) 1)\n   (test ((lambda (a b) (cons a b)) 1 2) '(1 . 2))\n   (test (begin (define a 1)\n                (define b 2)\n                ((lambda (a) (cons a b)) 3))\n         '(3 . 2))\n\n   (test (cond (true 1)) 1)\n   (test (cond (false 1) (true 2)) 2)\n   (test (cond (false 1) (else 2)) 2)\n\n   (test (begin (define (a) 1)\n                (a))\n         1)\n   (test (begin (define (pair1 a b) (cons a b))\n                (pair1 1 2))\n         '(1 . 2))\n   (test (begin (define a 1)\n                (define (pair2 b) (cons a b))\n                (pair2 2))\n         '(1 . 2))\n\n   (test (begin (define (append1 x y)\n                  (if (null? x)\n                      y\n                      (cons (car x)\n                            (append1 (cdr x) y))))\n                (append1 '(a b c) '(d e f)))\n         '(a b c d e f))\n\n   (test (begin (define (factorial1 n)\n                  (if (= n 1)\n                      1\n                      (* n (factorial1 (- n 1)))))\n                (factorial1 5))\n         120)\n   (test (begin (define (factorial2 n)\n                  (define (iter n result)\n                    (if (= n 0)\n                        result\n                        (iter (- n 1) (* result n))))\n                  (iter n 1))\n                (factorial2 5))\n         120)\n\n   (test (< 1 (gc-runs)) true)\n\n   (test (begin (define (countdown n)\n                  (if (= n 0)\n                      'done\n                      (countdown (- n 1))))\n                (countdown (+ 1 (stack-max-depth))))\n         'done)\n\n   (display (list 'passed '= passed-tests 'failed '= failed-tests))))\n"
  },
  {
    "path": "scheme/sicp/05/support/bin/.gitignore",
    "content": "51\n52\ncompiled_interpreter\n"
  },
  {
    "path": "scheme/sicp/05/tests/02-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../02.scm\")\n\n(define sicp-5.02-tests\n  (test-suite\n    \"Tests for SICP exercise 5.02\"\n\n    (test-case \"(factorial 5)\"\n      (set-register-contents! factorial-machine 'n 5)\n      (start factorial-machine)\n\n      (check-eq? (get-register-contents factorial-machine 'p)\n                 120))\n))\n\n(run-tests sicp-5.02-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/03-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../03.scm\")\n\n(define sicp-5.03-tests\n  (test-suite\n    \"Tests for SICP exercise 5.03\"\n\n    (test-case \"(simple-sqrt 2.0)\"\n      (set-register-contents! simple-sqrt-machine 'x 2.0)\n      (start simple-sqrt-machine)\n\n      (check-= (get-register-contents simple-sqrt-machine 'g)\n               1.41421\n               0.00001))\n\n    (test-case \"(simple-sqrt 4.0)\"\n      (set-register-contents! simple-sqrt-machine 'x 4.0)\n      (start simple-sqrt-machine)\n\n      (check-= (get-register-contents simple-sqrt-machine 'g)\n               2.0\n               0.00001))\n\n    (test-case \"(complex-sqrt 2.0)\"\n      (set-register-contents! complex-sqrt-machine 'x 2.0)\n      (start complex-sqrt-machine)\n\n      (check-= (get-register-contents complex-sqrt-machine 'g)\n               1.41421\n               0.00001))\n\n    (test-case \"(complex-sqrt 4.0)\"\n      (set-register-contents! complex-sqrt-machine 'x 4.0)\n      (start complex-sqrt-machine)\n\n      (check-= (get-register-contents complex-sqrt-machine 'g)\n               2.0\n               0.00001))\n))\n\n(run-tests sicp-5.03-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/04-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../04.scm\")\n\n(define sicp-5.04-tests\n  (test-suite\n    \"Tests for SICP exercise 5.04\"\n\n    (test-case \"(recursive-expt 2 8)\"\n      (set-register-contents! recursive-expt-machine 'b 2)\n      (set-register-contents! recursive-expt-machine 'n 8)\n      (start recursive-expt-machine)\n\n      (check-eq? (get-register-contents recursive-expt-machine 'val)\n                256))\n\n    (test-case \"(iterative-expt 2 8)\"\n      (set-register-contents! iterative-expt-machine 'b 2)\n      (set-register-contents! iterative-expt-machine 'n 8)\n      (start iterative-expt-machine)\n\n      (check-eq? (get-register-contents iterative-expt-machine 'val)\n                256))\n))\n\n(run-tests sicp-5.04-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/06-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../06.scm\")\n\n(define sicp-5.06-tests\n  (test-suite\n    \"Tests for SICP exercise 5.06\"\n\n    (test-case \"(fibonacci 8)\"\n      (set-register-contents! fibonacci-machine 'n 8)\n      (start fibonacci-machine)\n\n      (check-eq? (get-register-contents fibonacci-machine 'val)\n                 21))\n))\n\n(run-tests sicp-5.06-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/08-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../08.scm\")\n\n(define sicp-5.08-tests\n  (test-suite\n    \"Tests for SICP exercise 5.08\"\n\n    (check-exn (regexp \"Duplicate label: here\")\n               (lambda ()\n                 (make-machine\n                   '(a)\n                   '()\n                   '(\n                       (goto (label here))\n                     here\n                       (assign a (const 3))\n                       (goto (label there))\n                     here\n                       (assign a (const 4))\n                       (goto (label there))\n                     there))))\n))\n\n(run-tests sicp-5.08-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/09-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../09.scm\")\n\n(define sicp-5.09-tests\n  (test-suite\n    \"Tests for SICP exercise 5.09\"\n\n    (check-exn (regexp \"Operations are not applicable to labels\")\n               (lambda ()\n                 (make-machine\n                   '(a)\n                   (list (list '+ +))\n                   '(foo\n                      (assign a (op +) (label foo) (label bar))\n                     bar))))\n\n\n))\n\n(run-tests sicp-5.09-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/10-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../10.scm\")\n\n(define sicp-5.10-tests\n  (test-suite\n    \"Tests for SICP exercise 5.10\"\n\n    (test-case \"(fibonacci 8)\"\n      (set-register-contents! fibonacci-machine 'n 8)\n      (start fibonacci-machine)\n\n      (check-eq? (get-register-contents fibonacci-machine 'val)\n                 21))\n))\n\n(run-tests sicp-5.10-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/11-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../11.scm\")\n\n(define sicp-5.11-tests\n  (test-suite\n    \"Tests for SICP exercise 5.11\"\n\n    (test-case \"a. Shorter Fibonacci machine\"\n      (use-version-a!)\n      (let ((fibonacci-machine (make-shorter-fibonacci-machine)))\n        (set-register-contents! fibonacci-machine 'n 8)\n        (start fibonacci-machine)\n\n        (check-eq? (get-register-contents fibonacci-machine 'val)\n                   21)))\n\n    (test-case \"b. Erroring out on restoring wrong register\"\n      (use-version-b!)\n      (check-exn (regexp \"Mismatching registers: x \\\\(restore y\\\\)\")\n                 (lambda ()\n                   (start (make-machine '(x y)\n                                        '()\n                                        '((assign x (const 1))\n                                          (save x)\n                                          (restore y)))))))\n\n    (test-case \"c. A stack per register\"\n      (use-version-c!)\n      (let ((machine (make-machine '(x y)\n                                   '()\n                                   '((assign x (const 1))\n                                     (assign y (const 2))\n                                     (save x)\n                                     (save y)\n                                     (assign x (const 3))\n                                     (assign y (const 4))\n                                     (restore x)\n                                     (restore y)))))\n        (start machine)\n\n        (check-eq? (get-register-contents machine 'x) 1)\n        (check-eq? (get-register-contents machine 'y) 2)))\n))\n\n(run-tests sicp-5.11-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/12-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../12.scm\")\n(load \"helpers/sample-machines.scm\")\n\n(define sicp-5.12-tests\n  (test-suite\n    \"Tests for SICP exercise 5.12\"\n\n    (check-equal? (fibonacci-machine 'data-path-instructions)\n                  '((assign continue (label after-fib-n-1))\n                    (assign continue (label after-fib-n-2))\n                    (assign continue (label fib-done))\n                    (assign n (op -) (reg n) (const 1))\n                    (assign n (op -) (reg n) (const 2))\n                    (assign n (reg val))\n                    (assign val (op +) (reg val) (reg n))\n                    (assign val (reg n))\n                    (branch (label immediate-answer))\n                    (goto (label fib-loop))\n                    (goto (reg continue))\n                    (restore continue)\n                    (restore n)\n                    (restore val)\n                    (save continue)\n                    (save n)\n                    (save val)\n                    (test (op <) (reg n) (const 2))))\n\n    (check-equal? (fibonacci-machine 'data-path-entry-point-registers)\n                  '(continue))\n\n    (check-equal? (fibonacci-machine 'data-path-stack-registers)\n                  '(continue n val))\n\n    (check-equal? (fibonacci-machine 'data-path-register-sources)\n                  '((continue (label after-fib-n-1)\n                              (label after-fib-n-2)\n                              (label fib-done))\n                    (n ((op -) (reg n) (const 1))\n                       ((op -) (reg n) (const 2))\n                       (reg val))\n                    (val ((op +) (reg val) (reg n))\n                         (reg n))))\n\n    (check-equal? (factorial-machine 'data-path-register-sources)\n                  '((continue (label after-fact)\n                              (label fact-done))\n                    (n ((op -) (reg n) (const 1)))\n                    (val ((op *) (reg n) (reg val))\n                         (const 1))))\n))\n\n(run-tests sicp-5.12-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/13-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../13.scm\")\n\n(define fibonacci-machine\n  (make-machine\n    (list (list '< <) (list '- -) (list '+ +))\n    '(\n        (assign continue (label fib-done))\n      fib-loop\n        (test (op <) (reg n) (const 2))\n        (branch (label immediate-answer))\n        (save continue)\n        (assign continue (label after-fib-n-1))\n        (save n)\n        (assign n (op -) (reg n) (const 1))\n        (goto (label fib-loop))\n      after-fib-n-1\n        (restore n)\n        (restore continue)\n        (assign n (op -) (reg n) (const 2))\n        (save continue)\n        (assign continue (label after-fib-n-2))\n        (save val)\n        (goto (label fib-loop))\n      after-fib-n-2\n        (assign n (reg val))\n        (restore val)\n        (restore continue)\n        (assign val (op +) (reg val) (reg n))\n        (goto (reg continue))\n      immediate-answer\n        (assign val (reg n))\n        (goto (reg continue))\n      fib-done)))\n\n(define sicp-5.13-tests\n  (test-suite\n    \"Tests for SICP exercise 5.13\"\n\n    (test-case \"(fibonacci 8)\"\n      (set-register-contents! fibonacci-machine 'n 8)\n      (start fibonacci-machine)\n\n      (check-eq? (get-register-contents fibonacci-machine 'val)\n                 21))\n))\n\n(run-tests sicp-5.13-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/15-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../15.scm\")\n\n(define sicp-5.15-tests\n  (test-suite\n    \"Tests for SICP exercise 5.15\"\n\n    (test-begin \"Counting instructions\"\n      (let ((machine (make-machine '(a) '()\n                                   '(begin\n                                       (goto (label middle))\n                                       (assign a (const 1))\n                                     middle\n                                       (assign a (const 2))\n                                       (assign a (const 3))\n                                     end))))\n        (start machine)\n        (check-eq? (machine 'instruction-count) 3)\n        (check-eq? (machine 'instruction-count) 0)))\n))\n\n(run-tests sicp-5.15-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/16-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../16.scm\")\n\n(define instructions '())\n(define (get-instructions)\n  (reverse instructions))\n(define (collect-instructions inst)\n  (set! instructions (cons inst instructions)))\n(define (reset-tracing!)\n  (set! instructions '()))\n\n(define machine\n  (make-machine '(a) '()\n                '(begin\n                    (goto (label middle))\n                    (assign a (const 1))\n                  middle\n                    (assign a (const 2))\n                    (assign a (const 3))\n                  end)))\n\n(define sicp-5.16-tests\n  (test-suite\n    \"Tests for SICP exercise 5.16\"\n\n    (test-begin \"Tracing instructions\"\n      (reset-tracing!)\n      (machine 'trace-on)\n      ((machine 'install-trace-proc) collect-instructions)\n      (start machine)\n      (check-equal? (get-instructions)\n                    '((goto (label middle))\n                      (assign a (const 2))\n                      (assign a (const 3)))))\n\n    (test-begin \"Tracing turned off\"\n      (reset-tracing!)\n      (machine 'trace-off)\n      ((machine 'install-trace-proc) collect-instructions)\n      (start machine)\n      (check-equal? (get-instructions) '()))\n))\n\n(run-tests sicp-5.16-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/17-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../17.scm\")\n\n(define instructions '())\n(define (get-instructions)\n  (reverse instructions))\n(define (collect-instructions inst)\n  (set! instructions (cons inst instructions)))\n(define (reset-tracing!)\n  (set! instructions '()))\n\n(define machine\n  (make-machine '(a) '()\n                '(begin\n                    (goto (label middle))\n                    (assign a (const 1))\n                  middle\n                    (assign a (const 2))\n                    (assign a (const 3))\n                  end)))\n\n(define sicp-5.17-tests\n  (test-suite\n    \"Tests for SICP exercise 5.17\"\n\n    (test-begin \"Tracing labels\"\n      (reset-tracing!)\n      (machine 'trace-on)\n      ((machine 'install-trace-proc) collect-instructions)\n\n      (start machine)\n\n      (check-eq? (machine 'instruction-count) 3)\n      (check-equal? (get-instructions)\n                    '(begin\n                      (goto (label middle))\n                      middle\n                      (assign a (const 2))\n                      (assign a (const 3)))))\n))\n\n(run-tests sicp-5.17-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/18-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../18.scm\")\n\n(define traces '())\n(define (get-traces)\n  (reverse traces))\n(define (collect-traces name old new)\n  (set! traces (cons `(,name old = ,old new = ,new) traces)))\n(define (reset-tracing!)\n  (set! traces '()))\n\n(define machine\n  (make-machine '(a) '()\n                '((assign a (const 1))\n                  (assign a (const 2)))))\n\n(define sicp-5.18-tests\n  (test-suite\n    \"Tests for SICP exercise 5.18\"\n\n    (test-case \"Tracing a register\"\n      (reset-tracing!)\n      ((machine 'install-register-trace-proc) collect-traces)\n      ((machine 'register-trace-on) 'a)\n\n      (start machine)\n\n      (check-equal? (get-traces)\n                    '((a old = *unassigned* new = 1)\n                      (a old = 1            new = 2))))\n\n    (test-case \"Tracing turned off\"\n      (reset-tracing!)\n      ((machine 'install-register-trace-proc) collect-traces)\n      ((machine 'register-trace-off) 'a)\n\n      (start machine)\n\n      (check-equal? (get-traces) '()))\n))\n\n(run-tests sicp-5.18-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/19-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/simulator.scm\")\n(load \"../19.scm\")\n\n(define (test-machine)\n  (make-machine '(a)\n                '()\n                '(start\n                    (assign a (const 1))\n                    (assign a (const 2))\n                    (assign a (const 3))\n                    (assign a (const 4))\n                    (assign a (const 5))\n                  before-six\n                    (assign a (const 6))\n                    (assign a (const 7))\n                    (assign a (const 8))\n                    (assign a (const 9))\n                    (assign a (const 10)))))\n\n\n(define sicp-5.19-tests\n  (test-suite\n    \"Tests for SICP exercise 5.19\"\n\n    (test-case \"Checking breakpoints\"\n      (define machine (test-machine))\n\n      (set-breakpoint machine 'start 3)\n      (set-breakpoint machine 'start 5)\n      (set-breakpoint machine 'before-six 3)\n\n      (start machine)\n      (check-eq? (get-register-contents machine 'a) 2)\n\n      (proceed-machine machine)\n      (check-eq? (get-register-contents machine 'a) 4)\n\n      (proceed-machine machine)\n      (check-eq? (get-register-contents machine 'a) 7))\n\n    (test-case \"Canceling breakpoints\"\n      (define machine (test-machine))\n\n      (set-breakpoint machine 'start 3)\n      (set-breakpoint machine 'start 5)\n      (set-breakpoint machine 'before-six 3)\n\n      (cancel-breakpoint machine 'start 3)\n\n      (start machine)\n      (check-eq? (get-register-contents machine 'a) 4)\n\n      (cancel-all-breakpoints machine)\n      (proceed-machine machine)\n      (check-eq? (get-register-contents machine 'a) 10))\n))\n\n(run-tests sicp-5.19-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/21-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/memory.scm\")\n(load \"../21.scm\")\n\n(define sicp-5.21-tests\n  (test-suite\n    \"Tests for SICP exercise 5.21\"\n\n    (test-case \"recursive count-leaves\"\n      (set-register-contents! count-leaves-machine 'tree\n                              (allocate-list count-leaves-machine '((1 (2 3) (4 5)) ((6) 7))))\n      (start count-leaves-machine)\n\n      (check-equal? (get-register-contents count-leaves-machine 'result)\n                    '(n 7)))\n\n    (test-case \"count-leaves with explicit counter\"\n      (set-register-contents! count-leaves-explicit-counter-machine 'tree\n                              (allocate-list count-leaves-explicit-counter-machine\n                                             '((1 (2 3) (4 5)) ((6) 7))))\n      (start count-leaves-explicit-counter-machine)\n\n      (check-equal? (get-register-contents count-leaves-explicit-counter-machine 'result)\n                    '(n 7)))\n))\n\n(run-tests sicp-5.21-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/22-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/memory.scm\")\n(load \"../22.scm\")\n\n(define sicp-5.22-tests\n  (test-suite\n    \"Tests for SICP exercise 5.22\"\n\n    (test-suite \"append\"\n      (set-register-contents! append-machine 'x (allocate-list append-machine '(1 2 3)))\n      (set-register-contents! append-machine 'y (allocate-list append-machine '(4 5 6)))\n\n      (check-equal? (memory-dump append-machine)\n                    '((n1 n2 n3 n4 n5 n6 __ __ __ __ __ __ __ __ __ __ __ __ __ __)\n                      (p1 p2 e0 p4 p5 e0 __ __ __ __ __ __ __ __ __ __ __ __ __ __)))\n\n      (check-equal? (list-in-memory append-machine (get-register-contents append-machine 'x))\n                    '(1 2 3))\n      (check-equal? (list-in-memory append-machine (get-register-contents append-machine 'y))\n                    '(4 5 6))\n\n      (start append-machine)\n\n      (check-equal? (list-in-memory append-machine\n                                    (get-register-contents append-machine 'result))\n                    '(1 2 3 4 5 6))\n\n      (check-equal? (memory-dump append-machine)\n                    '((n1 n2 n3 n4 n5 n6 n1 n2 n3 __ __ __ __ __ __ __ __ __ __ __)\n                      (p1 p2 e0 p4 p5 e0 p7 p8 p3 __ __ __ __ __ __ __ __ __ __ __))))\n\n    (test-suite \"append!\"\n      (set-register-contents! append!-machine 'x (allocate-list append!-machine '(1 2 3)))\n      (set-register-contents! append!-machine 'y (allocate-list append!-machine '(4 5 6)))\n\n      (check-equal? (memory-dump append!-machine)\n                    '((n1 n2 n3 n4 n5 n6 __ __ __ __ __ __ __ __ __ __ __ __ __ __)\n                      (p1 p2 e0 p4 p5 e0 __ __ __ __ __ __ __ __ __ __ __ __ __ __)))\n\n      (start append!-machine)\n\n      (check-equal? (memory-dump append!-machine)\n                    '((n1 n2 n3 n4 n5 n6 __ __ __ __ __ __ __ __ __ __ __ __ __ __)\n                      (p1 p2 p3 p4 p5 e0 __ __ __ __ __ __ __ __ __ __ __ __ __ __))))\n))\n\n(run-tests sicp-5.22-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/23-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/evaluator.scm\")\n(load \"../23.scm\")\n\n(define (run exp)\n  (run-controller ec-cond-and-let extra-operations exp))\n\n(define sicp-5.23-tests\n  (test-suite\n    \"Tests for SICP exercise 5.23\"\n\n    (test-suite \"Cond\"\n      (check-equal? (run '(cond (true 1))) 1)\n      (check-equal? (run '(cond (false 1) (true 2))) 2)\n      (check-equal? (run '(cond (false 1) (else 2))) 2)\n      (check-exn exn? (lambda () (run '(cond (else 1) (true 2))))))\n\n    (test-suite \"Let\"\n      (check-equal? (run '(let ((x 1)) x)) 1)\n      (check-equal? (run '(let ((a 1) (b 2)) (+ a b))) 3)\n      (check-equal? (run '(let ((a 1) (b 2)) a b)) 2)\n      (check-equal? (run '(begin (define a 1)\n                                 (let ((b 2)\n                                       (c 3))\n                                   (+ a b c))))\n                    6))\n))\n\n(run-tests sicp-5.23-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/24-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/evaluator.scm\")\n(load \"../24.scm\")\n\n(define (run exp)\n  (run-controller ec-cond extra-operations exp))\n\n(define sicp-5.24-tests\n  (test-suite\n    \"Tests for SICP exercise 5.24\"\n\n    (test-suite \"Cond\"\n      (check-equal? (run '(cond (false 1))) #f)\n      (check-equal? (run '(cond (true 1))) 1)\n      (check-equal? (run '(cond (false 1) (true 2))) 2)\n      (check-equal? (run '(cond (false 1) (else 2))) 2)\n\n      (check-equal? (run '(begin (define a 1)\n                                 (cond (true a))))\n                    1)\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 (cond (false a) (true b))))\n                    2)\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 (cond (false a) (else b))))\n                    2))\n))\n\n(run-tests sicp-5.24-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/25-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/evaluator.scm\")\n(load \"../25.scm\")\n\n(define (run exp)\n  (run-controller ec-core extra-operations exp))\n\n(define sicp-5.25-tests\n  (test-suite\n    \"Tests for SICP exercise 5.25\"\n\n    (check-equal? (run '(begin (define count 0)\n                               (define (two)\n                                 (set! count (+ 1 count))\n                                 2)\n                               (define (square n)\n                                 (* n n))\n                               (square (two))\n                               count))\n                  2)\n\n    (test-suite \"Self-evaluating expressions\"\n      (check-equal? (run '1) 1)\n      (check-equal? (run '\"something\") \"something\"))\n\n    (test-suite \"Quotation\"\n      (check-equal? (run '(quote foo)) 'foo))\n\n    (test-suite \"Begin\"\n      (check-equal? (run '(begin 1 2)) 2))\n\n    (test-suite \"Define\"\n      (check-equal? (run '(define x 1)) 'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 x))\n                    1)\n      (check-equal? (run '(define (x) 1)) 'ok)\n      (check-equal? (run '(begin (define (x) 1)\n                                 (x)))\n                    1))\n\n    (test-suite \"Set!\"\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)))\n                    'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)\n                                 x))\n                    2))\n\n    (test-suite \"If\"\n      (check-equal? (run '(if true 1 2)) 1)\n      (check-equal? (run '(if false 1 2)) 2)\n      (check-equal? (run '(if true 1)) 1)\n      (check-equal? (run '(if false 1)) false)\n\n      (check-equal? (run '(begin (define (x arg) arg)\n                                 (if (x true) 1 2)))\n                    1)\n      (check-equal? (run '(begin (define (x arg) arg)\n                                 (if (x false) 1 2)))\n                    2)\n      )\n\n    (test-suite \"Lambda\"\n      (check-equal? (run '((lambda () 1))) 1)\n      (check-equal? (run '((lambda (a b) (cons a b)) 1 2)) '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 ((lambda (a) (cons a b)) 3)))\n                    '(3 . 2)))\n\n    (test-suite \"Procedure application\"\n      (check-equal? (run '(begin (define (a) 1)\n                                 (a)))\n                    1)\n      (check-equal? (run '(begin (define (pair a b) (cons a b))\n                                 (pair 1 2)))\n                    '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define (pair b) (cons a b))\n                                 (pair 2)))\n                    '(1 . 2)))\n\n    (test-suite \"Defining append\"\n      (check-equal? (run '(begin (define (append x y)\n                                   (if (null? x)\n                                       y\n                                       (cons (car x)\n                                             (append (cdr x) y))))\n                                 (append '(a b c) '(d e f))))\n                    '(a b c d e f)))\n\n    (test-suite \"Factorial\"\n      (check-equal? (run '(begin (define (factorial n)\n                                   (if (= n 1)\n                                       1\n                                       (* n (factorial (- n 1)))))\n                                 (factorial 5)))\n                    120)\n      (check-equal? (run '(begin (define (factorial n)\n                                   (define (iter n result)\n                                     (if (= n 0)\n                                         result\n                                         (iter (- n 1) (* result n))))\n                                   (iter n 1))\n                                 (+ 0 (factorial 5))))\n                    120))\n))\n\n(run-tests sicp-5.25-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/30-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/evaluator.scm\")\n(load \"../30.scm\")\n\n(define (run exp)\n  (run-controller ec-error-support extra-operations exp))\n\n(define sicp-5.30-tests\n  (test-suite\n    \"Tests for SICP exercise 5.30\"\n\n    (check-equal? (run 'x) 'unbound-variable)\n    (check-equal? (run '(+ 1 x)) 'unbound-variable)\n\n    (check-equal? (run '(car '(a))) 'a)\n    (check-equal? (run '(car '())) 'car-on-null)\n    (check-equal? (run '(car 1)) 'car-on-non-pair)\n    (check-equal? (run '(+ 1 (car '()))) 'car-on-null)\n    (check-equal? (run '(+ 1 (car 1))) 'car-on-non-pair)\n\n    (check-equal? (run '(/ 10 5)) 2)\n    (check-equal? (run '(/ 10 0)) 'zero-division-error)\n    (check-equal? (run '(+ 1 (/ 10 0))) 'zero-division-error)\n\n    (check-equal? (run '(+ 2 3)) 5)\n))\n\n(run-tests sicp-5.30-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/32-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/evaluator.scm\")\n(load \"../32.scm\")\n\n(define (run exp)\n  (run-controller ec-core-optimized extra-operations exp))\n\n(define sicp-5.32-tests\n  (test-suite\n    \"Tests for SICP exercise 5.32\"\n\n    (check-equal? (run '(begin (define (twice x) (+ x x))\n                          (twice 2)))\n                  4)\n    (check-equal? (run '(begin (define (twice x) (+ x x))\n                               (define (op) twice)\n                          ((op) 2)))\n                  4)\n\n    (test-suite \"Self-evaluating expressions\"\n      (check-equal? (run '1) 1)\n      (check-equal? (run '\"something\") \"something\"))\n\n    (test-suite \"Quotation\"\n      (check-equal? (run '(quote foo)) 'foo))\n\n    (test-suite \"Begin\"\n      (check-equal? (run '(begin 1 2)) 2))\n\n    (test-suite \"Define\"\n      (check-equal? (run '(define x 1)) 'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 x))\n                    1)\n      (check-equal? (run '(define (x) 1)) 'ok)\n      (check-equal? (run '(begin (define (x) 1)\n                                 (x)))\n                    1))\n\n    (test-suite \"Set!\"\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)))\n                    'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)\n                                 x))\n                    2))\n\n    (test-suite \"If\"\n      (check-equal? (run '(if true 1 2)) 1)\n      (check-equal? (run '(if false 1 2)) 2)\n      (check-equal? (run '(if true 1)) 1)\n      (check-equal? (run '(if false 1)) false))\n\n    (test-suite \"Lambda\"\n      (check-equal? (run '((lambda () 1))) 1)\n      (check-equal? (run '((lambda (x) x) 1)) 1)\n      (check-equal? (run '((lambda (a b) (cons a b)) 1 2)) '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 ((lambda (a) (cons a b)) 3)))\n                    '(3 . 2)))\n\n    (test-suite \"Procedure application\"\n      (check-equal? (run '(begin (define (a) 1)\n                                 (a)))\n                    1)\n      (check-equal? (run '(begin (define (pair a b) (cons a b))\n                                 (pair 1 2)))\n                    '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define (pair b) (cons a b))\n                                 (pair 2)))\n                    '(1 . 2)))\n\n    (test-suite \"Defining append\"\n      (check-equal? (run '(begin (define (append x y)\n                                   (if (null? x)\n                                       y\n                                       (cons (car x)\n                                             (append (cdr x) y))))\n                                 (append '(a b c) '(d e f))))\n                    '(a b c d e f)))\n\n    (test-suite \"Factorial\"\n      (check-equal? (run '(begin (define (factorial n)\n                                   (if (= n 1)\n                                       1\n                                       (* n (factorial (- n 1)))))\n                                 (factorial 5)))\n                    120)\n      (check-equal? (run '(begin (define (factorial n)\n                                   (define (iter n result)\n                                     (if (= n 0)\n                                         result\n                                         (iter (- n 1) (* result n))))\n                                   (iter n 1))\n                                 (factorial 5)))\n                    120))\n))\n\n(run-tests sicp-5.32-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/36-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/compiler.scm\")\n(load \"../36.scm\")\n\n(define (run exp)\n  (run-compiler-with-text explicit+compile-text extra-operations exp))\n\n(define sicp-5.36-tests\n  (test-suite\n    \"Tests for SICP exercise 5.36\"\n\n    (check-equal? (run '(begin (define order 'unknown)\n                               (define (f a b) 'done)\n                               (f (set! order 'right-to-left)\n                                  (set! order 'left-to-right))\n                               order))\n                  'left-to-right)\n\n    (check-equal? (run '(+ 1)) 1)\n    (check-equal? (run '(- 2 1)) 1)\n))\n\n(run-tests sicp-5.36-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/38-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/compiler.scm\")\n(load \"../38.scm\")\n\n(define (run exp)\n  (let ((machine (make-machine (append '(arg1 arg2) ec-registers)\n                               (append `((+ ,+) (- ,-) (* ,*) (= ,=)) cm-operations)\n                               explicit+compile-text)))\n    (compile-in-machine machine exp)\n    (get-register-contents machine 'val)))\n\n(define sicp-5.38-tests\n  (test-suite\n    \"Tests for SICP exercise 5.38\"\n\n    (check-equal? (run '(+ 1 2)) 3)\n    (check-equal? (run '(+ 1 2 3)) 6)\n    (check-equal? (run '(+ (+ 1 2 3) (+ 4 5 6) (+ 7 8 9))) 45)\n\n    (check-equal? (run '(begin (define a 1)\n                               (define b 2)\n                               (+ a b)))\n                  3)\n\n    (check-equal? (run '(begin (define (a) 1)\n                               (+ (a) (a))))\n                  2)\n\n    (check-equal? (run '(begin (define (twice n) (+ n n))\n                               (define n 4)\n                               (+ (twice 1) n (twice 1))))\n                  8)\n\n    (check-equal? (run '(begin (define (factorial n)\n                                 (if (= n 1)\n                                     1\n                                     (* n (factorial (- n 1)))))\n                               (factorial 5)))\n                  120)\n\n    (check-equal? (run '(begin (define (factorial n)\n                                 (define (iter product counter)\n                                   (if (> counter n)\n                                       product\n                                       (iter (* product counter)\n                                             (+ counter 1))))\n                                 (iter 1 1))\n                               (factorial 5)))\n                  120)\n))\n\n(run-tests sicp-5.38-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/39-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/compiler.scm\")\n(load \"../39.scm\")\n\n(define (env mappings)\n  (if (null? mappings)\n      the-empty-environment\n      (extend-environment (caar mappings)\n                          (cadar mappings)\n                          (env (cdr mappings)))))\n\n(define sicp-5.39-tests\n  (test-suite\n    \"Tests for SICP exercise 5.39\"\n\n    (check-equal? (lexical-address-lookup '(0 0) (env '(((a b) (1 2)))))\n                  1)\n\n    (check-equal? (lexical-address-lookup '(0 1) (env '(((a b) (1 2)))))\n                  2)\n\n    (check-equal? (lexical-address-lookup '(1 0) (env '(((a b) (1 2))\n                                                       ((c d) (3 4)))))\n                  3)\n\n    (check-equal? (lexical-address-lookup '(1 1) (env '(((a b) (1 2))\n                                                       ((c d) (3 4)))))\n                  4)\n\n    (check-equal? (lexical-address-lookup '(2 0) (env '(((a b) (1 2))\n                                                       ((c d) (3 4))\n                                                       ((e f) (5 6)))))\n                  5)\n\n    (check-equal? (lexical-address-lookup '(2 1) (env '(((a b) (1 2))\n                                                       ((c d) (3 4))\n                                                       ((e f) (5 6)))))\n                  6)\n\n    (check-exn exn? (lambda () (lexical-address-lookup '(0 0) (env '(((a) (*unassigned*)))))))\n\n    (test-case \"setting a lexical variable in the top frame\"\n      (let ((environment (env '(((a b) (1 2))))))\n        (lexical-address-set! '(0 1) 3 environment)\n        (check-equal? (lexical-address-lookup '(0 1) environment) 3)))\n\n    (test-case \"setting a lexical variable in the top frame\"\n      (let ((environment (env '(((a b) (1 2))\n                                ((c d) (3 4))))))\n        (lexical-address-set! '(1 1) 5 environment)\n        (check-equal? (lexical-address-lookup '(1 1) environment) 5)))\n    ;(test-case \"setting a lexical variable in a frame, other than the top\")\n))\n\n(run-tests sicp-5.39-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/40-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/compiler.scm\")\n(load \"../40.scm\")\n\n(define (run exp)\n  (let ((machine (make-explicit+compile-machine)))\n    (compile-in-machine machine exp)\n    (get-register-contents machine 'val)))\n\n(define sicp-5.40-tests\n  (test-suite\n    \"Tests for SICP exercise 5.40\"\n\n    (test-suite \"Self-evaluating expressions\"\n      (check-equal? (run '1) 1)\n      (check-equal? (run '\"something\") \"something\"))\n\n    (test-suite \"Quotation\"\n      (check-equal? (run '(quote foo)) 'foo))\n\n    (test-suite \"Begin\"\n      (check-equal? (run '(begin 1 2)) 2))\n\n    (test-suite \"Define\"\n      (check-equal? (run '(define x 1)) 'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 x))\n                    1)\n      (check-equal? (run '(define (x) 1)) 'ok)\n      (check-equal? (run '(begin (define (x) 1)\n                                 (x)))\n                    1))\n\n    (test-suite \"Set!\"\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)))\n                    'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)\n                                 x))\n                    2))\n\n    (test-suite \"If\"\n      (check-equal? (run '(if true 1 2)) 1)\n      (check-equal? (run '(if false 1 2)) 2)\n      (check-equal? (run '(if true 1)) 1)\n      (check-equal? (run '(if false 1)) false))\n\n    (test-suite \"Lambda\"\n      (check-equal? (run '((lambda () 1))) 1)\n      (check-equal? (run '((lambda (x) x) 1)) 1)\n      (check-equal? (run '((lambda (a b) (cons a b)) 1 2)) '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 ((lambda (a) (cons a b)) 3)))\n                    '(3 . 2)))\n\n    (test-suite \"Cond\"\n      (check-equal? (run '(cond (true 1))) 1)\n      (check-equal? (run '(cond (false 1) (true 2))) 2)\n      (check-equal? (run '(cond (false 1) (else 2))) 2)\n      (check-exn exn? (lambda () (run '(cond (else 1) (true 2))))))\n\n    (test-suite \"Procedure application\"\n      (check-equal? (run '(begin (define (a) 1)\n                                 (a)))\n                    1)\n      (check-equal? (run '(begin (define (pair a b) (cons a b))\n                                 (pair 1 2)))\n                    '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define (pair b) (cons a b))\n                                 (pair 2)))\n                    '(1 . 2)))\n\n    (test-suite \"Defining append\"\n      (check-equal? (run '(begin (define (append x y)\n                                   (if (null? x)\n                                       y\n                                       (cons (car x)\n                                             (append (cdr x) y))))\n                                 (append '(a b c) '(d e f))))\n                    '(a b c d e f)))\n\n    (test-suite \"Factorial\"\n      (check-equal? (run '(begin (define (factorial n)\n                                   (if (= n 1)\n                                       1\n                                       (* n (factorial (- n 1)))))\n                                 (factorial 5)))\n                    120)\n      (check-equal? (run '(begin (define (factorial n)\n                                   (define (iter n result)\n                                     (if (= n 0)\n                                         result\n                                         (iter (- n 1) (* result n))))\n                                   (iter n 1))\n                                 (factorial 5)))\n                    120)) \n))\n\n(run-tests sicp-5.40-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/41-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../41.scm\")\n\n(define sicp-5.41-tests\n  (test-suite\n    \"Tests for SICP exercise 5.41\"\n\n    (check-equal? (find-variable 'z '((y z) (a b c d e) (x y)))\n                  '(0 1))\n\n    (check-equal? (find-variable 'c '((y z) (a b c d e) (x y)))\n                  '(1 2))\n\n    (check-equal? (find-variable 'x '((y z) (a b c d e) (x y)))\n                  '(2 0))\n\n    (check-equal? (find-variable 'w '((y z) (a b c d e) (x y)))\n                  'not-found)\n\n    (check-equal? (find-variable 'x '())\n                  'not-found)\n))\n\n(run-tests sicp-5.41-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/42-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/compiler.scm\")\n(load \"../42.scm\")\n\n(define (run exp)\n  (let ((machine (make-explicit+compile-machine)))\n    (compile-in-machine machine exp)\n    (get-register-contents machine 'val)))\n\n(define sicp-5.42-tests\n  (test-suite\n    \"Tests for SICP exercise 5.42\"\n\n    (check-equal? (run '(begin (define a 42)\n                               ((lambda () a))))\n                  42)\n\n    (check-equal? (run '((lambda (a b) b) 1 2))\n                  2)\n\n    (let ((not-so-simple-expression '(((lambda (x y)\n                                         (lambda (a b c d e)\n                                           ((lambda (y z) (* x y z))\n                                            (* a b x)\n                                            (+ c d x))))\n                                       3 4)\n                                      5 6 7 8 9)))\n      (check-equal? (run not-so-simple-expression) (eval not-so-simple-expression)))\n\n    (check-equal? (run '(begin (define x 1)\n                               (set! x 2)\n                               x))\n                  2)\n\n    (check-equal? (run '(begin (define (foo x)\n                                 (set! x 2)\n                                 x)\n                               (foo 1)))\n                  2)\n\n    (check-equal? (run '(begin ((lambda (a)\n                                  ((lambda (b)\n                                    (set! a b))\n                                   2)\n                                  a)\n                                1)))\n                  2)\n))\n\n(run-tests sicp-5.42-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/43-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/compiler.scm\")\n(load \"../43.scm\")\n\n(define (run exp)\n  (let ((machine (make-explicit+compile-machine)))\n    (compile-in-machine machine exp)\n    (get-register-contents machine 'val)))\n\n(define sicp-5.43-tests\n  (test-suite\n    \"Tests for SICP exercise 5.43\"\n\n    (check-equal? (run '(begin (define (foo)\n                                 (define x 1)\n                                 (set! x 2)\n                                 x)\n                               (foo)))\n                  2)\n))\n\n(run-tests sicp-5.43-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/44-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/compiler.scm\")\n(load \"../44.scm\")\n\n(define (run exp)\n  (let ((machine (make-explicit+compile-machine)))\n    (compile-in-machine machine exp)\n    (get-register-contents machine 'val)))\n\n(define sicp-5.44-tests\n  (test-suite\n    \"Tests for SICP exercise 5.44\"\n\n    (check-equal? (run '(begin (define (vect+ v1 v2)\n                                 (cons (+ (car v1) (car v2))\n                                       (+ (cdr v1) (cdr v2))))\n                               (define (vect* n v)\n                                 (cons (* n (car v))\n                                       (* n (cdr v))))\n                               (define (linear + * a b x y)\n                                 (+ (* a x) (* b y)))\n                               (linear vect+ vect*\n                                       2 3\n                                       '(5 . 7) '(11 . 13))))\n                  '(43 . 53))\n))\n\n(run-tests sicp-5.44-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/47-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"helpers/compiler.scm\")\n(load \"../47.scm\")\n\n(define (run machine exp)\n  (eval-in-machine machine exp)\n  (get-register-contents machine 'val))\n\n(define sicp-5.47-tests\n  (test-suite\n    \"Tests for SICP exercise 5.47\"\n\n    (test-case \"target = val, linkage != return\"\n      (define machine (make-explicit+compile-machine))\n      (compile-in-machine machine '(define (f n) (+ 1 (g n))))\n      (eval-in-machine machine '(define (g n) (* n n)))\n      (check-equal? (run machine '(f 3)) 10))\n\n    (test-case \"target != val, linkage != return\"\n      (define machine (make-explicit+compile-machine))\n      (compile-in-machine machine '(define (twice n) (+ n n)))\n      (eval-in-machine machine '(define (get-twice) twice))\n      (compile-in-machine machine '(define (ten) ((get-twice) 5)))\n      (check-equal? (run machine '(ten)) 10))\n\n    (test-case \"target = val, linkage = return\"\n      (define machine (make-explicit+compile-machine))\n      (compile-in-machine machine '(define (twice-1+ n) (twice (+ n 1))))\n      (eval-in-machine machine '(define (twice n) (+ n n)))\n      (check-equal? (run machine '(twice-1+ 4)) 10))\n\n))\n\n(run-tests sicp-5.47-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/50-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(require r5rs/init)\n(load \"helpers/compiler.scm\")\n(load \"../50.scm\")\n\n(define (run exp)\n  (compile-in-machine machine `(evaluate ',exp the-global-environment))\n  (get-register-contents machine 'val))\n\n(define sicp-5.50-tests\n  (test-suite\n    \"Tests for SICP exercise 5.50\"\n\n    (test-suite \"Self-evaluating expressions\"\n      (check-equal? (run '1) 1)\n      (check-equal? (run '\"something\") \"something\"))\n\n    (test-suite \"Quotation\"\n      (check-equal? (run '(quote foo)) 'foo))\n\n    (test-suite \"Begin\"\n      (check-equal? (run '(begin 1 2)) 2))\n\n    (test-suite \"Define\"\n      (check-equal? (run '(define x 1)) 'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 x))\n                    1)\n      (check-equal? (run '(define (x) 1)) 'ok)\n      (check-equal? (run '(begin (define (x) 1)\n                                 (x)))\n                    1))\n\n    (test-suite \"Set!\"\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)))\n                    'ok)\n      (check-equal? (run '(begin (define x 1)\n                                 (set! x 2)\n                                 x))\n                    2))\n\n    (test-suite \"If\"\n      (check-equal? (run '(if true 1 2)) 1)\n      (check-equal? (run '(if false 1 2)) 2)\n      (check-equal? (run '(if true 1)) 1)\n      (check-equal? (run '(if false 1)) false))\n\n    (test-suite \"Lambda\"\n      (check-equal? (run '((lambda () 1))) 1)\n      (check-equal? (run '((lambda (x) x) 1)) 1)\n      (check-equal? (run '((lambda (a b) (cons a b)) 1 2)) '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define b 2)\n                                 ((lambda (a) (cons a b)) 3)))\n                    '(3 . 2)))\n\n    (test-suite \"Cond\"\n      (check-equal? (run '(cond (true 1))) 1)\n      (check-equal? (run '(cond (false 1) (true 2))) 2)\n      (check-equal? (run '(cond (false 1) (else 2))) 2)\n      (check-exn exn? (lambda () (run '(cond (else 1) (true 2))))))\n\n    (test-suite \"Procedure application\"\n      (check-equal? (run '(begin (define (a) 1)\n                                 (a)))\n                    1)\n      (check-equal? (run '(begin (define (pair a b) (cons a b))\n                                 (pair 1 2)))\n                    '(1 . 2))\n      (check-equal? (run '(begin (define a 1)\n                                 (define (pair b) (cons a b))\n                                 (pair 2)))\n                    '(1 . 2)))\n\n    (test-suite \"Defining append\"\n      (check-equal? (run '(begin (define (append x y)\n                                   (if (null? x)\n                                       y\n                                       (cons (car x)\n                                             (append (cdr x) y))))\n                                 (append '(a b c) '(d e f))))\n                    '(a b c d e f)))\n\n    (test-suite \"Factorial\"\n      (check-equal? (run '(begin (define (factorial n)\n                                   (if (= n 1)\n                                       1\n                                       (* n (factorial (- n 1)))))\n                                 (factorial 5)))\n                    120)\n      (check-equal? (run '(begin (define (factorial n)\n                                   (define (iter n result)\n                                     (if (= n 0)\n                                         result\n                                         (iter (- n 1) (* result n))))\n                                   (iter n 1))\n                                 (factorial 5)))\n                    120))\n\n    ; Those are just some sanity checks. It is not necessary that it takes\n    ; that many instructions and stack operations to run the tests, but makes\n    ; sure that if I did not short-circuit something when this number changes.\n\n    (check-equal? total-instructions 215524)\n    (check-equal? ((machine 'stack) 'statistics)\n                  '(total-pushes = 8036 maximum-depth = 22))\n\n    ; The numbers get way cooler when we do a lame recursive version of\n    ; Fibonacci 10.\n\n    (test-case \"The tenth Fibonacci number\"\n      (set! total-instructions 0)\n      ((machine 'stack) 'initialize)\n\n      (check-equal? (run '(begin (define (fib n)\n                                   (if (< n 2)\n                                       1\n                                       (+ (fib (- n 1)) (fib (- n 2)))))\n                                 (fib 10)))\n                    89)\n\n      (check-equal? total-instructions 1561470)\n      (check-equal? ((machine 'stack) 'statistics)\n                    '(total-pushes = 190611 maximum-depth = 76)))\n))\n\n(run-tests sicp-5.50-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/51-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../51.scm\")\n\n(define sicp-5.51-tests\n  (test-suite\n    \"Tests for SICP exercise 5.51\"\n\n    (compile-interpreter)\n    (check-equal? (interpreter-test-results) \"(passed = 24 failed = 0)\")\n))\n\n(run-tests sicp-5.51-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/52-tests.scm",
    "content": "(require rackunit rackunit/text-ui)\n(load \"../52.scm\")\n\n(define sicp-5.52-tests\n  (test-suite\n    \"Tests for SICP exercise 5.52\"\n\n    (write-interpreter interpreter-in-c)\n    (compile-runtime)\n    (check-equal? (interpreter-test-results)\n                  \"(passed = 27 failed = 0)\")\n))\n\n(run-tests sicp-5.52-tests)\n"
  },
  {
    "path": "scheme/sicp/05/tests/helpers/compiler.scm",
    "content": "(load-relative \"../../showcase/compiler/helpers.scm\")\n\n(define (run-compiler-with-text controller-text extra-operations exp)\n  (let ((machine (make-machine ec-registers\n                               (append cm-operations extra-operations)\n                               controller-text)))\n    (compile-in-machine machine exp)\n    (get-register-contents machine 'val)))\n"
  },
  {
    "path": "scheme/sicp/05/tests/helpers/evaluator.scm",
    "content": "(load-relative \"../../showcase/explicit/evaluator.scm\")\n\n(define (make-explicit-machine controller-text additional-operations)\n  (make-machine ec-registers\n                (append ec-operations additional-operations)\n                controller-text))\n\n(define (run-controller controller-text additional-operations exp)\n  (let ((machine (make-explicit-machine controller-text additional-operations)))\n    (set-register-contents! machine 'exp exp)\n    (set-register-contents! machine 'env (setup-environment))\n\n    (start machine)\n\n    (get-register-contents machine 'val)))\n"
  },
  {
    "path": "scheme/sicp/05/tests/helpers/memory.scm",
    "content": "(load-relative \"simulator.scm\")\n\n(define (add-pointers p1 p2)\n  (let ((type1 (car p1)) (type2 (car p2))\n        (value1 (cadr p1)) (value2 (cadr p2)))\n    (if (eq? type1 type2)\n        (list type1 (+ value1 value2))\n        (error \"Attempting to add incompatible pointers\" p1 p2))))\n\n(define (vector-ref-pointer vector pointer)\n  (if (eq? (car pointer) 'p)\n      (vector-ref vector (cadr pointer))\n      (error \"Cannot index vector with this pointer\" pointer)))\n\n(define (vector-set!-pointer vector pointer value)\n  (if (eq? (car pointer) 'p)\n      (vector-set! vector (cadr pointer) value)\n      (error \"Cannot modify vector with this pointer\" pointer)))\n\n(define (null?-pointers pointer)\n  (equal? pointer '(e 0)))\n\n(define (pair?-pointers pointer)\n  (eq? (car pointer) 'p))\n\n(define (allocate-list machine lst)\n  (define the-cars (get-register-contents machine 'the-cars))\n  (define the-cdrs (get-register-contents machine 'the-cdrs))\n  (define saved-pairs '())\n  (define (save-pair pair offset)\n    (set! saved-pairs (cons (cons pair (list 'p offset)) saved-pairs)))\n  (define (saved-pair-offset pair)\n    (define (lookup pairs)\n      (cond ((null? pairs) #f)\n            ((eq? pair (caar pairs)) (cdar pairs))\n            (else (lookup (cdr pairs)))))\n    (lookup saved-pairs))\n  (define (saved? pair)\n    (not (eq? (saved-pair-offset pair) #f)))\n  (define (allocate item)\n    (cond ((number? item) (list 'n item))\n          ((null? item) (list 'e 0))\n          ((saved? item) (saved-pair-offset item))\n          ((pair? item)\n           (let ((offset (cadr (get-register-contents machine 'free))))\n             (set-register-contents! machine 'free (list 'p (+ offset 1)))\n             (save-pair item offset)\n             (vector-set! the-cars offset (allocate (car item)))\n             (vector-set! the-cdrs offset (allocate (cdr item)))\n             (list 'p offset)))\n          (else (error \"Don't know how to allocate this -- ALLOCATE-LIST\" item))))\n  (allocate lst))\n\n(define (list-in-memory machine pointer)\n  (define the-cars (get-register-contents machine 'the-cars))\n  (define the-cdrs (get-register-contents machine 'the-cdrs))\n  (define (build pointer)\n    (cond ((eq? (car pointer) 'n) (cadr pointer))\n          ((equal? pointer '(e 0)) '())\n          ((eq? (car pointer) 'p)\n           (cons (build (vector-ref the-cars (cadr pointer)))\n                 (build (vector-ref the-cdrs (cadr pointer)))))\n          (else (error \"Don't know how to build -- LIST-IN-MEMORY\" pointer))))\n  (build pointer))\n\n(define (memory-dump machine)\n  (define (shorten pointer)\n    (if (pair? pointer)\n        (string->symbol (string-append (symbol->string (car pointer))\n                                       (number->string (cadr pointer))))\n        '__))\n  (list (map shorten (vector->list (get-register-contents machine 'the-cars)))\n        (map shorten (vector->list (get-register-contents machine 'the-cdrs)))))\n\n(define (make-machine-with-memory registers controller-text)\n  (let ((machine (make-machine (append registers '(free the-cars the-cdrs))\n                               (list (list 'vector-ref vector-ref-pointer)\n                                     (list 'vector-set! vector-set!-pointer)\n                                     (list '+ add-pointers)\n                                     (list 'null? null?-pointers)\n                                     (list 'pair? pair?-pointers))\n                               controller-text)))\n    (set-register-contents! machine 'the-cars (make-vector 20))\n    (set-register-contents! machine 'the-cdrs (make-vector 20))\n    (set-register-contents! machine 'free '(p 0))\n    machine))\n"
  },
  {
    "path": "scheme/sicp/05/tests/helpers/monitored-stack.scm",
    "content": "(define (make-stack)\n  (let ((s '())\n       (number-pushes 0)\n       (max-depth 0)\n       (current-depth 0))\n    (define (push x)\n      (set! s (cons x s))\n      (set! number-pushes (+ 1 number-pushes))\n      (set! current-depth (+ 1 current-depth))\n      (set! max-depth (max current-depth max-depth)))\n    (define (pop)\n      (if (null? s)\n          (error \"Empty stack -- POP\")\n          (let ((top (car s)))\n            (set! s (cdr s))\n            (set! current-depth (- current-depth 1))\n            top)))\n    (define (initialize)\n      (set! s '())\n      (set! number-pushes 0)\n      (set! max-depth 0)\n      (set! current-depth 0)\n      'done)\n    (define (statistics)\n      (list 'total-pushes '= number-pushes\n            'maximum-depth '= max-depth))\n    (define (dispatch message)\n      (cond ((eq? message 'push) push)\n            ((eq? message 'pop) (pop))\n            ((eq? message 'initialize) (initialize))\n            ((eq? message 'statistics) (statistics))\n            (else (error \"Unknown request -- STACK\" message))))\n    dispatch))\n\n(define (stack-stats-for machine exp)\n  (set-register-contents! machine 'exp exp)\n  ((machine 'stack) 'initialize)\n  (start machine)\n  ((machine 'stack) 'statistics))\n"
  },
  {
    "path": "scheme/sicp/05/tests/helpers/sample-machines.scm",
    "content": "(load-relative \"../../showcase/simulator/sample-machines.scm\")\n"
  },
  {
    "path": "scheme/sicp/05/tests/helpers/simulator.scm",
    "content": "(load-relative \"../../showcase/simulator/simulator.scm\")\n"
  },
  {
    "path": "scheme/sicp/README.markdown",
    "content": "# Structure and Interpretation of Computer Programs\n\nI'm doing a SICP study group with a couple of friends. This is where I will kepp the solutions to the exercises.\n\n## Scheme implementation\n\nDespite this being SICP, I've chosen to use [Racket](http://racket-lang.org/).  The people there have their own opinion on how to do an introductionary course in Scheme, called [How to Design Programs](http://www.htdp.org/). This is beside the point, though - the idea here is to read through SICP, not to learn Scheme or programming.\n\nAt the time, Racket does not have a decent sicp language pack. Instead of trying to figure out a way to restrict the language, I will try to stick at the R5S5 subset, using Racket. If that fails for some reason, I might reconsider.\n\n## Tests\n\nI like to keep a bunch of tests for each exercise. I'm just that kind of person.\n\nAlthough I will do the solutions in SICP-level Scheme, I will not hesitate to use full-blown Racket in the tests. This will give me a nice opportunity to do some cargo-culting, which might be useful if I want to learn Racket in the future.\n\n## Tools\n\nI'm not just interested in solving the exercise. I'm interested in building an environment that is up for the task, tailored to me. If Racket was a bit more modern, I would have tried to go with its own tools. Since this is not the case (IMHO), I will just use Ruby.\n\n### Generating scaffolds\n\nIt is fairly simple. If you want to generate a scaffold for exercise 1.01, just run:\n\n    rake exercise[1,1]\n\nIf you want to generate the scaffold for the next unsolved task, just do:\n\n    rake next\n\n### Running tests\n\nTests can be run the following way:\n\n    rake run:exercise[1,1]\n\nIf you want to run all tests do:\n\n    rake run:all\n\nYou can also use watchr to do continuous testing. Just run:\n\n    rake watch\n\n## Showcases\n\nSome of the chapters require chunks of work that don't fit as exercises. Instead, I need a larger program that can show something meaningful. Occasionally, I will create a \"showcase\" for those. You can see a list of showcases by running `rake -T`.\n\nThe showcases have a specific directory structure, that's pretty easy to grok. Note, that if you want to run a showcase with a different version of Racket, you need to specify the `RACKET` environment variable to point to an executable. For example:\n\n    RACKET=/path/to/racket rake run:showcase:example\n\n### The Picture Language (section 2.2.4)\n\nThis is the Escher-like picture library, introduced when talking about data abstraction and robust design. Note, that this might not run with the Racket that you install from Homebrew. It has a bunch of problems with depending on `libcairo` that I don't care to debug. Downloading a pre-compiled distribution from the Racket site is enough.\n\n    RACKET=~/Code/runtime/racket/bin/racket rake run:showcase:picturelang\n\n### The metacircular evaluator (section 4.1)\n\nThis is the basic metacircular evaluator explored in Chapter 4 for the book. It is very basic and featureless. It is fairly easy to run it, although you should be careful what you are typing in. Run it with:\n\n    rake run:showcase:evaluator\n"
  },
  {
    "path": "scheme/sicp/Rakefile",
    "content": "require 'pathname'\n\nROOT = Pathname(File.dirname(__FILE__))\n\ndef run_racket(file)\n  executable = ENV['RACKET'] || 'racket'\n  command = [executable, '-r', file.to_s]\n  system(*command) or raise \"Failed to execute #{command * ' '}\"\nend\n\nclass Exercise\n  attr_reader :chapter, :number\n\n  def initialize(chapter, number)\n    @chapter = chapter.to_i\n    @number  = number.to_i\n  end\n\n  def valid?\n    chapter.nonzero? and number.nonzero?\n  end\n\n  def test_file\n    ROOT.join '%02d/tests/%02d-tests.scm' % [chapter, number]\n  end\n\n  def file\n    ROOT.join '%02d/%02d.scm' % [chapter, number]\n  end\n\n  def name\n    \"%1d.%02d\" % [chapter, number]\n  end\n\n  def having_a_test?\n    test_file.exist?\n  end\n\n  def run\n    run_racket file\n  end\n\n  def run_test\n    Dir.chdir File.dirname(test_file) do\n      run_racket test_file\n    end\n  end\n\n  def generate_scaffold\n    FileUtils.mkdir_p File.dirname(test_file)\n\n    open(file, 'w') { |f| f.write(<<-END) }\n; SICP exercise #{name}\n  END\n\n    open(test_file, 'w') { |f| f.write(<<-END) }\n(require rackunit rackunit/text-ui)\n(load \"../#{sprintf('%02d', number)}.scm\")\n\n(define sicp-#{name}-tests\n  (test-suite\n    \"Tests for SICP exercise #{name}\"\n\n))\n\n(run-tests sicp-#{name}-tests)\n    END\n  end\n\n  class << self\n    def each_with_a_test\n      Dir.chdir ROOT do\n        Dir.glob('0*').sort.each do |chapter|\n          Dir.glob(\"#{chapter}/tests/*.scm\").sort.each do |test_file|\n            test_file =~ %r{(\\d)/tests/(\\d+)-tests.scm}\n            yield Exercise.new $1, $2\n          end\n        end\n      end\n    end\n\n    def next\n      Dir.chdir ROOT do\n        chapter = Dir.glob('0*').max\n        number  = '%02d' % Dir.glob(\"#{chapter}/*.scm\").grep(/(\\d+)\\.scm/) { $1.to_i }.max.succ\n\n        Exercise.new chapter, number\n      end\n    end\n  end\nend\n\nclass Showcase\n  attr_reader :name, :chapter\n\n  def initialize(name, chapter)\n    @name    = name.to_sym\n    @chapter = chapter.to_i\n  end\n\n  def directory\n    ROOT.join \"%02d/showcase/%s\" % [chapter, name]\n  end\n\n  def run\n    Dir.chdir directory do\n      run_racket 'main.scm'\n    end\n  end\n\n  class << self\n    def all\n      Dir.chdir ROOT do\n        Dir['0*/showcase/*/main.scm'].map do |path|\n          path =~ %r[(\\d+)/showcase/(.+)/]\n          new $2, $1\n        end.compact\n      end\n    end\n  end\nend\n\n\n\ndesc 'Scaffolds an exercise solution and its unit test'\ntask :exercise, :chapter, :exercise do |task, args|\n  exercise = Exercise.new args[:chapter], args[:exercise]\n\n  raise ArgumentError, <<-END unless exercise.valid?\nYou need to supply chapter and exercise numbers. If you want to generate exercise 2.23:\n\n  rake exericse[2,23]\nEND\n\n  exercise.generate_scaffold\nend\n\ndesc 'Generates the next exercise'\ntask :next do\n  exercise = Exercise.next\n\n  puts \"Generating files for exercise #{exercise.name}\"\n  exercise.generate_scaffold\nend\n\nnamespace :run do\n  desc \"Runs a specific exercise\"\n  task :exercise, :chapter, :exercise do |task, args|\n    exercise = Exercise.new args[:chapter], args[:exercise]\n\n    exercise.run\n  end\n\n  desc 'Runs the test of a specific exercise'\n  task :test, :chapter, :exercise do |task, args|\n    exercise = Exercise.new args[:chapter], args[:exercise]\n\n    raise ArgumentError, <<-END unless exercise.valid?\nYou need to supply chapter and exercise numbers. If you want to run exercise 2.23:\n\n  rake run:exericse[2,23]\nEND\n\n    raise \"Test for #{exercise.name} does not exist\" unless exercise.having_a_test?\n    exercise.run_test\n  end\n\n  desc 'Runs the tests of all exercises'\n  task :all do\n    Exercise.each_with_a_test do |exercise|\n      print \"#{exercise.name}: \"\n      exercise.run_test\n    end\n  end\n\n  namespace :showcase do\n    Showcase.all.each do |showcase|\n      desc \"Run the #{showcase.name} showcase\"\n      task showcase.name do\n        showcase.run\n      end\n    end\n  end\nend\n\ndesc 'Runs watchr on the tests'\ntask :watch do\n  exec 'watchr tests.watchr'\nend\n"
  },
  {
    "path": "scheme/sicp/notes/week-01.markdown",
    "content": "# Week 1 (2012-02-27 - 2012-03-06)\n\nNotes on my first week with SICP. We have just started the study group.\n\n## Questions\n\n* Is [Nikolay's `good-enough?`][nb-01-07] different?\n* What is the time complexity of 1.14?\n* What is the time complexity of normal-order in 1.20?\n\n[nb-01-07]: https://github.com/nb/sicp/blob/a468e7e08c03cde42b317d94b5cf0e4db7613212/1.7.scm\n\n## Various\n\n* I enjoy writing text on the side of the code. I don't do that in my day job, since I consider it an anti-pattern. It makes me more reflective.\n* I enjoy reaching a certain depth in my fiddling with Scheme. It makes the experience nicer.\n* I take a lot of time to ensure nice commit message and nice looking solutions. That way the code should be a pleasure to read.\n* Consider giving me the thumbs up, if you are following along and enjoying it ;)\n* Building tools is interesting, although it turned into yak shaving - I spent and hour and something on the Rakefile.\n* Fib(n) can be calculated in o(log(n)). I knew it, but I still find it freaky.\n\n## How to Design Programs\n\nThe Racket community has its own introductory-level book that teaches Scheme (called [How to Design Programs](http://htdp.org/). It takes a different approach from SICP and even criticizes it a bit. It looks promising - it is using DrRacket a lot and it even combines pictures and code in a cool way.\n\nThe book is even more basic than SICP, which doesn't make it very interesting to me. Besides, the point of the study group is to finish SICP, not HtDP. I might take a look at it once we're finished.\n\n## Concepts, Techniques and Models of Computer Programming\n\nThere is another book that looks promising - [Concepts, Techniques and Models of Computer Programming][ctm]. It is dubbed by some people as \"the book to read after SICP\". It looks promising and there are some [nice comments about it on c2][ctm-on-c2]. I learned about it form a [thread on Hacker News][sicp-vs-htdp-hn] that is also worth taking a look at.\n\n[ctm]: http://mitpress.mit.edu/catalog/item/default.asp?ttype=2&tid=10142\n[ctm-on-c2]: http://c2.com/cgi/wiki?ConceptsTechniquesAndModelsOfComputerProgramming\n[sicp-vs-htdp-hn]: http://news.ycombinator.com/item?id=428651\n\n## Why MIT switched from Scheme to Python?\n\nSussman has an [interesting comment][why-python] on why MIT switched to Python. It is short and I cannot pick up a representative quote. To sum it up, programming has changed fundamentally and while in the past you could understand your program all the way down, now you have to do basic science on some of the libraries you are using. Definitelly worth reading it.\n\n[why-python]: http://www.wisdomandwonder.com/link/2110/why-mit-switched-from-scheme-to-python\n\n## Invariant quantity\n\nThere is an interesting idea in exercise 1.16. We're designing an iterative algoright to do fast exponentiation. For each iteration we are keeping three state variables (a, b and n) and we require that an invariant holds on each iteration (namely abⁿ is constant). The three of them change on each iteration, but the abⁿ remains unchanged. n is reduced on every iteration and when it finaly reaches 0, the result is in a.\n\nInvariant quantities appear to be an interesting way to design algorithms.\n\n## Tail recursion and normal-order evaluation\n\nNormal-order evaluation can dramatically change the order of growth when combined with tail recursion. I thought it just changes the constant, but it can actually change the function.\n\nExercise 1.20 shows a nice example. In applicative-order evaluation, gcd has log(n) order of growth, but in normal-order evaluation it becomes a lot slower. I'm not sure what the new order of growth is, but it is at least linear.\n\nI doubt it happens in practice, but it is still an interesting observation.\n\n## Some school-level algebra\n\nI just love it when I discover something neat in algebra I learned in school. Namely, there is a neat way to geometrically explain (n + 1)². Assume we have a square with size n and we want to increase its size with n. Here's a nice ASCII graphic:\n\n    +---+---+---+---+---+---+ . +      Each \"small square\" has area of 1. The \"thick\" squares\n    |   |   |   |   |   |   | x .      make up the original square with size n, while the\n    +---+---+---+---+---+---+ . +      \"thin\" ones make up the extra areas we need to add\n    |   |   |   |   |   |   | x .      to increase the size with 1. Let's count the added\n    +---+---+---+---+---+---+ . +      squares. We add n squares on the right (marked with x)\n    |   |   |   |   |   |   | x .      and another n squares on the bottom (marked with x).\n    +---+---+---+---+---+---+ . +      We need to add an extra square, diagonally to complete\n    |   |   |   |   |   |   | x .      the shape, marked with o. Thus, we end up adding 2n + 1\n    +---+---+---+---+---+---+ . +      squares. When we take all together, we get:\n    |   |   |   |   |   |   | x .\n    +---+---+---+---+---+---+ . +      n² + 2n + 1\n    |   |   |   |   |   |   | x .\n    +---+---+---+---+---+---+ . +      which of course is:\n    . x . x . x . x . x . x . o .\n    + - + - + - + - + - + - + . +      (n + 1)²\n\nIt's easy enough to generalize this to (a + b)². The number of times we add a to each side is b, which makes it 2ab for the x squares. We need to add b² to complete the o squares. It ends up as:\n\na² + 2ab + b²\n\nThere is probably some Greek person that wrote this down a couple of thousand years ago, but somehow I managed to miss it. Anyway, it's still fun when I discover something simple about school math that I did not know.\n\n## Meetup summary\n\nWe established that we the target for next week is 1.3.2. One of my question was answered, but the other two remain a mystery to me.\n\n### Notes\n* Is [Nikolay's `good-enough?`][nb-01-07] different?\n  * Nikolay says that he is doing multiplication, while I'm doing divisions. He claims that multiplication is (1) faster and (2) more accurate. He does not quote sources.\n* Ackermann's function seems pretty useless to me, but apparently it has some interesting properties. It is mostly theoretical, though.\n\n[nb-01-07]: https://github.com/nb/sicp/blob/a468e7e08c03cde42b317d94b5cf0e4db7613212/1.7.scm\n"
  },
  {
    "path": "scheme/sicp/notes/week-02.markdown",
    "content": "# Week 2 (2012-03-06 - 2012-03-13)\n\nThis is my second week in the book. I'm still very excited, but I am also gotten the farthest in the exercise from all the people in the study group. Thus, I will attempt to take it slower. It will not be that hard, since I have travelling involved.\n\n## Questions\n\n* What is the time complexity of 1.14?\n* What is the time complexity of normal-order in 1.20?\n* Am I getting the Robin-Miller test from 1.28 wrong? I expected all numbers a < n to fail the simple test (the one without the non-trivial square root test).\n* In 1.29, my implementation of Simpson's rule appears to be less precise. Am I doing something wrong?\n\n## Various\n\n### Uncle Bob's method ordering convention\n\nI'm following Uncle Bob's approach to ordering procedures in Scheme. I am putting the most important function on top. It will refer undefined (yet) procedures. I find the first such procedure in the body and put it afterwards. If the second procedure has undefined names, I define them before continuing with the remaining undefined names from the first procedures. Essentially, this orders the procedures depth-first.\n\nThe argument is that this way the code reads from top to bottom. I don't find it optimal, but I believe it works great in this case.\n\n### Recursive process vs. recursive procedure\n\nThis is from chapter 1.2.1, and while I've known it all along, it took me a while to appreciate the subtlety. Consider a tail-recursive and a non-tail-recursive implementations of factorial. Both of them are recursive procedures. But the first generates an iterative process, while the latter - a recursive one.\n\nIt's curious that recursive definitions do not always imply recursive processes. As far as I can tell, this totally depends on the tail recursion call.\n\nWhich got me thinking about tail recursion. While it's extremely nice, there is the risk of modifying a tail-recursive function in a way that preserves correctness, but makes it non-tail-recursive. This can happen accidentally and can be a regression, because the function will run out of stack space for larger inputs. That's why I find it extremely nice that Scala has a `@tailrec` annotation that enforces tail recursion.\n\n## Meetup summary\n\nIt was rather quick. I found out that some of my thoughts were utterly invalid and that some of my solutions were wrong. Here are some assorted thouhgts:\n\n* Plamen claims that it is proven that n.log(n) is the fastest a sorting algorithm can get. I'm not so certain about this, but hey - what do I know about sorting.\n* I should check out what Radix sort is. It is purported to be constrained, but faster.\n* My note from Week 1 on tail recursion + normal-order evaluation needs some clarification. I claimed that the time gets worse when both are present. It is actually not true, since normal-order evaluation is sufficient to degrade performance. Tail recursion is a factor, however, in the way you write programs. I would claim that if you had no tail recursion in your language, you would not go with a recursive procedure. Therefore, it is very unlikely that you stumble in that kind of degradation. Normal-order would still be slower, however.\n* I got 1.15 wrong. Time is Θ(logn).\n* I sill have questions from earlier. I will not carry them over to Chapter 2, but I will still keep them around in hope that somebody would provide a satisfactory answer.\n"
  },
  {
    "path": "scheme/sicp/notes/week-03.markdown",
    "content": "# Week 3 (2012-03-13 - 2012-03-20)\n\nThis is the third week of our humble study group. Some of us are lagging behind, but nontheless, we decided that we will complete Chapter 1.\n\n## Questions\n\n* What is the time complexity of 1.14?\n* What is the time complexity of normal-order in 1.20?\n* Am I getting the Robin-Miller test from 1.28 wrong? I expected all numbers a < n to fail the simple test (the one without the non-trivial square root test).\n* In 1.29, my implementation of Simpson's rule appears to be less precise. Am I doing something wrong?\n\n## Ruby, lambdas and procedures as general methods\n\nChapter 1.3.3 makes a very nice point about procedures. When a procedure is parametrized with functions (as opposed to values), it can create a more powerful abstraction. The `fixed-point` function is a nice example of that - it is a general abstraction for Newton's method of finding square roots (exercise 1.07). This is cool, but I would say that it is not used in Ruby.\n\nRuby is pretty decent, when your method needs just one lambda - it can be passed as a block. When you need too lambdas, however, it becomes rather awkward. Ruby has the `lambda` keyword, but it has at least two problems - (1) multiline lambdas are tricky (you have to use `{`/`}` instead of `do`/`end`) and (2) it feels awkward to pass lambdas to functions an invoke them. In such cases, I would probably go with a Template Method instead.\n\nWhile Ruby has all the power and flexibility to do this, I feel that the Ruby culture frowns upon it. Thus, Ruby feels less powerful in that sense. Note that it just **feels** that way.\n\n## First-class citizens and Ruby\n\nThis is a continuation of the previous thought. Section 1.3.4 talks about procedures as first-class citizens and what the term means. It says, that when more elements are first-class, this provides for more powerful abstractions.\n\nIt is curious how this question looks in Ruby. Are methods first-class in Ruby or not? On one hand, they are, since they (1) may be named as variables, (2) may be passed as arguments to procedures, (3) can be returned as the result of procedures and (4) may be included in data structures. Working with them, however, is slightly awkward, since they are obtained with `#method` and need special handling (invoking with `#call`). The awkwardness is very apparent when you compare with Python.\n\nI find the following interesting: the slight awkwardness in Ruby makes Ruby programmers avoid those constructs. Nobody really ever passes a method or returns a lambda to be called. I find two reasons for this. First, the code appears un-Rubyic, which is a cultural reason. Second, and more to the point, this is not orthogonal to blocks - most of those things can be accomplished by blocks, which makes such use of the constructs unpopular.\n\nBottom line, I find the concept of \"first-class citizens\" blurry at best. It might be useful to explain the differences of procedures in C and those in LISP, but it is very imprecise in Ruby. Methods there appear to be first-class in letter, but not in spirit. Which is a useful insight on its own.\n\n## Meetup summary\n\nIt was a longer, nicer meeting. We still need to be way more structured. I also believe that we should try to make them longer. Here are some assorted notes:\n\n* There is a book called [Structure and Interpretation of Classical Mechanics][sicm] from one of the authors. I find this equally disturbing and fascinating.\n* Slavena did a couple of neat algebraic tricks. Nothing fancy - just straightforward formula transformations that simplify the Scheme code. In [1.39][slav-1-39] she divides the whole expression by x, which makes an `if` in the numerator unnecessary. This reminds me of negotiating requirements to simplify code - when done properly, both sides win.\n* Somebody said that the next study group should be on a Haskell group. I'm quite happy that (1) we're talking about a next study group and (2) that it is Haskell. I personally prefer Introduction to Algorithms, though.\n* I promised everybody dinner after we complete Chapter 2. Either I take them out or I cook.\n* I don't like how the meetup summary of a week ends up in the notes from the next, so I rearranged all the notes\n\n[sicm]: http://mitpress.mit.edu/sicm/\n[slav-1-39]: https://github.com/slavv/sicp-exercises/blob/master/01/39.scm\n"
  },
  {
    "path": "scheme/sicp/notes/week-04.markdown",
    "content": "# Week 4 (2012-03-20 - 2012-03-27)\n\nWe are finally starting Chapter 2. It goes into data structures and I'm super excited. Plus, I really, really, REALLY like using `car` and `cdr` for recreation.\n\n## Questions\n\n* There is a quote in the foreword - \"In Pascal the plethora of declarable data structures induces a specialization within functions that inhibits and penalizes casual cooperation. It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structure.\". I'm not sure what it means, because of the ambiguity - \"It is better in Pascal\" or \"It is better in general\"?\n* How do you put more than one call in an if branch? (2.23)\n* Can 2.28 be done with a simple recursion, without reverse and append?\n\n## Various\n\n* With the rational numbers example, calculating the `gcd` can be done either in construction time (`make-rat`) or in selection time (`numer` and `denom`). This is a good example of the flexibility in data abstraction. I didn't occur to me that doing it in selection time can be faster in some cases.\n* The parts of subtraction are called \"minuend\", \"subtrahend\" and \"difference\". Neat.\n* \"The names car and cdr persist because simple combinations like cadr are pronounceable.\" This even sounds true. Wow.\n\n## Constructors, selectors and abstraction barriers\n\nThere is an interesting difference in how SICP advocates designing compound data and classical OOP wisdom. It is easy to show when implementing rational numbers. In an object-oriented fashion, we will have two levels of abstraction - (1) the clients of the `Rational` class and the (2) implementation of its operations (as methods). The methods use the private representation of the class. In contrast, the book talks about three levels - (1) the clients that use rational numbers, (2) the rational number operations (addition, subtraction, multiplication, divison) and (3) a set of constructors and selectors, what the operations are implemented with. That way representation can change without affecting the operations.\n\nIf we have a class `Rational`, the operations (2nd layer) and the internal representation (3rd layer) are naturally grouped in the same context (the class). Usually there is no separation - the operations access the private state directly. This makes changing the representation harder.\n\nIntroducing a layer of _constructors and selectors_ in a Ruby class seems a neat idea. I wonder if there is a good way to make it explicit.\n\n## Procedural representation of pairs\n\nI know what procedural representation of data is, but this caught me off guard - you can implement LISP pairs with lambdas. Like this:\n\n    (define (cons x y)\n      (define (dispatch m)\n        (cond ((= m 0) x)\n              ((= m 1) y)\n              (else (error \"Argument not 0 or 1 -- CONS\" m))))\n      dispatch)\n\n    (define (car z) (z 0))\n    (define (car z) (z 1))\n\nWhile I never gave serious thought about it, I always assumed pairs have to be implemented in C. Interestingly, this will be a sufficient implementation for a lot of LISP code.\n\nI'm curious how `pair?` will be implemented in this approach.\n\n## Mathematics and naïveté\n\nThe extended exercise of 2.1.4 shows an interesting insight: you can rarely approch mathematics naïvely. The idea was generally sound in the beginning, but the accumulated error in tolerance quickly makes the code untrustworthy. Furthermore, in order to minimize the error, one has to devise a way of simplifying arithmetic expressions. This is a task, way larger than the original.\n\nAnother interesting aspect of the exercise, is that the accumulated error was not immediatelly obvious from the initial design.\n\n## Meetup summary\n\nThis time I was in London and we held a brief meeting over Skype. Everybody was in the beginning of the material, except for me and Plamen.\n\n* Plamen seems to enjoy the video lectures. I should check them out.\n* I should show the real-time aspect of how I implement the exercises.\n* Veselin said he will show us the group annotation software next time.\n\nWe decided to keep the scope to 2.2.2, although Plamen and I might race a bit forward.\n"
  },
  {
    "path": "scheme/sicp/notes/week-05.markdown",
    "content": "# Week 5 (2012-03-25 - 2012-04-03)\n\nI was ahead of everybody else, so I took a small break this week. I was in London too - I did some reading and some exercise, but not entirely enough.\n\n## Meetup summary\n\nEverybody was busy, sick or having special plans, so we decided to skip a meeting.\n"
  },
  {
    "path": "scheme/sicp/notes/week-06.markdown",
    "content": "# Week 6 (2012-04-02 - 2012-04-10)\n\nI had no time at all to dedicate to SICP this week. I'm still up with everybody else, but I'm starting to feel guilty.\n\n## Meetup summary\n\nWe did the meetup in initLab this time.\n\n* Nikolay highlights the following quote:\n> As programmers, we should be alert to opportunities to identify the underlying abstractions in our programs and to build upon them and generalize them to create more powerful abstractions. This is not to say that one should always write programs in the most abstract way possible; expert programmers know how to choose the level of abstraction appropriate to their task. But it is important to be able to think in terms of these abstractions, so that we can be ready to apply them in new contexts. The significance of higher-order procedures is that they enable us to represent these abstractions explicitly as elements in our programming language, so that they can be handled just like other computational elements.\n* I've got 1.29 totally wrong and I should revisit\n* Firefox can show a 3D view of DOM? Really?!\n* I should clean up trailing whitespace\n* You can transpose with `(apply map list matrix)`\n"
  },
  {
    "path": "scheme/sicp/notes/week-07.markdown",
    "content": "# Week 07 (2012-04-10 - 2012-04-17)\n\nThis week I barely did anything. I just managed to complete 3 exercises, once of which in a very poor fashion. I was planning to have tons of free time around Easter, but that's life for you - making plans is the surest way to make your deity laugh.\n\n## Notes\n\n* `queens` in 2.42 is written independent of the presentation. `empty-board` contributes to that. Neat. However, this forces a crappy implementation.\n* I can't help but think that 2.42 can be written way better if the required functions are implemented via another layer of data abstraction.\n\n## Top-down versus bottom-up test-driving\n\nIt is hard to test-drive 2.42 (eight queens puzzle) in an outside-in fashion. There are three reasons for that:\n\n* There is a scaffold of the procedure that gets in the way of writing it incrementally.\n* It will force us to decide on representation, which we don't want to do.\n* We don't know the solutions.\n\nIn this sense, it makes to do a bottom-up test-drive. The upsides are obvious. There are downsides, though - (1) we can throw away a function we just test-drove or (2) we can invalidate all our tests by changing representation. Both of them happened to me.\n\nThe take away is: when doing up bottom-up test-driving, do more up-front planning.\n\n## Meetup summary\n\n* Veselin suggests to check out [(fluxus)][fluxus].\n* Plamen is playing a lot with Gimp and visualizing the painters in it.\n* I suggest that this should all happen with shelling out to ImageMagick. Or the Racket Drawing Kit.\n* My eight queens suck. I should redo them nicely.\n\n[fluxus]: http://www.pawfal.org/fluxus/\n"
  },
  {
    "path": "scheme/sicp/notes/week-08.markdown",
    "content": "# Week 08 (2012-04-17 - 2012-04-24)\n\nThis week was BaconConf. I was very productive and did a lot of progress.\n\n## Notes\n\n* My estimate on 2.43 is a bit off. I should check or ask around.\n* I'm testing 2.44 in a funky way. I'm replacing below and besides with procedures that construct lists and am asserting on the resulting list.\n* Racket has a plt-r5rs executable. Maybe I can use it instead?\n** Plamen said it did not really live up to its name.\n* Matrix transformations are fun!\n\n## The Rakefile\n\nWriting the Rakefile was immense fun. It also optimized a lot of things in my process. I realize, that spending time in order to build an environment where you can be effective is very, very important and totally worth investing in. For two reasons.\n\nFirst, you get the productivity boost. You automate repetative tasks and you reduce the time to accomplish your goal.\n\nSecond, and more important, you create an environment you can keep growing. If you need a new feature, you won't have to start from scratch - you have a place to put it and you probably have some code to build ontop of. It's pretty similar to the dotfiles and the Vim configuration. There is a general, underlying concept here, that I need to pinpoint.\n\n## Procedural representation is a hack\n\nWhile it is a very nice showcase of the power of programming languages, procedural representation feels like a hack to me. Consider implementing pairs as lambdas. It has a bunch of problems:\n\n* No types. There is no way to define `pair?`.\n* Either it is limited to one selector or it has some awkwardness.\n* There is no way to introspect it.\n* It is hard to manipulate the underlying structure. You can just invoke the selector.\n\nThere might be a deeper application I have not thought of. And it is occasionally very pragmatic (e.g. the picture language). But it feels hacky for me.\n\n## Meetup summary\n\nWe did not hold a meetup, because half of us were ill.\n"
  },
  {
    "path": "scheme/sicp/notes/week-09.markdown",
    "content": "# Week 09 (2012-04-24 - 2012-05-01)\n\nThe weekend after BaconConf we did not do any progress, unfortunatelly.\n\n## Meetup summary\n\nWe had a small meetup with half of us missing. I showed my Rakefile to Plamen\nand Veselin, but apart from that, it was not very productive.\n"
  },
  {
    "path": "scheme/sicp/notes/week-10.markdown",
    "content": "# Week 10 (2012-05-01 - 2012-05-08)\n\nNo progress again.\n\n## Meetup summary\n\nNo meetup. Everybody had an excuse.\n"
  },
  {
    "path": "scheme/sicp/notes/week-11.markdown",
    "content": "# Week 11 (2012-05-08 - 2012-05-15)\n\nWe decided that this is going to be the week we finish chapter 2. Whatever\nhappens by the end of the week, we move to chapter 03 in the next week.\n\nTo note the occasion, I gathered everybody at home and cooked some dinner.\n\n## Meetup summary\n\nIt was me, Veselin, Plamen and Slavena. Nobody had any progress in the past\nweeks. We decided that we should not keep strugling with the rest of chapter\n02 - we should move forward instead.\n\nWe decided that we will skip the next Tuesday and have a very simple,\nachievable target for after two weeks.\n"
  },
  {
    "path": "scheme/sicp/notes/week-12.markdown",
    "content": "# Week 12 (2012-08-21 - 2012-08-28)\n\nAs the git history clearly indicates, we dropped the ball at some point and I stopped solving exercises. This I picked it up. Nikolay started a new trend since Chapter 3 - now when we meet we don't discuss the exercise, but we read the text instead. That's actually a lot of fun. On the downside, we the progress is slower.\n\nI just finished a huge chunk of exercise and I am going to make some points.\n\n## Meetup summary\n\nWe read 3.3.5 Propagation of Constraints. The model there is quite interesting, although there was nothing groundbreaking in it.\n\n## Data-directed programming\n\nThe data-directed programming introduced in 2.4.3 is a very interesting idea. It is quite similar to multi-dispatch. It involves building a lot of infrastructure and slowing down the execution, but in the end, it has some interesting advantages. First, it solves the structures vs. classes problem to some extend. It allows adding both a new operation and a new type without resulting to Shotgun Surgery. It gets a bit more complicated when there are two separate packages, where the first one introduces a new type while the second - a new operation. The new types does not support the new operation if one of the package does not know about the other. This is a curious issue, but I don't think there is a good solution.\n\n## Systems with Generic Operations\n\nSection 2.5 was a lot of fun. I had to implement generic arithmetic operations over a bunch of numbers, including complex numbers with multiple representations and polynomials with both multiple representations and mixed-type coefficients. An interesting thing to note is when the types and operations are not organized in classes, they are way nicer to implement. For example, there is no need to have Python's `__radd__` and `__rmul`__ to support `3 * Vector(1, 2)`. It still feels that there can be more abstraction on operations (symmetrical opreations for example) but I don't dare venture there without knowing how to write macros. Or rather, I dare, but I'm too lazy to build complex procedures that take too many lambdas.\n\n## Coercion\n\nCoercion was implemented in a suboptimal way, since it involved raising types and getting arguments to the same type. This makes sense if we're extremely duck-typed and we don't know what types the operation is defined for. Our table, however, allows us to inspect what types an operation is defined for and we should be able to determine which procedure to invoke and what type conversion to do. This is an interesting problem I don't know much about, but I'm guessing that they avoided it because (1) it can be quite fat and (2) we don't know enough about state in order to inspect the table. I'm curious whether this topic will be revisited. I should also consider creating a showcase for this system once I learn how to do macros (since they are never introduced in this book).\n"
  },
  {
    "path": "scheme/sicp/notes/week-13.markdown",
    "content": "# Week 13 (2012-08-28 - 2012-09-03)\n\n## Notes\n\n* Racket does not support `set-car!` and `set-cdr!`. There is a [blog post][getting-rid] explaining why. While certainly unnice, it can be performed either with `mcons` and friends or by using \"legacy Scheme\" by doing `(require r5rs/init)`.\n* Dynamic scoping is very cool, because it allows doing `with-output-to-string`. This allows overriding the default print port, thus capturing the output from `display`. That way the printing side-effect can be tested. I just love that.\n"
  },
  {
    "path": "scheme/sicp/notes/week-14.markdown",
    "content": "# Week 14 (2012-09-03 - 2012-09-11)\n\n## On Scheme and VimScript\n\nI tweeted that reading the book made me a VimScript programmer. That is a very awkward statement, yet anyway, it highlights a fundamental truth - spending all my time in OOP languages, I've lost confidence in writing structured, non-OO code. In that sense, the book provides a freash breath of air - I get to excercise my \"structured programming muscles\" and I can later apply them in a suboptimal environment like VimScript (or possibly Emacs Lisp?).\n\nThere is a more general notion here about going with the current, being intuitive or analyzing everything I do.\n"
  },
  {
    "path": "scheme/sicp/notes/week-15.markdown",
    "content": "# Week 15 (2012-09-18 - 2012-09-25)\n\n## Meetups\n\nWe have been very slow on doing our meetups. On the other hand, I've been quite quick in progressing through the book. Currently I'm running far infront of everybody, since the book is finally starting to get interesting.\n\n## On namespaces and objects\n\nThis is not related to SICP, but an interesting thought nontheless. Once you get back to procedural/functional programming, you get into a nightmare of managing names in each namespace. If you are using a bunch of modules, you need to import the names you need and make sure they are available in a maintainable way. Think about `from foo import bar as baz` in Python or the imports in Scala.\n\nObject-oriented programming gets that out of the way, since it namespaces all operations under the type. This is obviosly limiting (for example, no \"global\" functions in Java), but makes name handling a lot easier - you just import the class and Robert's your uncle.\n"
  },
  {
    "path": "scheme/sicp/notes/week-16.markdown",
    "content": "# Week 16 (2012-12-04 - 2012-12-11)\n\n## Meetups\n\nWe haven't met in ages. I'm venturing forward by myself. So far, it has been an interesting experience.\n\n## Progress\n\nI implemented the lazy evaluator and the nondeterministic evaluator.\n\n## Abstractions in Scheme\n\nIt becomes apparent to me, that builting a lot of small abstractions is really important in order to make scheme code readable. For example, exercise 4.49 requires generation instead of parsing of sentences. I modified the parse-word procedure in the following way:\n\n    (define (parse-word word-list)\n      (if (null? (cdr word-list))\n          (amb)\n          (amb (list (car word-list) (cadr word-list))\n               (parse-word (cons (car word-list) (cddr word-list))))))\n\nThis obviously works, but it is far from optimal. The text defined the procedure an-element-of, which I could use to rewrite it as:\n\n    (define (parse-word word-list)\n\t\t  (list (car word-list) (an-element-of (cdr word-list))))\n\nThe result is obviously way simpler. Instead, I went for recursion.\n\nI'm not sure why I lack the discipline to introduce such small nice abstractions. On one hand, this follows naturally from the TDD process - you first beat the code until it works and only then you introduce abstractions. On the other hand, I'm rarely carrying this through - once I've gotten the tests of the exercises to pass, I continue with the next one.\n\nThere is a take-away on TDD, design and disciple here, that I've not yet formulated.\n\n## Macros and functions\n\nIt is kind of obvious, but I realized that macros have a certain inferiority in comparison to function. Namely, they cannot be passed in as first order functions (or combined in some dynamic way). That indeed makes them \"merely syntax\", as Alyssa points out in 4.26. This trade-off is makes them a tiny bit less useful. It is curious that Io manages to implement macro-like functions, without sacrificing this ability.\n"
  },
  {
    "path": "scheme/sicp/notes/week-17.markdown",
    "content": "# Week 17 (2012-12-11 - 2012-12-18)\n\n## Notes\n\nThis week was all abount implementing the logic programming environments. I don't have much insight to share. I have, however, written a lot of code. I got a lot of pleasant flashbacks to the time in FMI when we were learning Prolog. I wanted to write a Prolog implementation in the summer after the second year, but I never got around to do it. I still want to do it some time. There is a book that might be useful - [An Introduction to Logic Programming through Prolog][logic-programming].\n\n[logic-programming]: http://spivey.oriel.ox.ac.uk/corner/Logic_Programming\n\n## The predicate? convention and the query language\n\nEvery time I write a rule or assertion in the query language, I have the urge to postfix it with a question mark (?) to indicate that it is a predicate. This makes no sense, since all the rules and assertions are in fact predicates. This is an important point about notation - you introduce it to distinguish between different things. Since there are no non-predicates in the query data base, the question mark does not indicate anything and therefore it is a useless notation.\n"
  },
  {
    "path": "scheme/sicp/notes/week-18.markdown",
    "content": "# Week 18 (2012-12-18 - 2012-12-25)\n\n## Notes\n\nThis week is about the first four sections of the final chapter - everything but compilation.\n\n## Recursive vs. Iterative\n\nExercuse 5.27 shows some interesting results. The recursive factorial is not bound in the stack size it consumes, but it performs the computation with less pushes. I'm curious whether this is a weirdness of the explicit control evaluator, or whether it is actually true in general. The idea that recursive functions can be faster than iterative in some cases is interesting. I did not spend much time researching, but there is an interesting [answer on Stack Overflow][answer].\n\n[answer]: http://stackoverflow.com/questions/2651112/is-recursion-ever-faster-than-looping/2651200#2651200\n"
  },
  {
    "path": "scheme/sicp/notes/week-19.markdown",
    "content": "# Week 19 (2012-12-25 - 2012-12-31)\n\nI finally finished the book. By the end it was a huge crunch. I finished chapter 5 in two weeks and I was working really hard to do so.\n\n## Internal defines revisited\n\nThe discussion on why internal defines need to be scanned out finally started making sense when we wen't into lexical addressing. Basically, if internal defines are not scanned out (and converted to a let statement), lexical addressing just won't work.\n\n## Writing C again\n\nI had not written C since high school and revisiting it was an interesting experience. I could automate a lot of things with rake and watchr, but debugging it was still very hard. I did not use a debugger and just scattered `printf()` calls in the code. In retrospective, I should have taken some time to figure out gdb and used it instead. A huge pain point was debugging the garbage collector. I could not figure out why some memory got collected and I modified the C code to dump the memory and used a Ruby program to analyze it. The lack of introspection in C is really hurtful. Furthermore, C code tends to be very verbose and the lack of nice types (namely hashes and lists) makes it tricky to write code to figure out why something happens. Jakob said that he likes C because \"it punishes you really hard if you don't think a lot before you write\" and I've started to see what he means by that.\n\n## Prototyping, C and refactorability\n\nI've developed a new appreciation of the idea of writing a prototype in a higher-level language. Doing exploratory development with C is just too hard. You end up defining a lot of stuff and then changing it because you discover a better design. I'm starting to think that \"refactorability\" is an important feature of the language and the more less refactorable a language is, the more up-front design you have to do. It's easy to refactor Ruby, since there is not that much to write and you can get through the intermediate states with consice (if cryptic) expressions. In C, you have to write a lot.\n"
  },
  {
    "path": "scheme/sicp/tests.watchr",
    "content": "watch(%r{^(\\d+)/(\\d+).scm$})             { |m| run_file m[1], m[2] }\nwatch(%r{^(\\d+)/tests/(\\d+)-tests.scm$}) { |m| racket_test m[1], m[2] }\n\ndef run_file(chapter, exercise)\n  if File.exists? \"#{chapter}/tests/#{exercise}-tests.scm\"\n    racket_test chapter, exercise\n  else\n    system 'clear'\n    system \"rake run:exercise[#{chapter},#{exercise}]\"\n  end\nend\n\ndef racket_test(chapter, exercise)\n  system 'clear'\n  system \"rake run:test[#{chapter},#{exercise}]\"\nend\n"
  },
  {
    "path": "textmate/PLT Scheme.tmbundle/README",
    "content": "I decided to switch from Vim to TextMate when playing with PLT Scheme. Since\nI wanted to learn about making TextMate bundles, I decided to let go of the\nScheme bundle and create one of my own for the experience.\n\nYou should definitelly not use this. I'm adding only stuff that I need. Since\nI am using a subset of the language (a rather weird one, I might add), you'll\nget strange highlighting, lack of features and so on.\n\nTextMate has a nice Scheme bundle, that I'm shamelessly ripping code off (to\ngive credit where due). You can find it here:\n\n  http://svn.textmate.org/trunk/Bundles/Scheme.tmbundle/\n"
  },
  {
    "path": "textmate/PLT Scheme.tmbundle/Syntaxes/Scheme.tmLanguage",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>fileTypes</key>\n\t<array>\n\t\t<string>ss</string>\n\t</array>\n\t<key>keyEquivalent</key>\n\t<string>^~P</string>\n\t<key>name</key>\n\t<string>PLT Scheme</string>\n\t<key>patterns</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>include</key>\n\t\t\t<string>#comment</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>include</key>\n\t\t\t<string>#constants</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>include</key>\n\t\t\t<string>#keywords</string>\n\t\t</dict>\n\t</array>\n\t<key>repository</key>\n\t<dict>\n\t\t<key>comment</key>\n\t\t<dict>\n\t\t\t<key>captures</key>\n\t\t\t<dict>\n\t\t\t\t<key>1</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>name</key>\n\t\t\t\t\t<string>punctuation.definition.comment.scheme</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>match</key>\n\t\t\t<string>(;).*$\\n?</string>\n\t\t\t<key>name</key>\n\t\t\t<string>comment.line.semicolon.scheme</string>\n\t\t</dict>\n\t\t<key>constants</key>\n\t\t<dict>\n\t\t\t<key>patterns</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>match</key>\n\t\t\t\t\t<string>#[t|f]</string>\n\t\t\t\t\t<key>name</key>\n\t\t\t\t\t<string>constant.language.boolean.scheme</string>\n\t\t\t\t</dict>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>match</key>\n\t\t\t\t\t<string>(?&lt;=[\\(\\s])((#e|#i)?[0-9]+(\\.[0-9]+)?|(#x)[0-9a-fA-F]+|(#o)[0-7]+|(#b)[01]+)(?=[\\s;()'\",\\[\\]])</string>\n\t\t\t\t\t<key>name</key>\n\t\t\t\t\t<string>constant.numeric.scheme</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t</dict>\n\t\t<key>keywords</key>\n\t\t<dict>\n\t\t\t<key>patterns</key>\n\t\t\t<array>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>match</key>\n\t\t\t\t\t<string>(?x)\n\t\t\t\t\t\t(?&lt;=(\\s|\\(|\\[))\n\t\t\t\t\t\t( define|module|let|cond|if|require|provide|lambda )\n\t\t\t\t\t\t(?=(\\s|\\(|\\[))\n\t\t\t\t\t</string>\n\t\t\t\t\t<key>name</key>\n\t\t\t\t\t<string>keyword.control.scheme</string>\n\t\t\t\t</dict>\n\t\t\t</array>\n\t\t</dict>\n\t</dict>\n\t<key>scopeName</key>\n\t<string>source.scheme</string>\n\t<key>uuid</key>\n\t<string>7AF4CBF5-CF08-4855-8BAB-CBDBFB1F429D</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "textmate/PLT Scheme.tmbundle/info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>changed</key>\n\t<dict/>\n\t<key>deleted</key>\n\t<array/>\n\t<key>isDelta</key>\n\t<true/>\n\t<key>uuid</key>\n\t<string>79867339-0358-4314-96AE-E4EC68DADF10</string>\n</dict>\n</plist>\n"
  }
]