Кубик Рубика Борется

21

Ваша задача - создать случайную последовательность ходов, которую можно использовать для шифрования кубика Рубика. Такая схватка состоит из ровно 25 ходов. Каждый ход состоит из букв, UDRLFBза которыми может следовать один из суффиксов '2.

Это обозначение называется обозначением Singmaster. UDRLFBпредставляет одну из 6 граней, а необязательный суффикс '2представляет угол поворота. Эта информация ни в коем случае не является необходимой для решения задачи.

Чтобы гарантировать, что схватки имеют «хорошее качество», должны применяться следующие два правила:

  • Два последовательных хода не должны иметь одинаковую букву. Это запрещает последовательные шаги UU, DD, RR, LL, FFи BBвсе их комбинации с использованием дополнительных суффиксов , как U2Uили U'U'.

    Эти пары ходов запрещены, потому что они могут быть легко уменьшены до 1 или 0 ходов. U2Uимеет тот же эффект, что U'и R'Rтот же эффект, что и .

  • Три последовательных хода не должны относиться к одной группе букв. Буквенные группы UD, RLи FB. Это правило дополнительно запрещает последовательные шаги UDU, DUD, RLR, LRL, FBF, BFBи все их комбинации с использованием дополнительных суффиксов , как U2DU, RL'Rили B2FB'.

    Группы сортируют грани по их оси перемещения. Uи Dнаходятся в одной группе, потому что оба вращаются вокруг одной оси. Поэтому Uдвижение не влияет на части Dлица, и Dдвижение не влияет на части Uлица. Следовательно, два хода могут быть обменены, UDUимеет такой же эффект UUD, что и может быть уменьшен до U2D.

Вызов

Напишите скрипт или функцию, которая генерирует одну случайную схватку. Там нет ввода. Сценарий / функция должен печатать 25 ходов без разделения или разделенных одним пробелом или возвращать соответствующую строку.

Ваша программа должна быть в состоянии создать каждую схватку, которая удовлетворяет правилам выше. Конечно, предполагая, что генератор случайных чисел является истинно случайным, а не псевдослучайным.

Это код-гольф. Самый короткий код (в байтах ) выигрывает.

Примеры выходов:

Вызов скрипта / функции 3 раза должен напечатать / вернуть что-то вроде:

R'B2R2F2R2FB'R2DR2ULFB2RB'U2B'FL'BR'U'RB'
U'DBR'B2U'B'U'RUF'B'RDR2U'B'LR'B'F2D2UF2L'
BR2F'B'R'D'R'U2B'F2D2R'F2D'F'D2R2B'L2R'UB'R2L'D

Если вы разделяете ходы пробелом каждый:

R2 L' F2 U2 D' R2 L2 F L' D2 U R B D' U2 L B2 L U B2 D U2 R' D2 U'
B R D2 F U2 B' R2 F2 B' U' L' R2 B U2 R' D B' F' U2 R' B' L R D2 R2
B2 R2 U D' B R D' R L2 D2 L2 R B2 F U' F2 B2 U' F U' D F R2 U2 B'

Обратите внимание, что все эти выходные данные состоят из 25 ходов, но имеют разную длину из-за необязательных суффиксов. Это не разрешено печатать пространство, когда либо 2или 'являются использование в качестве суффикса. Вы должны распечатать L2UR2F'R'U2или L2 U R2 F' R' U2. L2U R2F'R'U2не разрешено.

Jakube
источник
Вы UR 2имели в виду не допускается? Я думаю, что это U R2 должно быть разрешено, поскольку промежутки между ходами имеют смысл.
mbomb007
@ mbomb007 Я имею в виду такие вещи, как L2U R2F'R'U2. Uне имеет необязательного суффикса и поэтому не должен иметь пробела. Пробел не должен заменять дополнительный суффикс.
Якуб
Что если между каждым ходом есть пробелы? Можем ли мы вывести U F2 L D2 R'..., например? В этом случае нет лишнего пробела, который, по моему мнению, должен быть в порядке в соответствии с вашим правилом.
mbomb007
@ mbomb007 Да, я добавлю это в описание.
Якуб
Разве 2 перед письмом? oO
Оливер Ни

Ответы:

6

CJam, 47 45 байт

Это решение использует подход, который отличается от любого другого, опубликованного до сих пор. Он использует преимущества сжатого списка операций CJam для создания доступного списка перемещений и случайного выбора одного из них. Модификаторы просто генерируются независимо.

Попробуйте онлайн.

{BA^2/6,_B-?A:B-mr0=:A"UDRLFB"=3mr[L2'']=}25*

объяснение

{               "Loop...";
  BA^2/           "If the two previous moves were not from the same group, ...";
  6,              "... then produce the available move list [0 1 2 3 4 5], ...";
  _B-             "... else produce the available move list [0 1 2 3 4 5] with
                   the second previous move removed";
  ?
  A:B             "Save the previous move as the second previous move";
  -               "Remove the previous move from the available move list";
  mr0=            "Randomly select an available move";
  :A              "Save this move as the previous move";
  "UDRLFB"=       "Map this move to its character (implicitly printed)";
  3mr[L2'']=      "Randomly select a modifier (implicitly printed)";
}25*            "... 25 times";
Runer112
источник
9

С, 129

f(){int i,n,m,r,s,t;for(i=26;i--;i<25&&printf("%c%c","URFDLB"[s%6],"'2"[r%3])){for(n=m,t=1;t;t=m*n==9)m=(r=rand()%15)/3+1;s+=m;}}

Внутренний цикл генерирует значение mв диапазоне, 1..5которое при добавлении sи взятии по модулю 6 гарантирует, что никакие два последовательных движения не будут на одной стороне куба. Старое значение mсохраняется в, nи тест m*n==9гарантирует, что значение m= 3 никогда не будет сгенерировано дважды в строке (поэтому противоположные грани нельзя выбрать два раза подряд; обратите внимание на порядок граней в строке.)

Наименее значительная часть rиспользуется для определения , какой суффикс ( ', 2или нуль) , чтобы использовать, воспользовавшись нулевым символом в конце "'2".

Внешний цикл работает 26 раз. Первый раз, Uникогда не может быть выбран, поэтому printfподавляется для первой итерации.

Разгруженный код в тестовой программе

Код ungolfed помещает пробел между каждым ходом для ясности (код в гольфе не делает, чтобы сохранить один байт.) Кроме того, код в гольф сохраняет точку с запятой, перемещая printfвнутри forскобки.

f(){
  int i,n,m,r,s,t;
  for(i=26;i--;){
    for(n=m,t=1;t;t=m*n==9)m=(r=rand()%15)/3+1;
    s+=m;
    i<25&&printf("%c%c ","URFDLB"[s%6],"'2"[r%3]);
  }
}

main(){
  int j;
  srand(time(0));
  for(j=0;j<5;j++)f(), puts("");
}

Типичный вывод

U' B D2 B' R' L F' D2 B D2 B2 R' B2 U D2 F' R U R' L B' L R2 B2 F'
U B U B F L2 D2 B' U' L B L R' D B U' D R D' B' F2 D' B D R
L D F2 B2 R' U F B' D2 L U R' L' U2 F' R F D U2 B L' B' U L2 F'
R2 B' F2 R2 L2 F' U2 L U' B' F R' D' F2 D F' L2 U2 R' D' B2 D F R2 L'
U2 F2 B2 D' F D F R L2 U' B D2 L' R D R F2 R' F2 U2 D R' D2 L F2
Уровень реки St
источник
118 байт
floorcat
4

Pyth, 65 66

Я никогда не играл в гольф на Pyth, может быть, написал программу или две. Это в основном @ решение steveverrill , переведенное на Pyth. Предложения по улучшению приветствуются.

Обновление: добавлен 1 байт, чтобы сделать схватки также начать сU . Может быть, решение C полагается на неопределенное поведение, чтобы заставить его работать ...

=YO6V25JZK1WK=GO15=Z/+3G3=Kq9*ZJ)~YZpd+@"URFDLB"%Y6?@"'2"%G3>2%G3k

Я считаю, что это должно быть сделано с меньшим количеством назначений, но это потребовало бы от меня много изменений в алгоритме. (Ну, может попробовать.)

Вот объяснение, основанное на коде C:

=YO6           s = random.choice(range(6))
V25            for i in range(25):
  JZ               n = m
  K1               t = 1
  WK               while t:
    =GO15              r = random.choice(range(15))
    =Z/+3G3            m = (r + 3) / 3
    =Kq9*ZJ            t = 9 == m * n
  )
  ~YZ              s += m
  pd               print(..., end = " ")
  +                ... + ...
  @"URFDLB"%Y6     "URFDLB"[s % 6]
  ?@"'2"%G3>2%G3k  "'2"[G % 3] if 2 > G % 3 else ""
PurkkaKoodari
источник
Переключите переменные Yи Z. Zинициализируется 0, поэтому вы сохраняете первые 3 символа.
Якуб
@Jakube Но тогда мне нужно установить n = m(3-я строка объяснения), что должно означать n = 0первый раз, который в свою очередь должен Yбыл бы быть 0.
PurkkaKoodari
Yпредварительно инициализирован с пустым списком []. И я не думаю, что значение имеет nзначение в первой итерации.
Якуб
Кстати, ваш код не производит скремблирования, которые начинаются с U.
Якуб
@Jakube спасибо, исправлено.
PurkkaKoodari
4

JavaScript (ES6) 175 178 204

редактировать 3 байта меньше, 1 изменяя код и 2 изменяя способ подсчета байтов (не считая F=)

Код, позволяющий избежать повторений, взят из @stevemiller. Его способ управления группами писем еще лучше, но я не собираюсь его красть.

Бонус: вы можете по желанию указать количество ходов.

(n=25,R=n=>Math.random()*n|0)=>(r=>{for(N=_=>'UDRLFB'[(r-=~R(5))%6],b=N(a=N(s=''));n;~(a+b+c).search('^([UD]*|[RL]*|[FB]*)$')?0:s+=(--n,a=b,b=c)+["","'",2][R(3)])c=N()})(0)||s

Меньше гольфа

(n = 25) => 
{
  R = n => Math.random()*n | 0;
  N = _ => 'UDRLFB'[(r += 1+R(5)) % 6];
  r = 0;
  b = N();
  a = N();
  for(s = '' ; n; )
     c = N(),
     ~(a+b+c).search('^([UD]*|[RL]*|[FB]*)$')
       ? 0
       : s += (--n, a=b, b=c) + ["","'",2][R(3)];
  return s
}

Тестовое задание

var F=
(n=25,R=n=>Math.random()*n|0)=>(r=>{for(N=_=>'UDRLFB'[(r-=~R(5))%6],b=N(a=N(s=''));n;~(a+b+c).search('^([UD]*|[RL]*|[FB]*)$')?0:s+=(--n,a=b,b=c)+["","'",2][R(3)])c=N()})(0)||s

function go() {
  console.log(F(+M.value))
}

go()
Moves <input type=number min=1 id=M value=25 max=999>
<button onclick='go()'>Test</button>

edc65
источник
2

Javascript - 112

for(c=b=j=25,r=Math.random;j;c+b-5|c-m&&b-m?document.write("URFBLD"[j--,c=b,b=m]+" 2'"[0|r()*3]+" "):0)m=0|r()*6
Mama Fun Roll
источник
2

Java 8, 189 183 байта

v->{for(int i=26,n,m=0,r=0,s=0,t;i-->0;){for(n=m,t=1;t>0;t=m*n==9?1:0)m=(r=(int)(Math.random()*15))/3+1;s+=m;if(i<25)System.out.print("URFDLB".charAt(s%6)+(r%3<1?"'":r%3<2?"2":""));}}

Порт @LevelRiverSt C ответа «s . Я попробовал некоторые вещи сам, но это было короче, чем у меня было ..

Попробуйте онлайн.

Кевин Круйссен
источник
1

Clojure, 223 байта

(let[R(range)F(fn[f p c](apply concat(filter f(partition-by p c))))](apply str(map str(take 25(F(fn[p](<(count p)3))(zipmap"UDLF""1122")(F(fn[p](=(count p)1))int(for[_ R](rand-nth"UDRLFB")))))(for[_ R](rand-nth[""\'\2])))))

Это в значительной степени зависит от шаблона «sequence -> partition-by -> filter -> concat», он используется для фильтрации «недопустимых» последовательностей граней. Этот seq затем отображается на строку вместе со случайным постфиксом (включая пустую строку).

Исходная точка без швов:

(->> (for[_(range)](rand-nth"UDRLFB"))
     (partition-by int)           ; "identity" would be the correct fn to use here
     (filter(fn[p](=(count p)1))) ; Only one identical value in partition
     (apply concat)
     (partition-by(zipmap"UDLF""1122")) ; R & B are in the implicit nil group
     (filter(fn[p](<(count p)3)))       ; Only 1 or 2 consecutive faces from a group
     (apply concat)
     (take 25))
NikoNyrh
источник