Generate input for this hardware

13

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

Bubbler

Posted 2019-10-28T23:32:25.757

Reputation: 16 616

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) – Jonathan Allan – 2019-10-29T00:35:11.253

1@JonathanAllan Sorry, but I feel like it's a bit of stretch. – Bubbler – 2019-10-29T00:43:51.530

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. – Jonathan Allan – 2019-10-29T00:50:56.607

Answers

3

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

Jonathan Allan

Posted 2019-10-28T23:32:25.757

Reputation: 67 804

3

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!

Value Ink

Posted 2019-10-28T23:32:25.757

Reputation: 10 608

If you would believe it, I came up with the exact same idea that you did, just about a minute later – Embodiment of Ignorance – 2019-10-29T01:46:01.063

@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 – Value Ink – 2019-10-29T01:47:36.590

4Am I missing something or should it be FEDCBA...? – Gnudiff – 2019-10-29T13:30:26.657

2

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!

tsh

Posted 2019-10-28T23:32:25.757

Reputation: 13 072

2

C (gcc), 35 32 bytes

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

Try it online!

nwellnhof

Posted 2019-10-28T23:32:25.757

Reputation: 10 037

2

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)

david

Posted 2019-10-28T23:32:25.757

Reputation: 180

You can wrap a line of code into a function like this. Also, save a byte by going tacit. For general tips, check out APL golfing tips.

– Bubbler – 2019-12-20T00:46:38.100

1

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

Neil

Posted 2019-10-28T23:32:25.757

Reputation: 95 035

1

Haskell, 38 bytes

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

Try it online!

Joseph Sible-Reinstate Monica

Posted 2019-10-28T23:32:25.757

Reputation: 556

1

Python 3, 60 56 52 37 bytes

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

Try it online!

Delta

Posted 2019-10-28T23:32:25.757

Reputation: 543

+1. I had basically the same idea: lambda n:"FEDCBA9801234567"[4+n:][:8] (Same length) – pizzapants184 – 2019-10-29T21:31:20.627

@pizzapants184 i find your solution even more elegant :) – Delta – 2019-10-30T05:56:21.797

1

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

nwellnhof

Posted 2019-10-28T23:32:25.757

Reputation: 10 037

1

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

user85052

Posted 2019-10-28T23:32:25.757

Reputation:

1

Keg, 19 bytes (SBCS)

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

Try it online!

user85052

Posted 2019-10-28T23:32:25.757

Reputation:

Turns out the 22 byter I gave earlier was kinda broken. Fixed 22 byter

– Lyxal – 2019-10-30T03:59:55.713

19 bytes – Lyxal – 2019-12-18T09:14:14.347

1

05AB1E, 12 11 bytes

4Ø4Ÿα7݇hJ

Try it online!

Grimmy

Posted 2019-10-28T23:32:25.757

Reputation: 12 521

You can remove the trailing J and just output as a list of characters, can you not? – Kevin Cruijssen – 2019-11-04T09:40:17.760

1

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

Business Cat

Posted 2019-10-28T23:32:25.757

Reputation: 8 927

1

PHP, 38 bytes

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

Try it online!

Night2

Posted 2019-10-28T23:32:25.757

Reputation: 5 484

0

JavaScript (ES6), 42 bytes

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

Try it online!

Arnauld

Posted 2019-10-28T23:32:25.757

Reputation: 111 334

0

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!

Embodiment of Ignorance

Posted 2019-10-28T23:32:25.757

Reputation: 7 014

0

Bash, 35

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

Try it online!

Digital Trauma

Posted 2019-10-28T23:32:25.757

Reputation: 64 644

1I believe the last 8 in line 1 is unnecessary. – 79037662 – 2019-10-29T18:07:04.510

@79037662, thanks! not sure how that one crept in! – Digital Trauma – 2019-10-29T19:31:17.947