Bir kamera döndürün; Astronotu kurtar


23

Not: Marslı için küçük spoiler bu sorunla karşı karşıya. Dikkatle okuyun


Marslı , yanlışlıkla Mars'ta mahsur kalan astronot ve botanikçi olağanüstü Mark Markney hakkında bir Bilim Kurgu romanı . Kitabın bir noktasında, Mark NASA ile iletişim kurmaya çalışıyor, ancak sahip oldukları tek iletişim aracı bir kamera. Mark, indeks kartlarına yazarak mesaj gönderir ve NASA kamerayı 360 derece döndüğü için NASA, kamerayı "Evet" veya "Hayır" etiketli kartlara işaretleyerek geri gönderir.

NASA'nın gönderebileceği tek veri, kameranın karşı karşıya olduğu yön olduğundan, Mark mesaj yazmak için üzerlerinde alfabe karakterli kartlara işaret edebilecekleri bir sistem ile gelir. Ancak 'az' harflerini kullanmak pratik değildir. Kitabı alıntılamak için ( bu cevaptan scifi.se'ye kadar):

Her yarım saatte bir evet / hayır sorularından daha hızlı konuşmamız gerekecek. Kamera 360 derece dönebilir ve çok fazla anten parçam var. Alfabe yapma zamanı. Fakat sadece A'dan Z'ye kadar olan harfleri kullanamıyorum. Yirmi altı harf artı soru kartım toprak sahibinin etrafında yirmi yedi kart olacak. Her biri yalnızca 13 derece yay alır. JPL kamerayı mükemmel bir şekilde işaret etse bile, hangi harfi kastettiklerini bilemem iyi bir şans.

Bu yüzden ASCII kullanmak zorunda kalacağım. Bilgisayarların karakterleri bu şekilde yönetmesi. Her karakter 0 ile 255 arasında sayısal bir koda sahiptir. 0 ile 255 arasındaki değerler 2 onaltılık basamak olarak ifade edilebilir. Bana altıgen basamak çiftleri vererek, sayılar, noktalama işaretleri, vb. Gibi istedikleri karakteri gönderebilirler.

...

Bu yüzden 0'dan 9'a kadar, A'dan F'ye kadar kartlar yapacağım. Bu, kamera etrafına yerleştirilecek 16 kart artı soru kartı. 17 kart, her biri 21 derecenin üzerinde anlamına gelir. Başa çıkmak çok daha kolay.

NASA'nın en iyi yazılım mühendislerinden biri olarak bugün hedefiniz, kameranın çeşitli açılarını kodlayacak bir program yazmak. Mark'ın işaret ettiği on yedi kart (sırayla):

?0123456789ABCDEF

ve bu kartların her biri bu yüzden kamerayı döndürmek için, ayrı 21 derecedir ?için 0,, kamerayı 21 derece döndürmek gerektiğini ve 2hiç 1-21 derecedir. (O değil tam 21 ama daha basit tutmak yuvarlanacak edeceğiz) bu yüzden gitmek için, bu sargıları Fiçin 3105 derece (5 turlu, 5 * 21 = 105) 'dir. Bu kamera -252'den daha verimli, çünkü kamera uzaklaşmak zorunda kalmayacak.

Programınızın veya fonksiyonunuzun yapması gerekenler.

  1. Giriş olarak bir dize atın. Bu dizgeye s diyelim . Basitleştirmek için, girişin yalnızca yazdırılabilir ASCII olacağını söyleyeceğiz. Örneğimize göre, girdi girdiydi.STATUS

  2. Her karakteri onaltılık gösterime dönüştürün. Bu dönüştürmek istiyorum STATUSiçin 53 54 41 54 55 53.

  3. Her karta işaret etmek ve “Soru Kartına” geri dönmek için fotoğraf makinesinin yapması gereken ardışık derece dönüşleri yazdırın veya iade edin. Örneğimiz için bu şöyle olurdu:

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

    Veya, dizi biçiminde:

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

Her zaman olası dönüşlerden en küçüğünü almanız gerektiğini unutmayın. Eğer girdi buysa NO, ki şu şekilde 4E 4Fçıktı almalısınız:

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

Ziyade:

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

İşte biraz daha çalışılmış örnekler:

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]

NASA verimlilikten gurur duyduğundan, hedefiniz mümkün olan en kısa kodu yazmaktır. Standart boşluklar uygulanır. Şimdi onu eve getir!


Yan not: Bu test vakaları el ile yapılmış ve bir tür acı vardı, bu yüzden bazı küçük yanlışlıklar olabilir. Bir şey yanlış görünüyorsa lütfen bana bildirin. :)
DJMcMayhem

Yanıtlar:


5

JavaScript (ES6), 103 99 bayt

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

Test durumları


Bu işe yarar mı? s.replace(/./g,->[...s].map(
Luke

@Luke Nope, çünkü her onaltılık basamağı ayırmamız gerekiyor. ...s.replace(/./g,örneğin verir "4","8","6","5","6","c".... ...[...s.map(verecek"48","65","6c",...
ETHproductions

4

C, 212 202 199 187 bayt

@KritixiLithos! 'A 3 bayt kaydedildi

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

Çevrimiçi deneyin!


1
Bunun 8>i?i:17-iyerine yapabileceğini düşünüyorum17-i>i?...
Kritixi Lithos

@KritixiLithos yup, teşekkürler.
17'de

3

Python, 187 178 bayt

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

Test durumları

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


1

Jöle , 21 19 bayt

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

Çevrimiçi deneyin!

Nasıl?

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

Oh , 20 19 bayt (CP437), rakipsiz

DÜZENLE : Bir harita bloğunu tekrarlanan tek bileşenli haritalara değiştirerek 1 bayt kurtarıldı.

Örtük bir vektörleşmem olsaydı, muhtemelen biraz daha kısa olurdu.

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

Açıklama:

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

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

Yıkmak

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

Tabii ki, 21oldukça yanlış ve 14 karakterden daha uzun olan dizeler için başarısız olabilir; ama sonra ... 360/17dört bayt daha uzun olurdu.

Alternatif bir çözüm, kameraya bir lazer pointer eklemek;
Tüm basılabilir ascii karakterleri ve "soru" kartını her biri 3.75 derecede kullanabilirdik.

Başka bir alternatif: Her biri 6 karakterden oluşan 16 kart (22.5 derecede):
bir tür T9 uygulayın ve yüksek atlamayı kaldırabiliriz. ;)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.