Rasio perlengkapan lego

23

Saya sedang membangun robot lego raksasa dan saya perlu membuat beberapa rasio roda gigi tertentu menggunakan satu set roda gigi. Saya memiliki banyak gigi dengan ukuran gigi lego yang umum: 8, 16, 24, atau 40 gigi. Tulis program yang bisa saya gunakan di mana saya memasukkan rasio roda gigi dan program memberi tahu saya kombinasi roda gigi mana yang harus saya gunakan untuk mendapatkan rasio yang diminta.

Rasio input akan ditentukan pada input standar (atau setara bahasa Anda) dengan dua bilangan bulat yang dipisahkan oleh titik dua. Rasio a:bberarti bahwa poros keluaran harus berputar a/bkali lebih cepat dari poros input.

Output ke output standar harus berupa garis tunggal yang berisi daftar rasio roda gigi yang dipisahkan oleh ruang, dalam bentuk di x:ymana xukuran roda gigi pada poros input dan yadalah ukuran roda gigi pada poros output. Anda harus menggunakan jumlah roda gigi minimum yang dimungkinkan untuk rasio yang diberikan. Masing x- masing dan yharus menjadi salah satu 8,16,24,40.

contoh:

1:5 -> 8:40
10:1 -> 40:8 16:8
9:4 -> 24:16 24:16
7:1 -> IMPOSSIBLE
7:7 ->
6:15 -> 16:40

Jika rasio roda gigi yang diinginkan tidak mungkin, cetak "IMPOSSIBLE". Jika tidak diperlukan roda gigi, cetak string kosong.

Ini kode golf, jawaban terpendek menang.

Keith Randall
sumber
Bukankah rasio gigi berbanding terbalik dengan kecepatan sudut? Jadi, misalnya jika kecepatan input yang diinginkan adalah 1: 5, bukankah rasionya 40: 8 dan bukannya 8:40? Atau apakah rasio tangan kiri rasio gigi efektif dengan rasio gigi sebenarnya?
DavidC
Pertanyaan yang menarik ... 1:5 -> 8:40dan 10:1 -> 40:8masuk akal tetapi yang lain tidak begitu banyak.
Rob
@ Davidvider: Saya kira Anda bisa mendefinisikannya baik. Saya berusaha konsisten secara internal. 1:5berarti poros keluaran berputar 5 kali lebih lambat, dan 8 gigi pada input dan 40 gigi pada output membuat itu terjadi.
Keith Randall
@ MikeDtrick: yah 10:1 -> 40:8 16:8, tidak apa yang kamu katakan. Bagaimana dengan yang lain membingungkan Anda? 9:4diimplementasikan melakukan 3:2dua kali. 3:2diimplementasikan menggunakan 24:16.
Keith Randall
2
@MikeDtrick: Ya untuk pertanyaan pertama Anda. Untuk mendapatkan 10: 1 Anda dapat melakukan 5: 1 (menggunakan 40 gigi / 8 gigi) dan kemudian 2: 1 (menggunakan 16 gigi / 8 gigi). 7:7sama dengan 1:1, jadi tidak memerlukan roda gigi untuk diimplementasikan.
Keith Randall

Jawaban:

4

Python - 204

Ok, saya akan pergi dulu:

def p(n,a=[1]*9):
 n=int(n)
 for i in(2,3,5):
    while n%i<1:n/=i;a=[i]+a
 return a,n
(x,i),(y,j)=map(p,raw_input().split(':'))
print[' '.join(`a*8`+':'+`b*8`for a,b in zip(x,y)if a!=b),'IMPOSSIBLE'][i!=j]
edit:

Untuk 'mengoptimalkan' output, ini dapat ditambahkan sebelum printpernyataan,

for e in x:
 if e in y:x.remove(e);y.remove(e)

membawa total hingga 266 karakter , saya percaya.

daniero
sumber
1
<1dapat menggantikan ==0. Juga if b:a=...return abisa return b and...or a.
ugoren
Tidak berfungsi untuk, mis 23:12. , .
Keith Randall
Terlihat dengan baik. Itu berjalan karena 12 dapat dibagi. Menambahkan elif i!=1:return[]ke yang asli memecahkan masalah tetapi memperkenalkan yang lain. $ python gears.py <<< 21:28=> 24:16.. Aku akan memeriksanya. Sepertinya masalahnya tidak begitu sederhana: DI Pikirkan kodenya harus lebih lama, atau saya perlu pendekatan lain.
daniero
Ini dia; Saya pikir yang ini berfungsi seperti yang diharapkan. Bahkan membuatnya lebih kecil :)
daniero
Terlihat bagus, tetapi tidak optimal. 6:15dapat dilakukan dengan 16:40tetapi kode Anda kembali 24:40 16:24.
Keith Randall
4

Perl - 310 306 294 288 272

Saya sedikit berkarat dengan perl dan tidak pernah melakukan kode-golf ... tapi tidak ada alasan. Penghitungan karakter tanpa jeda baris. Menggunakan perl v5.14.2.

($v,$n)=<>=~/(.+):(.+)/;
($x,$y)=($v,$n);($x,$y)=($y,$x%$y)while$y;
sub f{$p=shift;$p/=$x;for(5,3,2){
while(!($p%$_)){$p/=$_;push@_,$_*8}}
$o="IMPOSSIBLE"if$p!=1;
@_}
@a=f($v);@b=f($n);
if(!$o){for(0..($#b>$#a?$#b:$#a)){
$a[$_]||=8;
$b[$_]||=8;
push@_,"$a[$_]:$b[$_]"}}
print"$o@_\n"

Saya menantikan kritik dan petunjuk. Tidak mudah menemukan tip dan trik untuk kode-golf (dalam perl).

Patrick B.
sumber
Anda dapat menyimpan 9 karakter dengan menghapus $1:$2 -> , itu tidak diperlukan dalam output.
DaveRandom
Oh, saya salah membaca spec. Terima kasih.
Patrick B.
Anda dapat mengurangi pernyataan seperti $a[$_]=8 if!$a[$_];ke$a[$_]||=8;
ardnew
Baris baru dihitung sebagai satu karakter.
Timtech
Baris pertama dapat disingkat menjadi ($v,$n)=split/:|\s/,<>;(belum diuji).
msh210
2

swi-prolog, 324 250 248 204 byte

Prolog cukup baik dalam memecahkan masalah seperti ini.

m(P):-(g(P,L),!;L='IMPOSSIBLE'),write(L).
g(A:A,''):-!.
g(A:B,L):-A/C/X,C>1,B/C/Y,!,g(X:Y,L);A/C/X,!,B/D/Y,C*D>1,g(X:Y,T),format(atom(L),'~D:~D ~a',[C*8,D*8,T]).
X/Y/Z:-(Y=5;Y=3;Y=2;Y=1),Z is X//Y,Y*Z>=X.

Input diberikan sebagai parameter jangka waktu untuk predikat m. Output ditulis ke stdout. Maaf tentang jejak 'benar'; itu hanya cara penerjemah untuk memberi tahu saya bahwa semuanya baik-baik saja.

?- m(54:20).
24:40 24:16 24:8 
true.

?- m(7:7).
true.

?- m(7:1).
IMPOSSIBLE
true.
Ruud Helderman
sumber
2

C, 246 216 213 byte

Dalam upaya (sia-sia) untuk mengalahkan solusi Prolog saya sendiri, saya sepenuhnya menulis ulang solusi C.

b,c,d;f(a,b,p){while(c=a%5?a%3?a%2?1:2:3:5,d=b%5?b%3?b%2?1:2:3:5,c*d>1)c<2|b%c?d<2|a%d?p&&printf("%d:%d ",8*c,8*d):(c=d):(d=c),a/=c,b/=d;c=a-b;}main(a){scanf("%d:%d",&a,&b);f(a,b,0);c?puts("IMPOSSIBLE"):f(a,b,1);}

Solusi C asli saya (246 byte):

#define f(c,d) for(;a%d<1;a/=d)c++;for(;b%d<1;b/=d)c--;
b,x,y,z;main(a){scanf("%d:%d",&a,&b);f(x,2)f(y,3)f(z,5)if(a-b)puts("IMPOSSIBLE");else
while((a=x>0?--x,2:y>0?--y,3:z>0?--z,5:1)-(b=x<0?++x,2:y<0?++y,3:z<0?++z,5:1))printf("%d:%d ",a*8,b*8);}

Itu latihan yang bagus untuk membuktikan bahwa itu bisa dilakukan tanpa membuat daftar.

Ruud Helderman
sumber
2

Pyth, 101 byte

(Hampir pasti non-bersaing dalam kontes karena menggunakan bahasa yang lebih baru dari September / 2012)

D'HJH=Y[)VP30W!%JN=/JN=Y+NY))R,YJ;IneKhm'vdcz\:J"IMPOSSIBLE").?V.t,.-Y.-hK=J.-hKYJ1In.*Npj\:m*8d_Np\ 

Implementasi jawaban python @daniero ' tetapi semi-dioptimalkan untuk Pyth.

D'H                               - Define a function (') which takes an argument, H.
   JH                             - J = H (H can't be changed in the function)
     =Y[)                         - Y = []
         V                        - For N in ...
          P30                     - Prime factors of 30 (2,3,5)
             W!%JN                - While not J%N
                  =/JN            - J /= N
                      =Y+NY       - Y = N + Y
                           ))R,YJ - To start of function, return [Y,J]

ENDFUNCTION

If 
         cz\:  - Split the input by the ':'
     m'vd      - ['(eval(d)) for d in ^]
   Kh          - Set K to the first element of the map (before the :)
  e            - The second returned value
             J - The second returned value after the : (The variables are globals)
 n             - Are not equal

Then 
"IMPOSSIBLE" - Print "IMPOSSIBLE"

Else
V                                      - For N in
 .t                1                   - transpose, padded with 1's
             .-hKY                     - 1st function first return - 2nd function first return
           =J                          - Set this to J
       .-hK                            - 1st function first return - ^
    .-Y                                - 2nd function first return - ^
   ,              J                    - [^, J]
                                         (Effectively XOR the 2 lists with each other)
                    I                  - If
                     n.*N              - __ne__(*N) (if n[0]!=n[1])
                         pj\:m*8d_N    - print ":".join([`d*8` for d in reversed(N)])
                                   p\  - print a space seperator

Coba di sini

Atau uji setiap kasus

Biru
sumber
0

ES6, 230 byte

x=>([a,b]=x.split`:`,f=(x,y)=>y?f(y,x%y):x,g=f(a,b),d=[],a/=g,f=x=>{while(!(a%x))a/=x,d.push(x*8)},[5,3,2].map(f),c=d,d=[],a*=b/g,[5,3,2].map(f),a>1?'IMPOSSIBLE':(c.length<d.length?d:c).map((_,i)=>(c[i]||8)+':'+(d[i]||8)).join` `)

Salah satu golf terpanjang saya, jadi saya pasti telah melakukan sesuatu yang salah ... Tidak Diinginkan:

x => {
    [a, b] = x.split(":");
    f = (x, y) => y ? f(y, x % y) : x; // GCD
    g = f(a, b);
    f = x => {
        r = [];
        while (!(x % 5)) { x /= 5; r.push(5); }
        while (!(x % 3)) { x /= 3; r.push(3); }
        while (!(x % 2)) { x /= 2; r.push(2); }
        if (x > 1) throw "IMPOSSIBLE!";
        return r;
    }
    c = f(a);
    d = f(b);
    r = [];
    for (i = 0; c[i] || d[i]; i++) {
        if (!c[i]) c[i] = 8;
        if (!d[i]) d[i] = 8;
        r[i] = c[i] + ":" + d[i];
    }
    return r.join(" ");
}
Neil
sumber