Bu cevap, ben ve 0 'arasındaki işbirliğinin bir parçası. İkimiz birlikte çalıştık, yayınlamamın tek nedeni Rock, Paper, Scissors kazandığım için.
\Q-->{Q=1};"(",\N,")",\B,{findnsols(N,I,(between(2,inf,I),\+ (between(3,I,U),0=:=I mod(U-1))),L)->append(_,[Y],L),Q is Y*B}.
Çevrimiçi deneyin!
açıklama
Bu cevap, prologda golfü neyin eğlenceli hale getirdiğinin mükemmel bir örneğidir.
Bu cevap, kesin yan tümce dilbilgileri için Prologs güçlü sistemini kullanır. İşte bizim dilbilgisi biraz ungolfed.
head(1)-->[].
head(Q)-->"(",head(N),")",head(B),{prime(N,Y),Q is Y*B}.
isprime(I):- \+ (between(3,I,U),0 =:= I mod(U-1)).
prime(N,Y):-
findnsols(N,I,(
between(2,inf,I),
isprime(I)
),L),
append(_,[Y],L),!.
İlk inşaat kuralı:
head(1)-->[].
Bu, Prolog'a boş dizenin 1'e karşılık geldiğini bildirir.
İkinci inşaat kuralımız biraz daha karmaşık.
head(Q)-->"(",head(N),")",head(B),{prime(N,Y),Q is Y*B}.
Bu, boş olmayan herhangi bir dizenin, aynı kurallara sahip bir cümle etrafında, aynı kurallara sahip bir cümlenin sağında parantez içerdiğini gösterir.
Ayrıca bize bu maddenin ( Q
) değerinin kurala uyduğunu söyler :
{prime(N,Y),Q is Y*B}
Bunu kırmak Q
, 2 sayının Y
ve B
. B
sola maddenin sadece değeridir ve Y
bir N
inci asal N
parantez içinde maddesinin değeridir.
Bu kural, faktör ağacının oluşum kurallarının her ikisini de kapsar
- Birleştirme çoğalır
- Muhafaza en önemli olanı aldı
Şimdi kesin tanımlar için. Golf edilmemiş versiyonda iki tahmin vardır (gerçek kodumda tahminleri uzakta zincirledim). Burada ilgili iki tahmin isprime/1
, asal sayı ile eşleşen ve prime/2
verilen N
ve Y
asff Y
ile eşleşen asal sayıdır N
. İlk önce
isprime(I):- \+ (between(3,I,U),0 =:= I mod(U-1)).
Asallık bir oldukça standart tanımının Bu eserler, biz 2 arasında numara yoksa ısrar ve I
2 değil de dahil olmak üzere, I
böler o I
.
Bir sonraki yüklem de oldukça basit
prime(N,Y):-
findnsols(N,I,(
between(2,inf,I),
isprime(I)
),L),
append(_,[Y],L),!.
Asal findnsols
olan ilk N
sayıları bulmak için kullanırız , sonra sonuncuyu döndürürüz. Buradaki hile findnsols
, en küçük N
asalları bulması garanti edilmese de, SWI'nin işleyiş şekli nedeniyle between
her zaman daha küçük asalları bulacaktır. Ancak bu, daha fazla prim bulmasını önlemek için kesmemiz gerektiği anlamına gelir.
Golfler
Kodumuzdaki nedeni iki kez iletebiliriz. Çünkü isprime
tanımı sadece içine taşınabiliyorsa prime
. Bir sonraki, prime
doğrudan DCG'nin içine taşınmaktır , ancak çok fazla prim üretmesini prime
önlemek için bir kesim kullandığımızdan findnsols
, bir sorunumuz var. Kesim, istediğimiz bit yerine tüm DCG'yi keser. Biraz dokümantasyon kazısından sonra, once/1
sadece bu kısmı kesmek için kullanılabilir, ancak tüm DCG'yi değil. Bununla birlikte, daha fazla belge kazma, ->
operatörün benzer bir görevi yerine getirmek için de kullanılabileceğini ortaya koymuştur . ->
Operatör eşdeğerdir ,!,
biz diğer tarafına bizim kesim taşındı bu yüzden append/3
ve onu değiştirdi ->
.
SWI-Prolog'da tahminler (ve kurallar), operatörlere normalde gereken parantezleri bırakmamızı sağlayan adlar olarak verilebilir. Böylece kuralı çağırarak 6 bayt tasarruf edebiliriz \
.