Паролі сильно проти єпископів


13

Не плутати з паролем Єпископ Добро !

Давши рядок, дайте відповідь (правда / фальшивість або два послідовних значення), якщо він є паролем, який є сильним проти єпископів .

Пароль є сильним проти єпископів, якщо це рядок, що складається з чергування букв (в a-h) та цифр (в 1-8), таким чином, що кожна пара символів може бути інтерпретована як квадрат на шаховій дошці, і якщо ви розміщуєте білий пішак на кожному квадраті з назвою в паролі, тоді білий єпископ не може подорожувати в будь-якій кількості послідовних рухів, від будь-якої площі в першому ( 1) рядку до будь-якого квадрата в останньому ( 8) рядку.

Приклади

Паролі сильні проти єпископів

  • a1b1c1d1e1f1g1h1
  • a8b8c8d8e8f8g8h8
  • a1b2c3d4d5f5f4g3g4h2b5
  • h4g4f4e4c4b4a4c3e3
  • a1b1c1d1e1f1g1a8b8c8d8e8f8g8
  • b4b5d4d5f4f5g3h5

Наприклад, a1b1c1d1e1f1g1a8b8c8d8e8f8g8відповідає позиції fooі b4b5d4d5f4f5g3h5відповідає позиціїfoo

Паролі слабкі проти єпископів

  • a4c4e4g4g5d6f6e3d2b2 (добре сформована, але не сильна - дякую Джо Кінгу за цей приклад!)
  • b1c1d1e1f1g1h1a8b8c8d8e8f8g8 (добре сформований, але не сильний)
  • h4g4f4e4c4b4a4c3 (добре сформований, але не сильний)
  • d4 (добре сформований, але не сильний)
  • b4b5d4d5f4f5g2h5 (добре сформований, але не сильний)
  • correct horse battery staple (неправильно сформований)
  • 1a1b1c1d1e1f1g8a8b8c8d8e8f8g (неправильно сформований)
  • a (неправильно сформований)
  • aa (неправильно сформований)

1
Яких кольорів кольорів продовжує єпископ?
Втілення

2
Ваш останній тестовий випадок суперечить вашим характеристикам. Вам також потрібно пояснити, як " кожну пару символів можна інтерпретувати як квадрат на шаховій дошці ".
Кошлатий

1
a1b2c3d4d5f5f4g3g4h2b5 не є сильним проти єпископів, оскільки єпископ може дістатись до h5, а потім спуститися до d1
Втілення невігластва

2
@TRITICIMAGVS, Ourous: Я уточнив, що і пішаки, і єпископ білі, тому ні одному не дозволяється захоплювати (або приземлятися, або рухатися, або перестрибувати) іншого.
Квомплусон

1
Також, чи можете ви додати приклад для одного із тестових справ. Тому що я розумію, що квадрати пароля заповнені білими пішаками, але я не розумію, де розміщений білий єпископ. І якщо місце це добре, чому вона не може поїхати в кожному рядку 1через 8в першому тесті? Він не може подорожувати до кожного стовпця, оскільки aстовпець повністю заповнений пішаками, але він може переходити до кожного ряду без проблем, чи не так? У мене є відчуття, що мені чогось не вистачає ..: S
Кевін Круїйсен

Відповіді:


4

Рубі, 115 182 163 байт

->s{z=('00'..'99').map{|x|x=~/[09]/||s[(x[1].ord+48).chr+x[0]]};(11..18).map &g=->x{z[x]||[x-11,x-9,x+z[x]=9,x+11].map(&g)};s=~/^([a-h][1-8])*$/&&(z[81,9]-[9])[8]}

Спробуйте в Інтернеті!

Повертається 1для сильних і nilдля слабких. (+67 байт був для врахування "зворотного відстеження".)

->s{
 z=                             # this is the board
 ('00'..'99').map{|x|           # coordinates are described as y*10 + x
  x=~/[09]/||                   # truthy if out of bounds...
  s[(x[1].ord+48).chr+x[0]]     # ...or impassable
 }                              # now only the passable squares are falsey
 (11..18).map                   # for each x position at y=1,
  &g=->x{                       # call helper function on that square
   z[x]||                       # if the square is passable (i.e. falsey),
    [x-11,x-9,x+z[x]=9,x+11]    # mark it impassable by setting to 9 (truthy)
     .map(&g)                   # call helper recursively for each neighbor
  }
 s=~/^([a-h][1-8])*$/           # make sure the input was valid,
 &&(z[81,9]-[9])[8]             # and check that the last row was never reached
}

Кілька використаних хитрощів:

  • Замість числового діапазону 0..99ми використовуємо діапазон рядків,'00'..'99' щоб число автоматично було ліворуч до двох цифр і було закреслено рядком. Це робить поза межами перевірки дуже короткою - відповідність з регулярним виразом /[09]/.

  • Усередині функції - помічника, при побудові списку нових координат [x-11, x-9, x+9, x+11], ми одночасно призначити z[x]для 9процесу, який , трапляється, значення truthy (маркування квадрат відвідуваний).

  • В останньому рядку ми хочемо перевірити, z[81,9]чи не містить масив 9. Ми робимо це, видаляючи всі екземпляри 9( z[81,9]-[9]), а потім запитуємо 9-й елемент результуючого масиву ( [8]). Оскільки ми знаємо, що в масиві спочатку було 9 елементів, якщо такі були вилучені, ми отримаємо nil, тоді як якщо всі вони залишилися, ми отримаємо останній елемент масиву (який трапляється завжди 1).


2

Python 2 , 330 318 313 309 370 байт

import numpy as n
b=n.ones([8,8])
q=r=1
s=input()
l=len(s)
def g(x,y=0,p=0):
    if b[y,x]and p<32:
        if y<7:
            if x<7:
                g(x+1,y+1,p+1)
                if y:g(x+1,y-1,p+1)
            if x:
                g(x-1,y+1,p+1)
                if y:g(x-1,y-1,p+1)
        else:global q;q=0
for i in range(l/2):
    x=ord(s[2*i])-97;y=ord(s[2*i+1])-49
    if y>8or y<0 or l%2or x>8or x<0:r=0
    if r:b[7-y,x]=0
map(g,range(8))
print q&r

Спробуйте в Інтернеті!

Спробуйте практичну версію онлайн! (оригінал може зайняти 4 ^ 32 операції, щоб повністю перевірити, я пропоную використовувати цю - таку ж кількість байтів)

Не надто коротке рішення - я не міг зрозуміти, як зробити версію функції лямбда на g коротшою, ніж сама.

-4 байти завдяки Quuxplusone

+61 байт, що враховує зворотний трек (спасибі за вказівку на те, що Джо Кінг та поради щодо гольфу)


Приємно. q=r=1було б коротше q=1 r=1, правда? І if r:коротше, ніж if r>0:.
Quuxplusone

2

Пітон 2 , 490 476 474

def f(p):
 a=[set(ord(c)-33 for c in s)for s in"* )+ *, +- ,. -/ .0 / \"2 !#13 \"$24 #%35 $&46 %'57 &(68 '7 *: )+9; *,:< +-;= ,.<> -/=? .0>@ /? 2B 13AC 24BD 35CE 46DF 57EG 68FH 7G :J 9;IK :<JL ;=KM <>LN =?MO >@NP ?O BR ACQS BDRT CESU DFTV EGUW FHVX GW JZ IKY[ JLZ\\ KM[] LN\\^ MO]_ NP^` O_ R QS RT SU TV UW VX W".split()];x=set((ord(p[i+1])-49)*8+ord(p[i])-97 for i in range(0,len(p),2))
 r=set(range(8))-x
 for i in range(99):r=set().union(*[a[c]for c in r])-x
 return all(c<56 for c in r)

Спробуйте в Інтернеті!

Це працює за допомогою "заливної заливки". Спочатку ми створюємо список, aякі квадрати примикають до інших квадратів, єпископські. Потім створюємо набір xвиключень (виходячи з пароля). Потім ми ініціалізуємо набір rквадратів, що доступні, який починається як тільки перший ряд (мінус будь-які виключення), і неодноразово «заливається» назовні, звідси, 99 разів, що має бути більш ніж достатньо. Нарешті, ми перевіряємо, чи не потрапив будь-який з квадратів в останньому ряду в нашому досяжному наборі. Якщо так, у нас слабкий пароль! Якщо ні, у нас є надійний пароль.

Недолік, можливо, дискваліфікація (я не знаю тут звичайного правила): Якщо пароль неправильно сформований (наприклад, "правильний штабельний акумулятор"), ми викидаємо виняток замість повернення False. Але ми завжди повертаємо Trueiff, якщо пароль сильний!

Мінус 16 байт завдяки Джо Кінгу. Ми вказуємо aв одному місці, де воно використовується, і постійно складаємо деяку математику.

def f(p):
 x=set(ord(p[i])-489+8*ord(p[i+1])for i in range(0,len(p),2));r=set(range(8))-x
 for i in[1]*99:r=set().union(*[[set(ord(k)-33for k in s)for s in"* )+ *, +- ,. -/ .0 / \"2 !#13 \"$24 #%35 $&46 %'57 &(68 '7 *: )+9; *,:< +-;= ,.<> -/=? .0>@ /? 2B 13AC 24BD 35CE 46DF 57EG 68FH 7G :J 9;IK :<JL ;=KM <>LN =?MO >@NP ?O BR ACQS BDRT CESU DFTV EGUW FHVX GW JZ IKY[ JLZ\\ KM[] LN\\^ MO]_ NP^` O_ R QS RT SU TV UW VX W".split()][c]for c in r])-x
 return all(c<56for c in r)

@JoKing дякую! Ще два пробіли до двох forсекунд, які я не бачив, як їх видалити. Я виявив, що заміни range(99)на repr(f)роботи на моїй локальній машині, але не на перекладача tio.run ... але потім я виявив, що [1]*99все одно було коротше! Так що збережено ще 4 байти.
Quuxplusone

пробіл до двох forс, який я не бачив, як видалити - О! Мабуть, Python трактує 33forяк два лексеми (тоді як for33це буде один маркер). Сьогодні я дізнався. Мінус ще 2 байти, значить.
Quuxplusone

1

Чисто , 285 байт

import StdEnv,Data.List
$_[_]=1<0
$a[x,y:l]=case[[u,v]\\u<-[0..7],v<-[0..7]|u==toInt x-97&&v==toInt y-49]of[p]= $[p:a]l;_=1<0
$a _=all(\[_,y]=y<7)(iter 64(nub o\e=e++[k\\[u,v]<-e,p<-[-1,1],q<-[-1,1],k<-[[abs(u+p),abs(v+q)]]|all((<>)k)a&&all((>)8)k])(difference[[e,0]\\e<-[0..7]]a))

$[]

Спробуйте в Інтернеті!

$[]буде $ :: [[Int]] [Char] -> Boolскладено з першим аргументом, що дає \ [Char] -> Bool.

Функція працює, використовуючи рядок два символи одночасно, негайно повертаючи помилку, якщо рядок у недійсному форматі, як тільки вона бачить недійсну частину. Після того, як рядок буде оброблений, вона розміщує єпископа на кожному порожньому квадраті з одного боку дошки і всіляко переміщує їх 64 рази і перевіряє, чи є одна з кінцевих позицій у цільовому ряду.


Здається, неправильно повернутися Trueдо a1b1c1d1e1f1g1? Не те, щоб я щось розумів, як це працює. :)
Quuxplusone

2
@Quuxplusone У мене був мозок і я думав, що білі єпископи використовують лише білі квадрати. Я також додав пояснення.
Οurous

1

Мова Вольфрама (Mathematica) , 339 316 358 353 345 байт

-23 байти завдяки @Doorknob.

+42 байти обліку зворотного відстеження.

p[m_]:=StringPartition[#,m]&;l=Range@8;f[n_]:=Check[w=(8#2+#1-8)&@@@({LetterNumber@#,FromDigits@#2}&@@@(p@1/@p[UpTo@2]@n));g=Graph[Sort/@UndirectedEdge@@@Position[Outer[EuclideanDistance@##&,#,#,1],N@Sqrt@2]&@GraphEmbedding@GridGraph@{8,8}//Union]~VertexDelete~w;c:=#~Complement~w&;m=0;Do[m+=Length@FindPath[g,i,j],{i,c@l},{j,c[l+56]}];m==0,0>1]

Спробуйте в Інтернеті!

Я переписав більшу частину цього для врахування зворотного відстеження, я думаю, що може бути простіший спосіб визначення графіка g, Mathematica має GraphData[{"bishop",{8,8}}]такий графік усіх рухів, який єпископ може зробити на шаховій дошці ( Bishop Graph ), але цей графік включає додаткові з'єднання ніж найближчий діагональний сусід. Якщо хтось знає коротший спосіб зробити це, дайте мені знати. Кредит на побудову графіка відповідає цій відповіді MathematicaSE .

Повернення Trueдля надійних паролів, Falseдля слабких / неправильно сформованих паролів. Зауважте, що для більшості неправильно сформованих паролів він створить купу повідомлень про помилки, а потім повернеться False. Якщо це не відповідає правилам, їх можна придушити, перейшовши f[n_]:=...на f[n_]:=Quiet@...6 байт.

Безголівки:

p[m_] := StringPartition[#, m] &;

f[n_] :=
 Check[
  w = (8 #2 + #1 - 
       8) & @@@ ({LetterNumber@#, FromDigits@#2} & @@@ (p@1 /@ 
        p[UpTo@2]@n));
  r = GridGraph[{8, 8}];
  g = Graph[Sort /@ UndirectedEdge @@@
             Position[Outer[EuclideanDistance@## &, #, #, 1],N@Sqrt@2] &@
              GraphEmbedding@r // Union]~VertexDelete~w;
  s = Complement[{1,2,3,4,5,6,7,8},w];
  e = Complement[{57,58,59,60,61,62,63,64},w];
  m = 0;
  Do[m += Length@FindPath[g, i, j], {i, s}, {j, e}];
  If[m == 0,True,False]
  , False]

Зламатися:

p[m_]:=StringPartition[#,m]& 

Бере аргумент рядка і розбиває його на список рядків кожної довжини m.

Check[...,False]

Повертається, Falseякщо створюються будь-які повідомлення про помилки, саме так ми фіксуємо неправильно сформовані рядки (тобто припускаємо, що вони добре сформовані, неминуче створюючи помилку внизу лінії).

(8*#2 + #1 - 8) & @@@ ({LetterNumber@#, FromDigits@#2} & @@@ (p@1 /@ 
        p[UpTo@2]@n));

Займає рядок позицій пішака і розбиває його таким, що "a2h5b"стає {{"a","2"},{"h","5"},{"b"}}, потім LetterNumberперетворює букву в число ( a -> 1і т.д.) і FromDigitsперетворює цифру в ціле число. Якщо рядок не сформований належним чином, цей крок призведе до помилки, яка буде викрита Check, повертаючись False. Ці два числа потім перетворюються на ціле число, що відповідає квадрату на дошці.

r = GridGraph[{8, 8}];
g = Graph[
     Sort /@ UndirectedEdge @@@ 
          Position[Outer[EuclideanDistance@## &, #, #, 1], 
           N@Sqrt@2] &@GraphEmbedding@r // Union]~VertexDelete~w;

Побудує графік усіх діагональних країв найближчого сусіда з видаленими положеннями пішаків.

s = Complement[{1,2,3,4,5,6,7,8},w];
e = Complement[{57,58,59,60,61,62,63,64},w];

Це списки незайнятих вершин і початкових кінців відповідно

m=0
Do[m += Length@FindPath[g, i, j], {i, s}, {j, e}];
If[m == 0,True,False]

Петлі над початковою і кінцевою вершинами, для кожної пари FindPathбуде список шляхів між ними. Якщо між ними немає шляхів, це буде порожній список, тому Length@повертається 0. Якщо шляхів взагалі немає, то mбуде нуль, і ми повернемося True, інакше повернемось False.


Кілька порад: Trueі Falseможе бути, 1>0і 0>1відповідно. p[1]@#&/@рівнозначно справедливому p@1/@. Sequence@@можна замінити на ##&@@. Замість цього {LetterNumber[#[[1]]],FromDigits[#[[2]]]}&/@можна використовувати {LetterNumber@#,FromDigits@#2}&@@@.
Дверна ручка

@Doorknob дякую! Гольф з кодом навчає мене всіляких нових речей про Mathematica. Я все ще не на 100% розумію p@1/@, але бачу загальну ідею. Я думаю p@1 = StringPartition[#,1]&, це трохи заплутано для мене, я здогадуюсь, тому що pдва аргументи мають два різні способи: один як, m_а інший як #...&, я думаю, це лише питання пріоритету. Це має сенс хоча p@m = p[m].
Кай

Це є і для мене! Основна зміна там полягає в тому, що для будь-якої функції, fяка приймає один аргумент, f@#&є така ж поведінка, як і просто f- ось, fє p[1]. (Тоді я змінив []позначення на @, яке завжди тотожне, крім пріоритету.)
Дверна ручка

@JoKing це хитро, це складніше, ніж я думав спочатку, також потрібно враховувати рухи назад. Дякую
Кай

@JoKing написав нове, яке пояснює зворотний трек.
Кай
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.