Drehe eine Kamera. Rette einen Astronauten


23

Hinweis: Kleinere Spoiler für The Martian sind in dieser Herausforderung. Lesen Sie mit Vorsicht weiter


Der Marsmensch ist ein Science-Fiction-Roman über den Astronauten und Botaniker Mark Watney , der versehentlich auf dem Mars gestrandet ist. An einem Punkt im Buch versucht Mark, mit der NASA zu kommunizieren, aber das einzige Kommunikationsmittel, das sie haben, ist eine Kamera. Mark sendet Nachrichten, indem er auf Karteikarten schreibt. Da die NASA die Kamera um 360 Grad drehen kann, sendet die NASA Antworten zurück, indem sie die Kamera auf Karten mit der Bezeichnung "Ja" oder "Nein" richtet.

Da die einzigen Daten, die die NASA senden kann, die Blickrichtung der Kamera sind, hat Mark ein System entwickelt, mit dem sie auf Karten mit Buchstaben zeigen können, um Nachrichten einzugeben. Die Verwendung der Buchstaben 'az' wäre jedoch unpraktisch. Um das Buch zu zitieren (von dieser Antwort über scifi.se):

Wir müssen jede halbe Stunde schneller sprechen als Ja / Nein-Fragen. Die Kamera kann sich um 360 Grad drehen und ich habe viele Antennenteile. Zeit, ein Alphabet zu machen. Aber ich kann nicht nur die Buchstaben A bis Z verwenden. Sechsundzwanzig Buchstaben plus meine Fragekarte wären siebenundzwanzig Karten im Lander. Jeder würde nur 13 Grad Bogen bekommen. Selbst wenn JPL die Kamera perfekt ausrichtet, besteht die Möglichkeit, dass ich nicht weiß, welchen Buchstaben sie meinten.

Also muss ich ASCII verwenden. So verwalten Computer Charaktere. Jedes Zeichen hat einen numerischen Code zwischen 0 und 255. Werte zwischen 0 und 255 können als 2 hexadezimale Ziffern ausgedrückt werden. Indem Sie mir Paare von Hexadezimalziffern geben, können sie jedes beliebige Zeichen senden, einschließlich Zahlen, Interpunktion usw.

...

Also mache ich Karten für 0 bis 9 und A bis F. Das ergibt 16 Karten, die um die Kamera gelegt werden, plus die Fragekarte. Siebzehn Karten bedeuten jeweils über 21 Grad. Es ist viel einfacher damit umzugehen.

Als einer der besten Software-Ingenieure der NASA ist es heute Ihr Ziel, ein Programm zu schreiben, mit dem Sie die verschiedenen Kamerawinkel codieren können. Die siebzehn Karten, auf die Mark zeigen soll, sind (in der Reihenfolge):

?0123456789ABCDEF

und jede dieser Karten ist 21 Grad voneinander entfernt. Um die Kamera von ?nach zu drehen 0, sollten Sie die Kamera um 21 Grad und 2auf 1-21 Grad drehen . (Es ist nicht genau 21, aber wir werden runden, um es einfacher zu halten.) Diese Umschlingung, von Fzu zu gehen , 3ist 105 Grad (5 Umdrehungen, 5 * 21 = 105). Dies ist effizienter als -252, da sich die Kamera nicht so weit bewegen muss.

Hier ist, was Ihr Programm oder Ihre Funktion tun muss.

  1. Nehmen Sie eine Zeichenfolge als Eingabe. Wir nennen diesen String s . Um es einfach zu halten, werden wir sagen, dass die Eingabe immer nur druckbares ASCII sein wird. Nehmen wir für unser Beispiel an, dass die Eingabe warSTATUS

  2. Konvertieren Sie jedes Zeichen in seine hexadezimale Darstellung. Dies würde konvertieren STATUSzu 53 54 41 54 55 53.

  3. Drucken Sie die aufeinanderfolgenden Umdrehungen aus, die die Kamera ausführen muss, um auf jede Karte zu zeigen und zur "Fragekarte" zurückzukehren. Für unser Beispiel wäre dies:

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

    Oder im Array-Format:

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

Beachten Sie, dass Sie immer die kleinstmögliche Umdrehung machen müssen. Wenn also die Eingabe war NO, was ist 4E 4F, sollten Sie Folgendes ausgeben:

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

Eher, als:

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

Hier sind einige weitere Beispiele:

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]

Da die NASA stolz auf Effizienz ist, ist es Ihr Ziel, den kürzestmöglichen Code zu schreiben. Es gelten Standardlücken. Jetzt bring ihn nach Hause!


Randnotiz: Diese Testfälle wurden von Hand angefertigt und waren eine Art Schmerz, sodass es zu geringfügigen Ungenauigkeiten kommen kann. Bitte lassen Sie mich wissen, wenn etwas falsch aussieht. :)
DJMcMayhem

Antworten:


5

JavaScript (ES6), 103 bis 99 Byte

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

Testfälle


Würde das funktionieren? s.replace(/./g,->[...s].map(
Luke

@Luke Nope, weil wir jede hexadezimale Ziffer trennen müssen. ...s.replace(/./g,gibt zB "4","8","6","5","6","c"...dabei. ...[...s.map(würde geben"48","65","6c",...
ETHproductions

4

C 212 202 199 187 Bytes

3 Bytes gespart dank @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));}

Probieren Sie es online!


1
Ich denke, Sie können 8>i?i:17-ianstelle von17-i>i?...
Kritixi Lithos

@KritixiLithos yup, danke.
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))]

Testfälle

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


1

Jelly , 21 bis 19 Bytes

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

Probieren Sie es online!

Wie?

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 bis 19 Byte (CP437), nicht konkurrierend

BEARBEITEN : 1 Byte durch Ändern eines Kartenblocks in wiederholte Einkomponenten-Karten gespeichert.

Wäre wahrscheinlich etwas kürzer, wenn ich implizite Vektorisierung hätte.

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

Erläuterung:

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

Nervenzusammenbruch

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

Natürlich 21ist es ziemlich ungenau und kann bei Zeichenfolgen mit mehr als 14 Zeichen fehlschlagen. aber dann ... 360/17wären vier Bytes länger.

Eine alternative Lösung wäre gewesen, einen Laserpointer an der Kamera anzubringen;
wir könnten alle druckbaren ASCII-Zeichen und eine "Frage" -Karte mit jeweils 3,75 Grad verwenden.

Eine weitere Alternative: Verwenden Sie 16 Karten (bei 22,5 Grad) mit jeweils 6 Zeichen:
Implementieren Sie eine Art T9, und Sie können das hohe Knabbern weglassen. ;)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.