En büyük ortak böleni görselleştirin


28

Arka fon

En büyük ortak bölen ( kısaca gcd ) birçok kullanışlı özelliğe sahip olduğundan uygun bir matematiksel işlevdir. Bunlardan biri Bézout'un kimliği : eğer d = gcd(a, b)öyleyse tamsayılar var xve yöyle d = x*a + y*b. Bu zorlukta, sizin göreviniz bu özelliği basit ASCII sanatı ile görselleştirmek.

Giriş

Girişleriniz iki pozitif tamsayıdır ave bherhangi bir makul biçimde verilir. Aynı zamanda unary girişleri de alabilirsiniz (seçtiğiniz tek bir yazdırılabilir ASCII karakterinin tekrarı), ancak tutarlı olmanız ve her iki giriş için de aynı formatı kullanmanız gerekir. Girişler herhangi bir sırada olabilir ve eşit olabilirler.

Çıktı

Çıktınız bir suzunluk dizesidir lcm(a, b) + 1( lcm en düşük ortak katın kısaltmasıdır). Karakterleri sarasındaki tam sayıları temsil 0etmek lcm(a, b). Karakter s[i], bir ya da bir çarpı oişareti iise küçük harf , aksi takdirde bir nokta . Sıfırın her sayının katı olduğunu unutmayın. Şimdi, Bézout'un kimliği nedeniyle , mesafe tam olarak en az bir çift karakter olacak . Bu tür en soldaki çift, büyük harf s ile değiştirilir ; bu son çıktı.ab.osgcd(a, b)O

Örnek

Girişleri a = 4ve b = 6. Sonra biz var gcd(a, b) = 2ve lcm(a, b) = 12, böylece solacaktır 13. Katları ave bşöyle vurgulanmaktadır:

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

İki omesafeli iki çift s vardır, ancak yalnızca en soldakileri Os ile değiştiririz , yani son çıktı

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

Kurallar ve puanlama

Tam bir program veya bir fonksiyon yazabilirsiniz. En düşük bayt sayısı kazanır ve standart boşluklar izin verilmez.

Test durumları

 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
Unary girdi çekerken herhangi bir karakter seçebilir miyiz? (Özellikle, nasıl ., oya da O.) Ya da olmak zorunda 1mı? Ya da 0?
Martin Ender

1
@ MartinBüttner Tutarlı olduğunuz ve her iki giriş için aynı formatı kullandığınız sürece herhangi bir karakter olabilir.
Zgarb

2
Test vakalarından biri olarak 3 ve 5'i kullanmadığına şaşırdım.
Neil

Buildin kullanabilir miyim?
Akangka

@HristiyanIrwan Evet, tüm yerleşiklere izin verilir.
Zgarb

Yanıtlar:


7

Jolf, 52 bayt

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

Bu kodu iki bölüme ayıracağım.

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

Burada dene!


Şimdiye kadar her şeyden daha kısa. : P
Rɪᴋᴇʀ

1
@RikerW Evet! Umarım Jolf nihayet bir kere kazanır.
Conor O'Brien,

10

Julia, 111 110 107 103 96 bayt

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)

Bu, iki tam sayı kabul eden ve bir dize döndüren bir işlevdir.

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 sayesinde bir bayt kaydedildi!


10

Retina , 112 109 99 94 91 bayt

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

Çok rekabetçi değil bence, ancak Retina'daki sayı teorisi her zaman oldukça eğlencelidir. :)

Tek .haneli sayı olarak kullanarak girdiyi tek sayı olarak alır.

Çevrimiçi deneyin.

açıklama

^
. 

Bu ., girişin önüne bir ve bir boşluk ekler . Bu sonuçta çıktı haline gelecektir.

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

Bu, LCM prepends ave bdize. Zaten .orada bir yerimiz olduğundan, bununla sonuçlanacağız lcm(a,b)+1. Bu, bu yeni öneki bölmediği bsürece tekrar tekrar hazırlanarak gerçekleştirilir a. aBir grup ele geçiriyoruz ve daha sonra bu yakalamayı eşleştirerek dizenin başlangıcına ulaşıp ulaşamayacağımızı kontrol ediyoruz. bdaha sonra, nadiren kullanılan kordonun içerisine sokulduktan sonra , eşleşmeden sonra$' her şeyi ikame içerisine yerleştirir.

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

Bu, aveya ile bölünen konumlardaki karakterlerle eşleşir b. Sonucun simetrik olduğu gerçeğini kullanır: çünkü lcm(a,b)her ikisine de bölünür ave börneklerin çıkarılmasıyla ayrılır aveya ekleyerek bsağdan başlayarak aynı kalıbı verir 0. İlk bakış açısı basitçe ave yakalar b. İkinci bakış açısı , ilk boşluktan önce her birinin aveya bkarakterin bir katı olduğunu kontrol eder .

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

Vikipedi'de belirtildiği gibi, Bézout'un kimliğine ek olarak

En büyük ortak bölen d, yazılabilecek en küçük pozitif tamsayıdır ax + by.

Bu, GCD'nin oçıktıdaki iki s arasındaki en kısa boşluğa karşılık geleceği anlamına gelir . Bu yüzden GCD'yi bulmakta zorlanmamız gerekmiyor. Bunun yerine en kısa aralığın ilk örneğini arıyoruz. o(\.*)oBir aday boşluğu ile eşleşir ve genişliğini grup 1'de yakalar. Ardından, grup 1 ve os'ye geri dönüş arasında geçiş yaparak ilk isteğe ulaşmaya çalışırız (isteğe bağlı ek .s ile). Sağda daha kısa bir boşluk varsa, bu eşleşmeyecektir çünkü geri tepme ile bu boşluğu geçemeyiz. Tüm boşluklar en azından mevcut olan kadar geniş olduğunda, bu eşleşir. LCM dizisinin sonunu grup 2'ye kaydeder ve dizinin kalanını ile eşleştiririz .*. Büyük harf yazıyoruzO(ara boşluğu) ler de uzaklaştırmak için LCM dize geri kalan ancak uzayda başlayarak ıskarta her şeyi kadar ave bnihai sonucundan.


Retina sayı teorisi hakkında fazla bir şey bilmiyorum ama giriş karakterini, kaçış kaydetme baytları gerektirmeyen bir şeye ayarlamaz mıydınız? Yani (\.*)=>(a*)
Conor O'Brien,

@ CᴏɴᴏʀO'Bʀɪᴇɴ Evet, fakat daha sonra bunun yerine .daha sonra değiştirmek zorunda kalacağım ki bu dört bayta mal oluyor (ve kaçışlardan kurtulmak sadece 3 tasarruf sağlıyor).
Martin Ender

Ohh. Güzel! Çok ilginç bir cevap.
Conor O'Brien,

5

50, 50 karakter / 90 bayt

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

Try it here (Firefox only).

Bunu daha fazla golf oynamanın bir yolu olmalı!

açıklama

Bu, temel iki fazlı bir algoritmadır. Aslında oldukça basit.

Faz 1

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

İlk önce 0 ile LCM + 1 arasında bir aralık oluşturduk. Ardından, girişlerin herhangi birinin aralıktaki mevcut öğenin bir faktörü olup olmadığını kontrol ederek haritalandırırız. Öyleyse, bu öğeyi bir o; Aksi takdirde, a ile değiştiriyoruz .. Buna katılmak bize ikinci aşamaya geçebileceğimiz bir dizi o ve nokta verir.

Faz 2

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

Bu sadece büyük bir değiştirme işlevidir. Bir regex, o[dots]onokta miktarının GCD-1 tarafından belirlendiği şekilde oluşturulur . Bu regex global olmadığından, sadece ilk oluşum ile eşleşir. Daha sonra, O[dots]Obir toUpperCase işlevi kullanılarak eşleşme değiştirilir .


3

MATL , 72 bayt

Bu zorluktan daha eski olan 6.0.0 sürümünü kullanır . Kod, Matlab ve Octave'da çalışır.

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

Örnek

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

açıklama

Ben hiçbir fikri nasıl çalıştığını. Karakterleri rastgele yazdım. Bence bazı katlanmalar var.

Düzenleme: Çevrimiçi deneyin! Bağlantıdaki kod, dildeki değişikliklere uyması için biraz değiştirildi (2 Haziran 2016 itibariyle).


Rastgele bir 72 baytlık program yazamazsınız. Olasılığı daha sonra hesaplar (bir süre uyuduktan ve bir süre harekete geçtikten sonra)
CalculatorFeline

2

Japt , 83 bayt

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

Henüz tam olarak golf oynamadı ... Ve golf oynamak istemiyor: /


rYerinde kullanamaz $.replace($mısın?
ETHProductions

@ G g bayrağı olmadan nasıl değiştireceğimi bilemedim, bu yüzden hayır, yapamam.
nicael

2

Javascript, 170 164 161 153 145 141 136 bayt

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

Bu oldukça lonnnggggg ....

Demo , tercüman katı mod kullandığından açıkça tanımlanmış değişkenler.


Değiştirmeyi deneyin i%a<1||i%b<1?'o':'.'ilei%a&&i%b?'.':'o'
Mama Fun Roll-

Evet, bence diğer üyelere katılabilirsin.
Mama Fun Roll

@ ן nɟuɐɯɹɐ ן oɯ teşekkürler, aynı zamanda dizileri basit tekrarla da değiştiriyoruz.
nicael

Oh, o zaman bu durumda, muhtemelen 3 oluşumunuz olmadıkça takma isme katılmamalısınız.
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')size iki bayt kazandırır. (Ayrıca '.' Ve 'o' oluşturmak için string indexing'i kullanmaya çalıştım ama bu aslında iki byte'a mal oldu.)
Neil

1

Python 2, 217 200 191 bayt

Bu biraz kör, ama işe yarıyor. Herhangi bir golf ipucu, özellikle s[i] = s[v] = "o"karşılaştığım bu sorunu nasıl çözeceğinizi biliyorsanız , bunun "O" nın üzerine yazacağı yeri biliyorsunuzdur!

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.