816 Shortest distance among points.pl 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. #!/usr/bin/perl
  2. # Author: Trizen
  3. # Date: 26 November 2023
  4. # https://github.com/trizen
  5. # Shortest Distance Among Points
  6. # https://projecteuler.net/problem=816
  7. # Runtime: 25.038s
  8. use 5.036;
  9. use ntheory qw(powmod);
  10. {
  11. my @cache;
  12. sub rng ($n) {
  13. $n == 0 && return 290797;
  14. $cache[$n] //= powmod(rng($n - 1), 2, 50515093);
  15. }
  16. }
  17. sub hypot ($a, $b) {
  18. sqrt($a**2 + $b**2);
  19. }
  20. sub d ($k) {
  21. my @P = map { [rng(2 * $_), rng(2 * $_ + 1)] } (1 .. $k);
  22. my @C1 = sort { $a->[0] <=> $b->[0] } @P;
  23. my @C2 = sort { $a->[1] <=> $b->[1] } @P;
  24. my $min_dist = 1e9**1e9;
  25. foreach my $i (0 .. $#C1 - 1) {
  26. my $p1 = $C1[$i];
  27. my $p2 = $C1[$i + 1];
  28. my $dist = hypot($p1->[0] - $p2->[0], $p1->[1] - $p2->[1]);
  29. if ($dist < $min_dist) {
  30. $min_dist = $dist;
  31. }
  32. }
  33. foreach my $i (0 .. $#C2 - 1) {
  34. my $p1 = $C2[$i];
  35. my $p2 = $C2[$i + 1];
  36. my $dist = hypot($p1->[0] - $p2->[0], $p1->[1] - $p2->[1]);
  37. if ($dist < $min_dist) {
  38. $min_dist = $dist;
  39. }
  40. }
  41. sprintf('%.9f', $min_dist);
  42. }
  43. d(14) eq '546446.466846479' or die "error";
  44. d(1000) eq '14759.650571745' or die "error";
  45. d(2000) eq '16462.444107726' or die "error";
  46. say d(2000000);