C #, 660 байт
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}));}}}
Спробуйте це в Інтернеті
Це було дуже весело !! Повна програма, приймає вхід від STDIN, вихід на STDOUT. Вихід - це передачі в порядку від кінця до початку. Використання:
Здійснює простий пошук першої ширини, який вирішує проблему з 4 передачами менше ніж за секунду. Коефіцієнт розгалуження насправді не настільки великий, тому він повинен бути хорошим для значно більше (не дуже перевіреного). На жаль, він використовує Linq.
Q
Рядок являє собою таблицю всіх дозволених з'єднань передач (тобто r=3
і підключення до r=1
якщо dx=4
і dy=0
) в одному квадраті, який потім повертається , щоб знайти інші. Кожен набір з 3 -х байт є dx
, dy
і інформація радіус правового зв'язку. Вибір (
як зміщення був дуже обдуманим: колись було весело обирати символ ASCII для приємних властивостей, а не відчайдушно намагатися знайти приємні властивості для нав'язаних символів ASCII.
Я, напевно, можу зробити кращу роботу з читанням матеріалів, але мені ще не пощастило, в останню чергу тому, що Linq оплачується потребою у списку. Я також дуже розчарований кодом обертання, я відчуваю, що це можна зробити в значно меншій кількості байтів.
Форматований та коментований код з Q
генератором:
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
}));
}
}
}