Connect1 @@ connect([E1|R1],[E2|R2]) :- E1=E2, connect(R1,R2).
Connect2 @@ connect([],[]) :- ().

Shift1 @@ S=shift([E|R]) :- S=shift(E,R).
Shift2 @@ S=shift(E,[C|R]) :- S=[C|shift(E,R)].
Shift3 @@ S=shift(E,[]) :- S=[E].

NShift1 @@ N=nshift($count, L) :- $count = 0 | N=L.
NShift2 @@ N=nshift($count, L) :- $count > 0 | N=nshift($count-1,shift(L)).

Cut1 @@ cut(L,EB,EE,LREST,$size) :- $size=0 | LREST=L, EB=EE.
Cut2 @@ cut([E|L],EB,EE,LREST,$size) :- $size>0 |
        EB=[E|EBB],cut(L,EBB,EE,LREST,$size-1).

// C : 15 * $size^2 + 45 * $size + 30
Dome @@ R=dome($size) :- int($size) |
  p(line(ELB01,ELE01,ELB42,ELE42,$size,T0),
    line(ELB11,ELE11,ELB02,ELE02,$size,T1),
    line(ELB21,ELE21,ELB12,ELE12,$size,T2),
    line(ELB31,ELE31,ELB22,ELE22,$size,T3),
    line(ELB41,ELE41,ELB32,ELE32,$size,T4)),
  p(L0,L1,line(ELB03,ELE03,ELB0,ELE0,$size,H0),T0,H4),
  p(L2,L3,line(ELB13,ELE13,ELB1,ELE1,$size,H1),T1,H0),
  p(L4,L5,line(ELB23,ELE23,ELB2,ELE2,$size,H2),T2,H1),
  p(L6,L7,line(ELB33,ELE33,ELB3,ELE3,$size,H3),T3,H2),
  p(L8,L9,line(ELB43,ELE43,ELB4,ELE4,$size,H4),T4,H3),
  triangle(ELB01,ELE01,ELB02,ELE02,ELB03,ELE03,$size),
  triangle(ELB11,ELE11,ELB12,ELE12,ELB13,ELE13,$size),
  triangle(ELB21,ELE21,ELB22,ELE22,ELB23,ELE23,$size),
  triangle(ELB31,ELE31,ELB32,ELE32,ELB33,ELE33,$size),
  triangle(ELB41,ELE41,ELB42,ELE42,ELB43,ELE43,$size),
    R=[L0,L1|cover(ELB0,[L2,L3|cover(ELB1,[L4,L5|cover(ELB2,[L6,L7|cover(ELB3,[L8,L9|cover(ELB4,[])])])])])],
    ELE0=[],ELE1=[],ELE2=[],ELE3=[],ELE4=[].

// C : $size * 10
Cover1 @@ R=cover([E1,E2|ER],NEXT) :- c(E1,E3,c(E2,E4)), R=[E3,E4|cover(ER,NEXT)].
Cover2 @@ R=cover([],NEXT) :- R=NEXT.

// C : $len * 2
Line1 @@ line(ELB1,ELE1,ELB2,ELE2,$len,L,R) :- $len = 0 | L=R, ELB1=ELE1, ELB2=ELE2.
Line2 @@ line(ELB1,ELE1,ELB2,ELE2,$len,L,R) :- $len > 0 |
           line(ELR1,ELE1,ELR2,ELE2,$len-1,L,c(E2,E4)),
           R=c(E1,E3), ELB1=[E1,E2|ELR1], ELB2=[E3,E4|ELR2].

// C : 3 * $size^2 + 3 * $size
Triangle1 @@ triangle(EL1,EL1,EL2,EL2,EL3,EL3,$size) :- $size = 0 | ().
Triangle2 @@ triangle([E1|ELB1],ER1,[E3|ELB2],ER2,[E5|ELB3],ER3,$size),
               ELE1=[E2|ER1], ELE2=[E4|ER2], ELE3=[E6|ER3] :- $size > 0 | 
               triangle(SLB1,SLE1,SLB2,SLE2,SLB3,SLE3,$size-1),
               line(LLB1,[],SLB1,SLE1,$size-1,c(E2,M2),c(E1,M1)),
               line(LLB2,[],SLB2,SLE2,$size-1,c(E4,M3),c(E3,M1)),
               line(LLB3,[],SLB3,SLE3,$size-1,c(E6,M3),c(E5,M2)),
                 ELE1=[], ELE2=[],ELE3=[],
                 connect(ELB1,LLB1),connect(ELB2,LLB2),connect(ELB3,LLB3).

// C : 5
Pen @@ p(L0,L1,L2,L3,L4) :-
  c(L0,X0,X4), c(L1,X1,X0), c(L2,X2,X1), c(L3,X3,X2), c(L4,X4,X3).

// C : $len * ($size * 10 + 10)
Tube1 @@ tube ( EL1, EL2, $len) :- $len = 0 | connect(shift(EL1), EL2).
Tube2 @@ tube ( EL1, EL2, $len) :- $len > 0 | tube(ring(shift(EL1)), EL2, $len-1).

Ring1 @@ R=ring([E1,E2|EL1]) :- c(E1,E3,c(E2,E4)), R=[E3,E4|ring(EL1)].
Ring2 @@ R=ring([]) :- R = [].

// C :  60 * $size^2 + 120 * $size + 60
Ball @@ ball($size) :- int($size) |
    tube(dome($size),nshift($size*2,dome($size)), $size*3).

C60Tube @@ c60_tube($length) :- int($length) |
    tube(dome(0),dome(0),$length).

c60 :- ball(0).
c240 :- ball(1).
c540 :- ball(2).
c960 :- ball(3).
c1500 :- ball(4).

c60_tube(50).