เครื่องมือจับคู่สตริง FizzBuzz-ish


25

พูดว่าคุณมีสตริงเช่นนี้:

abaabbbbbaabba

นับจำนวนครั้งที่อักขระที่ระบุปรากฏในสายป้อน แต่ถ้าตัวอักษรที่ปรากฏขึ้นเพียงครั้งเดียวในแถว ตัวอย่างเช่นถ้าตัวอักษรเป็นa,

abaabbbbbaabba
^ x      x   ^

ผลรวมจะเท่ากับ 2 ( aaจะไม่นับเพราะaจะปรากฏสองครั้งติดต่อกัน)

สิ่งนี้เกี่ยวข้องกับ FizzBuzz อย่างไร

หากอักขระปรากฏขึ้น 3 ครั้งหรือหลายครั้งในแถวหรือ 5 (หรือหลายครั้ง) ในแถวตัวนับจะลดลงแทน ถ้ามันเป็นผลคูณของทั้ง 3 และ 5 ครั้งตัวนับจะยังคงเพิ่มขึ้น โปรดจำไว้ว่าตัวนับจะเพิ่มขึ้นเช่นกันหากอักขระปรากฏขึ้นเพียงครั้งเดียวในแถวเดียวและจะถูกละเว้นหากอักขระนั้นปรากฏเป็นจำนวนครั้งอื่น ๆ ในแถว (นอกเหนือจากสถานการณ์ที่อธิบายข้างต้น)

สรุปถ้าสตริงเพื่อการแข่งขันคือa,

input            counter (explanation)

a                 1 (single occurence)
aaa               -1(multiple of 3)
aaaaa             -1(multiple of 5)  
aaaaaaaaaaaaaaa   1 (multiple of 15)
aa                0 (none of the above)

aba               2 (two single instances)
aaba              1 (one single occurence(+1) and one double occurence(ignored))
aaaba             0 (one single occurence(+1) and one triple (-1)
aaaaaa            -1 (six is a multiple of three)

การอ้างอิง (ungolfed) การใช้งานใน java:

import java.util.Scanner;
import java.util.regex.*;

public class StrMatcher {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in); //Scanner to get user input
        int total = 0;//Running total of matches

        System.out.println("Enter a string: ");
        String strBeingSearched = sc.nextLine(); //String that will be searched

        System.out.println("Enter string to match with: ");
        String strBeingMatched = sc.nextLine(); //Substring used for searching

        //Simple regex matcher
        Pattern pattern = Pattern.compile("(" + strBeingMatched + ")+");
        Matcher matcher = pattern.matcher(strBeingSearched);

        while(matcher.find()){  //While there are still matches

            int length = matcher.end() - matcher.start();
            int numberOfTimes = length/strBeingMatched.length();//Calculate how many times in a row the string is matched

            if((numberOfTimes == 1)||((numberOfTimes % 3 == 0) && (numberOfTimes % 5 == 0))){
                total++; //Increment counter if single match or divisible by 15
            } else if((numberOfTimes % 3 == 0)||(numberOfTimes % 5 == 0)) {
                total--; //Decrement counter if divisible by 3 or 5 (but not 15)
            }

            strBeingSearched = strBeingSearched.substring(matcher.end());
            matcher = pattern.matcher(strBeingSearched); //Replace string/matcher and repeat
        }

        System.out.println(total);
    }   
}
  • สตริงที่จะค้นหาสามารถมีความยาวได้ แต่รูปแบบจะเป็นอักขระเดียวเท่านั้น
  • สตริงจะไม่มีอักขระพิเศษ regex
  • นี่คือ ; โปรแกรมที่สั้นที่สุดเป็นไบต์ชนะ
  • ไม่มีช่องโหว่มาตรฐาน

3
มันจะมีประโยชน์ถ้าคุณสามารถให้ตัวอย่างทดสอบเพิ่มเติมอีกสองสามข้อ โดยเฉพาะอย่างยิ่งลำดับที่มีตัวอักษรมากกว่าหนึ่งตัว
Reto Koradi

ฉันเพิ่มบางกรณี - หวังว่าจะช่วยได้ บอกฉันหากฉันต้องการกรณีเพิ่มเติม - เป็นครั้งแรกของฉันใน PPCG
Daniel M.

ฉันจะเปลี่ยนข้อกำหนดเพื่อให้ลำดับเป็นเพียงอักขระเดียวเนื่องจากการใช้งานนั้นเหมือนกันมาก แต่สับสนน้อยกว่า
Daniel M.

นี่เป็นเหมือนคำถามที่กระจัดกระจาย แต่ด้วยการเพิ่ม
FizzBuzz

คำตอบ:


32

Funciton , 1840 ไบต์

ภาษานี้เลวร้ายเหลือเกิน

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

และเช่นเคยคุณสามารถรับการเรนเดอร์ที่ดูดีขึ้น (โดยไม่มีการเว้นบรรทัด) หากคุณดำเนินการ$('pre').css('line-height',1)ในคอนโซลเบราว์เซอร์ของคุณ

      ┌───┐
      │╓─╖└─────────────┐
      └╢³╟┐    ┌─────┐ ┌┴┐╓─╖
┌─────┐╙─╜└────┤┌─╖ ┌┴╖│┌┘║¹║
│     ├───────┐└┤²╟─┤·╟┘│ ╙┬╜╔═══════╗
│    ┌┴╖╔═╗┌─╖├┐╘╤╝ ╘╤╝┌┘  └┬╢2097151║
│    │♭║║5╟┤%╟┘└─┴──┐│┌┘┌───┘╚═══════╝
│    ╘╤╝╚═╝╘╤╝╔═╗┌─╖│││┌┴┐┌────┐
│    ┌┴╖   ┌┘ ║3╟┤%╟┘││└┬┘│╔══╗└┐
│  ┌─┤·╟─┐ │  ╚═╝╘╤╝ │└┐  │║21╟┐│
│  │ ╘╤╝ ├─┘┌─────┘  └┐└┐ │╚══╝│└─┐
│ ┌┴╖┌┴╖┌┴╖┌┴╖┌─╖    ┌┴╖│ │┌─╖┌┴─╖│
│┌┤·╟┤?╟┤?╟┤?╟┤+╟────┤³║│ └┤²╟┤>>║└──┐
││╘╤╝╘╤╝╘╤╝╘╤╝╘╤╝    ╘╤╝│  ╘╤╝╘╤═╝╓─╖│
││ │ ┌┴╖┌┴╖┌┴╖┌┴╖╔═╗ ┌┴╖│  ┌┴╖ ├──╢²╟┤
││ └─┤·╟┤·╟┤?╟┤·╟╢1║┌┤·╟┘  │♯║┌┴╖ ╙─╜│
│└──┐╘╤╝╘╤╝╘╤╝╘╤╝╚═╝│╘╤╝   ╘╤╝│¹║┌───┘
└──┐│╔╧╗ └┬─┘ ┌┴╖   │┌┴─╖   │ ╘╤╝│
   ││║1║ ┌┴┐┌─┤?╟───┴┤>>╟┐ ┌┴╖┌┴╖│
   ││╚═╝ └┬┘│ ╘╤╝    ╘══╝│┌┤?╟┤=║│
   │└────┐│╔╧╗     ┌─────┘│╘╤╝╘╤╝│
╔═╗└────┐│├╢0║╔══╗┌┴╖┌─╖ ╔╧╗   └─┘
║ ║     │└┘╚═╝║21╟┤×╟┤♯╟┐║0║
╚╤╝     └──┐  ╚══╝╘═╝╘═╝│╚═╝
 │┌──┴────╖└────────────┘
 ││int→str║
 │╘══╤════╝
┌┴─╖┌┴╖┌─╖╔╗
│>>╟┤³╟┤¹╟╢║
╘═╤╝╘═╝╘═╝╚╝
╔═╧╗
║21║
╚══╝

(1840 ไบต์เมื่อเข้ารหัสเป็น UTF-16)

คำอธิบาย

  • ¹ ส่งคืนอักขระตัวแรกของสตริง
  • ²นับจำนวนครั้งของอักขระที่จุดเริ่มต้นของสตริงที่กำหนด ตัวอย่างเช่นเมื่อได้รับตัวอักษรaและสตริงaabaมันจะส่งกลับ 2 สำหรับaและbaaมันจะส่งกลับ 0
  • ³การเรียก²เพื่อให้ได้จำนวนอักขระเมื่อเริ่มต้นตรวจสอบว่าจำนวนหารด้วย 3 และ 5 หรือไม่และเท่ากับ 1 และพิจารณาการเพิ่ม / ลดที่เหมาะสม นอกจากนี้ยังลบอักขระพิเศษหนึ่งตัวจากจุดเริ่มต้นของสตริง (เช่นหากได้รับaaabbaจะลบอักขระ 3 + 1 = 4 ตัวให้ba) จากนั้นมันจะเรียกตัวเองซ้ำด้วยสตริงที่สั้นกว่าและเพิ่มผลลัพธ์
  • โปรแกรมหลักเรียกใช้¹เพื่อลบอักขระตัวแรกจากอินพุตและการโทร³ด้วยอักขระนั้นและส่วนที่เหลือของสตริงเป็นอาร์กิวเมนต์แยก

10
ฉันจะไม่ลงคะแนน Funciton
orlp

14

CJam, 40 36 35 32 30 ไบต์

0llcf=e`::*{(_g+Y13515Yb+=(+}/

ขอบคุณ @ MartinBüttnerสำหรับการลงเล่น 1 ไบต์!

ขอบคุณ @AndreaBiondo สำหรับการตีกอล์ฟขนาด 2 ไบต์และปูทางไปอีก 3 ลูก!

ลองใช้ออนไลน์ในล่าม CJam

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

0          e# Push a 0 (accumulator).
l          e# Read a line from STDIN.
lc         e# Read a second line and keep only the first character.
f=         e# Check each character from the first line for equality.
           e# This results in 1 for the specified character and 0 for others.
e`         e# Perform run-length encoding.
::*        e# Multiply each element by its number of repetitions.
{          e# For each remaining integer I:
  (_!      e#   Subtract 1, copy and push sign(I-1).
  +        e#   Add the results.
           e#     If I == 0, I-1 + sign(I-1) =  -1 + -1 = -2.
           e#     If I == 1, I-1 + sign(I-1) =   0 +  0 =  0.
           e#     If I >= 2, I-1 + sign(I-1) = I-1 +  1 =  I.
  Y        e#   Push 2.
  13515Yb  e#   Convert 13515 into the array of its binary digits.
  +        e#   Concatenate 2 and the array.
           e#   This pushes [2 1 1 0 1 0 0 1 1 0 0 1 0 1 1].
  =        e#   Retrieve the digit at (index I-1 + sign(I-1))%15.
           e#     If I == 0, this pushes 1.
           e#     Else, if I == 1, this pushes 2.
           e#     Else, if I%15 == 0, this pushes 2.
           e#     Else, if I%3==0 or I%5==0, this pushes 0.
           e#     Else, this pushes 1.
  (        e#   Decrement the result.
  +        e#   Add it to the accumulator.
}/         e#

คุณสามารถบันทึกอีก 2 ไบต์ด้วยตารางการค้นหาที่เข้ารหัสพื้นฐานและการทำดัชนีแบบโมดูลาร์: llcf=e`::*0-{(_!\6563282Zb:(=}%1bคือ 33 ไบต์
Andrea Biondo

@AndreaBiondo ที่บันทึกจริง 3 ไบต์ ขอบคุณ!
เดนนิส

7

C, 160 126 125 119 114 109 104 100 ไบต์

main(int q,char **z){int i=0,t=0,s=0,a=z[1][0],c;do{if((c=z[2][i])!=a){s+=(!!t)*((t==1)-!(t%3)-!(t%5)+3*!(t%15));t=0;}else{++t;}++i;}while(c);printf("%d\n",s);}

อาจเป็นไปได้ที่จะทำให้ดีขึ้น ... สิ่งนี้นำเข้าจากอาร์กิวเมนต์บรรทัดคำสั่ง (อาร์กิวเมนต์แรกคือรูปแบบที่สองคือสตริง) ไม่รองรับการค้นหารูปแบบของ NULL ถ่าน (\ x00)

แก้ไข ** 126 125 119 114 109 104 100 ไบต์ **: หลังจากรวมคำแนะนำของเดนนิสและแนวคิดเพิ่มเติมบางประการ (ลบส่วนคำสั่งอื่นให้รวมคำว่า while เป็นคำเดียวและใช้การลบแทน! =) ลบเซมิโคลอนพิเศษในวงออกไป (นั่นเป็นส่วนหนึ่งของข้อเสนอแนะของเดนนิส) ลดขนาดให้สั้นลงโดยการลบตัวแปร 'i' และ 'a'

t,s;main(c,z)char**z;{for(;c;t++)if((c=*z[2]++)-*z[1])s+=!!t*((t<2)-!(t%3)-!(t%5)+3*!(t%15)),t=-1;printf("%d",s);}

ลบตัวดำเนินการ if and negation ('!') ด้วยการใช้โอเปอเรเตอร์ที่ดูถูกเหยียดหยาม บีบอัดการตรวจสอบแบบแยกส่วนโดยใช้'และ' หลอกสอง & amp; เพราะ bitwise '&' มีข้อบกพร่องและวาง (t <2) เปรียบเทียบภายในผู้ประกอบการที่ประกอบไปด้วยสาม แทนที่ !! t * (... ) โดยการย้าย !! t เข้าสู่ผู้ประกอบการที่ประกอบไปด้วยสามดังนั้นจึงอนุญาตให้ฉันลบวงเล็บ

ผู้ชายฉันต้องการให้มันต่ำกว่า 100 ไบต์: S

t,s;main(c,z)char**z;{for(;c;)(c=*z[2]++)-*z[1]?s+=t%15?t%3&&t%5?t<2:-1:!!t,t=0:t++;printf("%d",s);}

วิธีแก้ไขปัญหาสำหรับ TENTATIVE: ฉันไม่แน่ใจว่าสิ่งเหล่านี้จะถือว่าใช้ได้หรือไม่ แต่ฉันสามารถลงไปได้ถึง 93 ตัวอักษรถ้าฉันใช้ exit (s) แทน printf ("% d", s) แต่ผลลัพธ์จะไม่สามารถมองเห็นได้ แต่จะเป็นรหัสส่งคืน หากผลผลิตมีความจำเป็นจริง ๆ ฉันสามารถลดขนาดลงเหลือ 98 ไบต์ แต่จะต้องพิมพ์ค่ากลางทั้งหมดของ s ก่อนคำตอบสุดท้ายด้วยเช่นกัน ...


3
ยินดีต้อนรับสู่ Programming Puzzles & Code Golf! ฉันยังไม่ได้ทดสอบอย่างละเอียด แต่i,t,s,a;main(c,z)char**z;{a=*z[1];while(c){if((c=z[2][i])!=a)s+=(!!t)*((t<2)-!(t%3)-!(t%5)+3*!(t%15)),t=0;else++t;++i;}printf("%d",s);}ควรใช้งานได้ดี (และสั้นกว่า 23 ไบต์)
เดนนิส

โอ้เป็นเรื่องที่ดีด้วยการเปลี่ยนประโยค if () {} เป็นข้อความเดียว!
Tob Ernack

อีกไม่กี่ไบต์: หากคุณเริ่มต้นmainด้วยfor(a=*z[1];c;i++)คุณไม่จำเป็นต้อง{}ไปรอบ ๆ ถ้า ... อื่น
เดนนิส

4

Ruby, 111 103 96 ไบต์

->s,m{s.chars.chunk{|x|x}.reduce(0){|x,(c,g)|l=g.size
x+(c!=m ?0:l<2||l%15<1?1:l%3*l%5<1?-1:0)}}

ความท้าทายนี้สร้างขึ้นเพื่อรูบี้Enumerable#chunkดังนั้นฉันจึงต้องโพสต์สิ่งนี้ :)

การทดสอบออนไลน์: http://ideone.com/pG4mAn

รหัสค่อนข้างตรงไปตรงมา ต่อไปนี้เป็นรุ่นที่สามารถอ่านเพิ่มเติมได้ที่: http://ideone.com/ub3siA


4

Python 3, 361, 300, 296, 263, 256, 237, 229, 188, 178 , 164 ไบต์

บันทึก 15 ไบต์ขอบคุณ vaultah จาก SOPython
บันทึกแล้ว 9 ไบต์จาก Joe Kington จาก SOPython
บันทึก 11 ไบต์ด้วย DSM จาก SOPython

นี่เป็นครั้งแรกที่ฉันส่งคำตอบดังนั้นฉันแน่ใจว่านี่อาจสั้นกว่านี้มาก มันจะใช้สตริงการทดสอบเป็นคำตอบแรกที่จะป้อนข้อมูลและค้นหาถ่านเป็นคนที่สอง

t=input()
m=input()
c=u=0
g=iter(t)
while g:
 r=next(g,0)
 if r==0:print(c);g=0
 while r==m:u+=1;r=next(g,0)
 if u:b=u%3<1;v=u%5<1;c+=((0,-1)[b|v],1)[u<2or b&v];u=0

เวอร์ชันที่ไม่ถูกปรับแต่ง:

import sys
test = sys.argv[1]
match_char = sys.argv[2]
counter = char_counter = 0
char_generator = (c for c in test)
while char_generator:
    try:
        char = next(char_generator)
    except StopIteration:
        print(counter)
        break
    while char == match_char:
        char_counter += 1
        try:
            char = next(char_generator)
        except StopIteration:
            break
    if char_counter == 0:
        continue
    counter += 1 if char_counter == 1 or (char_counter % 3 == 0 and char_counter % 5 == 0) else -1 if char_counter % 3 == 0 or char_counter % 5 == 0 else 0
    char_counter = 0

ค้นพบว่าฉันทำข้อสอบข้อใดข้อหนึ่งล้มเหลว



3

Java, 146 152 143 138 139 136 ไบต์

  1. แก้ไขข้อบกพร่อง
  2. เปลี่ยนการดำเนินการเปลี่ยนไปใช้ตัวดำเนินการระดับบิตสำหรับ %3&%5ตรวจสอบ
  3. i<2เปรียบเทียบสั้นลง
  4. แก้ไขข้อผิดพลาด ( %3&%5ตรวจสอบไม่ทำงานตามที่คิด)
  5. ใช้ทางลัดการคูณตามที่เห็นในคำตอบ Ruby ของ@ w0lf

นำมาใช้ใน a BiFunction<String, String, Integer>Java 8 แจ้งให้เราทราบว่านี่เป็นโปรแกรมเต็มรูปแบบ (หรือถ้าฉันสามารถวางjava.util.regexคำนำหน้าแพ็คเกจด้านล่าง)

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

(a,b)->java.util.regex.Pattern.compile("[^"+b+"]").splitAsStream(a)
.mapToInt(v->v.length()).map(i->i<2?i:i%15<1?1:i%3*i%5<1?-1:0).sum();

คำอธิบายหยาบ:

  1. สมัคร regex ที่มีรูปแบบที่ไม่ตรงคือb"[^"+b+"]"
  2. รับความยาวของแต่ละโทเค็น (เช่น"a" -> 1)
  3. สมัครการทำแผนที่ที่ต้องการ-1, และ01
  4. sum() เพื่อรับคำตอบ

2

Javascript, 206 ไบต์

function f(n,e){var t=n.match(new RegExp(e,"g")).length,g=n.match(new RegExp(e+"{2,}","g"));return null!==g&&g.forEach(function(n){t-=n.length,n.length%15==0?t+=1:(n.length%3==0||n.length%5==0)&&(t-=1)}),t}

ขยาย:

function funkyFizzb(n, c) {
    var score = n.match(new RegExp(c, "g")).length; 
    var repeatOccurence = n.match(new RegExp(c + "{2,}", "g"));

    if(repeatOccurence !== null) {
        repeatOccurence.forEach(function(v,i){
            // remove multiple occurrence counts
            score -= v.length;

            if(v.length % 15 == 0) {
                score += 1;
            }

            else if(v.length % 3 == 0 || v.length % 5 == 0) {
                score -= 1;
            }
        });
    }

    return score;
};

คำอธิบาย:

ฉันใช้ regex เพื่อนับรวมเวลาที่ตัวละครปรากฏขึ้นจากนั้นลบออกจากทุกครั้งที่ปรากฏในกลุ่ม ในที่สุดฉันก็ผ่านกลุ่มและทำเสียงพึมพำฟองเพิ่ม / ลด

ผ่านกรณีทดสอบที่กำหนดในคำถาม:

funkyFizzb("aaa", "a") => -1

และอื่น ๆ


ลบการnewใช้execแทนmatchและนามแฝงlengthและคุณควรจะดี
Mama Fun Roll

2

Perl, 82 65 63 59 ไบต์

58 ไบต์ + 1 ไบต์พารามิเตอร์บรรทัดคำสั่ง

ไม่สั้นโดยเฉพาะ แต่เป็นการเริ่มต้น - จะย่อให้สั้นลง

$l=y///c,$i+=!($l>1&&$l%15)||-!($l%3*$l%5)for/$^I+/g;$_=$i

สมมติว่า-iสามารถใช้เพื่อให้สายป้อนตัวอย่างการใช้งานดังต่อไปนี้:

echo "aaabaaa" | perl -pi"a" entry.pl


0

เหยี่ยว, 140

p=$2{b="[^"$1"]";for($0=2;$i-->0;){sub("^"b"*",_,p);p=substr(p,$++i=match(p,b))}for($i=length(p);$++j;)s+=$j%5?$j%3?$j<2:-1:$j%3?-1:1}$0=s""

ป้อนเป็น "char space string" เช่นนี้

echo "x axxbxcxdexxxfffghixxj" | awk 'p=$2{b="[^"$1"]";for($0=2;$i-->0;){sub("^"b"*",_,p);p=substr(p,$++i=match(p,b))}for($i=length(p);$++j;)s+=$j%5?$j%3?$j<2:-1:$j%3?-1:1}$0=s""'

Ungolfed

p=$2{
    #i=j=s=0                # make reusable
    b="[^"$1"]";           # pattern "not matching char"
    $0=2;                  # help starting the while loop
    while($i-->0){         # match didn't return -1; dec stack top
        sub("^"b"*",_,p);  # remove not matching chars at head of string
        $++i=match(p,b);   # push index of first occurence of not matching char
        p=substr(p,$i)     # remove matching chars from head of string
    };
    $i=length(p);          # get last value
    while($++j)            # sometimes last value on stack is 0
        s+=$j%5?$j%3?$j<2:-1:$j%3?-1:1

        # if $j%5!=0
        #   if $j%3!=0     (not divisible by 5 AND 3)
        #     s+=($j==1)   (single character)
        #   else           (divisible by 3 but not by 5)
        #     s-=1
        # else             (divisble by 5)
        #   if $j%3!=0
        #     s-=1         (divisible by 5 but not by 3)
        #   else
        #     s+=1         (divisible by 3 AND 5)

}$0=s"" # output

0

Pyth, 27 ไบต์

sm|!JPdx,02+}3J}5JhMf}zTrw8

ชุดทดสอบ

ป้อนข้อมูลในแบบฟอร์มเช่น:

a
aaaba

คำอธิบาย:

sm|!JPdx,02+}3J}5JhMf}zTrw8
                               z = input() (The match character)
                         w     input() (The string)
                        r 8    Run length encode
                    f}zT       Filter for the runs z is in.
                  hM           Take their lengths
 m|                            Map (d) to the logical or of
    Pd                         Find all prime factors of the current run length
   J                           Save them in J
  !                            Take the logical negation. This will be 1 if
                               d is 1, and 0 otherwise.
           +}3J                If d wasn't 1, add up 1 if 3 is in J
               }5J             and 1 if 5 is in J.
       x,02                    Then, take the index of the result in [0,2]
                               so 0 -> 0, 2 -> 1, 1 -> -1 (not found)
s                              Sum up the values for each run.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.