C #, 660 bayt
using System.Linq;using System;class P{int p=1,x,y,r;P l;static void Main(){var Q="$&.$'7$(@$*R$'/$(8$)A'(A('A$+S$(0$)9'(9('9$*B$,T$*2$+;$,D$.V*,V,*V";var I=Console.ReadLine().Split(',').Select(int.Parse).ToList();int i=0,t,s=7,u,v,w,p=I[3]*I[2];for(var D=new[]{new P{r=Math.Abs(I[3]),l=new P{r=Math.Abs(I[2]),x=I[0],y=I[1],p=3}}}.ToList();i>=0;){P c=D[i++],l=c.l;for(;(l=l?.l)!=null&&(s=(t=c.x-l.x)*t+(t=c.y-l.y)*t-(t=c.r+l.r)*t)>0;);if(s==0&&l.p>2&p*c.p<0)for(i=-1;c.l.p<3;c=c.l)Console.WriteLine(c.x+","+c.y+","+c.r);for(t=0;s>0&t<66;t++)for(u=Q[t++]-36,v=Q[t++]-36,s=1;s++<5&Q[t]%9==c.r;w=u,u=v,v=-w,D.Add(new P{l=c,r=Q[t]/9-4,x=c.x+u,y=c.y+v,p=-c.p}));}}}
Çevrimiçi Deneyin
Bu çok eğlenceliydi! Komple program, STDIN'den girişi, STDOUT'a çıkışı kabul eder. Çıkış, uçtan başa doğru sırasıyla dişlilerdir. Kullanımı:
4 vitesli bir sorunu bir saniyeden daha kısa sürede çözen basit bir Genişlik İlk Arama gerçekleştirir. Dallanma faktörü aslında o kadar büyük değil, bu yüzden önemli ölçüde daha fazlası için iyi olmalı (gerçekten test edilmedi). Ne yazık ki Linq kullanıyor.
Q
Dize tüm izin dişli bağlantılarının bir tablodur (bir yani r=3
ve bir bağlanmak r=1
eğer dx=4
ve dy=0
) daha sonra diğerlerini bulmak için döndürülür bir kadranda, içinde. 3 bayt Her kümesidir dx
, dy
yasal bir bağlantı için, ve yarıçap bilgileri. (
Bir ofset olarak seçim çok kasıtlıydı: bir kereliğine, empoze edilen ASCII karakterleri için güzel özellikler bulmaya çalışmak yerine, güzel özellikler için bir ASCII karakteri seçmek eğlenceliydi.
Muhtemelen girdiyi okumak için daha iyi bir iş yapabilirim, ama henüz şansım olmadı, en azından Linq'e bir liste ihtiyacı nedeniyle ödeniyor. Ayrıca döndürme kodu ile çok hayal kırıklığına uğradım, bu çok daha az bayt içinde yapılabilir gibi hissediyorum.
Q
Jeneratör ile Biçimlendirilmiş ve Yorumlanmış Kod :
using System.Linq; // seems to pay today
using System;
class P
{
static void GenQ()
{
int t, k = 0, m = 0;
Func<P, P, int> C = (P c, P l) => (t = c.x - l.x) * t + (t = c.y - l.y) * t - (t = c.r + l.r) * t; // ==0 -> touching, <0 -> not touching, >0 -> overlap
string str = "";
string T(int i) => "" + (char)('$' + i); // $ is zero, '$' == 36, so we can mod and div by 9, and greater than " so we don't have to escape it
foreach (int r in new[] { 1, 2, 3, 5 }) // at 0,0 (current gear)
foreach (int s in new[] { 1, 2, 3, 5 }) // gear to place
for (int i = 0; i <= r + s; i++) // x
for (int j = 1; j <= r + s; j++, m++) // y
if (C(new P { r = r }, new P { r = s, x = i, y = j }) == 0) //
{
str += T(i) + T(j) + T(r + s * 9);
k++;
}
System.Console.WriteLine("K : " + k);
System.Console.WriteLine("M : " + m);
System.Console.WriteLine(str);
System.Console.ReadKey(true);
return;
}
int p=1, // parity
x, // x
y, // y
r; // radias (TODO: store radias^2 ?)
P l; // previous in search list
static void Main()
{
//GenQ();
// '$' == 36 (4*9)
// 3char blocks: x,y,r+9*s
var Q="$&.$'7$(@$*R$'/$(8$)A'(A('A$+S$(0$)9'(9('9$*B$,T$*2$+;$,D$.V*,V,*V"; // quarter table
// primative read ints
var I=Console.ReadLine().Split(',').Select(int.Parse).ToList();
int i=0, // position in Due
t, // check differential cache, position in Q
s=7, // check cache, rotation counter (>0)
u, // rotation x
v, // rotation y
w, // rotation x cache
p=I[3]*I[2]; // parity (>0 -> same, even ; <0 -> different, odd)
// due (not point using a queue, the search space grows exponentially)
for(var D=new[]{
new P{r=Math.Abs(I[3]), // start (p==1)
l=new P{r=Math.Abs(I[2]),x=I[0],y=I[1],p=3} // terminal (detect with p==3)
}}.ToList();
i>=0;) // infinite number of configurations, no bounds, i is escape term
{
P c=D[i++], // current
l=c.l; // check, initially the one before the previous (we know we are touching last already)
// 'checks' c against l
//Func<int>C=()=>(t=c.x-l.x)*t+(t=c.y-l.y)*t-(t=c.r+l.r)*t; // ==0 -> touching, >0 -> not touching, <0 -> overlap
// check we arn't touching any before us (last thing we check is terminal)
for(;(l=l?.l)!=null&& // for each before us (skipping the first one)
(s=(t=c.x-l.x)*t+(t=c.y-l.y)*t-(t=c.r+l.r)*t)>0;); // check c against l and cache in s, ==0 -> touching, >0 -> not touching, <0 -> overlap
if(s==0&& // touching last checked?
l.p>2& // stopped on terminal?
p*c.p<0) // correct parity? -> win
for(i=-1; // escape
c.l.p<3;c=c.l) // for each that wasn't the first
Console.WriteLine(c.x+","+c.y+","+c.r);
// enumerate possible additions, and queue them in due
for(t=0;
s>0& // not touching or overlapping anything (including terminal)
t<66;t++) // 66 = Q.Length
for(
u=Q[t++]-36, // '$'
v=Q[t++]-36,
s=1;s++<5& // rotate 4 times
Q[t]%9==c.r; // our raidus matches
w=u, // chache y value
u=v, // rotate
v=-w,
D.Add(new P // add
{
l=c,
r=Q[t]/9-4, // radius
x=c.x+u,
y=c.y+v,
p=-c.p // flip parity
}));
}
}
}