乐高齿轮比


23

我正在构建一个大型的乐高机器人,我需要使用一组齿轮来生成一些特定的齿轮比。我有很多常见的乐高齿轮规格的齿轮:8齿,16齿,24齿或40齿。编写一个可以在输入齿轮比的地方使用的程序,该程序会告诉我应该使用哪种齿轮组合来获得所需的齿轮比。

输入比例将在标准输入(或您的语言的等效输入)上指定,并且两个整数之间用冒号分隔。比率a:b表示输出轴的旋转a/b时间应与输入轴的旋转速度相同。

输出到标准输出应该是包含齿轮比的一个空格分隔列表中的单个线路,在的形式x:y,其中x是在输入轴上的齿轮的尺寸和y是在输出轴的齿轮的尺寸。对于给定的传动比,必须使用尽可能少的齿轮数。每个xy必须的一个8,16,24,40

例子:

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

如果不可能达到所需的传动比,则打印“不可行”。如果不需要齿轮,请打印空字符串。

这是代码高尔夫,最短答案胜出。


齿的比例不是与角速度成反比吗?因此,例如,如果所需的输入输出速度为1:5,该比率是否应为40:8而不是8:40?还是左手传动比是您想要的有效齿轮齿数与实际齿轮齿数比?
DavidC 2012年

有趣的问题...... 1:5 -> 8:4010:1 -> 40:8有意义,但其他人没有这么多。
罗布2012年

@DavidCarraher:我想您可以用任何一种方式定义它。我试图保持内部一致。 1:5意味着输出轴的旋转速度慢了5倍,而输入端的8齿齿轮和输出端的40齿齿轮使这种情况发生了。
基思·兰德尔

@MikeDtrick:好吧,10:1 -> 40:8 16:8不是你所说的。那其他人会使您感到困惑吗? 9:4实现3:2两次。 3:2使用实现24:16
基思·兰德尔

2
@MikeDtrick:是的,第一个问题。要获得10:1,您可以进行5:1(使用40齿/ 8齿),然后进行2:1(使用16齿/ 8齿)。 7:7与相同1:1,因此无需执行任何齿轮。
基思·兰德尔

Answers:


4

Python-204

好吧,我先走:

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]
编辑:

要“优化”输出,可以将其添加到print语句之前,

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

我相信,总共可以包含266个字符


1
<1可以代替==0。也if b:a=...return a可以return b and...or a
ugoren 2012年

不适用于,例如23:12
基思·兰德尔

好眼力。因为12是可分割的,所以要经过。添加elif i!=1:return[]到原始解决了该问题,但引入了另一个。$ python gears.py <<< 21:28=> 24:16..我要研究一下。看起来问题毕竟不是那么简单:DI认为代码必须更长,否则我需要另一种方法。
daniero 2012年

你去了 我认为这一工作符合预期。甚至变小了:)
daniero 2012年

看起来不错,但不是最佳选择。 6:15可以完成,16:40但是您的代码返回24:40 16:24
基思·兰德尔

4

的Perl - 310 306 294 288 272

我对perl有点生疏,从来没有做过代码高尔夫……但是没有任何借口。字符数没有换行符。使用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"

我期待批评家和提示。在代码高尔夫球(在perl中)中找到技巧并非易事。


您可以删除来​​保存9个字符$1:$2 -> ,这在输出中不是必需的。
DaveRandom 2012年

哦,我看错了规格。谢谢。
Patrick B.

您可以减少之类的语句$a[$_]=8 if!$a[$_];$a[$_]||=8;
ardnew

换行符视为一个字符。
Timtech

第一行可以缩写为($v,$n)=split/:|\s/,<>;(未测试)。
msh210 '16

2

SWI-序言,324个 250 248 204字节

Prolog在解决此类问题方面做得很好。

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.

输入作为术语参数传递给谓词m。输出被写入标准输出。对后缀“ true”表示抱歉;那只是解释器让我知道一切都很好的方式。

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

?- m(7:7).
true.

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

2

C,246个 216 213字节

为了击败我自己的Prolog解决方案(徒劳),我完全重写了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);}

我原来的C解决方案(246字节):

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

这是一个很好的练习,以证明不需要构建列表就可以完成此操作。


2

Pyth,101个字节

(几乎可以肯定,非竞赛中使用的语言比sep / 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\ 

@daniero的python答案的实现,但对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

在这里尝试

或测试每种情况


0

ES6,230字节

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

我最长的高尔夫球场之一,所以我一定做错了什么。

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(" ");
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.