จำแนกภูมิภาคตามความชัน


16

คำนิยาม

k THแหวนของตารางเมทริกซ์ขนาดNที่1 ≤ k ≤เพดาน (N / 2)เป็นรายการที่เกิดขึ้นจากองค์ประกอบของk THและ(N-k + 1) THแถวและคอลัมน์ แต่ไม่มีองค์ประกอบk-1แรกและสุดท้าย

ตัวอย่าง:

เมทริกซ์:

1 2 3 4 5
6 7 8 9 1
8 7 6 5 4
3 2 1 9 8
7 6 5 4 3

คั่นด้วยวงแหวน

+ + -------------------
| 1 2 3 4 5 |
| + ----------- + |
| 6 | 7 8 9 | 1 |
| | + --- + | |
| 8 | 7 | 6 | 5 | 4 |
| | + --- + | |
| 3 | 2 1 9 | 8 |
| + ----------- + |
| 7 6 5 4 3 |
+ + -------------------

แหวนแรกที่กล่าวมาเป็น1,2,3,4,5,1,4,8,3,4,5,6,7,3,8,6ที่สองคือและสามคือ7,8,9,5,9,1,2,76

NโดยNเมทริกซ์ของจำนวนเต็มบวก (สำหรับวัตถุประสงค์ของความท้าทายนี้):

  • เว้าหากทุกจำนวนเต็มในที่k THแหวนเป็นอย่างเคร่งครัดมากกว่าผู้ที่อยู่ใน(k + 1) THแหวนที่kเป็นจำนวนเต็มใด ๆ ระหว่าง1และN (ผู้ที่อยู่ในแหวนแรกมากกว่าผู้ที่อยู่ในที่สองซึ่งเป็น จะยิ่งใหญ่กว่าสิ่งที่สามเป็นต้น) ตัวอย่าง:

    4 5 6 4 7 -> เพราะ 4,5,6,4,7,4,8,5,5,4,6,5,9,5,5,4 ทั้งหมดสูงกว่า
    4 3 2 2 4 ใด ๆ ของ 3,2,2,3,2,3,3,2 ซึ่งสูงกว่า 1 ทั้งหมด
    5 2 1 3 8
    5 3 3 2 5
    9 5 6 4 5
    
  • แบนถ้าจำนวนเต็มทั้งหมดในเมทริกซ์เท่ากัน ตัวอย่างอื่น (อาจซ้ำซ้อน):

    2 2 2 2
    2 2 2 2
    2 2 2 2
    2 2 2 2
    
  • นูนหากทุกจำนวนเต็มในที่k THแหวนเป็นอย่างเคร่งครัดต่ำกว่าผู้ที่อยู่ใน(k + 1) THแหวนที่kเป็นจำนวนเต็มใด ๆ ระหว่าง1และN (ผู้ที่อยู่ในแหวนแรกจะต่ำกว่าที่สองซึ่งเป็น ในทางกลับกันต่ำกว่าที่สาม ฯลฯ ) ตัวอย่าง:

    1 2 1 -> เพราะ 1 และ 2 ต่ำกว่า 6
    2 6 2
    1 2 1
    
  • ผสมกันถ้าเมทริกซ์ไม่ตรงตามเกณฑ์ข้างต้นใด ๆ ตัวอย่าง:

    3 3 3 3 3
    3 2 2 2 3
    3 2 3 2 3
    3 2 2 2 3
    3 3 3 3 3
    

ท้าทาย

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

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

กรณีทดสอบ

นี่คือตัวอย่างมากมายให้คุณเลือก - ฉันเลือก 6 จากแต่ละหมวดหมู่

เว้า

[[3, 3, 3], [3, 1, 3], [3, 3, 3]]
[[2, 3, 4], [5, 1, 6], [7, 8, 9]]
[[19, 34, 45], [34, 12, 14], [13, 13, 13]]
[[3, 4, 3, 4], [4, 2, 1, 3], [3, 1, 2, 4], [4, 3, 4, 3]]
[[4, 5, 6, 4, 7], [4, 3, 2, 2, 4], [5, 2, 1, 3, 8], [5, 3, 3, 2, 5], [9, 5, 6, 4, 5]]
[[7, 7, 7, 7, 7], [7, 6, 6, 6, 7], [7, 6, 5, 6, 7], [7, 6, 6, 6, 7], [7, 7, 7, 7, 7]]

แบน

[[1, 1, 1], [1, 1, 1], [1, 1, 1]]
[[2, 2, 2], [2, 2, 2], [2, 2, 2]]
[[8, 8, 8], [8, 8, 8], [8, 8, 8]]
[[120, 120, 120], [120, 120, 120], [120, 120, 120]]
[[10, 10, 10, 10], [10, 10, 10, 10], [10, 10, 10, 10], [10, 10, 10, 10]]
[[5, 5, 5, 5, 5, 5], [5, 5, 5, 5, 5, 5], [5, 5, 5, 5, 5, 5], [5, 5, 5, 5, 5, 5], [5, 5, 5, 5, 5, 5], [5, 5, 5, 5, 5, 5]]

นูนออก

[[1, 2, 1], [2, 6, 2], [1, 2, 1]]
[[1, 1, 1], [1, 2, 1], [1, 1, 1]]
[[19, 34, 45], [34, 76, 14], [13, 6, 13]]
[[3, 3, 3, 3], [3, 4, 4, 3], [3, 4, 4, 3], [3, 3, 3, 3]]
[[192, 19, 8, 6], [48, 324, 434, 29], [56, 292, 334, 8], [3, 4, 23, 23]]
[[291, 48, 7, 5], [47, 324, 454, 30], [58, 292, 374, 4], [9, 2, 53, 291]]

ผสม

[[1, 2, 3], [4, 5, 9], [6, 7, 8]]
[[10, 14, 21], [100, 8, 3], [29, 2, 19]]
[[5, 5, 5, 5], [5, 4, 4, 5], [5, 4, 6, 5], [5, 5, 5, 5]]
[[3, 3, 3, 3], [3, 1, 2, 3], [3, 3, 2, 3], [3, 3, 3, 3]]
[[12, 14, 15, 16], [12, 18, 18, 16], [12, 11, 11, 16], [12, 14, 15, 16]]
[[5, 5, 5, 5, 5], [5, 4, 4, 4, 5], [5, 4, 6, 4, 5], [5, 4, 4, 4, 5], [5, 5, 5, 5, 5]]

ความท้าทายนี้เคยโพสต์ไว้ในSandboxแล้ว ขอขอบคุณผู้ที่ให้ข้อเสนอแนะที่มีค่า
นาย Xcoder

2
เด็กชายมันคงจะดีถ้ามีการแปลงสตริงอาเรย์ของอาเรย์ไปเป็น / จากฟังก์ชั่นเมทริกซ์ที่มีประโยชน์ในการประมวลผลกรณีทดสอบทั้งหมดในหลากหลายภาษา :)
ngm

@ngm คุณไม่กล้าคิดว่าเราไม่มีแล้ว ! : P
Mr. Xcoder

คำตอบ:


5

Java (JDK 10) , 247 232 220 ไบต์

x->{int i=0,j=x.length,k,m,M,p=0,P=0,r=0;for(;i<j;){for(M=m=x[k=i][--j];k<=j;)for(int q:new int[]{x[i][k],x[j][k],x[k][i],x[k++][j]}){m=m<q?m:q;M=M<q?q:M;}r=i++>0?(k=P<m?3:p>M?1:P==m?2:4)*r!=r*r?4:k:0;p=m;P=M;}return r;}

ลองออนไลน์!

ขาออก:

  • 1 สำหรับ "เว้า"
  • 2 สำหรับ "แบน"
  • 3 สำหรับ "นูน"
  • 4 สำหรับ "มิกซ์"

Ungolfed:

x -> { // lambda that takes in the input int[][]
  int i = 0, // index of right bound of ring
      j = x.length, // index of left bound of ring
      k, // index of row-column-pair in ring
      m, // minimum of ring
      M, // maximum of ring
      p = 0, // minimum of previous ring
      P = 0, // maximum of previous ring
      r = 0; // result
  for (; i < j; ) { // iterate the rings from outside inwards
    // set both min and max to be to top right corner of the ring (and sneakily set some loop variables to save space)
    for (M = m = x[k = i][--j]; k <= j; ) // iterate the row-column pairs of the ring from top-right to bottom-left
      for (int q : new int[] {x[i][k], x[j][k], x[k][i], x[k++][j]}) { // iterate all of the cells at this row-column pair (and sneakily increment the loop variable k)
        // find new minimum and maximum
        m = m < q ? m : q;
        M = M < q ? q : M;
      }
    r = // set the result to be...
      i++ > 0 ? // if this is not the first ring... (and sneakily increment the loop variable i)
              // if the new result does not match the old result...
              (k = P < m ? // recycling k here as a temp variable to store the new result, computing the result by comparing the old and new mins/maxes
                         3
                         : p > M ?
                                 1
                                 : P == m ? 
                                          2
                                          : 4) * r != r * r ? // multiplying by r here when comparing because we want to avoid treating the case where r = 0 (unset) as if r is different from k
                                                            4 // set the result to "mixed"
                                                            : k // otherwise set the result to the new result
              : 0; // if this is the first ring just set the result to 0
    // set the old ring mins/maxes to be the current ones
    p = m; 
    P = M;
  }
  return r; // return the result
}

5

เยลลี่ ,  18 17  16 ไบต์

ฉันเชื่อว่ามีความเป็นไปได้สูงสำหรับความพยายามนี้ที่จะออกไปตีกอล์ฟ

L‘HạŒỤṀ€IṠQṢ«FE$

ลิงก์ monadic ยอมรับรายการของตัวเลขที่ส่งคืนรายการจำนวนเต็ม:

Concave ->  [0, 0]
Flat    ->  [-1, 0, 1]
Convex  ->  [-1, 0]
Mixed   ->  [-1, 0, 0]

ลองออนไลน์! หรือดูชุดทดสอบการทดสอบในตัว

L‘Hอาจถูกแทนที่ด้วยประสิทธิภาพน้อยลง แต่สั้นลงด้วยอะตอมJÆmด้วย

อย่างไร?

L‘HạŒỤṀ€IṠQṢ«FE$ - Link: list of (equal length) lists of numbers
L                - length
 ‘               - increment
  H              - halve
                 -   = middle 1-based index (in both dimensions as the input is square)
    ŒỤ           - sort multi-dimensional indices by their corresponding values
                 -   = a list of pairs of 1-based indexes
   ạ             - absolute difference (vectorises)
                 -   = list of [verticalDistanceToMiddle, horizontalDistanceToMiddle] pairs
      Ṁ€         - maximum of €ach
                 -   each = N/2-k (i.e. 0 as middle ring and N/2 as outermost)
        I        - incremental deltas (e.g. [3,2,2,3,1]->[3-2,2-2,3-2,1-3]=[-1,0,1,-2])
         Ṡ       - sign (mapping -n:-1; 0:0; and +n:1)
          Q      - de-duplicate
           Ṣ     - sort
                 -   = concave:[0, 1]; convex:[-1, 0]; flatOrMixed:[-1, 0, 1]
               $ - last two links as a monad
             F   -   flatten
              E  -   all equal? (1 if flat otherwise 0)
            «    - minimum (vectorises)
                 -   = concave:[0, 0]; convex:[-1, 0]; mixed:[-1, 0, 0]; flat:[-1, 0, 1]

5

Python 2 , 219 216 189 176 ไบต์

def g(M):A=[sorted((M[1:]and M.pop(0))+M.pop()+[i.pop(j)for j in[0,-1]for i in M])for k in M[::2]];S={cmp(x[j],y[~j])for x,y in zip(A,A[1:])for j in[0,-1]};return len(S)<2and S

ลองออนไลน์!

ผลลัพธ์set([1]), set([0]), set([-1]),หรือFalseเว้าแบนนูนหรือผสมตามลำดับ

thx สำหรับ: มหันต์ 27 ไบต์จากไม่กี่เพิ่มประสิทธิภาพโดยOVS แล้วอีก 13 ไบต์ต่อมา

รายการความเข้าใจA(เนื่องจาก ovs) สร้างรายการองค์ประกอบของแต่ละแหวนเรียง

ถัดไปเราเปรียบเทียบmaxและminค่าระหว่างวงแหวนที่อยู่ติดกันโดยดูที่องค์ประกอบที่ th 0และ-1th ของแต่ละรายการที่เรียงลำดับใน A โปรดทราบว่าถ้าเช่นMเป็นเว้าminของวงแหวนรอบนอกแต่ละอันจะต้องมากกว่าmaxของวงแหวนภายในสุดถัดไป ; และจากนั้นก็ติดตามว่าmaxวงแหวนรอบนอกแต่ละอันจะใหญ่กว่าminวงแหวนชั้นในสุดถัดไป

หากMเป็นเว้าแบนหรือนูนชุดmin/maxการเปรียบเทียบเหล่านี้จะมีเพียง 1 องค์ประกอบจาก{-1, 0, 1}; หากผสมกันจะมีองค์ประกอบสองอย่างหรือมากกว่านั้น


@ovs: นั่นเป็นสีสวย; ฉันบันทึกไบต์อื่นด้วยการแปลงให้เป็นรายการความเข้าใจ (และคิดว่านี่อาจเป็นเทคนิคที่มีประโยชน์มากสำหรับความท้าทายอื่น ๆ ที่คล้ายกัน)
Chas Brown

อาจจะมีวิธีที่จะลดลงความเข้าใจรายการ แต่ที่ห่วงในขณะที่ยังดูเหมือนจะสั้น: while M:k=M[0]+M[-1];M=M[1:-1];A+=sorted(k+[i.pop(j)for j in[0,-1]for i in M]),(174 bytes)
OVS

@ovs: คุณได้ละเว้น,A=()จากการนับไบต์ของคุณ ...
Chas สีน้ำตาล

ฉันได้รับ174 ไบต์ด้วยA=()
ovs

อา! ขอโทษฉันเข้าใจผิด while M: A+= (some expression)ซึ่งจะแตกต่างกว่ารุ่นก่อนหน้าของคุณซึ่งเป็นรูปแบบ:
Chas Brown


4

JavaScript (ES6), 168 ไบต์

ผลตอบแทน:

  • -1 สำหรับแบน
  • 0 สำหรับผสม
  • 1 สำหรับนูน
  • 2 สำหรับเว้า
f=(a,k=w=~-a.length/2,p,P,i,m,M,y=w)=>k<0?i%4%3-!i:a.map(r=>r.map(v=>Y|(X=k*k-x*x--)<0&&X|Y<0||(m=v>m?m:v,M=v<M?M:v),x=w,Y=k*k-y*y--))|f(a,k-1,m,M,i|M-m<<2|2*(M<p)|m>P)

ลองออนไลน์!

อย่างไร?

ขั้นต่ำและสูงสุดในแต่ละวงแหวน

เราคำนวณค่าต่ำสุดmและค่าสูงสุดMในแต่ละวงแหวน

เราทดสอบว่าเซลล์ตั้งอยู่บนวงแหวนที่กำหนดหรือไม่โดยคำนวณระยะทางยกกำลังสองจากศูนย์กลางของเมทริกซ์ในแต่ละแกน การรับค่าสัมบูรณ์จะได้ผลเช่นกัน แต่กำลังสองน้อยกว่า

เซลล์ที่(x, y)ตั้งอยู่บนวงแหวนn -th (ดัชนี 0, เริ่มต้นจากด้านนอกสุด) หากสูตรต่อไปนี้เป็นเท็จ :

((Y != 0) or (X < 0)) and ((X != 0) or (Y < 0))

ที่อยู่:

  • X = k² - (x - w) ²
  • Y = k² - (y - w) ²
  • w = (a.length - 1) / 2
  • k = w - n

ตัวอย่าง:เซลล์(1, 2)บนวงแหวนที่สองของเมทริกซ์ 6x6 หรือไม่?

  | 0 1 2 3 4 5   w = (6 - 1) / 2 = 2.5
--+------------   (x, y) --> ( x-w,  y-w) --> ((x-w)²,(y-w)²)
0 | 0 0 0 0 0 0   (1, 2) --> (-1.5, -0.5) --> (  2.25,   0.5)
1 | 0 1 1 1 1 0   
2 | 0[1]0 0 1 0   k = w - 1 = 1.5
3 | 0 1 0 0 1 0   k² = 2.25
4 | 0 1 1 1 1 0   X = 2.25 - 2.25 = 0 / Y = 2.25 - 0.5 = 1.75
5 | 0 0 0 0 0 0   ((X != 0) or (Y < 0)) is false, so (1,2) is on the ring

ธง

ในตอนท้ายของการวนซ้ำแต่ละครั้งเราเปรียบเทียบmและMกับpต่ำสุดและสูงสุดPของวงแหวนก่อนหน้าและอัปเดตตัวแปรธงiตามลำดับ:

  • i |= 1ถ้าm> P
  • i |= 2ถ้าM <p
  • เราตั้งบิตที่สูงขึ้นของiถ้าM! = m

ในตอนท้ายของกระบวนการเราแปลงค่าสุดท้ายของiดังนี้:

i % 4  // isolate the 2 least significant bits (for convex and concave)
% 3    // convert 3 to 0 (for mixed)
- !i   // subtract 1 if i = 0 (for flat)

4

K (ngn / k) , 100 71 69 ไบต์

{$[1=#?,/a:(,/x)@.=i&|i:&/!2##x;;(&/m>1_M,0)-&/(m:&/'a)>-1_0,M:|/'a]}

ลองออนไลน์!

ผลตอบแทน1= เว้า, ::= แบน, -1= นูน,0 = ผสม

( ::ใช้เป็นตัวยึดตำแหน่งสำหรับค่าที่หายไปเป็น k)


กลยุทธ์ที่แตกต่างโดยใช้ oK:&/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':(,/*:'(|+:)\)'-1_(-1_1_+-1_1_)\
zgrep

@zgrep ดี! :) อย่าลังเลที่จะโพสต์เป็นคำตอบที่แยกต่างหากและนำความคิดจากฉันถ้าคุณต้องการ - ตัวอย่างเช่นดูเหมือนว่าการแยกวงของฉันจะสั้นกว่า แต่ฉันยังไม่ได้ลองใน oK เลย
ngn


Ooh มันเป็นแหวนที่แยกออกมาได้ดีมาก! ฉันชอบมัน.
zgrep

2

oK , 56 ไบต์

&/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':{(,/x)@.=i&|i:&/!2##x}@

ตามออกของคำตอบของ NGN

ลองออนไลน์!

concave:1 0 0
   flat:0 0 1
 convex:0 1 0
  mixed:0 0 0

ไม่จำเป็นต้องมี @ ถ้าคุณเปลี่ยนทุกอย่างให้กลายเป็นแลมบ์ดาใหญ่ ๆ :{&/1_`{&/+(y>|/x;y<&/x;,/x=/:y)}':(,/x)@.=i&|i:&/!2##x}
ก.ย.

1

C ++ 17 (gcc) , 411 ไบต์

#import<map>
#define R return
#define T(f,s)X p,c;for(auto&e:r){c=e.second;if(p.a&&!p.f(c)){s;}p=c;}R
using I=int;struct X{I a=0;I z=0;I f(I n){R!a||n<a?a=n:0,n>z?z=n:0;}I
l(X x){R z<x.a;}I g(X x){R a>x.z;}I e(X x){R a==z&a==x.a&z==x.z;}};I
N(I i,I j,I s){i*=s-i;j*=s-j;R i<j?i:j;}auto C=[](auto&&m){I
s=size(m),i=-1,j;std::map<I,X>r;for(;++i<s;)for(j=-1;++j<s;)r[N(i,j,s-1)].f(m[i][j]);T(g,T(l,T(e,R 0)3)2)1;};

คะแนนสูงสุดใหม่! (ตอนที่โพสต์อย่างน้อย) อืมมันค่อนข้างดี แต่ก็ยัง C ++

ลองออนไลน์!

แลมบ์ดาCใช้เวลาstd::vector<std::vector<int>>และส่งกลับ 1 สำหรับเว้า 2 สำหรับนูน, 3 สำหรับแบนหรือ 0 สำหรับผสม

รหัสที่ชัดเจนยิ่งขึ้นพร้อมด้วยตัวระบุที่เป็นคำอธิบายความคิดเห็นR-> returnและI-> intเขียนออกมาและอื่น ๆ :

#include <map>

// Abbreviation for golfing. Spelled out below.
#define R return

// Macro to test whether all pairs of consecutive Ranges in `rings`
// satisfy a condition.
// func: a member function of Range taking a second Range.
// stmts: a sequence of statements to execute if the condition is
//        not satisfied. The statements should always return.
//        May be missing the final semicolon.
// Expands to a statement, then the return keyword.
// The value after the macro will be returned if all pairs of Ranges
// satisfy the test.
#define TEST(func, stmts)                                     \
    Range prev, curr;                                         \
    for (auto& elem : rings) {                                \
        curr = elem.second;                                   \
        // The first time through, prev.a==0; skip the test.  \
        if (prev.a && !prev.func(curr))                       \
        { stmts; }                                            \
        prev = curr;                                          \
    }                                                         \
    return

// Abbreviation for golfing. Spelled out below.
using I = int;

// A range of positive integers.
// A default-constructed Range is "invalid" and has a==0 && z==0.
struct Range
{
    int a = 0;
    int z = 0;
    // Add a number to the range, initializing or expanding.
    // The return value is meaningless (but I is shorter than void for golfing).
    int add(int n) {
        return !a||n<a ? a=n : 0, n>z ? z=n : 0;
        /* That is:
        // If invalid or n less than previous min, set a.
        if (a==0 || n<a)
            a = n;
        // If invalid (z==0) or n greater than previous max, set z.
        if (n>z)
            z = n;
        return dummy_value;
        */
    }

    // Test if all numbers in this Range are strictly less than
    // all numbers in Range x.
    int less(Range x)
    { return z < x.a; }

    // Test if all numbers in this Range are strictly greater than
    // all numbers in Range x.
    int greater(Range x)
    { return a > x.z; }

    // Test if both this Range and x represent the same single number.
    int equal(Range x)
    { return a==z && a==x.a && z==x.z; }
};

// Given indices into a square matrix, returns a value which is
// constant on each ring and increases from the first ring toward the
// center.
// i, j: matrix indices
// max: maximum matrix index, so that 0<=i && i<=max && 0<=j && j<=max
int RingIndex(int i, int j, int max)
{
    // i*(max-i) is zero at the edges and increases toward max/2.0.
    i *= max - i;
    j *= max - j;
    // The minimum of these values determines the ring.
    return i < j ? i : j;
}

// Takes a container of containers of elements convertible to int.
// Must represent a square matrix with positive integer values.
// Argument-dependent lookup on the outer container must include
// namespace std, and both container types must have operator[] to
// get an element.  (So std::vector or std::array would work.)
// Returns:
//   1 for a concave matrix
//   2 for a convex matrix
//   3 for a flat matrix
//   0 for a mixed matrix
auto C /*Classify*/ = [](auto&& mat)
{
    int mat_size=size(mat), i=-1, j;
    std::map<int, Range> rings;

    // Populate rings with the range of values in each ring.
    for (; ++i<mat_size;)
        for (j=-1; ++j<mat_size;)
            rings[RingIndex(i, j, mat_size-1)].add(mat[i][j]);

    // Nested macros expand to
    // Range prev, curr; for ... if (...) {
    //   Range prev, curr; for ... if (...) {
    //     Range prev, curr; for ... if (...) {
    //       return 0;
    //     } return 3;
    //   } return 2;
    // } return 1
    // Note each scope declares its own prev and curr which hide
    // outer declarations.
    TEST(greater, TEST(less, TEST(equal, return 0) 3) 2) 1;
};

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