prog.pl 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # License: GPLv3
  4. # https://github.com/trizen
  5. # An interesting text scrambling algorithm, invented by the author in ~2008.
  6. use utf8;
  7. use 5.010;
  8. use strict;
  9. use warnings;
  10. use ntheory qw(:all);
  11. sub double_scramble {
  12. my ($str) = @_;
  13. my $i = my $l = length($str);
  14. $str =~ s/(.{$i})(.)/$2$1/s while (--$i > 0);
  15. $str =~ s/(.{$i})(.)/$2$1/s while (++$i < $l);
  16. return $str;
  17. }
  18. sub double_unscramble {
  19. my ($str) = @_;
  20. my $i = my $l = length($str);
  21. $str =~ s/(.)(.{$i})/$2$1/s while (--$i > 0);
  22. $str =~ s/(.)(.{$i})/$2$1/s while (++$i < $l);
  23. return $str;
  24. }
  25. sub double_scramble_global {
  26. my ($str) = @_;
  27. my $i = my $l = length($str);
  28. $str =~ s/(.{$i})(.)/$2$1/sg while (--$i > 0);
  29. $str =~ s/(.{$i})(.)/$2$1/sg while (++$i < $l);
  30. return $str;
  31. }
  32. sub double_unscramble_global {
  33. my ($str) = @_;
  34. my $i = my $l = length($str);
  35. $str =~ s/(.)(.{$i})/$2$1/sg while (--$i > 0);
  36. $str =~ s/(.)(.{$i})/$2$1/sg while (++$i < $l);
  37. return $str;
  38. }
  39. sub scramble {
  40. my ($str) = @_;
  41. my $i = length($str);
  42. $str =~ s/(.{$i})(.)/$2$1/s while (--$i > 0);
  43. return $str;
  44. }
  45. sub unscramble {
  46. my ($str) = @_;
  47. my $i = 0;
  48. my $l = length($str);
  49. $str =~ s/(.)(.{$i})/$2$1/s while (++$i < $l);
  50. return $str;
  51. }
  52. sub scramble_global {
  53. my ($str) = @_;
  54. my $i = length($str);
  55. $str =~ s/(.{$i})(.)/$2$1/sg while (--$i > 0);
  56. return $str;
  57. }
  58. sub unscramble_global {
  59. my ($str) = @_;
  60. my $i = 0;
  61. my $l = length($str);
  62. $str =~ s/(.)(.{$i})/$2$1/sg while (++$i < $l);
  63. return $str;
  64. }
  65. my %encode_fails;
  66. my %decode_fails;
  67. foreach my $n(1..128) {
  68. my $w = fromdigits(scramble(todigitstring($n, 2)), 2);
  69. my $x = fromdigits(scramble_global(todigitstring($n, 2)), 2);
  70. my $y = fromdigits(double_scramble(todigitstring($n, 2)), 2);
  71. my $z = fromdigits(double_scramble_global(todigitstring($n, 2)), 2);
  72. my $w_ = fromdigits(unscramble(todigitstring($w, 2)), 2);
  73. my $x_ = fromdigits(unscramble_global(todigitstring($x, 2)), 2);
  74. my $y_ = fromdigits(double_unscramble(todigitstring($y, 2)), 2);
  75. my $z_ = fromdigits(double_unscramble_global(todigitstring($z, 2)), 2);
  76. ++$decode_fails{w} if ($w_ != $n);
  77. ++$decode_fails{x} if ($x_ != $n);
  78. ++$decode_fails{y} if ($y_ != $n);
  79. ++$decode_fails{z} if ($z_ != $n);
  80. ++$encode_fails{w} if ($w == $n);
  81. ++$encode_fails{x} if ($x == $n);
  82. ++$encode_fails{y} if ($y == $n);
  83. ++$encode_fails{z} if ($z == $n);
  84. printf("a(%3d) = (%3d %3d) (%3d %3d) (%3d %3d) (%3d %3d)\n", $n, ($w, $w_), ($x, $x_), ($y, $y_), ($z, $z_));
  85. }
  86. say '';
  87. say "Single scramble non-global encode fails: $encode_fails{w}";
  88. say "Single scramble global encode fails : $encode_fails{x}";
  89. say "Double scramble non-global encode fails: $encode_fails{y}";
  90. say "Double scramble global encode fails : $encode_fails{z}";
  91. say '';
  92. say "Single scramble non-global decode fails: $decode_fails{w}";
  93. say "Single scramble global decode fails : $decode_fails{x}";
  94. say "Double scramble non-global decode fails: $decode_fails{y}";
  95. say "Double scramble global decode fails : $decode_fails{z}";
  96. __END__
  97. # Single scramble global:
  98. 1, 1, 3, 4, 6, 5, 7, 1, 9, 3, 11, 5, 13, 7, 15, 8, 10, 9, 11, 24, 26, 25, 27, 12, 14, 13, 15, 28, 30, 29, 31, 1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31, 33, 49, 41, 57, 37, 53, 45, 61, 35, 51, 43, 59, 39, 55, 47, 63, 64, 66, 65, 67, 96, 98, 97, 99, 80, 82, 81, 83, 112, 114, 113, 115, 72, 74, 73, 75, 104, 106, 105, 107, 88, 90, 89, 91, 120, 122, 121, 123, 68, 70, 69, 71, 100
  99. # Single scramble non-global:
  100. 1, 1, 3, 4, 6, 5, 7, 2, 10, 3, 11, 6, 14, 7, 15, 8, 12, 9, 13, 24, 28, 25, 29, 10, 14, 11, 15, 26, 30, 27, 31, 4, 20, 5, 21, 12, 28, 13, 29, 6, 22, 7, 23, 14, 30, 15, 31, 36, 52, 37, 53, 44, 60, 45, 61, 38, 54, 39, 55, 46, 62, 47, 63, 64, 72, 65, 73, 96, 104, 97, 105, 66, 74, 67, 75, 98, 106, 99, 107, 80, 88, 81, 89, 112, 120, 113, 121, 82, 90, 83, 91, 114, 122, 115, 123, 68, 76, 69, 77, 100
  101. # Double scramble global:
  102. 1, 2, 3, 1, 3, 5, 7, 4, 5, 12, 13, 6, 7, 14, 15, 2, 6, 18, 22, 3, 7, 19, 23, 10, 14, 26, 30, 11, 15, 27, 31, 32, 34, 48, 50, 36, 38, 52, 54, 40, 42, 56, 58, 44, 46, 60, 62, 33, 35, 49, 51, 37, 39, 53, 55, 41, 43, 57, 59, 45, 47, 61, 63, 1, 33, 65, 97, 3, 35, 67, 99, 17, 49, 81, 113, 19, 51, 83, 115, 5, 37, 69, 101, 7, 39, 71, 103, 21, 53, 85, 117, 23, 55, 87, 119, 9, 41, 73, 105, 11
  103. # Double scramble non-global:
  104. 1, 2, 3, 1, 3, 5, 7, 4, 5, 12, 13, 6, 7, 14, 15, 2, 6, 18, 22, 3, 7, 19, 23, 10, 14, 26, 30, 11, 15, 27, 31, 8, 10, 40, 42, 12, 14, 44, 46, 24, 26, 56, 58, 28, 30, 60, 62, 9, 11, 41, 43, 13, 15, 45, 47, 25, 27, 57, 59, 29, 31, 61, 63, 1, 9, 65, 73, 3, 11, 67, 75, 33, 41, 97, 105, 35, 43, 99, 107, 5, 13, 69, 77, 7, 15, 71, 79, 37, 45, 101, 109, 39, 47, 103, 111, 17, 25, 81, 89, 19
  105. Single scramble non-global encode fails: 16
  106. Single scramble global encode fails : 22
  107. Double scramble non-global encode fails: 13
  108. Double scramble global encode fails : 19
  109. Single scramble non-global decode fails: 30
  110. Single scramble global decode fails : 30
  111. Double scramble non-global decode fails: 63
  112. Double scramble global decode fails : 47