| Bytes | Lang | Time | Link |
|---|---|---|---|
| 082 | Raku Perl 6 rakudo | 240719T185111Z | bb94 |
| 160 | Python 3 | 240719T005631Z | aeh5040 |
| 025 | Vyxal | 240717T202931Z | emanresu |
| 072 | MATL | 160104T015858Z | Luis Men |
| 191 | Python 2 | 160102T112104Z | Sherlock |
| 136 | Javascript | 160101T195422Z | nicael |
| 091 | Retina | 160101T194940Z | Martin E |
| 083 | Japt | 160101T213356Z | nicael |
| 096 | Julia | 160101T195528Z | Alex A. |
| 052 | Jolf | 160101T215259Z | Conor O& |
| 5090 | 𝔼𝕊𝕄𝕚𝕟 | 160101T200751Z | Mama Fun |
Raku (Perl 6) (rakudo), 82 bytes
->@a {{S/o($('.'x+^-[gcd] @a))o/O$0O/}([~] map {$_%@a.all??'.'!!'o'},0..[lcm] @a)}
Python 3, 160 bytes
def f(a,b):*o,l=111,lcm(a,b);y='.'*(a*b//l-1);x=[46]*a*b;x[::b]=o*a;x[::a]=o*b;return''.join(map(chr,x[:l])).replace(f'o{y}o',f'O{y}O',1)+'o'
from numpy import*
Uses slice replacement: x[::b]=o*a; x[::a]=o*b
Uses lcm from numpy
Vyxal, 25 bytes
ġ/ʀṘ*fDÞǔ‛.oİ‟Ẋ'?ġ+↔;h⁽ɾ¢
Try it Online! Input as pair of numbers, output as char list.
ġ/ # Divide both by gcd
ʀ # Range from 0 to each inclusive
Ṙ* # Multiply by each other
f # And flatten, resulting in all divisors of the inputs up to lcm(a,b)
Þǔ # Untruth; create a list with 1s at indices in list
‛.oİ # Index into ".o"
D ‟Ẋ # All pairs of the previous list
'----;h # Find the first one where
↔ # One element is equal to
?ġ+ # The other + gcd(input)
¢ # At those two indices
⁽ɾ # Uppercase
MATL, 72 bytes
Uses version 6.0.0, which is earlier than this challenge. The code runs in Matlab and in Octave.
2$tZm1+:1-bbvtbw\A~otbZ}ZdXK1+ltb(3X53$X+1K2$lh*t2=f1)tK+hwg1+Ib('.oO'w)
Example
>> 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
Explanation
I have no idea how it works. I just typed characters randomly. I think there is some convolution involved.
Edit: Try it online! The code in the link has been slightly modified to conform to changes in the language (as of June 2, 2016).
Python 2, 217 200 191 bytes
This is a little blunt, but it works. Any golfing tips are appreciated, especially if you know how to fix that Got it!s[i] = s[v] = "o" problem I encountered, where that would overwrite "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)
Javascript, 170 164 161 153 145 141 136 bytes
(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`)
That's quite lonnnggggg....
Demo, explicitly defined variables because the interpreter uses strict mode.
Retina, 112 109 99 94 91 bytes
^
.
+r`(?<!^\1+). (.+)
$'$0
.(?=.* (.+) (.+))(?=\1* |\2* )
o
o(\.*)o((\1\.*o)*) .*
O$1O$2
Not very competitive, I think, but number theory in Retina is always quite fun. :)
Takes input as unary numbers using . as the unary digit.
Explanation
^
.
This inserts a . and a space in front of the input. This will ultimately become the output.
+r`(?<!^\1+). (.+)
$'$0
This prepends the LCM of a and b to the string. Since we already have a . there, we'll end up with lcm(a,b)+1. This is accomplished by repeatedly prepending b as long as a does not divide this new prefix. We capture a into a group one and then check if we can reach the beginning of the string by matching that capture at least once. b is then inserted into the string via the rarely used $' which inserts everything after the match into the substitution.
.(?=.* (.+) (.+))(?=\1* |\2* )
o
This one matches characters at positions which are divided by a or b. It makes use of the fact that the result is symmetric: since lcm(a,b) is divided by both a and b going left by subtracting instances of a or b yields the same pattern as going right from 0 by adding them. The first lookahead simply captures a and b. The second lookahead checks that there is a multiple of each a or b characters before the first space.
o(\.*)o((\1\.*o)*) .*
O$1O$2
As stated on Wikipedia, in addition to Bézout's identity it is also true that
The greatest common divisor
dis the smallest positive integer that can be written asax + by.
This implies that the GCD will correspond to the shortest gap between two os in the output. So we don't have to bother finding the GCD at all. Instead we just look for first instance of the shortest gap. o(\.*)o matches a candidate gap and captures its width into group 1. Then we try to reach the first space by alternating between a backreference to group 1 and os (with optional additional .s). If there is a shorter gap further to the right, this will fail to match, because we cannot get past that gap with the backreference. As soon as all further gaps are at least as wide as the current one, this matches. We capture the end of the LCM-string into group 2 and match the remainder of the string with .*. We write back the uppercase Os (with the gap in between) as well as the remainder of the LCM string, but discard everything starting from the space, to remove a and b from final result.
Japt, 83 bytes
'.pD=U*V/(C=(G=@Y?G$($YX%Y :X} $($UV)+1 £Y%U©Y%V?".:o"} $.replace($E=`o{'.pC-1}o`Eu
Not fully golfed yet... And doesn't want to be golfed :/
Julia, 111 110 107 103 96 bytes
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)
This is a function that accepts two integers and returns a string.
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
Saved a byte thanks to nimi!
Jolf, 52 bytes
on*'.wm9jJΡR m*Yhm8jJDN?<*%Sj%SJ1'o'.}"'o%o"n"O%O"n
I will split this code up into two parts.
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
𝔼𝕊𝕄𝕚𝕟, 50 chars / 90 bytes
⩥Мū⁽îí+1)ⓜ$%î⅋$%í?⍘.:⍘o)⨝ċɼ(`o⦃⍘.ĘМũ⁽îí-1)}o”,↪$ú⬮
There must be a way to golf this further!
Explanation
This is a basic two-phase algorithm. It's actually quite simple.
Phase 1
⩥Мū⁽îí+1)ⓜ$%î⅋$%í?⍘.:⍘o)⨝
First, we create a range from 0 to the LCM+1. Then we map over it, checking if either of the inputs is a factor of the current item in the range. If so, we replace that item with an o; otherwise, we replace it with a . . Joining it gives us a series of o's and dots that we can pass to phase two.
Phase 2
ċɼ(`o⦃⍘.ĘМũ⁽îí-1)}o”,↪$ú⬮
This is just one big replace function. A regex is created as o[dots]o, where the amount of dots is determined by the GCD-1. Since this regex is not global, it will only match the first occurrence. After, the match is replaced by O[dots]O using a toUpperCase function.