เห็นภาพตัวหารร่วมมาก


28

พื้นหลัง

ตัวหารทั่วไปที่ยิ่งใหญ่ที่สุด ( gcdสำหรับระยะสั้น) เป็นฟังก์ชันทางคณิตศาสตร์ที่สะดวกเนื่องจากมีคุณสมบัติที่มีประโยชน์มากมาย หนึ่งในนั้นคือเอกลักษณ์ของเบซู : ถ้าd = gcd(a, b)แล้วมีอยู่ integers xและเช่นว่าy d = x*a + y*bในความท้าทายนี้งานของคุณคือการเห็นภาพคุณสมบัตินี้ด้วยศิลปะ ASCII แบบง่าย

อินพุต

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

เอาท์พุต

ผลลัพธ์ของคุณคือสตริงที่มีsความยาวlcm(a, b) + 1( lcmหมายถึงตัวคูณสามัญต่ำสุด) ตัวละครของsแทนจำนวนเต็มจากไป0 lcm(a, b)ตัวละครs[i]เป็นตัวพิมพ์เล็กoถ้าiเป็นหลายaหรือbและเป็นระยะเวลา.อื่น โปรดทราบว่าศูนย์เป็นจำนวนมากของทุกหมายเลข ตอนนี้เพราะเอกลักษณ์ของเบซูจะมีอย่างน้อยหนึ่งคู่ของตัวละครoในที่มีระยะทางตรงs gcd(a, b)คู่ซ้ายสุดดังกล่าวจะถูกแทนที่ด้วยตัวพิมพ์ใหญ่Os นี่คือผลลัพธ์สุดท้าย

ตัวอย่าง

พิจารณาปัจจัยการผลิตและa = 4 b = 6แล้วเรามีgcd(a, b) = 2และlcm(a, b) = 12เพื่อให้ความยาวของจะs 13ทวีคูณของaและbมีการเน้นดังต่อไปนี้:

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

มีสองคู่oที่มีระยะทางสอง แต่เราจะแทนที่คนซ้ายสุดด้วยOs เท่านั้นดังนั้นผลลัพธ์สุดท้ายคือ

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

กฎและการให้คะแนน

คุณสามารถเขียนโปรแกรมเต็มรูปแบบหรือฟังก์ชั่น จำนวนไบต์ต่ำสุดที่ชนะและช่องโหว่มาตรฐานไม่ได้รับอนุญาต

กรณีทดสอบ

 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
เมื่อทำการป้อนข้อมูลแบบเอกนารีเราสามารถเลือกตัวละครใด ๆ ได้หรือไม่? (โดยเฉพาะอย่างยิ่งวิธีการเกี่ยวกับ., oหรือO.) หรือไม่ก็จะต้องมี1? หรือ0?
Martin Ender

1
@ MartinBüttnerมันอาจเป็นตัวละครใดก็ได้ตราบใดที่คุณสอดคล้องและใช้รูปแบบเดียวกันสำหรับอินพุตทั้งสอง
Zgarb

2
ฉันประหลาดใจที่คุณไม่ได้ใช้ 3 และ 5 เป็นหนึ่งในกรณีทดสอบของคุณ
Neil

ฉันสามารถใช้ buildin ได้ไหม?
Akangka

@ChristianIrwan ใช่ตัวในทั้งหมดได้รับอนุญาต
Zgarb

คำตอบ:


7

Jolf, 52 ไบต์

on*'.wm9jJΡR m*Yhm8jJDN?<*%Sj%SJ1'o'.}"'o%o"n"O%O"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

ลองที่นี่!


สั้นลงกว่าทุกสิ่งทุกอย่าง : P
Rɪᴋᴇʀ

1
@RikerW ใช่! ฉันหวังว่า Jolf จะชนะในที่สุดครั้งเดียว
Conor O'Brien

10

Julia, 111 110 107 103 96 ไบต์

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)

นี่คือฟังก์ชั่นที่รับจำนวนเต็มสองจำนวนและส่งคืนสตริง

Ungolfed:

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

บันทึกเป็นไบต์ด้วย nimi!


10

เรติน่า , 112 109 99 94 91 ไบต์

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

ฉันคิดว่ามันไม่ได้มีการแข่งขันสูงนัก แต่ทฤษฎีจำนวนใน Retina นั้นค่อนข้างสนุก :)

รับอินพุตเป็นตัวเลขแบบเอกนารีโดยใช้.เป็นตัวเลขแบบเอกนารี

ลองออนไลน์

คำอธิบาย

^
. 

สิ่งนี้จะแทรก a .และช่องว่างด้านหน้าอินพุต สิ่งนี้จะกลายเป็นผลลัพธ์ในที่สุด

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

สิ่งนี้เป็นการเตรียม LCM ของaและbให้กับสตริง เนื่องจากเรามีอยู่แล้วที่นั่นเราจะจบลงด้วย. lcm(a,b)+1สิ่งนี้สามารถทำได้โดยการเพิ่มซ้ำbอย่างต่อเนื่องตราบaใดที่ไม่หารคำนำหน้าใหม่นี้ เราจับภาพaเป็นกลุ่มหนึ่งแล้วตรวจสอบว่าเราสามารถไปถึงจุดเริ่มต้นของสตริงได้หรือไม่โดยจับคู่การจับภาพนั้นอย่างน้อยหนึ่งครั้ง bจะถูกแทรกเข้าไปในสตริงผ่านทางที่ไม่ค่อยได้ใช้$'ซึ่งจะแทรกทุกอย่างหลังจากการแข่งขันลงในการเปลี่ยนตัว

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

หนึ่งในนี้ตรงกับตัวอักษรที่ตำแหน่งซึ่งจะแบ่งตามหรือa bมันใช้ประโยชน์จากความจริงที่ว่าผลลัพธ์นั้นสมมาตร: เนื่องจากlcm(a,b)ถูกหารด้วยทั้งสองaและbออกไปโดยการลบอินสแตนซ์ของaหรือbให้รูปแบบเดียวกันกับที่ได้จาก0การเพิ่มเข้าไป lookahead แรกเพียงแค่จับและa blookahead ที่สองจะตรวจสอบว่ามีหลาย ๆอักขระaหรือแต่ละbอักขระก่อนช่องว่างแรก

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

ตามที่ระบุไว้ใน Wikipedia นอกเหนือจากตัวตนของBézoutมันก็เป็นความจริงเช่นกัน

ตัวหารร่วมมากdคือจำนวนเต็มบวกที่เล็กที่สุดที่สามารถเขียนax + byได้

นี่ก็หมายความว่า GCD จะสอดคล้องกับช่องว่างที่สั้นที่สุดระหว่างสองos ในผลลัพธ์ ดังนั้นเราไม่ต้องกังวลกับการหา GCD เลย แต่เราแค่มองหาอินสแตนซ์แรกของช่องว่างที่สั้นที่สุด o(\.*)oจับคู่ช่องว่างของผู้สมัครและจับภาพความกว้างของมันไว้ในกลุ่มที่ 1 จากนั้นเราพยายามเข้าถึงช่องว่างแรกโดยสลับระหว่างการย้อนกลับไปยังกลุ่มที่ 1 และos (พร้อมตัวเลือกเพิ่มเติม.) หากมีช่องว่างที่สั้นกว่าด้านขวาสิ่งนี้จะไม่ตรงกันเนื่องจากเราไม่สามารถย้อนผ่านช่องว่างนั้นด้วยการอ้างอิงย้อนกลับ ทันทีที่ช่องว่างเพิ่มเติมทั้งหมดกว้างอย่างน้อยเท่ากับช่องว่างในปัจจุบันการจับคู่นี้ เราจับจุดสิ้นสุดของ LCM สตริงลงในกลุ่มที่ 2 .*และตรงกับส่วนที่เหลือของสตริงที่มี เราเขียนตัวพิมพ์ใหญ่กลับมาOs (ด้วยช่องว่างระหว่าง) เช่นเดียวกับส่วนที่เหลือของสตริง LCM แต่ทิ้งทุกอย่างที่เริ่มต้นจากพื้นที่เพื่อลบaและbจากผลสุดท้าย


ฉันไม่รู้เกี่ยวกับทฤษฎีจำนวนของ Retina มาก แต่จะไม่ตั้งค่าอักขระอินพุตเป็นสิ่งที่ไม่ต้องการการหลีกเลี่ยงการบันทึกไบต์? Ie (\.*)=>(a*)
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴใช่แล้วฉันจะต้องแทนที่ด้วยใน.ภายหลังซึ่งมีค่าใช้จ่ายสี่ไบต์ (และการกำจัดทางหนีเพียงบันทึก 3)
Martin Ender

โอ๋ เย็น! คำตอบที่น่าสนใจมาก
Conor O'Brien

5

ch, 50 ตัวอักษร / 90 ไบต์

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

Try it here (Firefox only).

จะต้องมีวิธีในการตีต่อไป!

คำอธิบาย

นี่เป็นอัลกอริทึมแบบสองเฟสขั้นพื้นฐาน จริงๆแล้วมันค่อนข้างง่าย

ขั้นตอนที่ 1

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

ก่อนอื่นเราสร้างช่วงจาก 0 ถึง LCM + 1 จากนั้นเราแผนที่เหนือมันตรวจสอบว่าปัจจัยการผลิตอย่างใดอย่างหนึ่งเป็นปัจจัยของรายการปัจจุบันในช่วง ถ้าเป็นเช่นนั้นเราจะแทนที่รายการนั้นด้วยo; .มิฉะนั้นเราจะแทนที่ด้วย การเข้าร่วมทำให้เราได้ชุดของ o และจุดที่เราสามารถผ่านไปยังเฟสสองได้

ระยะที่ 2

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

นี่เป็นฟังก์ชั่นการแทนที่ขนาดใหญ่เพียงฟังก์ชันเดียว สร้าง regex เป็นo[dots]oที่ซึ่งจำนวนจุดถูกกำหนดโดย GCD-1 เนื่องจาก regex นี้ไม่ใช่แบบโกลบอลมันจะตรงกับเหตุการณ์แรกเท่านั้น หลังจากนั้นการแข่งขันจะถูกแทนที่โดยO[dots]Oใช้ฟังก์ชัน toUpperCase


3

MATL , 72 ไบต์

ใช้เวอร์ชัน 6.0.0ซึ่งเร็วกว่าความท้าทายนี้ รหัสทำงานใน Matlab และใน Octave

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

ตัวอย่าง

>> 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

คำอธิบาย

ฉันไม่รู้ว่ามันทำงานอย่างไร ฉันแค่พิมพ์ตัวอักษรแบบสุ่ม ฉันคิดว่ามีการโน้มน้าวใจบ้าง

แก้ไข: ลองออนไลน์! รหัสในลิงก์ได้รับการแก้ไขเล็กน้อยเพื่อให้สอดคล้องกับการเปลี่ยนแปลงในภาษา (ณ วันที่ 2 มิถุนายน 2016)


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

2

Japt , 83 ไบต์

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

ยังไม่สมบูรณ์ golfed ... และไม่ต้องการที่จะ golfed: /


คุณไม่สามารถใช้rแทนได้$.replace($หรือไม่?
ETHproductions

@Eth ฉันไม่ได้คิดวิธีการแทนที่โดยไม่มีการตั้งค่าสถานะ g ดังนั้นไม่ฉันไม่สามารถ
nicael

2

Javascript, 170 164 161 153 145 141 136 ไบต์

(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`)

นั่นค่อนข้าง lonnnggggg ....

สาธิต , ตัวแปรที่กำหนดไว้อย่างชัดเจนเนื่องจากล่ามใช้โหมดเข้มงวด


ลองแทนที่i%a<1||i%b<1?'o':'.'ด้วยi%a&&i%b?'.':'o'
Mama Fun Roll

โอ้ใช่ฉันคิดว่าคุณสามารถเข้าร่วมนามแฝง
Mama Fun Roll

@ ןnɟuɐɯɹɐןoɯขอบคุณยังแทนที่อาร์เรย์ด้วยการทำซ้ำง่าย ๆ
nicael

โอ้จากนั้นในกรณีนี้คุณอาจไม่ควรใช้นามแฝงเข้าร่วมเว้นแต่ว่าคุณจะเกิดขึ้น 3 ครั้ง
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')ช่วยให้คุณสองไบต์ (ฉันยังพยายามใช้การจัดทำดัชนีสตริงเพื่อสร้าง '.' และ 'o' แต่จริง ๆ แล้วมีค่าใช้จ่ายสองไบต์)
Neil

1

Python 2, 217 200 191 ไบต์

นี่เป็นทื่อเล็กน้อย แต่ใช้งานได้ เคล็ดลับการเล่นกอล์ฟใด ๆ ได้รับการชื่นชมโดยเฉพาะอย่างยิ่งถ้าคุณรู้วิธีการแก้ไขs[i] = s[v] = "o"ปัญหาที่ฉันพบที่ที่จะเขียนทับ "O" s รับมัน!

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)

Ungolfed:

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