|
| 1 | +// Based on the OCaml version from "The Computer Language Benchmarks Game" |
| 2 | +// https://salsa.debian.org/benchmarksgame-team/benchmarksgame/ |
| 3 | +// Contributed by Ethan Burns, translated to Pony by GitHub Copilot. |
| 4 | + |
| 5 | +use "collections" |
| 6 | + |
| 7 | +actor Main |
| 8 | + new create(env: Env) => |
| 9 | + let n: USize = try env.args(1)?.usize()? else 7 end |
| 10 | + Fannkuch(env, n) |
| 11 | + |
| 12 | +class Fannkuch |
| 13 | + let _env: Env |
| 14 | + var _perm: Array[USize] |
| 15 | + var _copy: Array[USize] |
| 16 | + var _max_flips: USize = 0 |
| 17 | + var _checksum: ISize = 0 |
| 18 | + var _perm_count: USize = 0 |
| 19 | + let _n: USize |
| 20 | + |
| 21 | + new create(env: Env, n: USize) => |
| 22 | + _env = env |
| 23 | + _n = n |
| 24 | + _perm = recover Array[USize](n) end |
| 25 | + _copy = recover Array[USize](n) end |
| 26 | + |
| 27 | + for i in Range[USize](0, n) do |
| 28 | + _perm.push(i) |
| 29 | + end |
| 30 | + |
| 31 | + run() |
| 32 | + print_results() |
| 33 | + |
| 34 | + fun ref run() => |
| 35 | + // This is a direct translation of the recursive permutation |
| 36 | + // generation from the OCaml version. |
| 37 | + do_iter(_n) |
| 38 | + |
| 39 | + fun ref do_iter(ht: USize) => |
| 40 | + if ht == 1 then |
| 41 | + // Process the permutation |
| 42 | + _copy.clear() |
| 43 | + for i in Range[USize](0, _perm.size()) do |
| 44 | + try _copy.push(_perm(i)?) end |
| 45 | + end |
| 46 | + |
| 47 | + let flips = count_flips(_copy) |
| 48 | + |
| 49 | + // Update checksum: add for even permutations, subtract for odd |
| 50 | + if (_perm_count % 2) == 0 then |
| 51 | + _checksum = _checksum + flips.isize() |
| 52 | + else |
| 53 | + _checksum = _checksum - flips.isize() |
| 54 | + end |
| 55 | + |
| 56 | + if flips > _max_flips then |
| 57 | + _max_flips = flips |
| 58 | + end |
| 59 | + |
| 60 | + _perm_count = _perm_count + 1 |
| 61 | + else |
| 62 | + for i in Range[USize](0, ht) do |
| 63 | + do_iter(ht - 1) |
| 64 | + // Rotate the first `ht` elements |
| 65 | + if ht > 1 then |
| 66 | + try |
| 67 | + let t = _perm(0)? |
| 68 | + for j in Range[USize](1, ht) do |
| 69 | + _perm(j-1)? = _perm(j)? |
| 70 | + end |
| 71 | + _perm(ht-1)? = t |
| 72 | + end |
| 73 | + end |
| 74 | + end |
| 75 | + end |
| 76 | + |
| 77 | + fun ref count_flips(p: Array[USize]): USize => |
| 78 | + var flips: USize = 0 |
| 79 | + try |
| 80 | + var first = p(0)? |
| 81 | + while first != 0 do |
| 82 | + // Flip the first `first + 1` elements |
| 83 | + for i in Range[USize](0, (first / 2) + 1) do |
| 84 | + let k = first - i |
| 85 | + let t = p(i)? |
| 86 | + p(i)? = p(k)? |
| 87 | + p(k)? = t |
| 88 | + end |
| 89 | + flips = flips + 1 |
| 90 | + first = p(0)? |
| 91 | + end |
| 92 | + end |
| 93 | + flips |
| 94 | + |
| 95 | + fun ref print_results() => |
| 96 | + _env.out.print(_checksum.string()) |
| 97 | + _env.out.print("Pfannkuchen(" + _n.string() + ") = " + _max_flips.string()) |
0 commit comments