23
\$\begingroup\$

This challenge is brought to you by real (and tragic) inspiration. Recently, the number row on my keyboard has been a bit sporadic. The keys 1-9 work sometimes--but other times they have no result. As an avid programmer, this is horrible! (See that exclamation point? That's how you know they're working right now.) Not only do I often need the numbers themselves, but the symbols !@#$%^&*( are completely ineffective half the time as well! As a C programmer, rather than take time off my busy schedule of doodling around with code to fix my laptop, I've been more interested in working around the problem. Over the course of the past few weeks, slowly, all of the number literals in my code have been replaced with hexadecimal so that I don't have to go hunting around for numbers to copy and paste. However, some numbers aren't easy to type without the keys 1-9. For example, the number 1 cannot be written so simply in hexadecimal, and I've resorted to replacing 1s in my code with 0xF - 0xE. The only keys that are affected are 1-9, so I maintain full use of symbols like +, -, and /. However, I cannot use multiplication or parentheses, as * and ( are often broken. This leads to your challenge.

Input

An integer, n to stdin or your language's equivalent. If you wish, the integer may be preceded or followed by a new line or other whitespace character. Alternatively, you may receive input via a command line argument.

Your program should respond to negative input correctly, and be able to handle at least 32-bit signed integers.

Output

Your program should output, in some observable form, the shortest (in non-whitespace characters) possible way to write the number n as a sum, difference, or division of one or more hexadecimal values. There is more than one way to solve this problem, and there is no requirement that you favor any equal-length output over any other.

The output should be in the form A % A % A... where A is a hexadecimal value following 0x containing only digits A-F a-f, and % is one of of the symbols -+/. Let / describe integer division, not floating-point.

(Note that your output should result in n when evaluating divisions first, left to right, and then additions and subtractions, left to right, as is convention.)

Test Cases

Input Output

  1. 1

    0xF - 0xE (or 0xF-0xE or 0xB-0xA or 0xd - 0xc or 0xF/0xF)

  2. 15

    0xF

  3. 255

    0xFF

  4. 30

    0xF + 0xF

Scoring and Rules

This is code-golf. Your preliminary score is the number of bytes in your source file.

You may NOT use any of the digits 1-9 in your source.

You MAY use symbols !@#$%^&*( in your source, but each comes at a penalty of +20 to your score.

Your program may be replaced by a function that takes n as an argument as long as that function produces some form of human-readable output. Your function's return value does NOT count as output.

Standard loopholes are not allowed.

Lowest score wins! Good luck!

Did I goof something up formatting/questioning/clarity-wise? Let me know! This is my first submission to this site!

\$\endgroup\$
  • \$\begingroup\$ Is there an upper limit to the size of the integer? Also, will negative numbers be represented to some arbitrary precision (i.e. 32 bit)? \$\endgroup\$ – FryAmTheEggman Feb 21 '15 at 2:29
  • \$\begingroup\$ @FryAmTheEggman Edited the original post to clarify. Input may be negative, and your program should respond correctly to at least 32 bit input. Thanks! \$\endgroup\$ – BrainSteel Feb 21 '15 at 3:41
  • \$\begingroup\$ Related: codegolf.stackexchange.com/a/32114/21348 \$\endgroup\$ – edc65 Feb 21 '15 at 9:28
  • \$\begingroup\$ This looks like a pretty solid spec to me, but if you'd like some feedback, I'd recommend posting it in the sandbox (for future challenges) so you can get feedback before you post it on main and people start working on it. \$\endgroup\$ – Martin Ender Feb 21 '15 at 10:10
  • 1
    \$\begingroup\$ Integer or floating point division? \$\endgroup\$ – edc65 Feb 21 '15 at 10:30
5
\$\begingroup\$

JavaScript 287 (187+20*5) 295 (195 +20*5) 338 (198 + 20*7)

A function that check every possible combinations of the 6 allowed hex digits (0xA to 0xF) and the 3 allowed operators. Output via popup and not returning a value, as requested.

I used [] to group comma separated expression but could not avoid 5 7 open brackets for loops and function calling.
To avoid digits there are variables A,B,C for 1,2,3 (this makes the code even more obscure)

Edit code revised focusing on avoiding '('. Removed ifs and explicit RegExp creation

Beware: this function is incredibly slow, it will exceed the time limit for a script in FireFox, even for small input like 90.

To enumerate all the possible expression, I use number starting at 3 and going up forever. Digits encoding:
0,1,2 are the operators +,-,/
4 to 9 are the hex digits A..F
3 is not allowed
Each number is checked with a regexp /3|[0-2]{2}/ to avoid the digit 3 and having 2 consecutive operators (the check also avoid traling and leading operators - see code)

The resulting string is something like 0xA + 0xA - 0xD that is valid javascript, so I use eval to evaluate it. Unfortunatley the '/' operator is floating point and not integer in JavaScript, so I'm not 100% sure that the result are correct event casting to integer the final result (but I am quite confident, given that a small rounding error can not be amplified by a '*')

F=x=>{
  for(A=-~0,B=A+A,i=C=A+B,j=0;j?x-~~eval(L):A;)
  {
    j=++i+'0',k=0+j;
    for(c of~k.search(C+'|[0-'+B+']{'+B+'}',L='',w='0x')?j='':j)
      c>C?w+=' ABCDEF'[c-C]:[L+=w,w=' '+'+-/'[c]+' 0x']
  }
  alert(L)
}

Something else

Now, something funnier. I used an oversimplified expressione parser to avoid the eval call and, amusingly, that turned out to be a lot faster.

The parser is really simplified, in a real parser V and O should be arrays containing the pending values stack and the pending operators stack. Here V is the single pending value (and also the return value) and O is a string with at most 2 characters. P contains the operators precedence table, for '-+/' => '112'

This scores 275 + 4*20 => 355

F=x=>{
  for(A=-~0,B=A+A,i=C=A+B,D=A+C,j=0,P=''+A+A+B;j?x-V:A;)
  {
    j=++i+'0',k=0+j;
    for(c of~k.search(C+'|[0-'+B+']{'+B+'}',v=V=O=L='',w='0x')?j='':j)
      c>C?
        w+='ABCDEF'[v<<=D,v+=D+A-~c,c-D]
      :[
          P[O[0]]>=P[c]?[v=O>A?V/v|0:O>0?V+v:V-v,O=c]:O=c+O,
          L+=w,w=' '+'-+/'[c]+' 0x',V=v,v=0
      ]
  }
  alert(L)
}

Test In Firefox/FireBug console, change alert with return (a lot more usable)

;[0, 1, 15, 255, 30].forEach(x=>console.log(x,F(x)))

0 0xA - 0xA
1 0xA / 0xA
15 0xF
255 0xFF
30 0xF + 0xF

Just a little less obvious (but be patient)

;[16,40, 51, 62, 73, 84, 95].forEach(x=>console.log(x,F(x)))

16 0xBA / 0xB
40 0xA + 0xF + 0xF
51 0xDD - 0xAA
62 0xEA - 0xAC
73 0xA + 0xEA - 0xAB
84 0xFE - 0xAA
95 0xA + 0xFF - 0xAA

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

Python 2: 185 byte + 2 * 20 = 225

Way too long for a serious answer. But since there are no answers yet, I'll post it anyways.

from itertools import product as p
n=input()
l=t=0
while~l:
 l=-~l
 for i in p("0xABCDEF+-/",repeat=l):
  j=""
  for k in i:j+=k
  try:exec"t="+j
  except:0
  if t==n:print j;l=~0;break

product creates all different arrangements of the allowed chars. exec tries to decode it. This sadly returns an exception, thence the long try - catch block. It the result is fine, it prints and exists.

2 times penalty, because of those braces during function calls.

\$\endgroup\$
  • 2
    \$\begingroup\$ This answer could have a couple of issues: (1) 0 isn't a hexadecimal literal; (2) Division involving a negative number in Python gives a different result than in C. \$\endgroup\$ – feersum Feb 22 '15 at 2:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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