Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

are_we_fast_yet/towers.fz


# ported from https://github.com/smarr/are-we-fast-yet/blob/master/benchmarks/Java/src/Towers.java
public towers
post result = 8191
=>
  Towersdisk(size i32, next Towersdisk|nil) ref is

  mi : mutate is
  mi.go ()->

    piles := (mutate.array (choice Towersdisk nil)).type.new mi 3 nil
    moves_done := mut 0

    push_disk(disk Towersdisk, pile i32)
      pre
        match piles[pile]
          nil => true
          top Towersdisk =>
            top.size > disk.size
      =>
      piles[pile] := Towersdisk disk.size piles[pile]

    build_tower_at(pile i32, disks i32) =>
      for i in -disks..0 do
        push_disk (Towersdisk -i nil) pile

    pop_disk_from(pile i32) Towersdisk is
      match piles[pile]
        nil => panic "attempting to pop from empty pile"
        top Towersdisk =>
          piles[pile] := top.next
          top

    move_top_disk(from i32, to i32) =>
      push_disk (pop_disk_from from) to
      moves_done <- moves_done.get + 1

    move_disks(disks i32, from i32, to i32) unit is
      if disks = 1
        move_top_disk from to
      else
        other := 3 - from - to
        move_disks (disks - 1) from other
        move_top_disk from to
        move_disks (disks - 1) other to

    benchmark =>
      build_tower_at 0 13
      move_disks 13 0 1

    benchmark

    moves_done.get