Faites pivoter une caméra; sauver un astronaute

23

Remarque: des spoilers mineurs pour The Martian sont dans ce défi. À lire avec prudence


Le Martien est un roman de science-fiction sur l'astronaute et botaniste extraordinaire, Mark Watney , qui a été accidentellement échoué sur Mars. À un moment donné dans le livre, Mark essaie de communiquer avec la NASA, mais le seul moyen de communication dont ils disposent est une caméra. Mark envoie des messages en écrivant sur des fiches et, comme la NASA peut faire pivoter la caméra de 360 ​​degrés, la NASA renvoie les réponses en pointant la caméra vers des cartes étiquetées "Oui" ou "Non".

Étant donné que les seules données que la NASA peut envoyer sont la direction à laquelle la caméra est confrontée, Mark propose un système permettant de pointer des cartes avec des caractères alphabétiques dessus pour taper des messages. Mais l'utilisation des lettres «az» serait peu pratique. Pour citer le livre (à partir de cette réponse , sur scifi.se):

Nous devrons parler plus rapidement que les questions oui / non toutes les demi-heures. La caméra peut pivoter à 360 degrés et j'ai de nombreuses pièces d'antenne. Il est temps de faire un alphabet. Mais je ne peux pas simplement utiliser les lettres de A à Z. Vingt-six lettres et ma carte de question correspondraient à vingt-sept cartes autour de l'atterrisseur. Chacun n'obtiendrait que 13 degrés d'arc. Même si JPL pointe parfaitement la caméra, il y a de fortes chances que je ne sache pas de quelle lettre il s'agit.

Je vais donc devoir utiliser ASCII. C'est ainsi que les ordinateurs gèrent les personnages. Chaque caractère a un code numérique compris entre 0 et 255. Les valeurs comprises entre 0 et 255 peuvent être exprimées en 2 chiffres hexadécimaux. En me donnant des paires de chiffres hexadécimaux, ils peuvent envoyer n'importe quel caractère qu'ils aiment, y compris les chiffres, la ponctuation, etc.

...

Je vais donc faire des cartes de 0 à 9 et de A à F. Cela fait 16 cartes à placer autour de la caméra, plus la carte de question. Dix-sept cartes signifie plus de 21 degrés chacune. Beaucoup plus facile à gérer.

Votre objectif aujourd'hui, en tant que l'un des meilleurs ingénieurs logiciels de la NASA, est d'écrire un programme pour coder les différents angles de la caméra. Les dix-sept cartes que Mark a à vous montrer sont (dans l'ordre):

?0123456789ABCDEF

et chacune de ces cartes est distante de 21 degrés, donc pour faire pivoter l'appareil photo de ?à 0, vous devez faire pivoter l'appareil photo de 21 degrés et 2jusqu'à 1-21 degrés. (Ce n'est pas exactement 21, mais nous arrondirons pour le garder plus simple) Cela s'enroule, donc pour aller de Fà 3105 degrés (5 tours, 5 * 21 = 105). C'est plus efficace que d'aller à -252, car la caméra n'aura pas à aller aussi loin.

Voici ce que votre programme ou votre fonction doit faire.

  1. Prenez une chaîne en entrée. Nous appellerons cette chaîne s . Pour rester simple, nous dirons que l'entrée ne sera jamais imprimable en ASCII. Pour notre exemple, disons que l'entrée étaitSTATUS

  2. Convertissez chaque caractère en sa représentation hexadécimale. Cela se convertirait STATUSen 53 54 41 54 55 53.

  3. Imprimez ou retournez les tours de degrés consécutifs que l'appareil photo devra effectuer pour pointer sur chaque carte et revenir à la "Carte Question". Pour notre exemple, ce serait:

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

    Ou, au format tableau:

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

Notez que vous devez toujours effectuer la plus petite rotation possible. Donc, si l'entrée était NO, ce qui est 4E 4F, vous devriez sortir:

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

Plutôt que:

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

Voici quelques exemples plus travaillés:

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]

La NASA étant fière de son efficacité, votre objectif est d'écrire le code le plus court possible. Des échappatoires standard s'appliquent. Ramenez-le maintenant à la maison!

DJMcMayhem
la source
Note latérale: Ces cas de test ont été faits à la main et étaient une sorte de douleur, il pourrait donc y avoir quelques inexactitudes mineures. Veuillez me faire savoir si quelque chose ne va pas. :)
DJMcMayhem
En relation
Digital Trauma

Réponses:

5

JavaScript (ES6), 103 99 octets

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

Cas de test

ETHproductions
la source
Est-ce que cela fonctionnerait? s.replace(/./g,->[...s].map(
Luke
@Luke Nope, car nous devons séparer chaque chiffre hexadécimal. ...s.replace(/./g,donne par exemple "4","8","6","5","6","c"..., tandis que. ...[...s.map(donnerait"48","65","6c",...
ETHproductions
4

C, 212 202 199 187 octets

3 octets enregistrés grâce à @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));}

Essayez-le en ligne!

betseg
la source
1
Je pense que vous pouvez faire à la 8>i?i:17-iplace de17-i>i?...
Kritixi Lithos
@KritixiLithos yup, merci.
betseg
3

Python, 187 178 octets

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

Cas de test

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

Python 2 , 135 112 octets

h=reduce(lambda l,r:l+(r/16,r%16),map(ord,input()),())
print[(((r-l+8)%17)-8)*21for l,r in zip((-1,)+h,h+(-1,))]

Essayez-le en ligne!

Jonathan Allan
la source
1

Gelée , 21 19 octets

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

Essayez-le en ligne!

Comment?

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]
Jonathan Allan
la source
1

Ohm , 20 19 octets (CP437), non concurrent

EDIT : enregistré 1 octet en changeant un bloc de carte en cartes répétées à un composant.

Serait probablement un peu plus court si j'avais une vectorisation implicite.

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

Explication:

`»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
Nick Clifford
la source
0

PHP, 125 116 octets:

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

panne

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

Bien sûr, 21est assez inexact et peut échouer pour les chaînes de plus de 14 caractères; mais alors ... 360/17serait quatre octets de plus.

Une solution alternative aurait été d'attacher un pointeur laser à la caméra;
nous pourrions utiliser tous les caractères ascii imprimables et une carte "question" à 3,75 degrés chacun avec cela.

Une autre alternative: utilisez 16 cartes (à 22,5 degrés) avec 6 caractères chacune:
implémentez une sorte de T9 et nous pouvons omettre le quartet élevé. ;)

Titus
la source