Ruota una fotocamera; salva un astronauta


23

Nota: spoiler minori per The Martian sono in questa sfida. Continua a leggere con cautela


The Martian è un romanzo di fantascienza sull'astronauta e botanico straordinario, Mark Watney , che è stato accidentalmente bloccato su Marte. Ad un certo punto del libro, Mark prova a comunicare con la NASA, ma l'unico mezzo di comunicazione che hanno è una macchina fotografica. Mark invia i messaggi scrivendo su schede e, poiché la NASA può ruotare la telecamera di 360 gradi, la NASA invia risposte puntando la telecamera verso le schede denominate "Sì" o "No".

Poiché l'unico dato che la NASA può inviare è la direzione verso cui è rivolta la fotocamera, Mark crea un sistema in cui è possibile puntare su carte con caratteri alfabetici per scrivere i messaggi. Ma usare le lettere "az" non sarebbe pratico. Per citare il libro (da questa risposta , oltre su scifi.se):

Dovremo parlare più velocemente delle domande sì / no ogni mezz'ora. La fotocamera può ruotare di 360 gradi e ho molte parti di antenna. È ora di fare un alfabeto. Ma non posso semplicemente usare le lettere dalla A alla Z. Ventisei lettere più la mia carta domanda sarebbero ventisette carte intorno al lander. Ognuno otterrebbe solo 13 gradi di arco. Anche se JPL punta perfettamente la fotocamera, ci sono buone probabilità che non saprò quale lettera intendessero dire.

Quindi dovrò usare ASCII. Ecco come i computer gestiscono i personaggi. Ogni carattere ha un codice numerico compreso tra 0 e 255. I valori tra 0 e 255 possono essere espressi come 2 cifre esadecimali. Dandomi coppie di cifre esadecimali, possono inviare qualsiasi carattere che preferiscono, compresi numeri, punteggiatura, ecc.

...

Quindi realizzerò le carte da 0 a 9 e da A a F. Ciò farà sì che 16 carte vengano posizionate attorno alla videocamera, più la carta delle domande. Diciassette carte significano oltre 21 gradi ciascuna. Molto più facile da gestire.

Il tuo obiettivo oggi, come uno dei migliori ingegneri del software della NASA, è scrivere un programma per codificare i vari angoli della telecamera. Le diciassette carte a cui Mark deve puntare sono (in ordine):

?0123456789ABCDEF

e ognuna di queste carte è a 21 gradi di distanza, quindi per ruotare la fotocamera da ?a 0, è necessario ruotare la fotocamera di 21 gradi e 2di 1-21 gradi. (Non è esattamente 21, ma arrotonderemo per renderlo più semplice) Questo si avvolge, quindi per andare da Fa 3è 105 gradi (5 turni, 5 * 21 = 105). Questo è più efficiente di andare a -252, dal momento che la fotocamera non dovrà spostarsi così lontano.

Ecco cosa deve fare il tuo programma o funzione.

  1. Prendi una stringa come input. Chiameremo questa stringa s . Per semplicità, diremo che l'input sarà sempre e solo ASCII stampabile. Per il nostro esempio, supponiamo che l'input sia statoSTATUS

  2. Converti ogni personaggio nella sua rappresentazione esadecimale. Questo si convertirà STATUSin 53 54 41 54 55 53.

  3. Stampa o restituisci i gradi consecutivi che la telecamera dovrà effettuare per puntare su ciascuna carta e tornare alla "Carta delle domande". Per il nostro esempio, questo sarebbe:

    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-?)
    

    Oppure, in formato array:

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

Nota che devi sempre prendere la più piccola delle rotazioni possibili. Quindi, se l'input era NO, cioè 4E 4Fdovresti produrre:

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

Piuttosto che:

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

Ecco alcuni esempi più elaborati:

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]

Poiché la NASA è orgogliosa dell'efficienza, il tuo obiettivo è quello di scrivere il codice più breve possibile. Si applicano scappatoie standard. Ora portalo a casa!


Nota a margine: questi casi di test sono stati fatti a mano e sono stati un po 'dolorosi, quindi potrebbero esserci alcune piccole imprecisioni. Per favore fatemi sapere se qualcosa sembra sbagliato. :)
DJMcMayhem

Risposte:


5

JavaScript (ES6), 103 99 byte

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

Casi test


Funzionerebbe? s.replace(/./g,->[...s].map(
Luca

@ Luca No, perché dobbiamo separare ogni cifra esadecimale. ...s.replace(/./g,dà ad esempio "4","8","6","5","6","c"..., mentre. ...[...s.map(darei"48","65","6c",...
ETHproductions

4

C, 212 202 199 187 byte

3 byte salvati grazie 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));}

Provalo online!


1
Penso che tu possa fare 8>i?i:17-iinvece di17-i>i?...
Kritixi Lithos

@KritixiLithos yup, grazie.
Betseg,

3

Python, 187 178 byte

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))]

Casi test

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


1

Gelatina , 21 19 byte

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

Provalo online!

Come?

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 byte (CP437), non in competizione

EDIT : salvato 1 byte modificando un blocco mappa in ripetute mappe monocomponente.

Probabilmente sarebbe un po 'più breve se avessi la vettorializzazione implicita.

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

Spiegazione:

`»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 byte:

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);

abbattersi

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 "?"

Naturalmente, 21è piuttosto impreciso e potrebbe non riuscire per stringhe più lunghe di 14 caratteri; ma poi ... 360/17sarebbe più lungo di quattro byte.

Una soluzione alternativa sarebbe stata quella di collegare un puntatore laser alla fotocamera;
potremmo usare tutti i caratteri ASCII stampabili e una carta "domanda" a 3,75 gradi ciascuno con quello.

Un'altra alternativa: utilizzare 16 carte (a 22,5 gradi) con 6 caratteri ciascuna:
implementare una sorta di T9 e possiamo omettere l'alta morsa. ;)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.