Perl, 1428 1099
Bu 1193 ASCII karaktere sahiptir (960 izin verilen ikili basamak dahil). 1193-94 = 1099
$s='010011100001100010101100111111101001101011101000100000101011011010100110111111011111101011101000100110111111011100101000011101011110100000101000100101011111111110101100101101011010011100100100011110110001011100100001011010100111100000011110111110011100101000100110111111101001011110101011100110101110101101011110101100111111100010101101101100011110100101011111111111101101101000111111011110100111011100101000011101011110111111011010111111101100101101101011100010100111100000111110';$_=q{$i=join'',A..Z,a..z,0..9,'. ';print map({substr$i,oct'0b'.$_,1}$s=~/.{6}/g),$/;chop($s=<>);$s=join'',map{sprintf"%06b",index$i,$_}$s=~/./g;$t=join'',map{$_ x(480-(()=$s=~/$_/g))}0,1;print"\$s='$s';\$_=q{$_};eval#$t"};eval#000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
İlk tasarımım
Dennis'den ikiliye geçmesi için bir öneri almadan önce, programım sekizlik sayılara izin verdi.
İlk tasarımım her dizeyi karakter başına 2 basamakla 160 sekizlik basamakta kodlar. Bu kodlamanın 100 8 = 64 farklı karakteri vardır. Sekizli sistemin 8 farklı basamağı vardır. Program her basamağın 160 kopyasına sahip olmalıdır, böylece 8 × 160 = 1280 basamağa izin verir.
160 haneyi $s
, diğer 1120 haneyi tutuyorum $t
. Bir quine olmayan bir program ile başlamak, ama yalnızca atamaları yazdırır $s
ve $t
sonraki saldırı için. Budur:
$s = '2341425477515350405332467737535046773450353640504537765455323444366134413247403676345046775136534656553654774255543645377755507736473450353677327754555342474076';
$t = '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222223333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333334444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777';
# $i = character map of 64 characters, such that:
# substr($i, $_, 1) is the character at index $_
# index($i, $_) is the index of character $_
$i = join '', 'A'..'Z', 'a'..'z', '0'..'9', '. ';
# Decode $s from octal, print.
# 1. ($s =~ /../g) splits $s into a list of pairs of octal digits.
# 2. map() takes each $_ from this list.
# 3. oct() converts $_ from an octal string to a number.
# 4. substr() on $i converts number to character.
# 5. print() outputs the characters from map() and a final "\n".
print map({ substr $i, oct, 1 } $s =~ /../g), "\n";
# Read new $s, encode to octal.
# 1. ($s = <>) reads a line.
# 2. chop($s) removes the last character of $s, the "\n".
# 3. ($s =~ /./g) splits $s into characters.
# 4. map() encodes each character $_ as a pair of octal digits.
# 5. join() concatenates the pairs from map().
chop($s = <>);
$s = join '', map { sprintf "%02o", index $i, $_ } $s =~ /./g;
# Make new $t.
# 1. map() takes each $_ from 0 to 7.
# 2. $_ x (160 - (() = $s =~ /$_/g)) makes a string where $_ repeats
# 160 times, minus the number of times that $_ appears in $s.
# 3. join() concatentates the strings from map().
$t = join '', map { $_ x (160 - (() = $s =~ /$_/g)) } 0..7;
# Print the new assignments for $s and $t. This is not yet a quine,
# because it does not print the rest of the program.
print "\$s = '$s';\n\$t = '$t';\n";
(() = $s =~ /$_/g))
boş bir değişken listesine atamadır. Bu numarayı PerlMonks'taki bağlam öğreticisinden alıyorum . Liste içeriğini eşleştirme işlecinde zorlar =~
. Skaler bağlamda, maç doğru veya yanlış olur $i++ while ($s =~ /$_/g)
ve maçları saymak gibi bir döngüye ihtiyacım olur . Liste bağlamında, $s =~ /$_/g
eşleşmelerin listesidir. Bu listeyi bir çıkarımın skaler bağlamına koydum, bu yüzden Perl liste öğelerini sayar.
Bir Quine yapmak için, ben şeklinde $_=q{print"\$_=q{$_};eval"};eval
gelen Rosetta Kodu'ndaki Perl quines . Bu, bir atar bir dize q{...}
kadar $_
sonra ve çağrıları eval
bir dizesinde kodumu var ve ayrıca çalıştırmak, böylece. Benim programım son çizgiler benim üçte sarın bir quine olur $_=q{
ve };eval
ve benim son değiştirmek print
için print "\$s = '$s';\n\$t = '$t';\n\$_=q{$_};eval"
.
Son olarak, ilk ödevi $t
bir yoruma çevirerek ve fazladan karakterleri kaldırarak programımı golf oynuyorum.
1522 ASCII karakteri vardır (1280 izin verilen sekizlik basamaklar dahil).
1522-94 = 1428
$s='2341425477515350405332467737535046773450353640504537765455323444366134413247403676345046775136534656553654774255543645377755507736473450353677327754555342474076';#0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222223333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333334444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
$_=q{$i=join'','A'..'Z','a'..'z','0'..'9','. ';print map({substr$i,oct,1}$s=~/../g),"\n";chop($s=<>);$s=join'',map{sprintf"%02o",index$i,$_}$s=~/./g;$t=join'',map{$_ x(160-(()=$s=~/$_/g))}0..7;print"\$s='$s';#$t\n\$_=q{$_};eval"};eval
İkili programa geçiş
Yorumlarda Dennis, 960'a izin verilen ikili basamakların 1280 sekizlik basamaktan daha az olacağını fark etti. Bu nedenle, her bir taban için izin verilen basamak sayısını 2'den 16'ya kadar grafikledim.
Maxima 5.29.1 http://maxima.sourceforge.net
using Lisp ECL 13.5.1
...
(%i36) n : floor(x);
(%o36) floor(x)
...
(%i41) plot2d(n * ceiling(log(64) / log(n)) * 80, [x, 2, 16],
[xlabel, "base"], [ylabel, "number of permuted digits"]);
(%o41)
Taban 8 yerel bir minimum olmasına rağmen, taban 2 ve 3 ve 4 en iyi taban için 960 izin verilen basamakta bağlanır. Kod golf için taban 2 en iyisidir çünkü Perl taban 2 için dönüşümlere sahiptir.
1280 sekizlik basamağın 960 ikili basamakla değiştirilmesi 320 karakterden tasarruf sağlar.
Kodu sekizlikten ikili sayıya geçirmek 8 karakterdir:
- Değişim
oct
için oct'0b'.$_
maliyetlerin 7.
- Değişim
/../g
için /.{6}/g
maliyetlerin 2.
- Değişim
"%02o"
"% 06B" için `0 mal olur.
- Değişim
160
için 480
maliyetlerin 0.
- Kaydetme
0..7
olarak değiştirme 0,1
1.
Bazı Perl golf ipuçlarını öğrendim . 14 karakter kaydederler:
- Değişim
'A'..'Z','a'..'z','0'..'9'
için A..Z,a..z,0..9
, kullanan barewords ve çıplak sayılar, yalnızca 12 karakter kazandırır.
- 2 karakter kaydetmek
"\n"
için değiştirin $/
.
#$t
Yorumu dosyanın sonuna taşıyarak 3 karakter kaydediyorum . Bu, yorumu sonlandıran yeni satırı \n
ve ayraçtaki bir değişmezi kaldırır .
Bu değişiklikler toplam 329 karakter kazandırıyor ve puanımı 1428'den 1099'a düşürüyor.