Карел Дж. Генератор послідовностей AlphaBot


14

Оцінки

Цей розділ заповнюватиметься після введення матеріалів.

Нормальний

1. bopjesvla    Perl                54
2. edc65        Javascript (ES6)    91
3. name         language            score
4. name         language            score
5. name         language            score

Бонусний раунд

1. name   language   score
2. name   language   score
3. name   language   score
4. name   language   score
5. name   language   score

Карел Дж. АльфаБот

Фон

Популярний вступний курс до Java - це Карел Дж. Робот (я сам його використовую). Робот взаємодіє з сіткою вулиць (позитивні цілі y-координати) та проспектами (позитивні цілі x-координати), а також бджолами, які можна розміщувати та зберігати в сітці (зауважте, що Карел та будь-які бджоли можуть існувати лише на ґратах бали). Карел (робот) повинен виконати лише п’ять дій: рухатися вперед на 1, повернути ліворуч на місце, подати звуковий сигнал, забрати звуковий сигнал і вимкнути себе.

У моєму класі інформатики одним із наших перших завдань було запрограмувати Карел, щоб навчитися повертати праворуч, повертати та виконувати комбіновану дію рухатися вперед на 1 та опускати звуковий сигнал. Через кілька днів завданням було використовувати ці методи та писати нові методи для створення літер алфавіту.

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

Кожного разу, коли я писав private void draw#для кожного символу #, я додавав коментар після нього, який би розказував мені абревіатури для послідовності команд, які мені знадобляться.

У мене в розпорядженні такі команди (написані псевдокодом) (уточнення - це єдині корисні команди).

Turn Left
    Rotate the robot 90˚ counterclockwise
    Abbreviated as "l"

Turn Right
    Rotate the robot 90˚ clockwise
    Abbreviated as "r"

Move
    Move one space forwards
    Abbreviated as "m"

Put Beeper
    Put a beeper on the spot that Karel is on
    Abbreviated as "p"

Drop Beeper
    Move, then Put Beeper
    Abbreviated as "d"

Turn Around
    Turn Left, then Turn Left
    Abbreviated as "a"

Умови

Робот повинен діяти в наступному порядку.

  • Робот заводиться в нижньому лівому куті прямокутника 5xN мінімальної площі, на якому буде намальована літера.
  • Робот малює лист.
  • Робот переміщується до правого нижнього кута прямокутника.
  • Робот переміщається на два простори праворуч і повинен повернутися на північ / вгору

Давайте попрацюємо на прикладі. Припустимо, ми хочемо малювати A. Місце роботи - це літера, яка вказує його напрямок (північ, південь, схід, захід). Буква пишеться з великої літери, якщо робот знаходиться на місці із звуковим сигналом та малі літери, якщо робот знаходиться на місці без звукового сигналу. oявляє собою плями з буперами і .представляє плями без буперів.

Як ми побачимо згодом, Aце так.

.ooo.
o...o
ooooo
o...o
o...o

Ось одне можливе рішення.

Grids   .....   .....   .....   .....   .....   .....   .....   .....   .....
        .....   .....   .....   .....   .....   .....   .....   .....   .....
        .....   .....   .....   N....   E....   oE...   ooE..   oooE.   oooW.
        .....   .....   N....   o....   o....   o....   o....   o....   o....
        n....   N....   o....   o....   o....   o....   o....   o....   o....

Letters           p       d       d       r       d       d       d       a

        .....   .....   .....   .....   .....   n....   e....   .E...   .oE..
        .....   .....   .....   .....   N....   o....   o....   o....   o....
        ooWo.   oWoo.   Wooo.   Nooo.   oooo.   oooo.   oooo.   oooo.   oooo.
        o....   o....   o....   o....   o....   o....   o....   o....   o....
        o....   o....   o....   o....   o....   o....   o....   o....   o....

          m       m       m       r       d       m       r       d       d

        .ooE.   .oooe   .ooos   .ooo.   .ooo.   .ooo.   .ooo.   .ooo.
        o....   o....   o....   o...S   o...o   o...o   o...o   o...o
        oooo.   oooo.   oooo.   oooo.   ooooS   ooooo   ooooo   ooooo
        o....   o....   o....   o....   o....   o...S   o...o   o...o
        o....   o....   o....   o....   o....   o....   o...S   o...E

          d       m       r       d       d       d       d       l

Остаточне mmlвиконання четвертої кулі неявне тому, що воно з’являється в кожному листі і тому, що я не хочу повертатися назад і додавати ще два стовпчики до всього, що є у запропонованому вище рішенні.

Таким чином, одне рішення зробити A- це pddrdddammmrdmrdddmrddddlmml.

Зауважте, що це не повинно бути вашим рішенням. Ваш алгоритм може пройти через кожен стовпчик, поставивши беріз у належні місця і не покладаючись на те, де розміщені чи будуть розміщені інші букери. Незалежно від того, яким є ваш алгоритм, робот може розміщувати в мережі лише один звуковий сигнал.


Програма

Ваша програма прийме як вхід 5xN сітку того, що таке сітка для листа. Зауважте, що на вході немає робота; припускається, що робот знаходиться в нижньому лівому (південно-західному) куті, зверненим на північ.

Виходом буде послідовність літер, що є скороченням для послідовності.

Зразки входів

.ooo.
o...o
ooooo
o...o
o...o

o...o.ooooo
o...o...o..
ooooo...o..
o...o...o..
o...o.ooooo

Зразки виходів

pddrdddammmrdmrdddmrddddlmml

prmmmlmlmmdrdrdddlmlmmdrdrmmmdrddddlmmlprdddlmldmmrmrmdmlmldmmrdrddddrmmmdlmml

Це код гольфу, хлопців. Діють стандартні правила CG. Виграє найкоротший код у байтах.


Бонусний раунд

Правила

Якщо ви хочете взяти участь у бонусному раунді, не забудьте зробити свої кодекси ефективними! Нижче представлена ​​бібліотека усіх 5x5 літер, які моя програма створює під час її запуску. Мета бонусного раунду - написати програму, яка надрукує послідовність, ABCDEFGHIJKLMNOPQRSTUVWXYZяка містить якомога менше рухів. Немає вводу в STDIN. Код буде класифікований не за довжиною коду, а за його "оцінкою переміщення". Оцінка ходу призначена для відсторонення алгоритмів підмітання, які відвідують кожну точку прямокутника.

d: 1
l: 1
m: 4
p: 1
r: 1

Листи

.ooo.   oooo.   ooooo   oooo.   ooooo   ooooo   .oooo   o...o
o...o   o...o   o....   o...o   o....   o....   o....   o...o
ooooo   oooo.   o....   o...o   oooo    oooo.   o.ooo   ooooo
o...o   o...o   o....   o...o   o....   o....   o...o   o...o
o...o   oooo.   ooooo   oooo.   ooooo   o....   oooo.   o...o

ooooo   ....o   o...o   o....   ooooo   o...o   ooooo   oooo.
..o..   ....o   o..o.   o....   o.o.o   oo..o   o...o   o...o
..o..   ....o   oo...   o....   o.o.o   o.o.o   o...o   oooo.
..o..   o...o   o..o.   o....   o...o   o..oo   o...o   o....
ooooo   .ooo.   o...o   ooooo   o...o   o...o   ooooo   o....

oooo.   oooo.   ooooo   ooooo   o...o   o...o   o...o   o...o
o..o.   o...o   o....   ..o..   o...o   o...o   o...o   .o.o.
o..o.   oooo.   ooooo   ..o..   o...o   .o.o.   o.o.o   ..o..
oooo.   o..o.   ....o   ..o..   o...o   .o.o.   o.o.o   .o.o.
....o   o...o   ooooo   ..o..   ooooo   ..o..   ooooo   o...o

o...o   ooooo
.o.o.   ...o.
..o..   ..o..
.o...   .o...
o....   ooooo

Необхідно дотримуватися тієї самої процедури, що і оригінальне завдання: букви повинні бути складені по черзі з пробілом між кожною буквою.

Діють стандартні правила CG. Виграє вступ із найнижчим показником ходу.




Підводячи підсумок, обидва коди по суті будуть робити те саме. Перший код повинен мати мінімальну кількість байтів у коді, а другий код повинен використовувати найменшу кількість ходів.


Акуратний виклик - не маю уявлення, чому ви ставитеся до себе.
Deusovi

1
Дякую @Deusovi. Я б хотів, щоб вони пояснили, чому я можу прояснити все, що не має сенсу, або покращити його.
Арктур

" Карел (робот) - це лише виконати п’ять дій ": я думаю, ти пропускаєш " здатний ", і ти точно не вистачаєш п'ятої дії. І я не впевнений, в чому полягає бонусний раунд: чи збираєтесь ви нагородити ту людину, яка пише найкраще рішення?
Пітер Тейлор

Можливо, замість кодового завдання на гольф змінити його на мінімальний виклик гольфу? Оскільки мова йде про ефективність.
LukStorms

1
Мінімальний виклик руху з обмеженим набором рухів не так цікавий без кодової частини гольфу. Оптимальний шлях BFS повинен бути досить простим.
bopjesvla

Відповіді:


5

perl -p0, 60 56 54 + 2 байти

гольф

/
/;$:="m"x"@-";$_=mmmmlma.s/
/rmr$:a/gr.mml;y/.o/md/;

примітки

/\n/; # capture the length of the first line
$:="m"x"@-"; # assign a string of m's with that length to $:
s/^/mmmmlmll/; # move to the starting position (-1,0)
s/\n/rmr$:rr/g; # replace all newlines with kareliage returns
y/.o/md/; # replace dots with moves and o's with drops
s/$/mml/; # append mml

Приємне використання @-, можливо, буде корисним поділитися порадами щодо гольфу в питанні Perl !
Дом Гастінгс

2

JavaScript (ES6), 91

Перша спроба основного виклику.

Встановіть тест запуску фрагмента нижче у веб-переглядачі, сумісному з EcmaScript 6 (протестовано у Firefox)

ВІДПОВІД BONUS CHALLENGE - Оцінка за повний алфавіт = 869

Випробування запущеної внизу програми в Firefox (краще на весь екран)

Оскільки мені не подобаються проблеми з фіксованим входом / фіксованим виходом , ви можете спробувати ввести. Пам'ятайте лише, що букви будуть надруковані.

// Optimal - working on small pattern but too slow (scale bad)
// So I build the total command letter by letter - that surely is NOT globally optimal

Key=sol=>sol.pos+' '+sol.setBits

Solve=(target, startRow, startDir, cmd)=>{
  // Target is a rectangle string 5x5, newline separated for total (5+1)*5 chars
  if (target[target.length-1] != '\n') target += '\n';
  
  var T = ~new Date()
  var width = 5, height = 5, startPos = (width+1)*startRow;
  var offset = [-width-1, 1, width+1, -1];
  var turns = [ "", "r", "rr", "l" ];
  var cmds = [ "m", "rm", "rrm", "lm", "d", "rd", "rrd", "ld" ];
  var visited = {}, scan =[[],[],[],[],[],[],[],[]], cscan;
  
  var baseSol = { steps:[], pos: startPos, dir: startDir, setBits: 0};
  var score = 0, j = 0
  var bit, key, turn, curSol, move, result
  var targetBits = 0; 
  [...target].map((c,i)=>targetBits |= ((c=='o')<<i)) // 30 bits
  
  // First step, from outside, set bit in mask if it's set in target
  if (target[startPos]=='o') baseSol.setBits = 1<<startPos;
  console.log(target, targetBits.toString(16))
  visited[Key(baseSol)] = scan[0].push(baseSol);
  

  for (j = 0; j<99; j++)
  {
     cscan = scan[j];
     scan.push([])
     
     // console.log(`T: ${T-~new Date} J: ${j} SC: ${cscan.length}`)
     while (cscan.length > 0)
     {
        baseSol = cscan.pop()
        //console.log('Base', baseSol.dir, baseSol.pos, baseSol.setBits.toString(16), baseSol.steps.length)
        for(turn = 0; turn < 4; turn++)
        {
           // set direction, move and drop if you can
           curSol = {};
           curSol.dir = baseSol.dir + turn & 3;
           curSol.pos = baseSol.pos + offset[curSol.dir];
           // console.log(turn, curSol.dir, curSol.pos)
           if(target[curSol.pos] > ' '
              || curSol.dir == 1 && target[curSol.pos]=='\n'
             ) // if inside grid or on right border facing east
           {
              score = j + (turn == 2 ? 3 : turn == 0 ? 1 : 2);
              bit = 1 << curSol.pos;
              if (targetBits & bit)
                 curSol.setBits = baseSol.setBits | bit, move = 4 | turn;
              else
                 curSol.setBits = baseSol.setBits, score += 3, move = turn;
              if (!visited[key = Key(curSol)]) 
              {
                 curSol.steps = [...baseSol.steps, move] // clone and add
                 // task completed if on  right border and all bits ok
                 if (target[curSol.pos]>' ')
                 { // not on right border, proceed  
                    visited[key] = scan[score].push(curSol)
                 }  
                 else if (curSol.setBits == targetBits)
                 {
                    result = curSol.steps.map(v=>cmds[v]).join``
                    result = (cmd == '' 
                    ? target[startPos]=='o' ? 'p' : '' 
                    : target[startPos]=='o' ? 'd' : 'm') + result;
                    console.log(`T: ${T-~new Date} J: ${j} CMD: ${result}`)
                    return [cmd+result, curSol.pos / (width+1) | 0];
                 }
              }
           }
        }
     }
  }
  // Miserable failure!
  return []
}  

console.log=(...x)=>LOG.innerHTML+=x+'\n';
// TEST
Karel=(cmd, width, height) =>  // even if for this test we have a limited height to handle
{ 
  var grid = [...('.'.repeat(width)+'\n').repeat(height)],
  o = width+1,p = o*(height-2)+1,d = [-o, 1, o, -1], // direction offsets
  steps = [],s = [...grid],q = 0; // face up

  s[p] = 'n';
  steps.push([s.join``,'-']);
  
  [...cmd].forEach(c => 
    (
      c == 'l' ? q = q-1 &3
      : c == 'r' ? q = q+1 &3
      : c == 'a' ? q = q+2 &3
      : c == 'm' ? p += d[q]
      : c == 'p' ? grid[p] = 'o'
      : c == 'd' ? grid[p += d[q]] = 'o'
      : 0,
      s = [...grid],  
      s[p] = s[p] == 'o' ? 'NESW'[q] : 'nesw'[q],
      steps.push([s.join``,c])
    )
  )
  return [s.join``,steps]
}  


var AlphabetMap = `.ooo..oooo..ooooo.oooo..ooooo.ooooo..oooo.o...o.ooooo.....o.o...o.o.....ooooo.o...o.ooooo.oooo..oooo..oooo..ooooo.ooooo.o...o.o...o.o...o.o...o.o...o.ooooo
o...o.o...o.o.....o...o.o.....o.....o.....o...o...o.......o.o..o..o.....o.o.o.oo..o.o...o.o...o.o..o..o...o.o.......o...o...o.o...o.o...o..o.o...o.o.....o.
ooooo.oooo..o.....o...o.oooo..oooo..o.ooo.ooooo...o.......o.oo....o.....o.o.o.o.o.o.o...o.oooo..o..o..oooo..ooooo...o...o...o..o.o..o.o.o...o.....o.....o..
o...o.o...o.o.....o...o.o.....o.....o...o.o...o...o...o...o.o..o..o.....o...o.o..oo.o...o.o.....oooo..o..o......o...o...o...o..o.o..o.o.o..o.o...o.....o...
o...o.oooo..ooooo.oooo..ooooo.o.....oooo..o...o.ooooo..ooo..o...o.ooooo.o...o.o...o.ooooo.o.........o.o...o.ooooo...o...ooooo...o...ooooo.o...o.o.....ooooo`.split('\n')
var LetterMap = [];
var l,row,m;

for (l=0;l<26;l++)
{
  for(m='',row=0;row<5;row++)
    m += AlphabetMap[row].substr(l*6,5)+'\n'
  LetterMap[l]=m;  
}

print=Message=>{
  var Alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  var startRow = 4, cmd=''
  var startDir = 0 // start facing UP
  ;[...Message].forEach(l => (
    [cmd, startRow] = Solve(LetterMap[Alphabet.search(l)], startRow, startDir, cmd),
    startDir = 1, // after each letter will be facing RIGHT
    cmd += '\n' // addin a newline (scoring 0) just for readability
  ))

  if (startRow != 4) 
    cmd += 'mr'+'m'.repeat(4-startRow)+'rr' // on last row and facing up
  else 
    cmd += 'ml' // ...facing up

  // Recalc score
  var score = 0
  ;[...cmd].forEach(c=>score += c=='m'? 4 : c<' '? 0: 1)

  var robot = Karel(cmd.replace(/\n/g,''), 26*7, 7)
  O.innerHTML=cmd+'\nScore:'+score
  R.innerHTML=robot[0]
  RS.innerHTML=robot[1].join`\n`
}  

function test()
{
  var msg = I.value.toUpperCase()
  msg=msg.replace(/[^A-Z]/g,'')
  I.value=msg
  print(I.value)
}

test()
fieldset {
  padding:0;
}

pre {
  margin: 2px;
}

#RS {
  height: 200px;
  width: 50%;
  overflow:auto;
}

#I { width: 50% }
<fieldset ><legend>Message to print</legend>
<input id=I value='ABCDEFGHIJKLMNOPQRSTUVWXYZ'><button onclick='test()'>go</button></fieldset>
<fieldset ><legend>Command Result (newlines added for readability)</legend>
<pre id=O></pre></fieldset>
<fieldset ><legend>Robot output</legend>
<pre id=R></pre></fieldset>
<fieldset ><legend>Robot step by step</legend>
<pre id=RS></pre></fieldset>
<fieldset ><legend>log</legend>
<pre id=LOG></pre></fieldset>


Як проходить бонус?
Арктур

@Eridan бонус йде добре. На жаль, у мене теж робота ... :)
edc65

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