Czy to jest liczba pierwsza? bez matematyki [zamknięte]

14

Napisz program lub funkcję w dowolnym języku, który mówi, czy wejście jest liczbą pierwszą.

  • Dane wejściowe to ciąg reprezentujący liczbę naturalną w bazie-10.
  • Wyjściem jest jeden z dwóch ciągów „Prime” lub „Not !!” który poprawnie identyfikuje dane wejściowe.
  • Operatory arytmetyczne, operatory bitowe, zmienne i stałe numeryczne, ogólnie „matematyka” itp. Są niedozwolone w twoim programie. Powinieneś użyć operacji na łańcuchach, aby wykonać wszystkie niezbędne „obliczenia”.
  • Możesz porównać długości łańcuchów (które są liczbami) - ale -10 do swojego wyniku, jeśli tego nie zrobisz.
  • Twój program powinien działać na dowolnym wejściu długościowym (biorąc pod uwagę wystarczającą ilość pamięci i czasu).
  • Wygrywa najniższa liczba bajtów (UTF-8).
Wally
źródło
Jakie są granice liczby? Czy to może być negatywne? Zero? Czy może zawierać kropkę dziesiętną?
Justin
Jeśli ma punkty bonusowe, to nie jest to golf kodowy
Peter Taylor
Dodano „naturalne”, aby określić granice wejścia.
Wally
Miałem nadzieję zaskoczyć jakąś szaloną jawną manipulacją ciągiem (osobiście myślałem o napisaniu kodu w celu „zmniejszenia” łańcucha, aby móc zapętlić - i byłem rozdarty między długim dzieleniem łańcucha a powtarzanym odejmowaniem łańcucha ...), zamiast tego był zaskoczony tym fajnym, małym pojedynczym wyrażeniem regularnym regex! Być może muszę ponownie zadać pytanie, nie pozwalając na wyrażenie regularne, aby zobaczyć, czy dostanę jeszcze więcej cudownych rzeczy? Ale nie sądzę, że cokolwiek będzie w stanie zbliżyć się do zwięzłości tego wyrażenia regularnego.
Wally,
Aby uzyskać „więcej cudownych rzeczy”, możesz spróbować zrobić z tego konkurs popularności . Jednak zmiana samego pytania jest generalnie niezadowolona. I nie jestem pewien, czy powinieneś zadać nowe pytanie lub zmienić cokolwiek tylko dlatego, że ktoś wpadł na coś, o czym nie pomyślałeś - myślę, że zdarza się to tutaj dość często. Również gięcie reguł jest częścią tego sportu :)
daniero

Odpowiedzi:

7

Rubin, 64-10 = 54

puts ('1
'..gets).map{?1}*''=~/^1?$|^(11+?)\1+$/?'Not!!': :Prime

Powoduje to iterację od ciągu „1” (plus nowy wiersz) do ciągu wejściowego, przy użyciu wbudowanej w Ruby metody iteracji ciągu, która wygląda okropnie podobnie jak dodanie 1, ale która nie tworzy technicznie zmiennej numerycznej wysokiego poziomu w dowolnym momencie . Wykorzystuje fakt, że będą istnieć n iteracje dla wejścia n, aby utworzyć ciąg o długości n, a następnie używa wyrażenia regularnego, aby ustalić, czy ten ciąg może być zgrupowany w identyczne podłańcuchy.

histocrat
źródło
Czy „1” na „mapie {? 1}” to Fixnum? - jeśli tak, być może trzeba go zmienić na „map ('1')? Nie mogę znaleźć żadnej dokumentacji dotyczącej wyrażenia? 1 oprócz pewnych wskazówek, że w starszych wersjach Ruby zwrócił kody ASCII, a teraz zwraca ciąg .
Wally
? 1 to to samo, co „1”, to dosłowny ciąg 1 znaków. Mógłbym zastąpić wszystkie wystąpienia 1, ale pierwszy każdą inną postacią.
histocrat
Ok - po prostu nie mogłem nigdzie znaleźć tej konstrukcji dobrze opisanej!
Wally
Wybieram to jako „zwycięzcę”, ponieważ robi wszystko, aby uniknąć choćby odrobiny matematyki.
Wally
3
Brak czapki dla Abigail? Wstyd. To jest prosty port rozwiązania perla z 1998 roku: catonmat.net/blog/perl-regex-that-matches-prime-numbers
skibrianski
16

Rubin: 52-10 = 42

Używając odmiany tego słynnego wyrażenia regularnego dopasowującego liczby pierwsze.

puts ?_*gets.to_i=~/^(_|(__+?)\2+)$/?"Not!!":"Prime"

Żeby było jasne: ?_*gets.to_ito operacja łańcuchowa, która dołącza się "_"do siebie n razy, gdzie n jest liczbą wejściową. Widzę, że długości łańcuchów nie są porównywane, więc powinno spełniać kryterium premii 10 znaków.

daniero
źródło
1
Nie znam się tak dobrze na Ruby, więc popraw mnie, jeśli się mylę, ale czy „to_i” nie przekształca ciągu na liczbę całkowitą? Nie to, że nie kocham genialnego sprawdzania liczb pierwszych jednoosobowo…
Wally
1
@Wally Nie sądzę, że „konwersja” nie jest właściwym słowem, ale metoda zwraca int, tak. Nadal nie używam żadnego z poniższych Arithmetic operators, bit-wise operators, numeric variables and constantsi nie można tak naprawdę zaklasyfikować wywoływania metody jako "math-stuff" in general..?
daniero
@daniero Brzmi rozsądnie - być może na skraju specyfikacji.
Wally
3

Perl 52-10 = 42

Realizacja

print((('-'x$ARGV[0])=~/^.$|^(..+?)\1+$/)?Not:Prime)

Próbny

$ seq 1 10|xargs -I{} bash -c "echo -n '{} '  && perl Prime.pl {} && echo"
1 Not
2 Prime
3 Prime
4 Not
5 Prime
6 Not
7 Prime
8 Not
9 Not
10 Not
Abhijit
źródło
4
1 nie jest naprawdę liczbą pierwszą.
elixenide
Używa liczbowego indeksu tablicowego - czyli na skraju specyfikacji.
Wally
Użyj popzamiast $ARGV[0], zapisz 4 znaki, usuń numeryczny indeks tablicowy
mob
1

ECMAScript 6, 159–10 = 149

Brzmi jak zadanie dla wyrażenia regularnego. I / O z prompt/ alertjak zwykle.

for(s=prompt(u=""); /[^0]/.test(s); )
  s=s.replace(/(.)(0*)$/,(_,d,t)=>u+="x"," 012345678"[d]+t.replace(/0/g,"9"))
alert(/^((xx+)\2+|x?)$/.test(u)?"Not!!":"Prime")

Pętla while zmniejsza liczbę dziesiętną o jeden w każdej iteracji wyłącznie za pomocą wyrażenia regularnego. Ostateczne wyrażenie regularne dopasowuje ciąg składający się ze złożonej liczby x, najpierw dopasowując jeden czynnik, a następnie drugi, powtarzając pierwszy czynnik jeden dla reszty łańcucha.

Robaczek świętojański
źródło
Podoba mi się funkcja zmniejszania łańcucha - jasne i zwięzłe.
Wally
1

JavaScript 266

function N(a){function b(a){return P.every(function(b){if(n=b,i=a.length,j=b.length,j>i) return;if(j==i) return 1;while(n.length<i)n+=b;return n.length!=i})}if(q=A,A!=a)for(;q.length.toString()!=a;)b(q)&&P.push(q),q+=A;console.log(b(q)?"Prime":"Not!!")}A="0",P=[A+A]

Tworzy funkcję o nazwie N, która wydrukuje pożądany wynik. Wersja nieuprawniona wygląda następująco. Zrobiłem ręczną minify, aby wyczyścić niektóre zmienne, a następnie przejrzałem to przez uglify, a następnie ręcznie zminimalizowałem to ponownie.

// A a string of "0" for using to generate long strings
// P is the store for all known primes
A="0", P=[A+A];
function N(val) {
  function _isPrime(str) {
    // go through all the known primes and return true
    // if we don't match on any of them
    return P.every(function(prime) {
      // prime is some known string whose length is a prime number
      tsr = prime, strlen = str.length, primelen = prime.length;
      // if the string we're checking has fewer chars than
      // this then it's not a prime
      if(strlen < primelen) return 0;
      // if the string we're checking has the same number of chars
      // as the the prime we're checking against then it is a prime
      if(primelen == strlen) return 1;
      // Keep incrementing our temporary string with the prime we're
      // checking. we'll break out of the loop once the temporary string
      // is greater than or equal to the string we're testing
      while(tsr.length < strlen) {
        tsr += prime;
      }
      return !(tsr.length == strlen)
    });
  }
  // start with a string of one unit
  nstr = A
  if(A!=val) {
    // keep incrementing the string so that we can compile a list
    // of known primes smaller than this value
    while(nstr.length.toString() !== val) {
      if(_isPrime(nstr)) {
        P.push(nstr);
      }
      nstr += A;
    }
  }
  console.log(_isPrime(nstr) ? "Prime" : "Not!!");
}

Przetestowałem to za pomocą tego fragmentu:

for(var X=0;X<10;X++) {
  console.log('checking: ' + X);
  N(X.toString());
}
Sugendran
źródło
1
Nie jestem pewien, czy widzę, jak to działa, ale widzę zmienną numeryczną (i) i operator arytmetyczny (i ++).
Wally
Och, nie zdawałem sobie sprawy, że nie mogę zrobić takiej pętli for .. przepisze ją dziś wieczorem.
Sugendran
Zasadniczo tworzę tablicę ciągów, których długości są liczbami pierwszymi. Więc kiedy dostaję dane wejściowe, ciągle dodam znaki do łańcucha, dopóki wartość długości łańcucha nie będzie zgodna z wartością wejściową. Następnie biorę ten ciąg i sprawdzam, czy mogę go równomiernie podzielić przez którąkolwiek ze znanych liczb pierwszych. Jeśli nie mogę, to musi być liczba pierwsza. Przez dzielenie rozumiem, że biorę znany ciąg główny i ciągle go dodam, długość ciągu jest równa lub większa niż ciąg, o którym mowa.
Sugendran
Zaktualizowałem kod, to faktycznie nieznacznie zmniejsza liczbę znaków :)
Sugendran
Chłodny. Wygląda na ten sam pomysł co wyrażenie regularne, ale jest bardziej wydajny i wyraźnie pokazuje rzeczywistą logikę.
Wally
0

Bash 66-10 = 56

Realizacja

[[ -z `printf %$1s|grep -P "^(..+?)\1+$"` ]]&&echo Prime||echo Not

Próbny

$ seq 1 10|xargs -I{} bash -c "echo -n '{} '  && ./Prime.sh {}"
1 Prime
2 Prime
3 Prime
4 Not
5 Prime
6 Not
7 Prime
8 Not
9 Not
10 Not
Abhijit
źródło
Jak wyżej, 1 nie jest liczbą pierwszą.
Wally