Girar una cámara; salvar a un astronauta


23

Nota: los spoilers menores de The Martian están en este desafío. Lee con precaución


The Martian es una novela de ciencia ficción sobre el extraordinario astronauta y botánico, Mark Watney , que ha quedado varado accidentalmente en Marte. En un momento del libro, Mark intenta comunicarse con la NASA, pero el único medio de comunicación que tienen es una cámara. Mark envía mensajes escribiendo en tarjetas de índice y, dado que la NASA puede girar la cámara 360 grados, la NASA envía respuestas apuntando la cámara hacia las tarjetas con la etiqueta "Sí" o "No".

Dado que los únicos datos que la NASA puede enviar es la dirección que está mirando la cámara, a Mark se le ocurre un sistema en el que pueden apuntar a tarjetas con caracteres alfabéticos para escribir mensajes. Pero usar las letras 'az' no sería práctico. Para citar el libro (de esta respuesta , en scifi.se):

Tendremos que hablar más rápido que las preguntas sí / no cada media hora. La cámara puede girar 360 grados, y tengo muchas partes de antena. Hora de hacer un alfabeto. Pero no puedo usar las letras de la A a la Z. Veintiséis letras más mi tarjeta de preguntas serían veintisiete tarjetas alrededor del módulo de aterrizaje. Cada uno solo obtendría 13 grados de arco. Incluso si JPL apunta la cámara perfectamente, hay una buena posibilidad de que no sepa a qué letra se referían.

Entonces tendré que usar ASCII. Así es como las computadoras manejan los personajes. Cada carácter tiene un código numérico entre 0 y 255. Los valores entre 0 y 255 se pueden expresar como 2 dígitos hexadecimales. Al darme pares de dígitos hexadecimales, pueden enviar cualquier carácter que deseen, incluidos números, signos de puntuación, etc.

...

Así que haré tarjetas de 0 a 9 y de A a F. Eso hace 16 tarjetas para colocar alrededor de la cámara, más la tarjeta de preguntas. Diecisiete cartas significa más de 21 grados cada una. Mucho más fácil de tratar.

Su objetivo hoy, como uno de los mejores ingenieros de software de la NASA, es escribir un programa para codificar los distintos ángulos de la cámara. Las diecisiete cartas que Mark tiene que señalar son (en orden):

?0123456789ABCDEF

y cada una de estas tarjetas tiene una separación de 21 grados, por lo tanto, para rotar la cámara de ?a 0, debe rotar la cámara 21 grados y 2a 1-21 grados. (No es exactamente 21, pero redondearemos para que sea más simple) Esto se ajusta, por lo que pasar de Fa 3es de 105 grados (5 vueltas, 5 * 21 = 105). Esto es más eficiente que ir a -252, ya que la cámara no tendrá que moverse tan lejos.

Esto es lo que debe hacer su programa o función.

  1. Tome una cadena como entrada. Llamaremos a esta cadena s . Para simplificarlo, diremos que la entrada solo será ASCII imprimible. Para nuestro ejemplo, digamos que la entrada fueSTATUS

  2. Convierta cada carácter a su representación hexadecimal. Esto se convertiría STATUSa 53 54 41 54 55 53.

  3. Imprima o devuelva los giros consecutivos que la cámara deberá realizar para apuntar a cada tarjeta y regresar a la "Tarjeta de preguntas". Para nuestro ejemplo, esto sería:

    6  * 21 = 126   (?-5)
    -2 * 21 = -42   (5-3)
    2  * 21 = 42    (3-5)
    -1 * 21 = -21   (5-4)
    0  * 21 = 0     (4-4)
    -3 * 21 = -63   (4-1)
    4  * 21 = 84    (1-5)
    -1 * 21 = -21   (5-4)
    1  * 21 = 21    (4-4)
    0  * 21 = 0     (5-5)
    0  * 21 = 0     (5-5)
    -2 * 21 = -42   (5-3)
    -4 * 21 = -84   (3-?)
    

    O, en formato de matriz:

    [126, -42, 42, -21, 0, -63, 84, -21, 21, 0, 0, -42, -84]
    

Tenga en cuenta que siempre debe tomar la menor de las rotaciones posibles. Entonces, si la entrada fue NO, que es 4E 4F, debe salir:

5    * 21 = 105
-7   * 21 = -147
7    * 21 = 147
-6   * 21 = -126
1    * 21 = 21

Más bien que:

 5   * 21 = 105
 10  * 21 = 210
 -10 * 21 = -210
 11  * 21 = 231
 -16 * 21 = -336

Aquí hay algunos ejemplos más trabajados:

Input: CROPS?
ASCII: 43 52 4F 50 53 3F
Worked Example:

5  * 21 = 105
-1 * 21 = -21
2  * 21 = 42
-3 * 21 = -63
2  * 21 = 42
-6 * 21 = -126
7  * 21 = 147
-5 * 21 = -105
5  * 21 = 105
-2 * 21 = -42
0  * 21 = 0
-5  * 21 = -105
1 * 21 = 21

Result: [105 -21 42 -63 42 -126 147 -105 105 -42 0 -105 21]


Input: DDD
ASCII: 44 44 44
Worked Example:

5   * 21 = 105
0   * 21 = 0
0   * 21 = 0
0   * 21 = 0
0   * 21 = 0
0   * 21 = 0
-5  * 21 = -105

Result: [105, 0, 0, 0, 0, 0, -105]


Input: Hello world!
ASCII: 48 65 6c 6c 6f 20 77 6f 72 6c 64 21
Worked example:

5   * 21 = 105
4   * 21 = 84
-2  * 21 = -42
-1  * 21 = -21
1   * 21 = 21
6   * 21 = 126
-6  * 21 = -126
6   * 21 = 126
-6  * 21 = -126
-8  * 21 = -168
4   * 21 = 84
-2  * 21 = -42
7   * 21 = 147
0   * 21 = 0
-1  * 21 = -21
-8  * 21 = -168
-8  * 21 = -168
-5  * 21 = -105
4   * 21 = 84
6   * 21 = 126
-6  * 21 = -126
-2  * 21 = -42
-2  * 21 = -42
-1  * 21 = -21
-2  * 21 = -42

Result: [105 84 -42 -21 21 126 -126 126 -126 -168 84 -42 147 0 -21 -168 -168 -105 84 126 -126 -42 -42 -21 -42]

Dado que la NASA se enorgullece de la eficiencia, su objetivo es escribir el código más corto posible. Se aplican lagunas estándar. ¡Ahora tráelo a casa!


Nota al margen: estos casos de prueba se hicieron a mano y fueron un poco molestos, por lo que podría haber algunas inexactitudes menores. Avísame si algo parece estar mal. :)
DJMcMayhem

Respuestas:


5

JavaScript (ES6), 103 99 bytes

s=>[...s.replace(/./g,c=>c.charCodeAt().toString(16)),10].map(n=>((24-p-~(p='0x'+n))%17-8)*21,p=-1)

Casos de prueba


¿Funcionaría esto? s.replace(/./g,->[...s].map(
Luke

@Luke Nope, porque necesitamos separar cada dígito hexadecimal. ...s.replace(/./g,da por ejemplo "4","8","6","5","6","c"..., mientras. ...[...s.map(daría"48","65","6c",...
ETHproductions

4

C, 212 202 199 187 bytes

¡3 bytes guardados gracias a @KritixiLithos!

i;f(a,b){i=abs(a-b);i=8>i?i:17-i;i=a<b&a>b-8?i:a<b&a<b-8?-i:b<a&b>a-8?-i:i;i*=21;}v;g(char*s){for(v=0;*s;s+=v++%2)printf("%d ",v?v%2?f(*s%16,s[1]?s[1]/16:-1):f(*s/16,*s%16):f(-1,*s/16));}

Pruébalo en línea!


1
Creo que puedes hacerlo en 8>i?i:17-ilugar de17-i>i?...
Kritixi Lithos

@KritixiLithos sí, gracias.
betseg

3

Python, 187 178 bytes

def g(x):w,z=map('?0123456789abcdef'.index,x);d=w-z;return min(d,d+17*(d<=0 or -1),key=abs)*21
def f(s):s=''.join(map('{:2x}'.format,s.encode()));return[*map(g,zip(s+'?','?'+s))]

Casos de prueba

for k in ['STATUS', 'NO', 'CROPS?', 'DDD', 'Hello world!']:
    print('Input:  {}\nOutput: {}'.format(k, f(k)))


1

Jalea , 21 19 bytes

Ob⁴F-;;-I+8%17_8×21

Pruébalo en línea!

¿Cómo?

Ob⁴F-;;-I+8%17_8×21 - Main link: string s        e.g. 'e.g.'
O                   - cast to ordinals            [101,     46,       103,      46]
 b                  - convert to base
  ⁴                 -     16                   [[6,   5], [2,  14], [6,   7], [2,  14]]
   F                - flatten                   [6,   5,   2,  14,   6,   7,   2,  14]
    -;              - -1 concatenate      [-1,   6,   5,   2,  14,   6,   7,   2,  14]
      ;-            - concatenate -1      [-1,   6,   5,   2,  14,   6,   7,   2,  14,  -1]
        I           - increments            [  7,  -1,  -3,  12,  -8,   1,  -5,  12, -15]
         +8         - add 8                 [ 15,   7,   5,  20,   0,   9,   3,  20,  -7]
           %17      - mod 17                [ 15,   7,   5,   3,   0,   9,   3,   3,  10]
              _8    - subtract 8            [  7,  -1,  -3,  -5,  -8,   1,  -5,  -5,   2]
                ×21 - multiply by 21        [147, -21, -63,-105,-168,  21,-105,-105,  42]

1

Ohm , 20 19 bytes (CP437), no competidor

EDITAR : guardado 1 byte cambiando un bloque de mapa a mapas repetidos de un solo componente.

Probablemente sería un poco más corto si tuviera una vectorización implícita.

`»x»}{»úΓXΓHδ▓_~21*

Explicación:

`»x»}{»úΓXΓHδ▓_~21*    Main wire, arguments: s

`»x                    Convert char codes of s to hex
   »}                  Split digit pairs
     {                 Flatten
      »ú               Convert digits back to base 10
        ΓXΓH           Append and prepend with -1
            δ          Get deltas between each element of array
             ▓         Map array over...
              _~21*      Negate, multiply by 21

0

PHP, 125 116 bytes:

function m($i){static$a;$a+=$d=($i-$a+10)%17-9;echo$d*21,"
";}for(;$c=ord($argv[1][$i++]);m($c%16))m($c/16|0);m(-1);

Descompostura

function m($i)              // function to turn camera:
{
    static$a;                   // remember angle
    $a+=                        // add delta to angle
    $d=($i-$a+10)%17-9;         // delta: target=nibble value+1-current angle
                                // add 9, modulo 17, -9 -> shortest movement
    echo$d*21,"\n";                 // print delta * 21 and a linebreak
}
for(;$c=ord($argv[1][$i++]);// loop through input characters
    m($c%16))                   // 2. move to low nibble value
    m($c/16|0)                  // 1. move to high nibble value
;
m(-1);                      // move back to "?"

Por supuesto, 21es bastante inexacto y puede fallar para cadenas de más de 14 caracteres; pero entonces ... 360/17sería cuatro bytes más largo.

Una solución alternativa habría sido conectar un puntero láser a la cámara;
podríamos usar todos los caracteres ascii imprimibles y una tarjeta de "preguntas" a 3.75 grados cada uno con eso.

Otra alternativa: usar 16 tarjetas (a 22.5 grados) con 6 caracteres cada una:
implementar algún tipo de T9 y podemos omitir el mordisco alto. ;)

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.