14
\$\begingroup\$

I have a hardware that has a 32-bit input register. The register has the following characteristics:

  • The 32-bit register consists of eight 4-bit fields.
  • Each 4-bit field holds a value in signed-magnitude; it can hold an integer between -7 and +7 inclusive, including -0 and +0 (signed zeroes).

For example, the hexadecimal value 0xABCD1234 represents the field values [-2, -3, -4, -5, +1, +2, +3, +4]. In fact, one hex digit represents one 4-bit value with the following mapping:

Hex    |  Input value
---------------------
0 ~ 7  |  +0 ~ +7
8 ~ F  |  -0 ~ -7

In order to operate this hardware, I figured that the most natural inputs would be 8 consecutive increasing values, treating -0 and +0 as distinct. So the input values will be one of the following:

field values for 8 fields        => 32-bit register value
[-7, -6, -5, -4, -3, -2, -1, -0] => 0xFEDCBA98 (offset -4)
[-6, -5, -4, -3, -2, -1, -0, +0] => 0xEDCBA980 (offset -3)
...
[-3, -2, -1, -0, +0, +1, +2, +3] => 0xBA980123 (balanced, offset 0)
...
[+0, +1, +2, +3, +4, +5, +6, +7] => 0x01234567 (offset +4)

I define the input 0xBA980123 as balanced, and the other inputs have an offset from the balanced input. The balanced input itself has offset 0.

Task

Given the offset, output the desired value for the input register for my hardware as described above.

Input and output

The input (offset) is an integer between -4 and 4 inclusive. You can take it as a string, optionally with explicit sign (e.g. +4).

You can output the result value as an integer or a string. If you choose to output as a string (either returning or printing), you can use base 2, 8, 10 or 16. In case of hexadecimal, mixing upper- and lowercase letters are allowed. Base prefixes (e.g. 0b or 0x), leading zeros, and leading/trailing whitespaces are also allowed.

You may use signed 32-bit values for output instead (imagine the values being used in a C program); in that case, the output values will be subtracted by 2^32, except for the input +4.

Scoring

The standard rules apply. The shortest code in bytes wins.

All test cases

There are only nine possible inputs, so here is the list of all input/output values your program/function needs to support.

input =>  output hex | decimal    | signed 32bit
-4    =>  0xFEDCBA98 | 4275878552 | -19088744
-3    =>  0xEDCBA980 | 3989547392 | -305419904
-2    =>  0xDCBA9801 | 3703216129 | -591751167
-1    =>  0xCBA98012 | 3416883218 | -878084078
 0    =>  0xBA980123 | 3130523939 | -1164443357
 1    =>  0xA9801234 | 2843742772 | -1451224524
 2    =>  0x98012345 | 2550211397 | -1744755899
 3    =>  0x80123456 | 2148676694 | -2146290602
 4    =>  0x01234567 | 19088743   | 19088743
\$\endgroup\$
3
  • \$\begingroup\$ It seems you've gone a long way to accept many base representation outputs, are lists of the place values as integers acceptable? (e.g. 0 -> [11,10,9,8,0,1,2,3] as a raw hexadecimal notation) \$\endgroup\$ Commented Oct 29, 2019 at 0:35
  • 1
    \$\begingroup\$ @JonathanAllan Sorry, but I feel like it's a bit of stretch. \$\endgroup\$
    – Bubbler
    Commented Oct 29, 2019 at 0:43
  • \$\begingroup\$ It is somewhat more natural than a string IMO, but OK, a 2 byte cost to convert from base 16 to an integer for Jelly it is. \$\endgroup\$ Commented Oct 29, 2019 at 0:50

19 Answers 19

4
\$\begingroup\$

Ruby, 30 bytes

Simple and clean. Outputs a substring of the larger with the right offset because it seemed cheaper than any method I could think of that calculated it properly.

->o{"FEDCBA9801234567"[o+4,8]}

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ If you would believe it, I came up with the exact same idea that you did, just about a minute later \$\endgroup\$
    – Gymhgy
    Commented Oct 29, 2019 at 1:46
  • \$\begingroup\$ @EmbodimentofIgnorance I believe it. This seemed like the easiest option right off the bat, anyways, so it's literally a matter of who sees the challenge first haha \$\endgroup\$
    – Value Ink
    Commented Oct 29, 2019 at 1:47
  • 4
    \$\begingroup\$ Am I missing something or should it be FEDCBA...? \$\endgroup\$
    – Gnudiff
    Commented Oct 29, 2019 at 13:30
4
\$\begingroup\$

C (gcc), 35 32 bytes

f(n){n=0xFEDCBA99l*~0u>>16-4*n;}

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Jelly, 14 bytes

12_r8Ḋ;8Ḷ¤ḣ8ḅ⁴

A monadic Link accepting an integer which yields an integer.

Try it online!

How?

12_r8Ḋ;8Ḷ¤ḣ8ḅ⁴ - Link: integer N     e.g. 4              or     -2
12             - literal twelve           12                     12
  _            - subtract N               8                      14
    8          - literal eight            8                      8
   r           - inclusive range          [8]                    [14,13,12,11,10,9,8]
     Ḋ         - dequeue                  []                     [13,12,11,10,9,8]
         ¤     - nilad followed by link(s) as a nilad:
       8       -   literal eight = 8
        Ḷ      -   lowered range = [0..7]
      ;        - concatenate              [0,1,2,3,4,5,6,7]      [13,12,11,10,9,8,0,1,2,3,4,5,6,7]
           8   - literal eight            8                      8
          ḣ    - head to index            [0,1,2,3,4,5,6,7]      [13,12,11,10,9,8,0,1]
             ⁴ - literal sixteen          16                     16
            ḅ  - to integer from base     3130523939             3703216129
\$\endgroup\$
3
\$\begingroup\$

JavaScript (Node.js), 38 bytes

n=>~(p=19088743)*16**(n+4)|p*16**(n-4)

Try it online!

In two's complement representation, 0xfedcba98 is "not 0x01234567 (19088743)". We first shift 0xfedcba98 \$ 4(n+4) \$ bits left, and shift 0x01234567 \$ 4(4-n) \$ bits right. Then use bit or to add them up.

JavaScript do not support n << 32, so we use n * 2 ** 32 instead. And bitwise or in JavaScript automatically convert operand to int32. The two float value trimed to int32 and calculated the result.


Another not quite interesting answer:

JavaScript (Node.js), 35 bytes

n=>'FEDCBA9801234567'.substr(4+n,8)

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Python 3, 60 56 52 37 bytes

lambda n:"FEDCBA9801234567"[4+n:12+n]

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ +1. I had basically the same idea: lambda n:"FEDCBA9801234567"[4+n:][:8] (Same length) \$\endgroup\$ Commented Oct 29, 2019 at 21:31
  • \$\begingroup\$ @pizzapants184 i find your solution even more elegant :) \$\endgroup\$
    – Paul-B98
    Commented Oct 30, 2019 at 5:56
2
\$\begingroup\$

APL (Dyalog Unicode), 23 22 bytes (SBCS)

8↑('FEDCBA98',⎕D)↓⍨4+⊢

Try it online!

First time trying to use APL for golf. Any suggestions for improvement would be greatly appreciated. I put s← in the code field for testing purposes; is there a better way to do that?

(Edit: Removed the s← and saved a byte thanks to Bubbler)

\$\endgroup\$
1
1
\$\begingroup\$

Charcoal, 20 bytes

Nθ⭆…⁻θ⁴⁺θ⁴⎇‹ι⁰⍘⁻⁷ιφι

Try it online! Link is to verbose version of code. Outputs 8 hex digits. Explanation:

Nθ                      Input the offset
  ⭆…                    Map and join over range
    ⁻θ⁴                 From offset - 4 (inclusive)
       ⁺θ⁴              To offset + 4 (exclusive)
          ⎇‹ι⁰          If current value is negative
              ⍘⁻⁷ιφ     Then subtract from 7 and convert to hex
                   ι    Else use directly as digit
                        Implicitly print
\$\endgroup\$
1
\$\begingroup\$

Haskell, 38 bytes

f n=take 8$drop(n+4)"FDECBA9801234567"

Try it online!

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 12 11 bytes

4Ø4Ÿα7݇hJ

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ You can remove the trailing J and just output as a list of characters, can you not? \$\endgroup\$ Commented Nov 4, 2019 at 9:40
1
\$\begingroup\$

Gaia, 12 11 bytes

11⁻7N8…+8<h

Try it online!

Test suite

11⁻          11 - input
   7N        Downward range from result to 7 (excluding 7, empty list if first number is 7)
     8…+     Append the range 0-7 (inclusive)
        8<   First 8 numbers
          h  Convert from hexadecimal
\$\endgroup\$
1
\$\begingroup\$

Bash, 35

  • 1 byte saved thanks to @79037662.
s=FEDCBA9801234567
echo ${s:$1+4:8}

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I believe the last 8 in line 1 is unnecessary. \$\endgroup\$
    – 79037662
    Commented Oct 29, 2019 at 18:07
  • \$\begingroup\$ @79037662, thanks! not sure how that one crept in! \$\endgroup\$ Commented Oct 29, 2019 at 19:31
1
\$\begingroup\$

Perl 6, 28 26 bytes

{:16[11-$_...^7,|^($_+4)]}

Try it online!

Explanation

{                        }  # Anonymous block
     11-$_...^7             # Range 11-n down to 7 exclusive
               ,|^($_+4)    # Followed by range 0 to n+4 exclusive
 :16[                   ]   # Convert from base 16
\$\endgroup\$
1
\$\begingroup\$

PHP, 38 bytes

<?=substr(FEDCBA9801234567,4+$argn,8);

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Wren, 40 bytes

Fn.new{|a|"FEDCBA9801234567"[a+4..a+11]}

Try it online!

Simply a port of most other answers.

Wren, 70 67 bytes

Horribly long answer; outputs to STDOUT.

Fn.new{|a|
for(i in a..a+7)System.write("4567FDECBA980123"[i%16])
}

Try it online!

Explanation

Fn.new{                                                // New anonymous function
       |a|                                             // with parameter a
                                                       // newline because this is
                                                       // not an expression
for(i in a..a+7)                                       // For every item in the range
                                                       // from a to a+7
                                                       // (Select 8 items in the string)
                System.write("4567FDECBA980123"        // Output the string
                                               [i%16]  // with the index of i modulo'd by 16.
                                                       // Moduloing maps the items in
                                                       // the iteration back to the start
                                                       // of the string.
)                                                      // Pretty self-explanatory.
}                                                      // no need to explain this
\$\endgroup\$
1
\$\begingroup\$

Keg, 19 bytes (SBCS)

7Ï89AFɧ(¿4+|")^(8|_

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Turns out the 22 byter I gave earlier was kinda broken. Fixed 22 byter \$\endgroup\$
    – lyxal
    Commented Oct 30, 2019 at 3:59
  • \$\begingroup\$ 19 bytes \$\endgroup\$
    – lyxal
    Commented Dec 18, 2019 at 9:14
1
\$\begingroup\$

K (ngn/k), 22 bytes

(8':"FEDCBA98",/$!8)4+

Try it online!

  • "FEDCBA98",/$!8 is shorthand for "FEDCBA9801234567" (sets up a raze seeded with "FEDCBA98", run over a list of strings each containing one digit from 0..7)
  • (8':...) take 8-length sliding windows of the generated string (creates a list of 9 items)
  • (...)4+ index into that list using the (implicitly) provided index, offsetting by +4 so -4 => 0, -3 => 1, ..., 4 => 8
\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 42 bytes

f=(o,n=8)=>n&&f(o-1,n-1)*16+(o<-3?4-o:o+3)

Try it online!

\$\endgroup\$
0
\$\begingroup\$

C# (Visual C# Interactive Compiler), 38 bytes

x=>"FEDCBA9801234567".Substring(x+4,8)

Each valid output is just a rotation of the string FEDCBA9801234567

Try it online!

\$\endgroup\$
0
\$\begingroup\$

JavaScript (Node.js), 32 bytes

f=n=>n+4?f(--n)*16|n+4:-19088744

Try it online!

Shorter than hardcode

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.