[Question]
  [
I'm building a giant lego robot and I need to generate some particular gear ratios using a set of gears. I have lots of gears with the common lego gear sizes: 8, 16, 24, or 40 teeth. Write a program I can use where I input a gearing ratio and the program tells me what combination of gears I should use to get the requested ratio.
The input ratio will be specified on standard input (or your language's equivalent) with two integers separated by a colon. A ratio of `a:b` means that the output shaft should turn `a/b` times as fast as the input shaft.
The output to standard output should be a single line containing a space-separated list of gear ratios, in the form of `x:y` where `x` is the size of the gear on the input shaft and `y` is the size of the gear on the output shaft. You must use the minimum possible number of gears for the given ratio. Each `x` and `y` must be one of `8,16,24,40`.
examples:
```
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
```
If the desired gear ratio is impossible, print "IMPOSSIBLE". If no gears are required, print the empty string.
This is code golf, shortest answer wins.
  
[Answer]
# Python - 204
Ok, I'll go first:
```
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:
To 'optimize' the output, this can be added before the `print` statement,
```
for e in x:
 if e in y:x.remove(e);y.remove(e)
```
bringing the total up to **266 characters**, I believe.
[Answer]
# Perl - 310 306 294 288 272
I'm a little rusty with perl and never did a code-golf... but no excuses. Char-count is without line-breaks. Using 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"
```
I'm looking forward to critics and hints. It's not so easy to find tips and tricks for code-golf (in perl).
[Answer]
# swi-prolog, 324 250 248 204 bytes
Prolog does pretty well at solving a problem like this.
```
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 is passed as a term parameter to predicate `m`. Output is written to stdout. Sorry about the trailing 'true'; that's just the interpreter's way of letting me know everything was fine.
```
?- m(54:20).
24:40 24:16 24:8 
true.
?- m(7:7).
true.
?- m(7:1).
IMPOSSIBLE
true.
```
[Answer]
# C, 246 216 213 bytes
In a (futile) attempt to beat my own Prolog solution, I completely rewrote the C solution.
```
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);}
```
My original C solution (246 bytes):
```
#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);}
```
It was a nice exercise to prove it can be done without building lists.
[Answer]
## Pyth, 101 bytes
```
D'HJH=Y[)VP30W!%JN=/JN=Y+NY))R,YJ;IneKhm'vdcz\:J"IMPOSSIBLE").?V.t,.-Y.-hK=J.-hKYJ1In.*Npj\:m*8d_Np\ 
```
An implementation of [@daniero' python answer](https://codegolf.stackexchange.com/a/7148/32686) but semi-optimised for 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
```
[Try it here](http://pyth.herokuapp.com/?code=D%27HJH%3DY%5B%29VP30W!%25JN%3D%2FJN%3DY%2BNY%29%29R%2CYJ%3BIneKhm%27vdcz%3AJ%22IMPOSSIBLE%22%29.%3FV.t%2C.-Y.-hK%3DJ.-hKYJ1In.*Npj%3Am*8d_Np+&input=9%3A4&test_suite=1&test_suite_input=1%3A5&debug=0)
[Or test every case](http://pyth.herokuapp.com/?code=D%27HJH%3DY%5B%29VP30W!%25JN%3D%2FJN%3DY%2BNY%29%29R%2CYJ%3BIneKhm%27vdcz%3AJ%22IMPOSSIBLE%22%29.%3FV.t%2C.-Y.-hK%3DJ.-hKYJ1In.*Npj%3Am*8d_Np+&input=9%3A4&test_suite=1&test_suite_input=1%3A5%0A10%3A1%0A9%3A4%0A7%3A1%0A7%3A7%0A6%3A15&debug=1)
[Answer]
## ES6, 230 bytes
```
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` `)
```
One of my longest golfs, so I must have done something wrong... 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(" ");
}
```
]