โปรแกรมที่อนุญาตให้ตัวเองเข้ารหัสสตริง (ตัวแปรย่อย)


16

เขียนโปรแกรมที่พิมพ์บรรทัด 80 ตัวอักษรต่อไปนี้:

โปรแกรมนี้จาก codegolf.stackexchange.com อนุญาตให้ตัวเองเข้ารหัสสตริง

จากนั้นยอมรับอินพุตหนึ่งบรรทัดจากนั้นพิมพ์ซอร์สโค้ดโดยมีจุดโค้ดที่อาจเรียงลำดับใหม่ (ไม่มีการเพิ่มและไม่มีการลบ) เมื่อรันโค้ดนั้นจะต้องเกิดขึ้นเช่นเดียวกันยกเว้นบรรทัดที่พิมพ์ออกมาจะเป็นบรรทัดอินพุตล่าสุด

Regex สไตล์ Perl ^[A-Za-z0-9. ]{80}$จะจับคู่กับอินพุตทุกบรรทัด คุณไม่สามารถตั้งสมมติฐานเพิ่มเติมได้

คะแนนการส่งของเป็นจำนวนของจุดรหัสในรหัสที่มาของมันน้อย 94 ต่ำกว่าดีกว่า

รหัสจะต้องไม่ทำอะไรที่ไม่สามารถยอมรับได้ในควินิน ( เช่นการอ่านไฟล์) โดยเฉพาะอย่างยิ่งการส่งใด ๆ ที่มีคะแนนติดลบจะต้องโกงอย่างใดอย่างหนึ่งเป็น 93 น้อยกว่า 64 80

เพิ่ม 2014-04-21:ซอร์สโค้ดทั้งหมดของโปรแกรมของคุณจะต้องมีรูปแบบที่ดีในการเข้ารหัสตัวอักษรที่คุณนับคะแนนรหัส ตัวอย่างเช่นคุณไม่สามารถใช้ 80 ไบต์ต่อเนื่องกันในช่วงไบต์ต่อท้าย UTF-8 (80..BF) และนับแต่ละรายการเป็นอักขระเปลี่ยน U + FFFD เดียว (หรือแย่กว่าไม่ใช่จุดรหัสเลย)

นอกจากนี้หากการเข้ารหัสอนุญาตให้มีหลายวิธีในการเข้ารหัสจุดโค้ด ( เช่น SCSU ) โปรแกรมของคุณรวมถึงโปรแกรมทั้งหมดที่สร้างขึ้นโดยตรงหรือโดยอ้อมต้องใช้หนึ่งในนั้นเท่านั้น (หรืออย่างน้อยที่สุดจะต้องได้รับการปฏิบัติอย่างเท่าเทียมกันตลอดทั้งรหัส )


หลังจากอ่านคำถามของคุณอีกครั้งฉันไม่แน่ใจว่าคำตอบของฉันทำในสิ่งที่คุณมีในใจหรือไม่ การไพพ์สตริงใหม่ลงในโปรแกรมตกลงหรือไม่หรือต้องเปิดใช้พรอมต์แบบโต้ตอบหรือไม่?
Dennis

@Dennis: นั่นไม่ใช่เหตุผลที่คำตอบของคุณไม่เป็นที่ยอมรับ แต่จะอ่านอินพุตก่อนพิมพ์ "โปรแกรมนี้จาก [... ]"
PleaseStand

นั่นคือสิ่งที่ฉันหมายถึงฉันแค่ไม่ได้แสดงออกมาอย่างดี ล่าม GolfScript อ่านทุกอย่างที่ถูกไพพ์ไปก่อนเริ่มดำเนินการสคริปต์ วิธีเดียวที่จะหลีกเลี่ยงปัญหานี้คือการเปิดใช้งานพรอมต์ซึ่งทำให้การวางท่อเป็นไปไม่ได้
เดนนิส

สวัสดีฉันลองใช้ JavaScript แล้ว ดูเหมือนจะเป็นไปไม่ได้ที่จะสร้าง quine โดยไม่อ่านข้อความระหว่างแท็ก <script>? จุดประสงค์ของการอนุญาตซอร์สโค้ดคืออะไร? คุณพูดว่า 'อาจจัดลำดับใหม่'; หมายความว่าเปลี่ยนแปลงหากจำเป็นเท่านั้น?
bacchusbeale

คำตอบ:


5

GolfScript, 231 162 131

'1àâ4ÿaVo5GùpZBtiXOürsóNîMmWåKHc09JdñúêyzíECäYïhDU ãáIFõ6é8òRìjTv23ønuðLwxfSkôbëAelqý.çèPQ
öûg7'{0@.$[{}/]:&\{@2$,*2$2$?+@@^}/{;65base}:b~{&=}%''+puts'"#{`head -1`}"'~{&?}%)b[94,{)1$1$%@@/}/;]-1%&\[{1$=.@^}/]"'".@+\+\'.~'}.~

มันทำงานอย่างไร

เราเริ่มต้นด้วยการเลือก 94 ตัวอักษรที่แตกต่างกันซึ่งจะได้รับอนุญาตให้เข้ารหัสสตริง อักขระ 94 ตัวใดก็ได้ที่จะใช้งานได้ แต่เราเลือกตัวเลือกต่อไปนี้เพื่อการเล่นกอล์ฟ:

\n .0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
àáâãäåçèéêëìíîïðñòóôõöøùúûüýÿ

ลองเรียกอาเรย์ของตัวละครเหล่านี้ว่า“ &”

บรรทัดของอินพุตจะมี 81 ตัวอักษรเสมอ (รวมถึง LF) อักขระทั้งหมดเหล่านี้มีอยู่ใน 65 อักขระแรกของ“ &” นี่คือเหตุผลเดียวในการเลือกอักขระใน 128 ไบต์ด้านบน

เราแทนที่อักขระแต่ละตัวของสตริงด้วยดัชนีใน“ &” ดังนั้น LF จะกลายเป็น 0 ช่องว่างกลายเป็น 1 เป็นต้น

เราพิจารณา 81 ตัวเลขที่ได้รับตัวเลขของฐาน 65 หมายเลขเดียว ลองเรียกหมายเลขนี้ว่า“ N”

ตอนนี้เราแจกแจงการเรียงสับเปลี่ยนที่เป็นไปได้ทั้งหมดของ "&" และดึงการเปลี่ยนแปลงที่สอดคล้องกับหมายเลขจากด้านบน นี่คือความสำเร็จในลักษณะดังต่อไปนี้:

  1. ชุดและc = 1A = []
  2. ย่อหน้าที่จะN % cA
  3. ชุดและN = N / cc = c + 1
  4. ถ้าc < 95กลับไปที่ 2
  5. ชุดและi = 0s = ""
  6. ดึงตัวอักษรออก&[A[i]]มาผนวกกับ“ s” แล้วลบออกจาก“ &”
  7. i = i + 1ชุด
  8. ถ้าi < 94ย้อนกลับไปที่ 6

สมมติว่าเรามีบล็อคโค้ด“ E” และ“ D” ที่เข้ารหัสและถอดรหัสสตริงตามที่อธิบายไว้ข้างต้น

ตอนนี้เราต้องการ wrapper สำหรับบล็อคโค้ดที่สอดคล้องกับข้อกำหนดของคำถาม:

'encoded string'{\.$[{}/]:&; D puts '"#{`head -1`}"'~ E "'".@+\+\'.~'}.~

นี่ทำสิ่งต่อไปนี้:

  • {…}.~กำหนดบล็อกทำซ้ำและดำเนินการสำเนาที่สอง สำเนาแรกจะยังคงอยู่ในสแต็ก

  • \.$ สลับสตริงที่เข้ารหัสด้วยบล็อกและสร้างสำเนาของสตริงที่เข้ารหัสด้วยอักขระที่เรียงลำดับ

  • [{}/]:&; แปลงสตริงจากด้านบนเป็นอาร์เรย์แล้วบันทึกลงใน“ &” และละทิ้งมัน

  • D puts ถอดรหัสสตริงที่เข้ารหัสและพิมพ์ผลลัพธ์

  • '"#{`head -1`}"'~อ่านอินพุตหนึ่งบรรทัดโดยเรียกใช้งานhead -1ในเชลล์

  • E "'".@+\+ เข้ารหัสสตริงและผนวกและผนวกคำพูดเดียว

  • \'.~''.~'แลกเปลี่ยนสตริงเข้ารหัสและการป้องกันและผนวกสตริง

  • หลังจากบล็อกถูกดำเนินการแล้ว GolfScript จะพิมพ์เนื้อหาของสแต็ก (สตริงเข้ารหัส, บล็อก, '.~') และออก

“ E” สามารถกำหนดได้ดังนี้

{&?}%        # Replace each character by its index in “&”.
);           # Remove the last integer from the array, since it corresponds to the LF.
65base       # Convert the array to an integer “N” by considering it a base 65 number.
[            #
  94,        # For each integer “c” in 0 … 93:
  {          #
    )        # Increment “c”.
    1$1$%    # Push “N % c”.
    @@/      # Rotate “N % c” below “N” and “c” and divide the first by the latter.
  }/;        # Discard “N”.
]            # Collect the results of “N % c” in an array “A”.
-1%          # Reverse “A”.
&\           # Push “&” and swap it with “A”.
[            #
  {          # For each “j” in “A”:
    1$=.[]+  # Push “&[j] [&[j]]”.
    @^       # Rotate “&” on top of “[&[j]]” and take their symmetric difference.
  }/         #
]            # Collect the charcters into an array.

“ D” สามารถกำหนดได้ดังต่อไปนี้:

0&           # Push 0 (initial value of the accumulator “A”) and “&”.
@            # Rotate the encoded string on top of “&”.
{            # For each character “c” of the encoded string:
    @2$,*    # Rotate “A” on top of the stack and multiply it by the length of “&”.
    2$2$?+   # Get the index of “c” in “&” and add it to “A”.
    @@^      # Rotate “A” below “&” and “c” and take their symmetric difference.
}/;          # Discard “&”.
65base       # Convert “A” into the array of its digits in base 65.
{&=}%        # Replace each digit by the corresponding character in “&”.
''+          # Convert the resulting array into a string.

การเล่นกอล์ฟรอบชิงชนะเลิศ:

  • แทนที่\.$[{}/]:&;0&@ด้วย0@.$[{}/]:&\เพื่อบันทึกอักขระสองตัว

  • กำหนดฟังก์ชั่น{;65base}:bเพื่อบันทึกหนึ่งตัวอักษร

  • ลบช่องว่างทั้งหมดยกเว้น LF ต่อท้ายและ LF ในสตริง

ตัวอย่าง

$ # Create GolfScript file using base64 to avoid encoding issues.
$ base64 > permute.gs -d <<< JzHg4jT/YVZvNUf5cFpCdGlYT/xyc/NO7k1tV+VLSGMwOUpk8frqeXrtRUPkWe9oRFUg4+FJRvU26TjyUuxqVHYyM/hudfBMd3hmU2v0YutBZWxx/S7n6FBRCvb7ZzcnezBALiRbe30vXTomXHtAMiQsKjIkMiQ/K0BAXn0vezs2NWJhc2V9OmJ+eyY9fSUnJytwdXRzJyIje2BoZWFkIC0xYH0iJ357Jj99JSliWzk0LHspMSQxJCVAQC99LztdLTElJlxbezEkPS5AXn0vXSInIi5AK1wrXCcufid9Ln4K
$
$ # Set locale to en_US (or any other where one character is one byte).
$ LANG=en_US
$
$ # Go back and forth between two different strings.
$ # Second and sixth line are user input, not output from the script.
$
$ golfscript permute.gs | tee >(tail -n+2 > tmp.gs) && golfscript tmp.gs && rm tmp.gs
This program from codegolf.stackexchange.com permutes itself to encode a string.
Permuting source code code points to encode a string is a certain quine variant.
'18äJoS3sgV9qdçëxm0ÿKMNe5íPî.Htn2ciâIuøbRZéð4AwB7áìUüöôWõèûfñåLàóDrhQlO6
pTaýzòkùYCyFêïãG júEvX'{0@.$[{}/]:&\{@2$,*2$2$?+@@^}/{;65base}:b~{&=}%''+puts'"#{`head -1`}"'~{&?}%)b[94,{)1$1$%@@/}/;]-1%&\[{1$=.@^}/]"'".@+\+\'.~'}.~
Permuting source code code points to encode a string is a certain quine variant.
This program from codegolf.stackexchange.com permutes itself to encode a string.
'1àâ4ÿaVo5GùpZBtiXOürsóNîMmWåKHc09JdñúêyzíECäYïhDU ãáIFõ6é8òRìjTv23ønuðLwxfSkôbëAelqý.çèPQ
öûg7'{0@.$[{}/]:&\{@2$,*2$2$?+@@^}/{;65base}:b~{&=}%''+puts'"#{`head -1`}"'~{&?}%)b[94,{)1$1$%@@/}/;]-1%&\[{1$=.@^}/]"'".@+\+\'.~'}.~
$
$ # Sort all characters from the original source code and hash them.
$ fold -1 permute.gs | sort | md5sum
b5d978c81df5354fcda8662cf89a9784  -
$
$ # Sort all characters from the second output (modified source code) and hash them.
$ golfscript permute.gs | tail -n+2 | fold -1 | sort | md5sum
Permuting source code code points to encode a string is a certain quine variant.
b5d978c81df5354fcda8662cf89a9784  -
$
$ # The hashes match, so the characters of the modified source code are a permutation
$ # of the character of the original one.

224 ลบ 94 คือ 130
mbomb007

คุณสามารถทำอย่างละเอียด?
Dennis

1

Perl, 1428 1,099

มีอักขระ 1193 ASCII (รวมถึงเลขฐานสองที่อนุญาต 960) 1193 - 94 = 1,099

$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

การออกแบบครั้งแรกของฉัน

ก่อนที่ฉันจะรับคำแนะนำจากเดนนิสเพื่อเปลี่ยนเป็นไบนารี่โปรแกรมของฉันใช้เลขฐานแปด

การออกแบบครั้งแรกของฉันเข้ารหัสสตริงแต่ละตัวในรูปแบบเลขฐานแปด 160 หลักโดยมี 2 หลักต่อตัวอักษร การเข้ารหัสนี้มี 100 8 = 64 ตัวอักษรที่แตกต่างกัน ระบบฐานแปดมี 8 หลักที่แตกต่างกัน โปรแกรมจะต้องมี 160 สำเนาของแต่ละหลักดังนั้นจึงอนุญาต 8 × 160 = 1280 หลัก

ฉันเก็บ 160 ตัวเลขใน$sและอื่น ๆ 1,120 $tตัวเลขใน ฉันเริ่มต้นด้วยโปรแกรมที่ไม่ใช่ quine แต่พิมพ์เฉพาะการมอบหมายไปยัง$sและ$tสำหรับการทำงานครั้งต่อไป นี่ไง:

$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))เป็นการกำหนดรายการตัวแปรที่ว่างเปล่า ฉันจะเอาเคล็ดลับนี้จากบริบทกวดวิชาที่ PerlMonks =~มันบังคับให้บริบทรายการกับผู้ประกอบการแข่งขัน ในบริบทสเกลาร์การแข่งขันจะเป็นจริงหรือเท็จและฉันต้องการวงวน$i++ while ($s =~ /$_/g)เพื่อนับการแข่งขัน ในบริบทรายการ$s =~ /$_/gคือรายการที่ตรงกัน ฉันใส่รายการนี้ในบริบทสเกลาร์ของการลบดังนั้น Perl นับองค์ประกอบของรายการ

ที่จะทำให้ควินผมใช้แบบฟอร์ม$_=q{print"\$_=q{$_};eval"};evalจากquines Perl ที่ Rosetta รหัส อันนี้กำหนดสตริงq{...}ให้$_แล้วโทรevalดังนั้นฉันสามารถมีรหัสของฉันในสตริงและเรียกใช้ โปรแกรมของฉันจะกลายเป็นควินเมื่อฉันห่อที่สามของฉันกับเส้นสุดท้ายใน$_=q{และ};evalและการเปลี่ยนแปลงล่าสุดของฉันไปprintprint "\$s = '$s';\n\$t = '$t';\n\$_=q{$_};eval"

ในที่สุดฉันเล่นกอล์ฟโปรแกรมของฉันโดยเปลี่ยนการมอบหมายแรก$tเป็นความคิดเห็นและโดยการลบอักขระพิเศษ

มีอักขระ ASCII 1522 ตัว (รวมทั้งตัวเลขฐานแปด 1280 หลักที่อนุญาต)
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

สลับเป็นไบนารี

ในความคิดเห็นเดนนิสสังเกตุว่าตัวเลขเลขฐานสองที่เปลี่ยนแปลง 960 ตำแหน่งจะน้อยกว่า 1,280 หลัก ดังนั้นฉันจึงกราฟจำนวนหลักที่อนุญาตสำหรับแต่ละฐานจาก 2 ถึง 16

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) 

กราฟที่มีฐานอยู่บนแกน x จำนวนหลักที่อนุญาตบนแกน y

แม้ว่า base 8 เป็นค่าต่ำสุดในท้องถิ่น แต่เบส 2 และ 3 และ 4 จะเป็นฐานที่ดีที่สุดที่ 960 หลักที่มีการเปลี่ยนแปลง สำหรับ code golf ฐาน 2 นั้นดีที่สุดเพราะ Perl มีการแปลงสำหรับ base 2

แทนที่ 1280 แปดหลักด้วย 960 หลักเลขบันทึก 320 ตัว

การสลับรหัสจากค่าฐานแปดไปเป็นไบนารี 8 ตัวอักษร:

  • เปลี่ยนoctเป็นoct'0b'.$_ค่าใช้จ่าย 7
  • เปลี่ยน/../gเป็น/.{6}/gค่าใช้จ่าย 2
  • เปลี่ยน"%02o"เป็น "% 06b" `ต้นทุน 0
  • เปลี่ยน160เป็น480ค่าใช้จ่าย 0
  • เปลี่ยน0..7เป็น0,1บันทึก 1

ฉันเรียนรู้เคล็ดลับกอล์ฟเพิร์ล พวกเขาบันทึก 14 ตัวอักษร:

  • เปลี่ยน'A'..'Z','a'..'z','0'..'9'เป็นA..Z,a..z,0..9ใช้ barewords และตัวเลขเปลือยบันทึก 12 ตัว
  • เปลี่ยน"\n"เป็น$/บันทึก 2 ตัวอักษร

ฉันบันทึกตัวละคร 3 ตัวโดยการย้าย#$tความคิดเห็นไปที่ท้ายไฟล์ สิ่งนี้จะลบบรรทัดใหม่ที่สิ้นสุดความคิดเห็นและตัวอักษร\nในควิน

การเปลี่ยนแปลงเหล่านี้บันทึกทั้งหมด 329 ตัวอักษรและลดคะแนนของฉันจาก 1428 เป็น 1,099


1
การใช้เลขฐานสองแทนเลขฐานแปดต้องใช้อักขระที่อนุญาตได้เพียง 960 ตัว
เดนนิส

@Dennis ขอขอบคุณสำหรับเคล็ดลับ! ฉันเปลี่ยนเป็นไบนารี (บันทึก 312 ตัวอักษร) ขณะอยู่ที่นี่ฉันเล่นกอล์ฟอีก 17 ตัว
kernigh
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.