fannkuch.lua 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. -- Fannkuch-redux benchmark from benchmarks game
  2. -- https://benchmarksgame-team.pages.debian.net/benchmarksgame/description/fannkuchredux.html
  3. --
  4. -- Based on the C version found at:
  5. -- https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/fannkuchredux-gcc-1.html
  6. --
  7. -- Code by Hugo Gualandi, translated to Lua from the C version. The thing with
  8. -- the count vector is complicated, but we need to copy that from the original
  9. -- program to ensure that the permutation order is the right one.
  10. --
  11. -- * note: I made the function return a list of values because Pallene cannot
  12. -- return multiple values yet, or print the integer checksum.
  13. --
  14. -- Expected output (N = 7):
  15. -- 228
  16. -- Pfannkuchen(7) = 16
  17. --
  18. -- Expected output (N = 12):
  19. -- 3968050
  20. -- Pfannkuchen(12) = 65
  21. local function fannkuch(N)
  22. local initial_perm = {}
  23. for i = 1, N do
  24. initial_perm[i] = i
  25. end
  26. local perm = {} -- Work copy, allocated once
  27. local count = {}
  28. count[1] = 0
  29. local r = N
  30. local perm_count = 0
  31. local max_flips = 0
  32. local checksum = 0
  33. while true do
  34. -- Flip the pancakes, working on a copy of the permutation
  35. do
  36. for i = 1, N do
  37. perm[i] = initial_perm[i]
  38. end
  39. local flips_count = 0
  40. local h = perm[1]
  41. while h > 1 do
  42. local i = 1
  43. local j = h
  44. repeat
  45. local a = perm[i]
  46. local b = perm[j]
  47. perm[i] = b
  48. perm[j] = a
  49. i = i + 1
  50. j = j - 1
  51. until i >= j
  52. flips_count = flips_count + 1
  53. h = perm[1]
  54. end
  55. if flips_count > max_flips then
  56. max_flips = flips_count
  57. end
  58. if perm_count % 2 == 0 then
  59. checksum = checksum + flips_count
  60. else
  61. checksum = checksum - flips_count
  62. end
  63. end
  64. -- Go to next permutation
  65. while r > 1 do
  66. count[r] = r
  67. r = r - 1
  68. end
  69. while true do
  70. if r == N then
  71. return { checksum, max_flips }
  72. end
  73. local tmp = initial_perm[1]
  74. for i = 1, r do
  75. initial_perm[i] = initial_perm[i+1]
  76. end
  77. initial_perm[r+1] = tmp
  78. local r1 = r+1
  79. count[r1] = count[r1] - 1
  80. if count[r1] > 0 then break end
  81. r = r1
  82. end
  83. perm_count = perm_count + 1
  84. end
  85. end
  86. return function(N)
  87. N = N or 7
  88. local ret = fannkuch(N)
  89. local checksum = ret[1]
  90. local flips = ret[2]
  91. print(checksum)
  92. print(string.format("Pfannkuchen(%d) = %d", N, flips))
  93. end