Lego dişli oranları


23

Dev bir lego robotu yapıyorum ve bir takım dişliler kullanarak belirli dişli oranları oluşturmam gerekiyor. 8, 16, 24 veya 40 diş: Lego'nun ortak ebatlarına sahip çok fazla vitesim var. Bir dişli oranını girdiğim yerde kullanabileceğim bir program yazın ve program, istenen oranı elde etmek için hangi vites kombinasyonunu kullanmam gerektiğini söyler.

Giriş oranı standart girişte (veya dilinizin eşdeğeri) iki noktadan iki noktayla ayrılmış olarak belirtilecektir. Bir oran a:bçıkış mili dönüş gerektiği vasıtasıyla a/bgiriş mili gibi hızlı kez.

Standart çıktıya çıkış şeklinde dişli oranlarının bir boşluk ile ayrılmış listesini içeren tek bir çizgi olmalıdır x:yburada xgiriş mili üzerine dişli boyutundadır ve yçıkış mili üzerine dişli boyutundadır. Verilen oran için mümkün olan en düşük vites sayısını kullanmanız gerekir. Her biri xve ybiri olmalı 8,16,24,40.

örnekler:

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

İstenilen vites oranı imkansızsa, "GELİŞMİŞ" i yazdırın. Dişliler gerekli değilse, boş dizgeyi yazdırın.

Bu kod golf, en kısa cevap kazanıyor.


Dişlerin oranı açısal hız ile ters orantılı değil mi? Örneğin, eğer istenen giriş çıkış hızı 1: 5 ise, oran 8:40 yerine 40: 8 olmamalı mı? Yoksa sol taraftaki etkili dişli dişlileri istediğiniz gerçek dişli dişlisi oranına mı göre?
DavidC

İlginç bir soru ... 1:5 -> 8:40ve 10:1 -> 40:8mantıklı ama diğerleri çok değil.
Rob

@DavidCarraher: Her iki şekilde de tanımlayabilirsiniz sanırım. Dahili olarak tutarlı olmaya çalıştım. 1:5çıkış şaftının 5 kat daha yavaş döndüğü ve giriş üzerinde 8 dişli ve çıkış üzerinde 40 dişli olması anlamına gelir.
Keith Randall

@MikeDtrick: iyi dediğin 10:1 -> 40:8 16:8gibi değil. Peki ya diğerleri kafanı karıştırıyor? iki kez 9:4yaparak uygulanır 3:2. 3:2kullanılarak uygulanır 24:16.
Keith Randall

2
@MikeDtrick: İlk sorunuza evet. 10: 1 almak için 5: 1 (40 diş / 8 diş kullanarak) ve sonra 2: 1 (16 diş / 8 diş kullanarak) yapabilirsiniz. 7:7aynıdır 1:1, bu yüzden uygulamak için dişliler gerektirmez.
Keith Randall

Yanıtlar:


4

Python - 204

Tamam, önce ben gideceğim:

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]
Düzenle:

Çıktıyı 'optimize etmek' için, bu printifadeden önce eklenebilir ,

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

toplamı 266 karakter getirdiğine inanıyorum.


1
<1yerini alabilir ==0. Ayrıca, if b:a=...return aolabilir return b and...or a.
ugoren

Örneğin, işe yaramaz 23:12.
Keith Randall

İyi benekli. 12 bölünebilir olduğu için geçiyor. elif i!=1:return[]Orijinali eklemek sorunu çözer ancak başka bir tanesini tanıtır. $ python gears.py <<< 21:28=> 24:16.. Ben içine bakacağım. Sonuçta sorun o kadar basit değildi gibi görünüyor: DI Kodun daha uzun olması gerektiğini düşünün, yoksa başka bir yaklaşıma ihtiyacım var.
daniero 4:12

İşte gidiyorsunuz; Sanırım bu beklendiği gibi çalışıyor. Hatta daha küçük yaptı :)
daniero 4:12

Oldukça iyi görünüyor, ama en uygun değil. 6:15ile yapılabilir 16:40ancak kodunuz geri döner 24:40 16:24.
Keith Randall

4

Perl - 310 306 294 288 272

Perl ile biraz paslıyım ve asla bir kod golf yapmadım ... ama mazeret yok. Char-count, satır sonu olmadan. Perl v5.14.2 kullanımı.

($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"

Eleştirmen ve ipuçlarını sabırsızlıkla bekliyorum. Code-golf için ipuçları ve püf noktaları bulmak o kadar kolay değil (perl olarak).


9 karakter çıkartarak kaydedebilirsiniz $1:$2 -> , çıkışta gerekli değildir.
DaveRandom

Oh, spec'i yanlış okudum. Teşekkürler.
Patrick B.

Sen gibi ifadeleri azaltabilir $a[$_]=8 if!$a[$_];için$a[$_]||=8;
ardnew

Newlines bir karakter olarak sayılır.
Timtech

İlk satır ($v,$n)=split/:|\s/,<>;(denenmemiş) olarak kısaltılabilir .
msh210

2

swi-prolog, 324 250 248 204 bayt

Prolog böyle bir problemi çözmekte oldukça başarılı.

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.

Girdi, tahmin etmek için bir terim parametresi olarak iletilir m. Çıktı stdout'a yazılmıştır. İzleyen 'gerçek' için üzgünüm; bu sadece tercümanın bana her şeyin yolunda gittiğini bildirme şekli.

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

?- m(7:7).
true.

?- m(7:1).
IMPOSSIBLE
true.

2

C, 246 216 213 bayt

Prolog çözümümü yenmek için (boşuna) bir girişimde, C çözümünü tamamen yeniden yazdım.

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);}

Orijinal C çözümüm (246 bayt):

#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);}

Listeler oluşturmadan yapılabileceğini kanıtlamak için güzel bir egzersizdi.


2

Pyth, 101 bayt

(Neredeyse kesinlikle eylül / 2012'den daha yeni bir dil kullanan yarışmada rekabet etmeyen)

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

@ Daniero 'python yanıtının bir uygulaması ancak Pyth için yarı optimize edilmiş bir cevap .

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

Burada dene

Veya her vakayı test edin


0

ES6, 230 bayt

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

En uzun golf sahalarımdan biri, bu yüzden yanlış bir şey yapmış olmalıyım ... Ungolfed:

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(" ");
}
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.