카메라를 회전시킵니다. 우주 비행사를 구하다


23

참고 : 화성 에 대한 경미한 스포일러 가이 도전에 직면 해 있습니다. 주의해서 읽으십시오


화성인 은 우연히 화성에 좌초 된 우주 비행사와 식물학 자의 특별한 마크 왓니 에 관한 공상 과학 소설이다 . 이 책의 어느 시점에서 Mark는 NASA와 통신을 시도하지만 그들이 가지고있는 유일한 통신 수단은 카메라입니다. Mark는 색인 카드에 글을 써서 메시지를 보내고 NASA는 카메라를 360도 회전 할 수 있기 때문에 NAS는 "예"또는 "아니오"라고 표시된 카드로 카메라를 가리켜 회신을 보냅니다.

NASA가 보낼 수있는 유일한 데이터는 카메라가 향하는 방향이므로 Mark는 알파벳 문자가있는 카드를 가리켜 메시지를 입력 할 수있는 시스템을 제공합니다. 그러나 'az'라는 글자를 사용하는 것은 비현실적입니다. 책을 인용하려면 ( 이 답변 에서 scifi.se를 통해) :

우리는 30 분마다 예 / 아니오 질문보다 빠르게 대화해야합니다. 카메라는 360도 회전 할 수 있으며 많은 안테나 부품이 있습니다. 알파벳을 만들 시간입니다. 그러나 나는 단지 A부터 Z까지의 문자를 사용할 수 없습니다. 26 개의 문자와 내 질문 카드는 착륙선 주위에 27 개의 카드가됩니다. 각각은 단지 13 도의 호를 얻을 것입니다. JPL이 카메라를 완벽하게 가리 키더라도 어떤 글자인지 알지 못할 가능성이 큽니다.

ASCII를 사용해야합니다. 그것이 컴퓨터가 캐릭터를 관리하는 방법입니다. 각 문자는 0에서 255 사이의 숫자 코드를 갖습니다. 0에서 255 사이의 값은 2 개의 16 진수로 표현할 수 있습니다. 16 진수 숫자 쌍을 제공하면 숫자, 문장 부호 등 원하는 문자를 보낼 수 있습니다.

...

0에서 9, A에서 F까지 카드를 만들겠습니다. 그러면 카메라 주위에 16 장의 카드와 질문 카드가 만들어집니다. 17 개의 카드는 각각 21도 이상을 의미합니다. 다루기가 훨씬 쉽습니다.

NASA의 최고 소프트웨어 엔지니어 중 하나 인 오늘의 목표는 다양한 카메라 각도를 인코딩하는 프로그램을 작성하는 것입니다. 마크가 당신을 가리킬 수있는 17 장의 카드는 (순서대로) :

?0123456789ABCDEF

이러한 카드의 각 그렇게에서 카메라 회전, 떨어져 21도이다 ?하는 0, 당신이 카메라를 21도 회전한다, 그리고 2에는 1-21 도입니다. (그것은 아니다 정확히 21 만, 우리는 그것을 간단하게 유지하기 위해 반올림 것이다) 그래서에서 가고,이 랩을 F하려면 3105 개도 (5 회전, 5 * 21 = 105)입니다. 카메라가 멀리 이동할 필요가 없기 때문에 -252보다 더 효율적입니다.

프로그램이나 기능이 수행해야 할 작업은 다음과 같습니다.

  1. 문자열을 입력으로 사용하십시오. 이 문자열을 s 라고 부릅니다 . 간단하게 유지하기 위해 입력은 인쇄 가능한 ASCII 만 가능하다고 말할 것입니다. 이 예에서는 입력이STATUS

  2. 각 문자를 16 진수 표현으로 변환하십시오. 이로 변환 STATUS됩니다 53 54 41 54 55 53.

  3. 카메라가 각 카드를 가리키고 "질문 카드"로 돌아 가기 위해 필요한 연속 회전 수를 인쇄하거나 반환합니다. 이 예에서는 다음과 같습니다.

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

    또는 배열 형식으로 :

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

항상 가능한 가장 작은 회전을 수행해야합니다. 따라서 입력이 NO인 경우 즉 4E 4F, 출력해야합니다.

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

오히려 :

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

몇 가지 더 효과적인 예는 다음과 같습니다.

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는 효율성에 자부심을 가지고 있으므로 목표는 가능한 가장 짧은 코드를 작성하는 것입니다. 표준 허점이 적용됩니다. 이제 그를 집으로 데려와!


참고 : 이 테스트 사례는 수작업으로 작성되었으며 일종의 고통이므로 약간의 부정확 한 부분이있을 수 있습니다. 문제가 있으면 알려주세요. :)
DJMcMayhem

답변:


5

자바 스크립트 (ES6), 103 99 바이트

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

테스트 사례


이게 효과가 있을까요? s.replace(/./g,->[...s].map(
Luke

@Luke Nope, 우리는 각 16 진수를 분리해야하기 때문입니다. ...s.replace(/./g,예를 들어 "4","8","6","5","6","c"..., 동안. ...[...s.map(줄 것이다"48","65","6c",...
ETHproductions

4

C, 212 202 199 187 바이트

@KritixiLithos 덕분에 3 바이트가 절약되었습니다!

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

온라인으로 사용해보십시오!


1
나는 당신이 할 수 있다고 생각 8>i?i:17-i대신에17-i>i?...
Kritixi LITHOS

@KritixiLithos 고맙습니다.
betseg

3

파이썬, 187178 바이트

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

테스트 사례

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


1

젤리 , 21 19 바이트

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

온라인으로 사용해보십시오!

방법?

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

, 20 19 바이트 (CP437), 비경쟁

편집 : 맵 블록을 반복 된 단일 컴포넌트 맵으로 변경하여 1 바이트를 저장했습니다.

암시 적 벡터화가 있다면 아마도 훨씬 짧을 것입니다.

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

설명:

`»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 바이트 :

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

고장

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

물론, 21정확하지 않으며 14 자보다 긴 문자열에서는 실패 할 수 있습니다. 그러나 ... 360/174 바이트 더 길 것입니다.

다른 해결책은 카메라에 레이저 포인터를 부착하는 것입니다.
인쇄 가능한 모든 ASCII 문자와 "질문"카드를 각각 3.75 도로 사용할 수 있습니다.

또 다른 대안 : 각각 6 문자로 16 개의 카드 (22.5도)를 사용하십시오 :
일종의 T9를 구현하면 높은 니블을 생략 할 수 있습니다. ;)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.