(A [l (t [e (r) n] e) s) t)) สตริง!


36

Alternestingคือการรับสตริงและซ้อนในวงเล็บ นี่คือวิธีที่คุณสลับสตริง

  • สำหรับสตริงที่มีความยาวNให้ใช้อักขระNกึ่งกลางและล้อมรอบไว้ในวงเล็บ ดังนั้นถ้าสตริงของเราคือHello world!(12 ตัวอักษร) เราจะจบลงด้วย

    (Hello world!)
    
  • จากนั้นนำn-2อักขระกึ่งกลางที่เหลือและล้อมรอบพวกเขาในวงเล็บเหลี่ยม ในกรณีนี้มีอักขระกลาง 10 ตัวello worldดังนั้นการทำซ้ำครั้งถัดไปคือ:

    (H[ello world]!)
    
  • ตราบใดที่มีมากกว่าตัวละครสองตัวที่เหลืออยู่ในช่วงกลางของสตริงทำซ้ำขั้นตอนที่สองที่ผ่านมาสลับกันระหว่างและ() []นี่คือขั้นตอนสุดท้าย:

    (Hello world!)
    (H[ello world]!)
    (H[e(llo worl)d]!)
    (H[e(l[l(o[ w]o)r]l)d]!)
    

    เนื่องจากมีอักขระเพียงสองตัวที่เหลืออยู่ตรงกลางในการทำซ้ำครั้งล่าสุดเราจึงหยุด สตริงสุดท้ายของเราคือ

    (H[e(l[l(o[ w]o)r]l)d]!)
    

    สังเกตว่ามีอักขระสองตัวในวงเล็บตรงกลางได้อย่างไร สิ่งนี้จะเกิดขึ้นเมื่ออินพุตมีความยาวเท่ากัน หากอินพุตเป็นความยาวคี่ (ตัวอย่างเช่นHello, world!เมื่อเพิ่มเครื่องหมายจุลภาค) เราจะมีอักขระเพียงตัวเดียวที่อยู่ตรงกลาง:

    (H[e(l[l(o[,( )w]o)r]l)d]!)
    

สำหรับความท้าทายในวันนี้คุณต้องเขียนโปรแกรมหรือฟังก์ชั่นที่รับสตริงเป็นอินพุตและสลับมันเพื่อแสดงผลสตริงใหม่ คุณสามารถนำเข้าและส่งออกในรูปแบบที่เหมาะสมตามที่คุณต้องการ ข้อมูลที่ป้อนจะมีความยาวอย่างน้อยหนึ่งตัวอักษรและจะมีเฉพาะ ASCII ที่พิมพ์ได้ นอกจากนี้คุณยังสามารถสมมติว่าอินพุตจะไม่มีวงเล็บหรือวงเล็บเหลี่ยม สำหรับภาษาดั้งเดิมสิ่งนี้ไม่ควรมีมากเกินไป แต่มันอาจทำให้ภาษาลึกลับบางอย่างง่ายขึ้น

ตามปกตินี่คือการแข่งขันดังนั้นพยายามทำให้คำตอบที่สั้นที่สุดในภาษาที่คุณเลือก มีความสุข!

ทดสอบ IO

#Input                      #Output

"Alternesting is fun!"  --> (A[l(t[e(r[n(e[s(t[in]g) ]i)s] )f]u)n]!)
"PPCG"                  --> (P[PC]G)
"Code-golf"             --> (C[o(d[e(-)g]o)l]f)
"4 8 15 16 23 42"       --> (4[ (8[ (1[5( [1]6) ]2)3] )4]2)
"a"                     --> (a)
"ab"                    --> (ab)
"abc"                   --> (a[b]c)


เราต้องเริ่มต้นด้วยวงเล็บ ( ()) เสมอหรือเราจะเริ่มด้วยวงเล็บ ( []) ได้ไหม?
มนุษย์โดยรวม

@tallyallyhuman มันควรเริ่มต้นด้วยวงเล็บเสมอ()
DJMcMayhem

testcase ที่เสนอ: HelloWorld.
Erik the Outgolfer

นอกจากนี้ยังอนุญาตให้ใช้ช่องว่างต่อท้ายได้หรือไม่
Erik the Outgolfer

คำตอบ:



9

C, 143 137 135 ไบต์

i,l,k;f(char*s){for(k=i=0,l=strlen(s);*s;printf("%c%c","([])"[i++%2+2*(i>l/2+!k)],*s++))i>l/2-1&&l&1^1&&putchar(*s++,k=++l);puts(")");}

ลองออนไลน์!

คำอธิบาย:

// Function (and variable) declaration.
i,l,k;f(char*s){

// Start the loop and initialize the variables. The loop terminates
// when the NUL-terminator of the string is reached.
for(k=i=0,l=strlen(s);*s;<this part saved for later>)

// Check if we have reached the middle of the string. Because of the
// short-circuiting of the conditions, we don't need to use an 'if'
// statement here; if a condition is false, no further conditions
// are evaluated.
i>l/2-1&&

// Equivalent to '!(l%2)', but one byte shorter. Checks if the length
// of the string is even.
l&1^1

// If we have reached the middle and the length of the string is even, 
// we'll need to skip one bracket, so we'll print the current character
// of the string and increment the pointer. Also we increment 'l' to
// avoid this getting done more than once, and give 'k' a non-zero
// value.
&&putchar(*s++,k=++l);

// The following is inside the 'increment' part of the 'for' loop.
// We print two characters. The first one is a bracket and the second
// one is the current character in the string.
printf("%c%c","([])"[i++%2+2*(i>l/2+!k)],*s++)

// The type of bracket is  chosen depending on the value of 'i'. A 
// character from the string "([])" is selected with the index 'i%2 + 2', 
// if we have reached the  middle of the string, and with index 'i%2', if
// we haven't.

// The exact part where this change happens depends on the parity of 
// the string length, so we use 'k' to signal if the length is even or 
// odd. If the length is odd, 'k==0', so '+!k' is the same as '+1'.  
// Otherwise 'k' is non-zero, so '+!k' is the same as '+0'.

// Output the final ')'.
puts(")");}

ถ้าผมจำได้อย่างถูกต้อง C 0ตัวแปรประกาศทั่วโลกกำลังจะเริ่มต้นใช้งาน k=i=0,ดังนั้นคุณไม่ควรต้อง ฉันอาจจะผิด. ดูคำตอบ SO นี้
Tas

@Tas คุณถูกต้องแน่นอน แต่ฟังก์ชั่นจะต้องนำมาใช้ซ้ำเพื่อให้การส่งที่ถูกต้องดังนั้นตัวแปรจะต้องเริ่มต้นได้ภายในฟังก์ชั่น
Steadybox

7

เรติน่า 52 ไบต์

+`(?<!\()[^()]+(?!\))
($&)
(\(.)\(
$1[
r`\)(.\))
]$1

ลองออนไลน์! ขั้นตอนแรกจะแทรกคู่ของวงเล็บระหว่างอักขระอินพุตแต่ละคู่ในขณะที่ขั้นตอนที่สองและสามแก้ไขวงเล็บสำรองให้กับวงเล็บ



6

JavaScript (ES6), 69 68 ไบต์

f=([c,...s],i,l=s.pop())=>'[('[i^=1]+c+(s[0]?f(s,i)+l:l||'')+'])'[i]

กรณีทดสอบ


5

V , 25 26 25 ไบต์

1 2 ไบต์ปิดขอบคุณ @DJMcMayhem

òC()Pé
%llòÍî
òF)%r[r];

ลองออนไลน์!

ยืมความคิด บางส่วนของ@ udioca ในที่สุดก็ใช้ปลั๊กอินเซอร์ราวด์ที่รวมอยู่ใน V เพื่อหาคำตอบแม้ว่ามันอาจจะไม่ใช่วิธีที่ดีที่สุดใครจะรู้ ไม่ต้องการใช้ปลั๊กอิน

hexdump:

00000000: e3e1 0a6b f2e9 286c 6ce9 5b6c 6cf2 6af2  ...k..(ll.[ll.j.
00000010: e129 6868 e15d 6868 f2cd ce              .)hh.]hh...

คำอธิบาย:

-> |abcdefg      (the input, where | is the cursor)
ò              ' recursively
 C()           ' (C)hange from the cursor to the end of the line to '()'
-> (|)    (where | is the cursor)
     P         ' (P)aste the changed bit (what was there) left of the cursor
-> (abcdef|g)
      é        ' nsert a newline
-> (abcdef
   |g)
%              ' Goto the previous matching parenthese
-> |(abcdef
   g)
 ll            ' Move two characters right
-> (a|bcdef
   g)
   ò           ' End recursive loop (it will break on ll when there are no characters left
-> (a(b(c
   d)
   e)
   f)
    Íî         ' Remove all newlines
-> (a(b(cd)e)f|)
ò              ' Recursively
 F)            ' Go backwards to the next )
-> (a(b(cd)e|)f)
   %r[         ' Go to the matching paren and (r)eplace it with [
-> (a|[b(cd)e)f)
               ' Go back to the previous cursor location
-> (a[b(cd)e|)f)
       r]      ' (r)eplace this paren with ]
-> (a[b(cd)e|]f)
         ;     ' repeat F)
-> (a[b(cd|)e]f)
               ' implicitly end recursion

ว้าวเยี่ยมมาก! ฉันติดอยู่ที่ 29 ไบต์ แต่ไม่มีกรณีขอบจำนวนมาก นี่เป็นคำตอบที่น่ารัก คุณสามารถบันทึกหนึ่งไบต์โดยใช้;แทนf) ลอง
DJMcMayhem

ตอนนี้มันเสียจริงเพราะช่องว่างฉันจะลบและแก้ไข
nmjcman101

@DJMcMayhem ฉันเห็น 29 ไบต์ของคุณได้ไหม? นอกเสียจากคุณวางแผนที่จะเล่นกอล์ฟภายใต้ฉันและแข่งขันซึ่งฉันจะไม่ประหลาดใจเกี่ยวกับ :)
nmjcman101

มันใช้งานไม่ได้ดังนั้นฉันไม่รังเกียจที่จะแสดงให้คุณเห็น: tio.run/##K/v/// ......โอ้และ BTW: chat.stackexchange.com/transcript/message/38434285#38434285 :)
DJMcMayhem

:( ทำการสลับ()และ[]เป็น byte ที่สั้นลง แต่ก็ดูเท่น้อยกว่า
nmjcman101

5

Haskell , 96 91 81 79 77 ไบต์

(cycle"()[]"!)
(l:r:a)!k|[x]<-k=[l,x,r]|x:y<-k=l:x:a!init y++[last y,r]|2>1=k

ลองออนไลน์!


1
คุณสามารถปล่อยพ่อแม่ที่อยู่รอบ ๆและ(x:y) สั้นเป็น (init y)k==""=""k==""=k
Laikoni

1
บันทึกไบต์เพิ่มเติมโดยเปลี่ยนcycle["()","[]"]เป็น"()[]": ลองออนไลน์!
Laikoni

@Laikoni คำแนะนำที่ดีขอบคุณ
bartavelle

1
การจับที่ดีนั้นทำให้cycleสั้นลงได้ คุณยังสามารถลบวงเล็บ(init y)ได้
Laikoni

1
คุณสามารถย้ายกรณีที่สิ้นสุดและเปลี่ยนไปk==""=k 0<1=k
Zgarb


2

Javascript (ES6) 110 105 ไบต์

ขอขอบคุณที่ @powelles x%y<1สำหรับการเตือนฉันเกี่ยวกับ

ขอบคุณ @Luke สำหรับ a-b?y:x

i=>'('+[...i].map((a,b,c,d=i.length/2-1,e=b%2<1)=>a+(d>b?e?'[':'(':d-b?(d%1==0?!e:e)?')':']'):'').join``


สิ่งแรกในการทำความเข้าใจกับสัตว์ร้ายตัวนี้ก็คือมันไม่อวดดี

function alternest(input) { //input is i in the original
  let inputArray = Array.from(input); //the [...i] section
  let result = inputArray.map((item, index, baseArray) => { //result is an added helper variable
    let middle = input.length / 2 - 1, //the middle of the string
        alternate = index % 2 == 0; //should you alternate from '(' and '[' or ')' and ']'

    let symbol; //the alternating symbol

    if(middle > index) { //if its opening braces
      symbol = alternate ? '[' : '(';
    } else if(middle < index) {
      if(middle % 1 === 0) //if middle is a whole number
        alternate = !alternate; //reverse alternate
      symbol = alternate ? ')' : ']';
    } else { //if middle === index
      symbol = ''; //there's no symbol in the center for even alternests
    }
    return item + symbol; //convert the array item into the item and symbol
  }).join('');

  return '(' + result; //add the first symbol.
}

เกือบทุกบรรทัดเป็นส่วนหนึ่งของเวอร์ชัน golfed ดังนั้นก้าวผ่าน:

บรรทัดที่ 1:คำสั่งฟังก์ชั่นจะกลายเป็นฟังก์ชั่นลูกศรเปลี่ยนชื่อไปinput จะกลายเป็นii=>

บรรทัดที่ 2: Array.fromเป็นวิธีใหม่ที่เหมาะสมในการแปลงสตริงให้เป็นอาร์เรย์และสิ่งที่เราใช้ในบรรทัดนี้ อย่างไรก็ตามพร้อมกับมันผู้ประกอบการแพร่กระจายเป็นวิธีที่ถูกกว่าเดิม.split('')ที่จะทำซึ่งเป็นสิ่งที่ใช้ในรุ่น golfed [...i]ปลายขึ้นเป็น

บรรทัดที่ 3: .mapลูปผ่านอาร์เรย์ให้คุณสามข้อโต้แย้ง: item( aในแข็งแรงเล่นกอล์ฟ), การindex; แข็งแรงเล่นกอล์ฟเป็นbและหรือbaseArray cในขณะที่เราสนใจitemและindexเราเก็บไว้baseArray(ดูบรรทัดที่ 4 สำหรับสาเหตุ) .map((a,b,c,...)=>...โรงแรมพร้อมสนามกอล์ฟไป

บรรทัดที่ 4:ตัวแปรmiddleหรืออาร์กิวเมนต์dในเวอร์ชัน golfed ถูกสร้างขึ้นเพื่อบันทึกสองสามไบต์เมื่อมีการทำซ้ำ อาร์กิวเมนต์cจะต้องถูกเก็บไว้dเพื่อสร้างอาร์กิวเมนต์ (...,d=i.length/2-1,...)จะถูกแปลงเป็น

บรรทัดที่ 5 : ตัวแปรalternateหรืออาร์กิวเมนต์ที่eใช้ในการตรวจสอบอักขระที่อยู่บน "(" หรือ "[" หรือถ้าผ่านเครื่องหมายตรงกลาง ")" และ "]" b%2<1เท่ากับb%2==0เพราะมันไม่สามารถเป็นอะไรที่น้อยกว่า 1 แต่เป็น 0 ในกรณีนี้ (...,e=b%2<1)เท่ากับ

บรรทัดที่ 6:ตัวแปรผู้ช่วยเพื่อให้ฉันไปแปลงternary operatorsเพื่อifงบ ไม่มีอะไรใน codegolf ที่แท้จริง

สาย 7-8 : หากดัชนีมีค่าน้อยกว่าตรงกลางของสตริงที่กำหนดสัญลักษณ์ที่จะสลับกันของ "[" และ "(" d>b?e?'[':'(':...เท่ากับ.

บรรทัดที่ 9-12 : อื่น ๆ (ถ้าดัชนีมากกว่ากลาง) ให้ตรวจสอบว่าตรงกลางเป็นจำนวนเต็มหรือไม่ถ้าเป็นเช่นนั้นให้สลับการสลับ จากนั้นตั้งค่าสัญลักษณ์เป็นทางเลือกของ ')' และ ']' (d%1==0?!e:e)?')':']'ยุ่งเหยิงไป

บรรทัดที่ 13-15 : หากเครื่องหมายตรงกลางตั้งสัญลักษณ์เป็นสตริงว่าง สิ่งนี้ใช้ไม่ได้กับตัวเลือกที่แปลกเนื่องจากตรงกลางมีทศนิยม กลายเป็น: d==b?'':....

บรรทัดที่ 16 : รวมอาร์เรย์อักขระกลับเข้าไปในสตริง .join``เท่ากับ

สาย 17 : คืนสัญลักษณ์เริ่มต้น "(" '('+...และผลที่สัมพันธ์กับ.


ชนะง่าย ๆ บางอย่างที่คุณอาจจะเปลี่ยน%2==0ไป%2<1และใช้[...i]แทนi.split
powelles

1
ขอบคุณ @powelles ฉันได้พยายามอธิบายมากกว่าคำตอบที่ตีกอล์ฟแล้วดังนั้นมันยังไม่ได้ทำการแก้ไข ฉันมีแล้ว[..i] ideaแต่ฉันลืมเกี่ยวกับ%2<1ขอบคุณ
David Archibald

b%2<1สามารถถูกแทนที่โดย!b%2
ลุค

นอกจากนี้d==b?x:yอาจจะกลายเป็นd-b?y:xและอาจจะกลายเป็นd%1==0 !d%1
ลุค

น่าเสียดายเนื่องจากคำสั่งของการดำเนินการใช้งานได้!d%1เฉพาะกับวงเล็บ: !(d%1)และมันไม่ได้กำจัดไบต์ใด ๆ ฉันลืมว่า 0 เป็นเลขที่มีความเท็จเท่านั้นด้วยเหตุผลบางอย่างที่ฉันคิดว่า -1 เป็นตัวเลขที่ผิดพลาด แก้ไขให้ถูกต้องหากฉันทำอะไรผิดเกี่ยวกับอันที่สอง
David Archibald

2

เยลลี่ , 23 21 ไบต์

LHĊRị
ç⁾)]żUFUż@ç⁾([$

ลองออนไลน์!

LHĊRị           - helper function. Takes inputs of the input string and list of brace types
L                 - length of the input string
 HĊ               - number of parenthesis/brackets facing a single direction
   R              - range
    ị             - indexed into right argument: list of brace types ')]' or '(['

ç⁾)]żUFUż@ç⁾([$ - main function 
ç⁾)]              - get list of left-facing parentheses/brackets
    żU            - zip to the end (U) of the input string
      FU          - move the beginning of the string back to the beginning
        ż@        - zip with (to the start of the string):
          ç⁾([$   -the list of right-facing parentheses/brackets to the beginning

-2 ไบต์ขอบคุณ @EricTheOutgolfer


คุณสามารถลบบรรทัดและย้ายไปที่ลิงก์ตัวช่วยสำหรับ -2 เช่นนี้:LHĊRị¶ç⁾)]żUFUż@ç⁾([$
Erik the Outgolfer

1

SCALA, 140 138 ตัวอักษร, 140 138 ไบต์

ฉันขอโทษฉันไม่สามารถทำได้ดีกว่า ... ฉันแน่ใจว่ามีหลายวิธีในการปรับปรุง ยังคง:

val n=s.length-1
var l=""
var r=""
for(i<-0 to n/2){l+=(if(i%2<1)"("else"[")
if(i!=n-i)l+=""+s(i)
r=""+s(n-i)+(if(i%2<1)")"else"]")+r}
l+r

ลองออนไลน์!

ขอบคุณสำหรับความท้าทายนี้มันค่อนข้างยากสำหรับฉัน

แก้ไข: -2 ไบต์ขอบคุณ Mar Dev

PS: ฉันจะถามอะไรบางอย่าง ฉันเข้าใจว่าเหตุใดรหัสนี้จึงซ้ำซ้อนอักขระกลางของสตริงของฉันถ้าฉันมีความยาวคี่ (ฉันแค่ไม่ตรวจสอบและเพิ่มสองครั้งทั้งในlและrสตริง) แต่ทำไมฉันจะได้รับคู่ของวงเล็บเมื่อฉันพยายามแก้ไขมันเหมือนว่า ? ฉันไม่เข้าใจเลย


1
คุณสามารถเปลี่ยนi%2==0ไปi%2<1เพื่อประหยัดไบต์ที่สอง
Mario Ishac

1

Perl, 77 74 (73 + 1) ไบต์

การแสดงออกปกติเป็นสิ่งที่น่ายินดี รันด้วย-pแฟล็กบรรทัดคำสั่ง

$x=qr/[^]()[]/;$z=qr/(^|$x)\K($x+)($|$x)/;s/$z/[$2]$3/ while s/$z/($2)$3/

1

05AB1E , 31 ไบต์

2ä`Rð«„)]Ig©×øRJ®Èƒ¦}s„([®×søJì

ลองออนไลน์!

คำอธิบาย

ด้วยตัวอย่างสำหรับการป้อนข้อมูล: abcd/abcde

2ä`                              # split input to 2 separate parts on stack
                                 # RESULT: 'ab','cd' / 'abc', 'de'
   R                             # reverse the second part
    ð«                           # append a space
      „)]                        # push the string ")]"
         Ig©×                    # repeat it len(input) times
             ø                   # zip with the second part of the input string
              RJ                 # reverse and join to string
                                 # RESULT:  ' )c]d)' /  ' )d]e)'
                ®Èƒ¦}            # remove the first (1,2) chars for (odd,even) length input
                                 # RESULT: 'c]d)' / ')d]e)'
                     s           # swap the first part of the input string to top of stack
                      „([®×      # repeat the string "([" len(input) times
                           sø    # zip with first part of input string
                                 # RESULT: ['(a', '[b'] / ['(a', '[b', '(c']
                             Jì  # join to string and prepend to the second part

1

C ++ 14, 154 145 ไบต์

[ซ้ำ]

auto L(string i,bool b=1){int l=i.length();string o=b?"(":"[";auto c=b?")":"]";if(l<3)return o+i+c;return o+i[0]+L(i.substr(1,l-2),!b)+i[l-1]+c;}

C ++ 14, 177 ไบต์

[ซ้ำ]

auto l(string s){int z=s.length();string r(z*2+z%2,'-');int i=0;for(;i<z;i+=2)r[i]=i/2%2?'[':'(',r[i+1]=s[i/2];for(i=z;i<2*z;i+=2)r[i]=s[i/2],r[i+1]=(i+1)/2%2?')':']';return r;}

0

Pyth , 42 (!) ไบต์

M?!lHH+@,\[\(G++hHg!GPtH+?qlH1keH@,\]\)Gg1

ทดสอบออนไลน์! การป้อนข้อมูลจะต้องยกมา

คำอธิบาย

M                                             # Define a function g with arguments G and H
 ?!lHH                                        # If len(H) == 0, return H. Otherwise...
      +@,\[\(G                                # Concatenate [ or ( to...
               +hHg!GPtH                      # ...to H[0] concatenated to g(not(G), H[1:-1]), itself concatenated...
              +          ?qlH1keH             # ...to H[-1] if len(H) != 1, otherwise to "" (that's for odd length input strings)...
                        +        @,\]\)G      # ...and to that concatenate ] or ).
                                        g1    # Call g(True, Q). Q is implicit input

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



0

PowerShell, 125 119 111 ไบต์

{param($s)for($p='()[]';($f,$s,$g=$s-split'(?<=.)(.+)(?=.)')[0]){$l+=$p[$i++]+$f;$r=$g+$p[$i++]+$r;$i%=4}$l+$r}

ลองออนไลน์!

รุ่นก่อนหน้า *

{for($s="($args)";$s-ne($t=$s-replace'(\(.)([^][]+)(.\))','$1[$2]$3'-replace'(\[.)([^)(]+)(.\])','$1($2)$3')){$s=$t}$s}

* ขอบคุณ @Digital Trauma



0

AWK, 118 ไบต์

{b=")";for(j=l=length(c=$0);j>0;){x=substr(c,j--,1);b=(j>l/2?(((d=!d)?"]":")")x):j==l/2?x:((d=!d)?"(":"[")x)b}print b}

ทดสอบด้วย gawk แต่ควรทำงานกับล่าม awk ที่เข้ากันได้

$ awk -f alternesting.awk <<< 'abc'
(a[b]c)

0

JavaScript, 101 ไบต์

ไม่ใช่ผู้ชนะ แต่มันก็น่าสนใจที่จะลองreplaceวิธีนี้ สิ่งนี้อาจได้รับการปรับปรุงให้ดีขึ้น แต่มันก็อยู่ห่างจากมือเร็ว ...

s=>"("+s.replace(/./g,(a,b)=>a+(l%2|b*2+2!=l?")][("[3*(c=l>(b+=l%2-1)*2+2)+(b-c*l)%2]:""),l=s.length)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.