Karel J. AlphaBot Sequence Generator

14

Puntuaciones

Esta sección se completará a medida que se ingresen los envíos.

Normal

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

Ronda de bonificación

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

Karel J. AlphaBot

Antecedentes

Un curso de introducción popular a Java es Karel J. Robot (lo estoy usando yo mismo). El robot interactúa con una cuadrícula de calles (coordenadas y enteras positivas) y avenidas (coordenadas x enteras positivas), así como con buscapersonas, que se pueden colocar y almacenar en la cuadrícula (tenga en cuenta que Karel y cualquier buscapersonas solo pueden existir en la red) puntos). Karel (el robot) solo debe realizar cinco acciones: avanzar 1 en 1, girar a la izquierda en su lugar, dejar un zumbador, recoger un zumbador y apagarse.

En mi clase de Ciencias de la Computación, una de nuestras primeras tareas fue programar a Karel para que aprenda a girar a la derecha, girar y realizar la acción combinada de avanzar por 1 y dejar un pitido. Unos días después, una tarea consistía en utilizar estos métodos y escribir nuevos métodos para producir letras del alfabeto.

Naturalmente, una vez que terminé esta tarea, escribí más métodos para hacer cada letra del alfabeto, así como los diez dígitos numéricos, y planeo descubrir cómo hacer una especie de procesador de texto con el robot, donde una cadena entraría a STDIN y el robot pondría buscapersonas en la cuadrícula de una manera que se pareciera a las letras.

Cada vez que escribía private void draw#para cada personaje #, agregaba un comentario después que me decía abreviaturas para la secuencia de comandos que necesitaría.

Tengo los siguientes comandos (escritos en pseudocódigo) a mi disposición (aclaración: estos son los únicos comandos útiles ).

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"

Condiciones

El robot debe proceder en el siguiente orden.

  • El robot comienza en la esquina inferior izquierda del rectángulo de 5xN de área mínima en la que se dibujará la letra.
  • El robot dibuja la carta.
  • El robot se mueve a la esquina inferior derecha del rectángulo.
  • El robot se mueve dos espacios a la derecha y debe mirar hacia el norte / arriba

Analicemos un ejemplo. Supongamos que queremos dibujar A. La ubicación del robot es la letra que indica su dirección (norte, sur, este, oeste). La letra se escribe con mayúscula si el robot está en un lugar con un busca y minúscula si el robot está en un lugar sin un busca. orepresenta manchas con buscapersonas y. representa manchas sin buscapersonas.

Como veremos más adelante, Aes esto.

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

Aquí hay una posible solución.

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

El final mmlpara completar la cuarta viñeta está implícito porque aparece en cada letra y porque no quiero regresar y agregar otras dos columnas a todo en la solución propuesta anteriormente.

Por lo tanto, una solución para hacer Aes pddrdddammmrdmrdddmrddddlmml.

Tenga en cuenta que esta no tiene que ser su solución. Su algoritmo puede pasar por cada columna, colocando los buscapersonas en los lugares adecuados y sin depender de dónde se han colocado o se colocarán otros buscapersonas. No importa cuál sea su algoritmo, el robot solo puede colocar una señal acústica por espacio en la cuadrícula.


El programa

Su programa tomará como entrada una cuadrícula de 5xN de cuál es la cuadrícula de la letra. Tenga en cuenta que no hay robot en la entrada; se supone que el robot está en la esquina inferior izquierda (suroeste), hacia el norte.

La salida será la secuencia de letras que son la abreviatura de la secuencia.

Entradas de muestra

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

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

Resultados de muestra

pddrdddammmrdmrdddmrddddlmml

prmmmlmlmmdrdrdddlmlmmdrdrmmmdrddddlmmlprdddlmldmmrmrmdmlmldmmrdrddddrmmmdlmml

Este es el código de golf, amigos. Se aplican las reglas estándar de CG. El código más corto en bytes gana.


Ronda de bonificación

Reglas

Si quieres participar en la ronda de bonificación, ¡asegúrate de que tus códigos se muevan de manera eficiente! A continuación se muestra una biblioteca de todas las letras de 5x5 que mi programa crea cuando se ejecuta. El objetivo de la ronda de bonificación es escribir un programa que imprima una secuencia ABCDEFGHIJKLMNOPQRSTUVWXYZque contenga la menor cantidad de movimientos posible. No hay entrada a STDIN. El código será calificado no en la longitud del código sino en su "puntaje de movimiento". El puntaje de movimiento está diseñado para desalentar los algoritmos de barrido que visitan cada punto del rectángulo.

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

Letras

.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

Se debe seguir el mismo procedimiento que el desafío original: las letras se deben dibujar de una en una con una separación de espacios entre cada letra.

Se aplican las reglas estándar de CG. La entrada con el puntaje de movimiento más bajo gana.




Para resumir, ambos códigos esencialmente harán lo mismo. El primer código debe tener un número mínimo de bytes en el código, y el segundo código debe usar el menor número de movimientos.

Arcturus
fuente
Desafío ordenado: no tengo idea de por qué te votan negativamente.
Deusovi
1
Gracias @Deusovi. Desearía que explicaran por qué para que pueda aclarar cualquier cosa que no tenga sentido o no lo mejore.
Arcturus
" Karel (el robot) solo debe realizar cinco acciones ": creo que te falta " capaz ", y definitivamente te estás perdiendo la quinta acción. Y no estoy seguro de qué se trata la ronda de bonificación: ¿vas a otorgar una recompensa a la persona que escribe la mejor solución?
Peter Taylor
¿Quizás en lugar de un desafío de código de golf cambiarlo a un desafío de golf de movimiento mínimo? Ya que esto se trata de eficiencia.
LukStorms
1
Un desafío de movimiento mínimo con un conjunto limitado de movimientos no es tan interesante sin el código de golf. Debería ser bastante fácil BFS la ruta óptima.
bopjesvla

Respuestas:

5

perl -p0, 60 56 54 + 2 bytes

golf

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

notas

/\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
bopjesvla
fuente
Buen uso de @-, podría ser útil para compartir los consejos para jugar al golf en la pregunta de Perl .
Dom Hastings
2

JavaScript (ES6), 91

Un primer intento al desafío básico.

Pruebe a ejecutar el fragmento a continuación en un navegador compatible con EcmaScript 6 (probado en Firefox)

RESPUESTA DE DESAFÍO DE BONIFICACIÓN - Puntuación para el alfabeto completo = 869

Pruebe a ejecutar el wnippet a continuación en Firefox (mejor pantalla completa)

Como no me gustan los desafíos de entrada fija / salida fija , puedes probar tu entrada. Solo recuerde, solo se imprimirán letras.

// 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>

edc65
fuente
¿Cómo va la bonificación?
Arcturus
@Eridan el bono va bien. Lamentablemente también tengo un trabajo ... :)
edc65
¡Okay! No te culpo Eres el único que ha intentado la bonificación.
Arcturus