Tạo sơ đồ Voronoi (biến thể ASCII)


24

Giả sử bạn được cung cấp một số chữ cái in hoa riêng biệt nằm rải rác trong một mảng hình chữ nhật của các ô trống khác. Mỗi ô trong mảng thuộc về chữ cái gần nó nhất, được định nghĩa là chữ cái có thể truy cập được trong số bước nhỏ nhất và / hoặc dọc - không có bước chéo. (Nếu một ô tương đương từ hai hoặc nhiều chữ cái gần nhất, thì nó thuộc về bất kỳ chữ cái nào trước tiên theo thứ tự bảng chữ cái. Một ô có chữ in hoa thuộc về chữ cái đó.) Ranh giới -cell là những chữ cái nằm ngang hoặc dọc liền kề với một hoặc nhiều ô không thuộc về chữ cái mà chúng thuộc về.

Viết chương trình con thủ tục với hành vi sau, tạo ra một loại sơ đồ Voronoi ...

Đầu vào : Bất kỳ chuỗi ASCII nào chỉ bao gồm các dấu chấm, chữ in hoa và dòng mới, sao cho khi được in, nó sẽ hiển thị một mảng hình chữ nhật của loại được mô tả ở trên, với các dấu chấm đóng vai trò là khoảng trắng.

Đầu ra : Một bản in của chuỗi đầu vào với mỗi ô ranh giới trống được thay thế bằng phiên bản chữ thường của chữ cái mà nó thuộc về. (Chương trình con thực hiện in.)

ví dụ 1

Đầu vào:

......B..
.........
...A.....
.........
.......D.
.........
.C.......
.....E...
.........

Đầu ra:

...ab.B..
....ab.bb
...A.abdd
aa...ad..
cca.ad.D.
..caeed..
.C.ce.edd
..ce.E.ee
..ce.....

Một bản phác thảo làm nổi bật các ranh giới:

Một bản phác thảo làm nổi bật các ranh giới

Ví dụ 2

Đầu vào:

............................U...........
......T.................................
........................................
.....................G..................
..R.......S..........F.D.E............I.
.........................H..............
.....YW.Z...............................
......X.................................
........................................
........................................
......MN...........V....................
......PQ................................
........................................
.............L...............J..........
........................................
........................................
....C...........K.......................
........................................
..................................A.....
...........B............................

Đầu ra:

..rt.....ts...sg......gduu..U.....ui....
..rt..T..ts...sg......gddeu......ui.....
...rt...ts....sg......gddeeu....ui......
....rttts.....sggggggGgdde.euuuui.......
..R.rywss.S....sfffffFdDdEeeeeeei.....I.
...ryywwzs.....sf....fddhHhhhhhhhi......
..ryyYWwZzs..sssffff.fddh.......hi......
..rxxxXxzzs.sllvvvvvffddh....hhhhi......
rrrxxxxnzzssl.lv....vfddh...hjjjjii.....
mmmmmmmnnnnnl.lv.....vvdh..hj....jai....
mmmmmmMNnnnnl.lv...V...vvhhj.....jaai...
ppppppPQqqql...lv.......vhj......ja.ai..
ppppp.pq.ql....lkv.....vjj.......ja..aii
cccccppqql...L.lkkv...vj.....J...ja...aa
.....cpqqlll..lk..kvvvvj........ja......
......cccbbbllk....kkkkj.......ja.......
....C...cb..bk..K......kj.....ja........
.......cb....bk........kjjjjjja.........
......cb......bk.......kaaaaaa....A.....
.....cb....B...bk......ka...............

Tăng cường màu sắc:

tăng cường màu sắc


1
+1; hấp dẫn; nhưng tôi nhận thấy rằng các ô trong đầu vào và đầu ra mẫu có một khoảng trống giữa mỗi ký tự. Đó có phải là một yêu cầu?
Doorknob

@DoorknobofSnow - Rất tiếc, lỗi của tôi - đó là ngoài ý muốn. Tôi sẽ chỉnh sửa để loại bỏ chúng.
res

Vì vậy, để rõ ràng đây là một sơ đồ số liệu Manhattan, không phải Euclide? Các sơ đồ Voronoi có thể khá tuyệt vời trong các không gian số liệu phi Euclide (xem tại đây hoặc kích hoạt Blender nếu bạn có một bản sao; nó có một số số liệu thú vị được tích hợp).
wchargein

@WChargin - Về cơ bản, vâng. Ở đây, "khoảng cách" giữa hai ô chỉ là số bước ít nhất cần thiết để đi từ ô này sang ô kia, chỉ bước giữa các ô nằm ngang hoặc dọc theo chiều dọc. (Nó luôn luôn là một số nguyên không âm.) Đây là số liệu taxi nếu chúng ta tưởng tượng các ô là giao lộ đường phố trong thành phố có đường có độ rộng bằng không và các khối là hình vuông đơn vị.
res

Câu trả lời:


5

GolfScript, 138 144 137 ký tự

:^n%,,{{^n/1$=2$>1<.'.'={;{@~@+@@+\{^3$?^<n/),\,@-abs@@-abs+99*+}++^'.
'-\$1<{32+}%}++[0..1.0..(.0]2/%..&,(\0='.'if}{@@;;}if}+^n?,%puts}/

Đầu vào được đưa cho chương trình con dưới dạng một chuỗi trên ngăn xếp. Thật không may, tôi đã phải sử dụng putsvì yêu cầu rằng thói quen phải in kết quả.

Giải thích về mã

Khối bên ngoài về cơ bản lặp trên tất cả các vị trí (x, y) theo kích thước của hình chữ nhật đầu vào. Trong vòng lặp, tọa độ x và y được để lại trên ngăn xếp mỗi lần. Sau khi mỗi dòng hoàn thành, kết quả được in ra bàn điều khiển.

:^              # save input in variable ^
n%,,{{          # split along newlines, count rows, make list [0..rows-1] 
    ???             # loop code, see below
}+^n?,%puts}/       # ^n?, count columns, make list [0..cols-1], loop and print

Mã được thực thi trong vòng lặp trước tiên lấy ký tự tương ứng của đầu vào.

^n/                 # split input into lines
1$=                 # select the corresponding row
2$>1<               # select the corresponding col

Sau đó, về cơ bản chúng tôi kiểm tra, nếu chúng tôi có một ., tức là nếu chúng tôi (có thể) phải thay thế nhân vật.

.'.'={              # if the character is '.'
    ;               # throw away the '.'
    ???             # perform more code (see below)
}{                  # else
    @@;;            # remove coordinates, i.e. keep the current character 
                    # (i.e. A, B, ... or \n)
}if                 # end if

Một lần nữa, mã bên trong bắt đầu bằng một vòng lặp, bây giờ trên tất cả các tọa độ (x, y) (x, y + 1) (x + 1, y) (x, y-1) (x-1, y)

{                   
    @~@+@@+\        # build coordinates x+dx, y+dy
    ???             # loop code
}++                 # push coordinates before executing loop code
[0..1.0..(.0]2/%    # loop over the coordinates [0 0] [0 1] [1 0] [0 -1] [-1 0]

Đoạn mã bên trong gần đây chỉ đơn giản trả về chữ cái (chữ thường) của điểm gần nhất, với hai tọa độ.

{                   # loop
    ^3$?^<          # find the current letter (A, B, ...) in the input string, 
                    # take anything before
    n/              # split at newlines
    ),              # from the last part take the length (i.e. column in which the letter is)
    \,              # count the number of lines remaining (i.e. row in which the letter is)
    @-abs@@-abs+    # calculate distance to the given coordinate x, y
    99*+            # multiply by 99 and add character value (used for sorting
                    # chars with equal distance)
}++                 # push the coordinates x, y
^'.
'-                  # remove '.' and newline
\$                  # now sort according to the code block above (i.e. by distance to letter)
1<{32+}%            # take the first one and make lowercase

Vì vậy, từ năm chữ cái gần nhất cho tọa độ (x, y) (x, y + 1) (x + 1, y) (x, y-1) (x-1, y) hãy lấy đầu tiên, nếu không phải tất cả đều bằng nhau, nếu không thì lấy a ..

.                   # copy five letter string
.&,(                # are there distinct letters?
\0=                 # first letter (i.e. nearest for coordinate x,y)
'.'                 # or dot
if                  # if command

Mã của bạn đã ổn với Ví dụ 1, vì vậy tôi đã rất ngạc nhiên khi nó đã thực hiện một số ô không chính xác trong Ví dụ 2: Trong mỗi ba dòng đầu tiên, nó đặt ".ui" trong đó "ui". nên, và trong dòng thứ tư, nó đặt "zs" trong đó "s." nên và đặt "ui" trong đó "i." nên, v.v.
res

@res Bỏ lỡ phần "bình đẳng - đầu tiên theo thứ tự bảng chữ cái". Thật không may, hoạt động sắp xếp không ổn định. Đã thêm một vài ký tự để sửa cái đó.
Howard

7

Python 3 - 424 422 417 332 295 ký tự:

def v(s):
 w=s.find("\n")+1;n=(-1,1,-w,w);r=range(len(s));x=str.replace;s=x(x(s,*".~"),*"\n~")+"~"*w;t=0
 while s!=t:t=s;s=[min(s[i+j]for j in n).lower()if"~"==s[i]and(i+1)%w else s[i]for i in r]+["~"]*w
 print(x("".join(s[i]if any(s[i]!=s[i+j].lower()!="~"for j in n)else"."for i in r),*"~\n"))

Có ba phần, mỗi phần cần nằm trên một dòng riêng do cú pháp của Python:

  1. Dòng đầu tiên thiết lập các biến. wlà chiều rộng của một hàng của bảng (bao gồm cả dòng mới ở cuối, sẽ được tái chế dưới dạng cột đệm). rlà một rangeđối tượng lập chỉ mục tất cả các ký tự trong s. nlà một bộ bù chỉ mục để lấy hàng xóm của một ký tự (vì vậy nếu bạn muốn cho phép các chữ cái trải ra theo đường chéo, bạn chỉ cần thêm -w-1,-w+1,w-1,w+1vào bộ dữ liệu). xlà một tên viết tắt của str.replacephương thức, được sử dụng nhiều lần trong mã sau này (các cuộc gọi sẽ trông kỳ lạ, vì tôi sử dụng x(s,*"xy")để lưu các ký tự, thay vì thông thường s.replace("x", "y")). Chuỗi stham số cũng được sửa đổi một chút vào thời điểm này, với các .ký tự và dòng mới được thay thế bởi~ký tự (vì chúng sắp xếp sau tất cả các chữ cái). Các ~ký tự đệm có giá trị của một hàng cũng được thêm vào cuối. tsau này sẽ được sử dụng làm tài liệu tham khảo cho phiên bản "cũ" s, nhưng nó cần được khởi tạo thành một cái gì đó không bằng slúc bắt đầu và không chỉ có một ký tự (giá trị Pythonic sẽ cao hơn None, nhưng đó là ba ký tự phụ) .
  2. Dòng thứ hai có một vòng lặp liên tục cập nhật sbằng cách sử dụng một danh sách hiểu. Khi sự hiểu biết lặp đi lặp lại qua các chỉ số của s, các ~ký tự được thay thế bởi các minhàng xóm của họ. Nếu một ~nhân vật bị bao vây hoàn toàn bởi các ~s khác , điều này sẽ không làm gì cả. Nếu nó nằm cạnh một hoặc nhiều chữ cái, nó sẽ trở thành nhỏ nhất trong số chúng (thiên "a"về hơn "b", v.v.). Các dòng mới được chuyển thành ~ký tự được giữ nguyên bằng cách phát hiện các chỉ mục của chúng bằng toán tử mô đun. Hàng đệm ở cuối không được cập nhật trong phần hiểu danh sách (vì phạm vi chỉ mục r, đã được tính trước khi chúng được thêm vào s). Thay vào đó, một hàng mới~các ký tự được thêm vào sau khi hiểu được thực hiện. Lưu ý rằng strở thành một danh sách các ký tự chứ không phải là một chuỗi sau lần đầu tiên của vòng lặp (nhưng vì Python linh hoạt về các loại nên chúng ta vẫn có thể lập chỉ mục để lấy các ký tự theo cùng một cách).
  3. Dòng cuối cùng làm nổi bật bên trong sơ đồ và xây dựng lại các ký tự thành một chuỗi sẽ được in. Đầu tiên, bất kỳ chữ cái nào được bao quanh chỉ bởi các bản sao khác của chính nó (hoặc các ~ký tự từ phần đệm) sẽ được thay thế bằng .. Tiếp theo, tất cả các ký tự được nối với nhau thành một chuỗi. Cuối cùng, các ~ký tự đệm được chuyển đổi trở lại dòng mới và chuỗi được in.

Có lẽ r=rangephải nằm trong thân hàm để được coi là một phần của thủ tục có thể gọi được, nhưng bạn có thể lưu các ký tự bằng cách viết r=range;s=[l.replace. Bạn cũng có thể bóp ra nhân vật hơn bằng cách viết if"~"==s[y][x]elseif"~"==s[y][x]else, với tổng số 422. (Btw, ran này cho tôi với Python 2.7)
res

@res: Cảm ơn những lời đề nghị đó. Tôi đã đặt r=rangeở cuối dòng đầu tiên của hàm (nơi tôi thiết lập các biến khác) và xóa đi một vài khoảng trắng mà tôi đã bỏ lỡ trước đó. Tôi không chắc chắn nếu tôi có cả hai người bạn đang đề cập đến, vì dường như bạn đã đề cập đến điều tương tự hai lần. Và, trong Python 2.7, nó có thể ngắn hơn hai ký tự, vì bạn không cần dấu ngoặc đơn sau print(thường chỉ lưu 1 ký tự, nhưng print"\n".join(...)hoạt động).
Blckknght

Rất tiếc, tôi đã dán sai thứ hai. Nó được cho là s[y][x]for(xóa một khoảng trắng), nhưng dường như bạn vẫn tìm thấy nó.
res

Đúng, đó là cái khác tôi có. Tôi chỉ quyết định thử một thay đổi lớn hơn và đi đến danh sách 1d thay vì 2d, hóa ra là để cứu một loạt các nhân vật!
Blckknght

3

Python, 229 226 ký tự

def F(s):
 e,f,b='~.\n';N=s.index(b)+1;s=s.replace(f,e)
 for i in 2*N*e:s=''.join(min([x[0]]+[[y.lower()for y in x if y>b],all(y.lower()in f+b+x[0]for y in x)*[f]][x[0]!=e])for x in zip(s,s[1:]+b,s[N:]+b*N,b+s,b*N+s))
 print s

F("""......B..
.........
...A.....
.........
.......D.
.........
.C.......
.....E...
.........
""")

Liệu một lũ lấp để tính kết quả. Dấu for/ zipkết hợp tạo ra một mảng xcho mỗi ô chứa giá trị trong ô đó và bốn ô lân cận. Sau đó, chúng tôi sử dụng thủ thuật của Blckknght và minmột loạt các khả năng cho mỗi ô. Đó là các giá trị ô ban đầu, bất kỳ hàng xóm nào nếu ô chưa được truy cập hoặc .nếu nó đã được truy cập và tất cả các lân cận đều .hoặc bằng chính ô đó.


Vì chương trình con được cho là thực hiện in ấn, bạn chỉ có thể thay đổi return sthành print s. Ngoài ra, không y!=bthể thay đổi thành y>b? Điều đó sẽ tạo ra 226 ký tự, tôi nghĩ vậy.
res

3

Nó đây rồi Đây là chương trình F # đầu tiên của tôi. Nếu tôi bỏ lỡ một tính năng của ngôn ngữ, xin vui lòng thông báo cho tôi vì tôi vẫn đang học.

Đây là đầu vào mẫu của tôi

 . . . . . . . . . . . . . . . . . . . . . . . . .
 . . . . . . . . . . . . B . . . . . . . . . . . .
 . . . . . . . . . . . . . . . . . . . . . . . . .
 . . . . . . . . A . . . . . . . . . . . . . . . .
 . . . . . . . . . . . . . . . . . . . . . . . . .
 . . . . . . . . . . . . . . . . C . . . . . . . .
 . . . . . . . . . . . . . . . . . . . . . . . . .
 . . . . . . . . . . . . . . . . . . . G . . . . .
 . . . . . . . D . . . . . . . . . . . . . . . . .
 . . . . . . . . F . . . . . . . . . . . . . . . .
 . . . . . . . E . . . . . . . . . . . . . . . . .
 . . . . . . . . . . . . . . . . . . . . . . . . .
 . . . . . . . . . . . . . . . . . . . . . . . . .
 . . . . . . . . . . . . . . . . . . . . . . . . .

Đây là đầu ra

 . . . . . . . . . a b . . . . . . . b g . . . . .
 . . . . . . . . . a b . B . . . b b b g . . . . .
 . . . . . . . . . . a b . . . b c c c g . . . . .
 . . . . . . . . A . . a b . b c . . c g . . . . .
 . . . . . . . . . . . a b b c . . . c g . . . . .
 a a a a a a a a . . . a b c . . C . c g . . . . .
 d d d d d d d d a a a a b c . . . c g . . . . . .
 . . . . . . . . d d d d b c . . c g . G . . . . .
 . . . . . . . D d d d d d c . . c g . . . . . . .
 d d d d d d d d f f f f f f c . c g . . . . . . .
 e e e e e e e e e e e e e e c . c g . . . . . . .
 . . . . . . . . . . . . . e c . c g . . . . . . .
 . . . . . . . . . . . . . e c . c g . . . . . . .
 . . . . . . . . . . . . . e c . c g . . . . . . .

Đây là mã. Thưởng thức.

// The first thing that we need is some data. 
let originalData = [
     "........................."
     "............B............" 
     "........................." 
     "........A................" 
     "........................." 
     "................C........"          
     "........................." 
     "...................G....." 
     ".......D................." 
     "........F................"           
     ".......E................."          
     "........................."
     "........................."
     "........................."
     ]

Bây giờ chúng ta cần chuyển đổi dữ liệu đó thành một mảng hai chiều để chúng ta có thể truy cập nó thông qua các bộ chỉ mục.

let dataMatrix = 
    originalData
    |> List.map (fun st -> st.ToCharArray())
    |> List.toArray

// We are going to need a concept of ownership for each
// cell. 
type Owned = 
    | Unclaimed
    | Owner of char
    | Claimed of char
    | Boundary of char

Chúng ta hãy tạo một ma trận thể hiện quyền sở hữu của mỗi ô

let claims =
    dataMatrix
    |> Array.map (fun row ->
        row
        |> Array.map (function
            | '.' -> Owned.Unclaimed
            | ch -> Owned.Owner(ch))
        )

Hãy để chúng tôi có một phương pháp tiện ích để xem những gì đã xảy ra.

let printIt () =
    printfn ""
    claims
    |> Array.iter (fun row ->
        row |> Array.iter (function
            | Owned.Claimed(ch) -> printf " ." 
            | Owned.Owner(ch) -> printf " %c" ch
            | Owned.Boundary(ch) -> printf " %c" ch
            | _ -> printf " ." )
        printfn "")            

Hãy để chúng tôi tạo một bản ghi để thể hiện nơi một chữ in hoa cụ thể cư trú.

type CapitalLocation = { X:int; Y:int; Letter:char }

Bây giờ chúng tôi muốn tìm tất cả các chữ in hoa.

let capitals = 
    dataMatrix
    |> Array.mapi (fun y row -> 
        row 
        |> Array.mapi (fun x item -> 
            match item with
            | '.' -> None
            | _ -> Some({ X=x; Y=y; Letter=item }))
        |> Array.choose id
        |> Array.toList
        )
    |> Array.fold (fun acc item -> item @ acc) List.empty<CapitalLocation>
    |> List.sortBy (fun item -> item.Letter)

Khi chúng ta di chuyển, chúng ta cần một khái niệm về hướng.

type Direction =
    | Left = 0
    | Up = 1
    | Right = 2
    | Down = 3   

// Function gets the coordinates of the adjacent cell. 
let getCoordinates (x, y) direction =
    match direction with
    | Direction.Left -> x-1, y
    | Direction.Up -> x, y-1
    | Direction.Right -> x+1, y
    | Direction.Down -> x, y+1
    | _ -> (-1,-1) // TODO: Figure out how to best throw an error here. 

Khi chúng ta di chuyển, chúng ta sẽ cần phải biết về kích thước. Điều này sẽ giúp chúng tôi theo dõi xem chúng tôi có di chuyển ra khỏi giới hạn hay không.

type Size = { Width:int; Height: int }    

// Get the size of the matrix. 
let size = {Width=originalData.Head.Length; Height=originalData.Length}

Mô hình hoạt động: khớp với tiêu chí của một ô đã cho.

let (|OutOfBounds|UnclaimedCell|Claimed|Boundary|) (x,y) =
    match (x,y) with 
    | _,_ when x < 0 || y < 0 -> OutOfBounds
    | _,_ when x >= size.Width || y >= size.Height -> OutOfBounds
    | _ ->                     
        match claims.[y].[x] with
        | Owned.Unclaimed -> UnclaimedCell(x,y)
        | Owned.Claimed(ch) -> Claimed(x,y,ch)
        | Owned.Boundary(ch) -> Boundary(x,y,ch)
        | Owned.Owner(ch) -> Claimed(x,y,ch)

Bây giờ chúng tôi đang giảm thuế đồng. Điều này tuyên bố tế bào!

let claimCell letter (x, y) =         
    // Side effect: Change the value of the cell
    (claims.[y].[x] <- Owned.Claimed (System.Char.ToLower letter)) |> ignore

Sử dụng mẫu đang hoạt động, xác nhận ô này nếu không được yêu cầu và trả về tọa độ của các ô liền kề.

let claimAndReturnAdjacentCells (letter, coordinates, direction) =
    match coordinates with 
    | UnclaimedCell (x,y) ->         
        // Claim it and return the Owned object.
        claimCell letter coordinates // meaningful side effect
        // use Direction as int to allow math to be performed. 
        let directionInt = int direction;            
        Some(
            // [counter-clockwise; forward; clockwise]
            [(directionInt+3)%4; directionInt; (directionInt+1)%4]                 
            |> List.map enum<Direction>                 
            |> List.map (fun newDirection -> 
                (
                    letter, 
                    getCoordinates coordinates newDirection, 
                    newDirection
                ))
        )
    | Claimed(cx,cy,cch) when cch <> System.Char.ToLower letter-> 
        // If we find a "Claimed" element that is not our letter, we have 
        // hit a boundary. Change "Claimed" to "Boundary" and return the 
        // element that led us to evaluating this element. It is also a 
        // boundary. 
        (claims.[cy].[cx] <- Owned.Boundary (System.Char.ToLower cch)) |> ignore
        let reverseDirection = enum<Direction>(((int direction)+2)%4)
        Some[(
            cch,
            getCoordinates (cx, cy) reverseDirection,
            reverseDirection
        )]
    | _ -> None

Chúng tôi đang bắt đầu tạo danh sách của túi dữ liệu này, hãy để chúng tôi tạo một loại để làm cho mọi thứ rõ ràng hơn.

type CellClaimCriteria = (char * (int * int) * Direction)

Đưa ra một danh sách các tiêu chí để yêu cầu các ô, chúng tôi sẽ lặp lại danh sách trả về các ô tiếp theo để yêu cầu và lặp lại vào danh sách đó.

let rec claimCells (items:CellClaimCriteria list) =
    items
    |> List.fold (fun acc item ->
        let results = claimAndReturnAdjacentCells item 
        if Option.isSome(results) 
        then (acc @ Option.get results) 
        else acc
        ) List.empty<CellClaimCriteria> 
    |> (fun l ->            
        match l with
        | [] -> []
        | _ -> claimCells l)

Đối với mỗi thủ đô, hãy tạo một tiêu chí yêu cầu theo từng hướng và sau đó yêu cầu đệ quy các ô đó.

let claimCellsFromCapitalsOut ()=
    capitals
    |> List.fold (fun acc capital ->
        let getCoordinates = getCoordinates (capital.X, capital.Y)
        [Direction.Left; Direction.Up; Direction.Right; Direction.Down]
        |> List.map (fun direction ->                
            (
                capital.Letter, 
                getCoordinates direction, 
                direction
            ))
        |> (fun items -> acc @ items)) List.empty<CellClaimCriteria>
    |> claimCells

Mỗi chương trình cần một chính.

[<EntryPoint>]
let main args = 
    printIt()
    claimCellsFromCapitalsOut()
    printIt()
    0

Hoàn thành tốt để có được một giải pháp làm việc bằng ngôn ngữ mà bạn không quen thuộc. Tuy nhiên, bạn đã bỏ lỡ bước cuối cùng: đây là môn đánh gôn , có nghĩa là mục đích là viết chương trình ngắn nhất có thể: số nhận dạng ký tự đơn, chỉ khoảng trắng được yêu cầu nghiêm ngặt để biên dịch, v.v.
Peter Taylor

3
PeterTaylor bạn đúng. Tôi bỏ lỡ điều đó. Trang web này cần nhiều "Câu đố lập trình" và ít "Code Golf" hơn.
Phillip Scott Givens
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.