Hình dung ước số chung lớn nhất


28

Lý lịch

Ước số chung lớn nhất ( viết tắt là gcd ) là một hàm toán học thuận tiện, vì nó có nhiều tính chất hữu ích. Một trong số đó là danh tính của Bézout : nếu d = gcd(a, b), thì tồn tại số nguyên xynhư vậy d = x*a + y*b. Trong thử thách này, nhiệm vụ của bạn là trực quan hóa tài sản này bằng nghệ thuật ASCII đơn giản.

Đầu vào

Đầu vào của bạn là hai số nguyên dương ab, được đưa ra ở bất kỳ định dạng hợp lý nào. Bạn cũng có thể sử dụng các đầu vào đơn nhất (lặp lại một ký tự ASCII có thể in duy nhất theo lựa chọn của bạn), nhưng bạn phải nhất quán và sử dụng cùng một định dạng cho cả hai đầu vào. Các đầu vào có thể theo thứ tự bất kỳ, và chúng có thể bằng nhau.

Đầu ra

Đầu ra của bạn là một chuỗi sđộ dài lcm(a, b) + 1( lcm là viết tắt của bội số chung thấp nhất). Các ký tự sđại diện cho số nguyên từ 0đến lcm(a, b). Ký tự s[i]là chữ thường onếu ilà bội số của ahoặc b, và một khoảng thời gian .khác. Lưu ý rằng số 0 là bội số của mọi số. Bây giờ, vì bản sắc Bézout của, sẽ có ít nhất một cặp nhân vật otrong scó khoảng cách là chính xác gcd(a, b). Cặp ngoài cùng bên trái sẽ được thay thế bằng chữ hoa O; đây là đầu ra cuối cùng

Thí dụ

Hãy xem xét các đầu vào a = 4b = 6. Sau đó, chúng tôi có gcd(a, b) = 2lcm(a, b) = 12, do đó, chiều dài ssẽ được 13. Bội số của abđược tô sáng như sau:

0  1  2  3  4  5  6  7  8  9 10 11 12
o  .  .  .  o  .  o  .  o  .  .  .  o

Có hai cặp os có khoảng cách hai, nhưng chúng ta sẽ chỉ thay thế các cặp ngoài cùng bằng Os, vì vậy đầu ra cuối cùng là

o...O.O.o...o

Quy tắc và tính điểm

Bạn có thể viết một chương trình đầy đủ hoặc một chức năng. Số byte thấp nhất sẽ thắng và các sơ hở tiêu chuẩn không được phép.

Các trường hợp thử nghiệm

 1  1 -> OO
 2  2 -> O.O
 1  3 -> OOoo
 4  1 -> OOooo
 2  6 -> O.O.o.o
 2  3 -> o.OOo.o
10  2 -> O.O.o.o.o.o
 4  5 -> o...OO..o.o.o..oo...o
 8  6 -> o.....O.O...o...o.o.....o
12 15 -> o...........O..O........o.....o.....o........o..o...........o
19 15 -> o..............o...o..........o.......o......o...........o..o..............OO.............o....o.........o........o.....o............o.o..............o.o............o.....o........o.........o....o.............oo..............o..o...........o......o.......o..........o...o..............o

1
Khi lấy đầu vào unary, chúng ta có thể chọn bất kỳ ký tự nào không? (Cụ thể, làm thế nào về ., ohoặc O.) Hoặc nó phải được 1? Hay là 0?
Martin Ender

1
@ MartinBüttner Nó có thể là bất kỳ ký tự nào, miễn là bạn nhất quán và sử dụng cùng một định dạng cho cả hai đầu vào.
Zgarb

2
Tôi ngạc nhiên khi bạn không sử dụng 3 và 5 như một trong những trường hợp thử nghiệm của bạn.
Neil

Tôi có thể sử dụng buildin không?
Akangka

@ChristianIrwan Có, tất cả các phần dựng sẵn đều được cho phép.
Zgarb

Câu trả lời:


7

Jolf, 52 byte

on*'.wm9jJΡR m*Yhm8jJDN?<*%Sj%SJ1'o'.}"'o%o"n"O%O"n

Tôi sẽ chia mã này thành hai phần.

on*'.wm9jJ
on         set n
  *'.       to a dot repeated
      m9jJ  the gcd of two numeric inputs

ΡR m*Yhm8jJDN?<*%Sj%SJ1'o'.}"'o%o"n"O%O"n
    *Y                                    multiply (repeat) Y (Y = [])
      hm8jJ                                by the lcm of two inputs + 1
  _m       DN              }              and map the array of that length
             ?<*%Sj%SJ1'o'.               "choose o if i%a*(i%b)<1; otherwise choose ."
 R                          "'            join by empty string
Ρ                            'o%o"n        replace once (capital Rho, 2 bytes): "o"+n+"o"
                                   "O%O"n   with "O"+n+"O"
                                          implicit printing

Hãy thử nó ở đây!


Ngắn hơn mọi thứ khác cho đến nay. : P
Rɪᴋᴇʀ

1
@RikerW Vâng! Tôi hy vọng Jolf cuối cùng sẽ chiến thắng, một lần.
Conor O'Brien

10

Julia, 111 110 107 103 96 byte

f(a,b)=replace(join([i%a*(i%b)<1?"o":"."for i=0:lcm(a,b)]),"o$(d="."^(gcd(a,b)-1))o","O$(d)O",1)

Đây là một hàm chấp nhận hai số nguyên và trả về một chuỗi.

Ung dung:

function f(a::Int, b::Int)
    # Construct an array of dots and o's
    x = [i % a * (i % b) < 1 ? "o" : "." for i = 0:lcm(a, b)]

    # Join it into a string
    j = join(x)

    # Replace the first pair with distance gcd(a, b) - 1
    replace(j, "o$(d = "."^(gcd(a, b) - 1))o", "O$(d)O", 1) 
end

Đã lưu một byte nhờ nimi!


10

Võng mạc , 112 109 99 94 91 byte

^
. 
+r`(?<!^\1+). (.+) 
$'$0
.(?=.* (.+) (.+))(?=\1* |\2* )
o
o(\.*)o((\1\.*o)*) .*
O$1O$2

Không phải là rất cạnh tranh, tôi nghĩ, nhưng lý thuyết số trong Retina luôn khá thú vị. :)

Lấy đầu vào là số unary sử dụng .như là chữ số unary.

Hãy thử trực tuyến.

Giải trình

^
. 

Điều này chèn một .và một khoảng trắng ở phía trước của đầu vào. Điều này cuối cùng sẽ trở thành đầu ra.

+r`(?<!^\1+). (.+) 
$'$0

Điều này chuẩn bị LCM của abcho chuỗi. Vì chúng tôi đã có .ở đó, chúng tôi sẽ kết thúc với lcm(a,b)+1. Điều này được thực hiện bằng cách liên tục trả trước bmiễn là akhông phân chia tiền tố mới này. Chúng tôi nắm bắt athành một nhóm và sau đó kiểm tra xem chúng tôi có thể đạt đến điểm bắt đầu của chuỗi hay không bằng cách khớp với việc bắt giữ đó ít nhất một lần. bsau đó được chèn vào chuỗi thông qua việc hiếm khi được sử dụng $'để chèn mọi thứ sau khi khớp vào thay thế.

.(?=.* (.+) (.+))(?=\1* |\2* )
o

Cái này khớp với các ký tự tại các vị trí được chia cho ahoặc b. Nó sử dụng thực tế là kết quả là đối xứng: vì lcm(a,b)được chia cho cả hai abđi sang trái bằng cách trừ các trường hợp ahoặc bmang lại cùng một mô hình như đi ngay từ 0khi thêm chúng. Cái nhìn đầu tiên chỉ đơn giản là chụp ab. Cái nhìn thứ hai kiểm tra rằng có nhiều bội số của mỗi ahoặc bký tự trước khoảng trắng đầu tiên.

o(\.*)o((\1\.*o)*) .*
O$1O$2

Như đã nêu trên Wikipedia, ngoài danh tính của Bézout, cũng đúng là

Ước số chung lớn nhất dlà số nguyên dương nhỏ nhất có thể được viết là ax + by.

Điều này ngụ ý rằng GCD sẽ tương ứng với khoảng cách ngắn nhất giữa hai os trong đầu ra. Vì vậy, chúng tôi không phải bận tâm tìm GCD. Thay vào đó chúng tôi chỉ tìm kiếm ví dụ đầu tiên của khoảng cách ngắn nhất. o(\.*)okhớp với một khoảng cách ứng cử viên và thu được chiều rộng của nó vào nhóm 1. Sau đó, chúng tôi cố gắng đạt được khoảng trống đầu tiên bằng cách xen kẽ giữa độ phản hồi của nhóm 1 và os (với các .s bổ sung tùy chọn ). Nếu có một khoảng cách ngắn hơn về phía bên phải, điều này sẽ không khớp, bởi vì chúng ta không thể vượt qua khoảng cách đó với độ phản hồi. Ngay khi tất cả các khoảng trống xa hơn ít nhất là rộng như hiện tại, điều này phù hợp. Chúng tôi nắm bắt phần cuối của chuỗi LCM vào nhóm 2 và khớp phần còn lại của chuỗi với .*. Chúng tôi viết lại chữ hoaOs (với khoảng cách ở giữa) cũng như phần còn lại của chuỗi LCM, nhưng loại bỏ mọi thứ bắt đầu từ khoảng trắng, để loại bỏ abtừ kết quả cuối cùng.


Tôi không biết nhiều về lý thuyết số Retina, nhưng sẽ không đặt ký tự đầu vào thành thứ gì đó không yêu cầu thoát byte lưu? Tức là (\.*)=>(a*)
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Có, nhưng sau đó tôi sẽ phải thay thế nó bằng cái .sau, tốn bốn byte (và thoát khỏi các lối thoát chỉ tiết kiệm được 3).
Martin Ender

Ồ Mát mẻ! Câu trả lời rất thú vị.
Conor O'Brien

5

, 50 ký tự / 90 byte

⩥Мū⁽îí+1)ⓜ$%î⅋$%í?⍘.:⍘o)⨝ċɼ(`o⦃⍘.ĘМũ⁽îí-1)}o”,↪$ú⬮

Try it here (Firefox only).

Phải có một cách để chơi golf này hơn nữa!

Giải trình

Đây là một thuật toán hai pha cơ bản. Nó thực sự khá đơn giản.

Giai đoạn 1

⩥Мū⁽îí+1)ⓜ$%î⅋$%í?⍘.:⍘o)⨝

Đầu tiên, chúng tôi tạo một phạm vi từ 0 đến LCM + 1. Sau đó, chúng tôi ánh xạ qua nó, kiểm tra xem một trong hai đầu vào có phải là một yếu tố của mặt hàng hiện tại trong phạm vi không. Nếu vậy, chúng tôi thay thế mục đó bằng một o; mặt khác, chúng tôi thay thế nó bằng một. . Tham gia nó cho chúng ta một loạt các dấu chấm và dấu chấm mà chúng ta có thể chuyển sang giai đoạn hai.

Giai đoạn 2

ċɼ(`o⦃⍘.ĘМũ⁽îí-1)}o”,↪$ú⬮

Đây chỉ là một chức năng thay thế lớn. Một regex được tạo như là o[dots]o, trong đó số lượng điểm được xác định bởi GCD-1. Vì regex này không phải là toàn cầu, nên nó sẽ chỉ phù hợp với lần xuất hiện đầu tiên. Sau đó, trận đấu được thay thế bằng O[dots]Ocách sử dụng hàm toUpperCase.


3

MATL , 72 byte

Sử dụng phiên bản 6.0.0 , sớm hơn thử thách này. Mã này chạy trong Matlab và Octave.

2$tZm1+:1-bbvtbw\A~otbZ}ZdXK1+ltb(3X53$X+1K2$lh*t2=f1)tK+hwg1+Ib('.oO'w)

Thí dụ

>> matl
 > 2$tZm1+:1-bbvtbw\A~otbZ}ZdXK1+ltb(3X53$X+1K2$lh*t2=f1)tK+hwg1+Ib('.oO'w)
 > 
> 1
> 1
OO

>> matl
 > 2$tZm1+:1-bbvtbw\A~otbZ}ZdXK1+ltb(3X53$X+1K2$lh*t2=f1)tK+hwg1+Ib('.oO'w)
 > 
> 2
> 3
o.OOo.o

>> matl
 > 2$tZm1+:1-bbvtbw\A~otbZ}ZdXK1+ltb(3X53$X+1K2$lh*t2=f1)tK+hwg1+Ib('.oO'w)
 > 
> 12
> 15
o...........O..O........o.....o.....o........o..o...........o

Giải trình

Tôi không biết làm thế nào nó hoạt động. Tôi chỉ gõ các ký tự ngẫu nhiên. Tôi nghĩ rằng có một số chập liên quan.

Chỉnh sửa: Hãy thử trực tuyến! Mã trong liên kết đã được sửa đổi một chút để phù hợp với những thay đổi trong ngôn ngữ (kể từ ngày 2 tháng 6 năm 2016).


Bạn không thể gõ chương trình 72 byte một cách ngẫu nhiên. Sẽ tính xác suất sau (sau khi ngủ và HÀNH ĐỘNG một lúc)
CalculatorFeline

2

Japt , 83 byte

'.pD=U*V/(C=(G=@Y?G$($YX%Y :X} $($UV)+1 £Y%U©Y%V?".:o"} $.replace($E=`o{'.pC-1}o`Eu

Chưa chơi gôn hoàn toàn ... Và không muốn chơi gôn: /


Bạn có thể không sử dụng rthay $.replace($thế?
Sản phẩm ETH

@Eth Tôi chưa tìm ra cách thay thế mà không có cờ g, vì vậy không, tôi không thể.
nicael

2

Javascript, 170 164 161 153 145 141 136 byte

(a,b)=>[...Array(a*b/(c=(g=(a,b)=>b?g(b,a%b):a)(a,b))+1)].map((x,i)=>i%a&&i%b?'.':'o').join``.replace(`o${e='.'.repeat(c-1)}o`,`O${e}O`)

Đó là khá lggnggggg ....

Demo , các biến được xác định rõ ràng bởi vì trình thông dịch sử dụng chế độ nghiêm ngặt.


Hãy thử thay thế i%a<1||i%b<1?'o':'.'bằngi%a&&i%b?'.':'o'
Mama Fun Roll

Ồ vâng, tôi nghĩ bạn có thể bí danh tham gia.
Mama Fun Roll

@ Nɟuɐɯɹɐ ן oɯ cảm ơn, cũng thay thế các mảng bằng lặp lại đơn giản.
nicael

Ồ, vậy thì trong trường hợp đó, có lẽ bạn không nên bí danh tham gia trừ khi bạn có 3 lần xuất hiện.
Mama Fun Roll

[...Array((d=a*b/(c=(g=(a,b)=>b?g(b,a%b):a)(a,b)))+1).keys()].map(i=>i%a&&i%b?'.':'o')giúp bạn tiết kiệm hai byte. (Tôi cũng đã thử sử dụng lập chỉ mục chuỗi để tạo '.' Và 'o' nhưng điều đó thực sự tốn hai byte.)
Neil

1

Python 2, 217 200 191 byte

Đây là một chút cùn, nhưng nó hoạt động. Bất kỳ mẹo chơi gôn nào cũng được đánh giá cao, đặc biệt là nếu bạn biết cách khắc phục s[i] = s[v] = "o"vấn đề mà tôi gặp phải, nơi điều đó sẽ ghi đè lên "O" s Got it!

g=lambda a,b:b and g(b,a%b)or a
def f(a,b):
 h=g(a,b);x=1+a*b/h;s=["."]*x;v=k=0
 for i in range(x):
    if(i%a)*(i%b)<1:
     if k:s[i]="o"
     else:k=i==h+v;s[i]=s[v]="oO"[k]
     v=i
 return''.join(s)

Ung dung:

def gcd(a,b):                           # recursive gcd function
    if b:
        return g(b,a%b)
    else:
        return a
def f(a,b):
    h = gcd(a,b)
    x = 1 + a*b/h                       # 1 + lcm(a,b)
    s = ["."] * x
    v = 0
    k = 0
    for i in range(x):
        if i%a == 0 and i % b == 0:
            if k == 0:
                k = (i == h+v)          # correct distance apart?
                if k:                   # if "O" just found
                    s[i] = s[v] = "O"
                else:
                    s[i] = s[v] = "o"
            else:
                s[i] = "o"              # if "O" already found, always "o"
            v = i                       # If we found an "o" or an "O", i is the new v
    return ''.join(s)
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.