tpermutations.nim 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. discard """
  2. output: '''
  3. @[@[1.0, 2.0], @[3.0, 4.0]]
  4. perm: 10.0 det: -2.0
  5. @[@[1.0, 2.0, 3.0, 4.0], @[4.0, 5.0, 6.0, 7.0], @[7.0, 8.0, 9.0, 10.0], @[10.0, 11.0, 12.0, 13.0]]
  6. perm: 29556.0 det: 0.0
  7. @[@[0.0, 1.0, 2.0, 3.0, 4.0], @[5.0, 6.0, 7.0, 8.0, 9.0], @[10.0, 11.0, 12.0, 13.0, 14.0], @[15.0, 16.0, 17.0, 18.0, 19.0], @[20.0, 21.0, 22.0, 23.0, 24.0]]
  8. perm: 6778800.0 det: 0.0
  9. '''
  10. """
  11. import sequtils, sugar
  12. iterator permutations*[T](ys: openarray[T]): tuple[perm: seq[T], sign: int] =
  13. var
  14. d = 1
  15. c = newSeq[int](ys.len)
  16. xs = newSeq[T](ys.len)
  17. sign = 1
  18. for i, y in ys: xs[i] = y
  19. yield (xs, sign)
  20. block outter:
  21. while true:
  22. while d > 1:
  23. dec d
  24. c[d] = 0
  25. while c[d] >= d:
  26. inc d
  27. if d >= ys.len: break outter
  28. let i = if (d and 1) == 1: c[d] else: 0
  29. swap xs[i], xs[d]
  30. sign *= -1
  31. yield (xs, sign)
  32. inc c[d]
  33. proc det(a: seq[seq[float]]): float =
  34. let n = toSeq 0..a.high
  35. for sigma, sign in n.permutations:
  36. result += sign.float * n.map((i: int) => a[i][sigma[i]]).foldl(a * b)
  37. proc perm(a: seq[seq[float]]): float =
  38. let n = toSeq 0..a.high
  39. for sigma, sign in n.permutations:
  40. result += n.map((i: int) => a[i][sigma[i]]).foldl(a * b)
  41. for a in [
  42. @[ @[1.0, 2.0]
  43. , @[3.0, 4.0]
  44. ],
  45. @[ @[ 1.0, 2, 3, 4]
  46. , @[ 4.0, 5, 6, 7]
  47. , @[ 7.0, 8, 9, 10]
  48. , @[10.0, 11, 12, 13]
  49. ],
  50. @[ @[ 0.0, 1, 2, 3, 4]
  51. , @[ 5.0, 6, 7, 8, 9]
  52. , @[10.0, 11, 12, 13, 14]
  53. , @[15.0, 16, 17, 18, 19]
  54. , @[20.0, 21, 22, 23, 24]
  55. ] ]:
  56. echo a
  57. echo "perm: ", a.perm, " det: ", a.det
  58. # bug #3499 last snippet fixed
  59. # bug 705 last snippet fixed