Bitflip and negate

42

2

Given an integer, make an expression that produces it from 0 using unary negation - and bitwise complement ~ (~n = -n-1), with the operators applied right to left.

...
-3  = ~-~-~0
-2  = ~-~0
-1  = ~0
 0  = 0
 1  = -~0
 2  = -~-~0
 3  = -~-~-~0
...

Your expression must be as short as possible, which means no redundant parts of ~~, --, -0, or 00. Output or print the expression as a string or a sequence of characters.

var QUESTION_ID=92598,OVERRIDE_USER=20260;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/92598/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

xnor

Posted 2016-09-07T18:49:16.050

Reputation: 115 687

11

So... you want us to put our thing down, flip it and reverse it?

– Jordan – 2016-09-07T20:42:17.697

1whitespace between ~ and 0 allowed? – Adám – 2016-09-07T20:54:02.423

No, output the strings exactly. – xnor – 2016-09-07T21:54:38.873

2

Obligatory https://xkcd.com/153/

– Jared Smith – 2016-09-08T20:17:51.220

Answers

17

Python, 32 bytes

lambda x:("-~"*abs(x))[x<0:]+"0"

Anonymous lambda function. Given an integer x writes "-~" abs(x) times and removes the first char if x is negative, then a zero is added to the end.

KarlKastor

Posted 2016-09-07T18:49:16.050

Reputation: 2 352

Aw, beat me to it. – mbomb007 – 2016-09-07T19:43:14.463

I just wrote the same too - with n in the place of x and ' in the place of " :) – Jonathan Allan – 2016-09-07T23:30:48.773

2@JonathanAllan Then you can safely consider it a dupe. – Erik the Outgolfer – 2016-09-08T12:03:54.177

16

JavaScript (ES6), 33 31 bytes

f=x=>x<0?"~"+f(~x):x&&"-"+f(-x)

Recursion < built-ins < loops (at least in this case). Basically unevaluates the input:

  • if it's less than 0, flip it and add a ~ to the string;
  • if it's more than 0, negate it and add a - to the string;
  • if it's exactly 0, return 0.

Takes advantage of this pattern:

 0         = 0
-1 = ~( 0) = ~0
+1 = -(-1) = -~0
-2 = ~(+1) = ~-~0
+2 = -(-2) = -~-~0
-3 = ~(+2) = ~-~-~0
+3 = -(-3) = -~-~-~0
etc.

ETHproductions

Posted 2016-09-07T18:49:16.050

Reputation: 47 880

11

Pyth, 14 13 12 Bytes

_<>0Q+0sm"~-

-2 Bytes thanks to @StevenH.

test suite

Decided to try out Pyth, so i translated my python answer to it. Any help welcome!

Explanation:

_<>0Q+0sm"~-     
        m"~-     # Map "~-" onto the input (= a list of n times "~-").
       s         # Join the list to a string.
     +0          # Add "0" in front. 
 <>0Q            # Slice off the last char if the input is negative.
_                # Reverse the whole thing.

KarlKastor

Posted 2016-09-07T18:49:16.050

Reputation: 2 352

Use implicit input at the end to save one byte: >0 instead of <Q0 – Steven H. – 2016-09-07T20:21:34.337

@StevenH. Thank you! Now we're in a tie with the shortest answer! – KarlKastor – 2016-09-07T20:31:04.683

2Very different solution (that, unfortunately, doesn't save any bytes): tW>0Q_+0sm"~- – Steven H. – 2016-09-07T20:45:53.070

2@StevenH. Golfed your solution down to 12: _<>0Q+0sm"~- I hope your okay with me adding this to my solution. – KarlKastor – 2016-09-07T22:44:31.577

8

C, 46 bytes

m(x){putchar(x?x<0?126:45:48);x&&m(-x-(x<0));}

Unlike most (all?) other answers, this one outputs the operators ~ and - one by one.

anatolyg

Posted 2016-09-07T18:49:16.050

Reputation: 10 719

7

05AB1E, 14 13 bytes

Ä„-~×¹0‹i¦}0J

Explanation

 „-~           # the string "-~"
Ä   ×          # repeated abs(input) times
     ¹0‹i¦}    # if input is negative, remove the first char
           0J  # join with 0

Try it online!

Emigna

Posted 2016-09-07T18:49:16.050

Reputation: 50 798

7

Retina, 19 17 bytes

Replace the number with unary, with a zero on the end. Replace each 1 with -~. Remove double negative if there is one.

\d+
$*10
1
-~
--

Try it online

All test cases at once (slightly modified program to support multiple test cases)

mbomb007

Posted 2016-09-07T18:49:16.050

Reputation: 21 944

7

Perl 38 35 33 (23 + 1 for -p) 24

s/\d+/"-~"x$&.0/e;s;--;

-13 thanks to Dada

Riley

Posted 2016-09-07T18:49:16.050

Reputation: 11 345

You probably meant -p instead of -r. Also you can get rid of those last parenthesis and semicolon : if$h<0 is enough. – Dada – 2016-09-07T21:03:55.133

I did, thanks. I've been writing too many answers in sed I guess. – Riley – 2016-09-07T21:05:42.493

Probably, yea. (Get rid of the last 2 parenthesis too) – Dada – 2016-09-07T21:09:17.537

You can also save 2 bytes by doing $h<0&&s;.; instead of s/.// if $h<0. (-p adds a ; at the end of the code, so no need for the last ; of s;.;;. And a if b is roughly equivalent to b && a, but in this case it saves you one byte because you can remove the space) – Dada – 2016-09-07T21:19:14.297

Thanks, I didn't know -p added a ; too. – Riley – 2016-09-07T21:22:43.950

A 25 bytes version : perl -l60pe 's/\d+/"-~"x$&/e;s;--;' – Dada – 2016-09-07T21:51:18.903

@Dada got it down to 24 by appending a 0 in the substitution instead of using -l60 – Riley – 2016-09-07T22:01:48.593

Very neat. Have a +1 – Ton Hospel – 2016-09-08T08:32:19.193

6

Haskell, 41 bytes

f n=['-'|n>0]++(tail$[1..abs n]>>"-~")++"0"

f n|n<0=tail$f(-n)|x<-[1..n]>>"-~"=x++"0"

Thanks to nimi for 3 bytes

BlackCap

Posted 2016-09-07T18:49:16.050

Reputation: 3 576

tail fails for n=0. You can use drop 1 instead. – nimi – 2016-09-07T20:25:04.707

@nimi Thanks; I have no idea how I missed that.. – BlackCap – 2016-09-07T20:31:31.860

1Don't waste the otherwise guard: f n|n<0=tail.f$abs n|x<-[1..n]>>"-~"=x++"0". – nimi – 2016-09-07T20:42:42.347

12 bytes to save: ...|n<0=tail$f(-n)|.... – nimi – 2016-09-07T21:02:03.407

6

Dyalog APL, 18 bytes

'0',⍨0∘>↓'-~'⍴⍨2×|

'0',⍨ character zero appended to

0∘> negativeness (i.e. 1 for numbers under 0; 0 for zero and up)

dropped from

'-~'⍴⍨ the string "~-" cyclically reshaped to length

two times

| the absolute value

+ plus

0∘< positiveness (i.e 1 for numbers over 0)

TryAPL online!

Adám

Posted 2016-09-07T18:49:16.050

Reputation: 37 779

5

V, 21 bytes

/ä
é
D@"ña-~ñá0kgJó--

Try it online!

V has very limited number support, and it actually has no concept of negative numbers. This means in order to support negatives (or even 0), we have to use some hacky workarounds.

Explanation:

/ä                  "Move forward to the first digit
é                   "And enter a newline
D                   "Delete this number, into register '"'
 @"                 "That number times:
   ñ   ñ            "Repeat the following:
    a               "  Append the string:
     -~             "  '-~'
        á0          "Append a 0
          k         "Move up a line
           gJ       "And join these two lines together
             ó--    "Remove the text '--', if it exists

James

Posted 2016-09-07T18:49:16.050

Reputation: 54 537

5

JavaScript (ES6), 39 37 bytes

x=>"-~".repeat(x<0?-x:x).slice(x<0)+0

Saved 2 bytes thanks to @Neil

Huntro

Posted 2016-09-07T18:49:16.050

Reputation: 459

5

Ruby, 34 bytes

->x{("-~"*x.abs+?0)[2[0<=>x]..-1]}

cia_rana

Posted 2016-09-07T18:49:16.050

Reputation: 441

5

Jelly, 10 bytes

A⁾-~ẋḊẋ¡N0

This is a full program. Try it online!

How it works

A⁾-~ẋḊẋ¡N0  Main link. Argument: n

A           Take the absolute value of n.
 ⁾-~ẋ       Repeat the string "-~" that many times. Result: s
       ¡    Conditional application:
     Ḋ        Dequeue; remove the first element of s...
      ẋ N     if s, repeated -n times, is non-empty.
         0  Print the previous return value. Set the return value to 0.
            (implicit) Print the final return value.

Dennis

Posted 2016-09-07T18:49:16.050

Reputation: 196 637

5

Java 7, 95 79 bytes

79 bytes:

String s(int x){String t=x<0?"~":"";while((x<0?++x:x--)!=0)t+="-~";return t+0;}

Ungolfed:

String s(int x) {
    String t = x<0 ? "~" : "";
    while((x<0 ? ++x : x--) != 0)
        t += "-~";
    return t+0;
}

Old version (95 bytes):

String s(int x){return new String(new char[x<0?-x:x]).replace("\0","-~").substring(x<0?1:0)+0;}

Usage:

class A {
    public static void main(String[]a) {
        System.out.println(s(-3));
        System.out.println(s(-2));
        System.out.println(s(-1));
        System.out.println(s(0));
        System.out.println(s(1));
        System.out.println(s(2));
        System.out.println(s(3));
    }
    static String s(int x){String t=x<0?"~":"";while((x<0?++x:x--)!=0)t+="-~";return t+0;}
}

Try it here!

Output:

~-~-~0
~-~0
~0
0
-~0
-~-~0
-~-~-~0

QBrute

Posted 2016-09-07T18:49:16.050

Reputation: 271

Hi, and welcome to PPCG! Nice first post! – Rɪᴋᴇʀ – 2016-09-08T10:59:18.787

Welcome to PPCG! Hmm, that's a shorter solution than mine, so I will delete my answer and upvote yours instead. :) – Kevin Cruijssen – 2016-09-08T11:42:35.910

3

EXCEL: 55 33 bytes

=REPT("-~",IF(A1>0,A1,ABS(A1)-1))&"0"

Input is in the form of putting a number in the A1 cell. Formula can go anywhere except A1.

user56309

Posted 2016-09-07T18:49:16.050

Reputation:

I don't think it works for negative numbers... – pajonk – 2016-09-09T05:09:09.813

3

CJam, 18 14 bytes

Took some inspiration from Emigna's answer to save 4 bytes.

li_z"-~"*\0<>0

Try it online! (As a linefeed-separated test suite.)

Explanation

li      e# Read input and convert to integer N.
_z      e# Duplicate and get |N|.
"-~"*   e# Repeat this string |N| times.
\0<     e# Use the other copy of N to check if it's negative.
>       e# If so, discard the first '-'.
0       e# Put a 0 at the end.

Martin Ender

Posted 2016-09-07T18:49:16.050

Reputation: 184 808

3

T-SQL, 87 bytes

select substring(replicate('-~',abs(x)),case when x<0then 2 else 1 end,x*x+1)+'0'from #

The x*x+1 condition in substring is sufficient, since x^2+1>=2*abs(x) for all x.

As usually in SQL, the input is stored in a table:

create table # (x int)

insert into # values (0)
insert into # values (1)
insert into # values (-1)
insert into # values (2)
insert into # values (-2)

pajonk

Posted 2016-09-07T18:49:16.050

Reputation: 2 480

3

Vim - 31 keystrokes

First vim golf, prolly missed a ton of stuff.

`i-~<esc>:s/-\~-/\~-/dwp<left>ii<esc><left>d$@"<esc>a0`

Maltysen

Posted 2016-09-07T18:49:16.050

Reputation: 25 023

Nice, welcome to the club! :) You could do :s/^- instead of :s/-\~/\~- and D instead of d$ – James – 2016-09-08T21:33:41.420

Now that I think about it, I don't think this handles 0. You could get around this by incrementing before deleting with <C-a> and then deleting two characters off the end. – James – 2016-09-08T22:17:10.617

@DJMcMayhem oh, 0i doesn't work? – Maltysen – 2016-09-09T01:37:11.717

No, unfortunately not. 0 moves the cursor to the first character on the current row. You can sorta use 0 as a count in V though. – James – 2016-09-09T01:39:02.680

2

Matlab, 61 bytes

x=input('');A=repmat('-~',1,abs(x));disp([A((x<0)+1:end) 48])

pajonk

Posted 2016-09-07T18:49:16.050

Reputation: 2 480

2

Pyke, 14 13 bytes

X,"-~"*Q0<>0+

Try it here!

Blue

Posted 2016-09-07T18:49:16.050

Reputation: 26 661

2

Perl 6, 25 bytes

{substr '-~'x.abs~0,0>$_}

Explanation:

{
  substr
    # string repeat 「-~」 by the absolute value of the input
    '-~' x .abs

    # concatenate 0 to that
    ~ 0

    ,

    # ignore the first character of the string if it is negative
    0 > $_
}

Brad Gilbert b2gills

Posted 2016-09-07T18:49:16.050

Reputation: 12 713

2

Jelly, 14 12 bytes

-2 bytes thanks to @Dennis (return 0 rather than concatenate "0", making this a full program only.)

0>‘
A⁾-~ẋṫÇ0

Test it at TryItOnline

How?

0>‘      - link 1 takes an argument, the input
0>       - greater than 0? 1 if true 0 if false
  ‘      - increment

A⁾-~ẋṫÇ0 - main link takes an argument, the input
      Ç  - y = result of previous link as a monad
A        - x = absolute value of input
 ⁾-~     - the string "-~"
    ẋ    - repeat the sting x times
     ṫ   - tail repeatedString[y:] (y will be 1 or 2, Jelly lists are 1-based)
       0 - implicit print then return 0

Jonathan Allan

Posted 2016-09-07T18:49:16.050

Reputation: 67 804

2

><>, 18 + 3 = 22 bytes

:?!n0$-:0):1go-
-~

Try it online! +3 bytes for the ​ -v flag to initialise the stack with the input. If assuming that STDIN is empty is okay, then the following is a byte shorter:

:?!ni*:0):1go-
-~

The program keeps flipping the input n as necessary until it reaches 0, after which it errors out.

[Loop]
:?!n      If n is 0, output it as a num. If this happens then the stack is now
          empty, and the next subtraction fails
0$-       Subtract n from 0
:0)       Push (n > 0)
:1go      Output the char at (n>0, 1) which is a char from the second line
-         Subtract, overall updating n -> -n-(n>0)

Sp3000

Posted 2016-09-07T18:49:16.050

Reputation: 58 729

2

PseudoD, 688 579 521 bytes

utilizar mate.pseudo
utilizar entsal.pseudo
adquirir n
adquirir a
adquirir r
adquirir i
fijar n a llamar LeerPalabra finargs
si son iguales n y CERO
escribir {0}
salir
fin
fijar a a llamar ValorAbsoluto n finargs
fijar i a CERO
si comparar Importar.Ent.Comparar n < CERO
fijar r a {~}
sino
fijar r a {-}
fin
mientras comparar Importar.Ent.Comparar i < a
escribir r finargs
si son iguales r y {~}
fijar r a {-}
Importar.Ent.Sumar i UNO i
sino
fijar r a {~}
fin
finbucle
si son iguales r y {~}
escribir {~}
fin
escribir {0}

Explain:

Read a number from STDIN;
If the number is zero (0); Then:
    Writes 0 to STDOUT and exits;
End If;
If the number is less than zero (0); Then:
    Set the fill character to "~";
Else:
    Set the fill character to "-";
End If;
For i = 0; While i is less than abs(number); do:
    Write the fill character to STDOUT;
    If the fill character is "~":
        Set the fill character to "-"
        Increment i by one
    Else:
        Set the fill character to "~"
    End if;
End for;
If the fill character is "~"; Then:
    Write "~" to STDOUT;
End If;
Write "0" to STDOUT

alinarezrangel

Posted 2016-09-07T18:49:16.050

Reputation: 21

1Welcome to PPCG! Is that as small as it gets? I see some long identifiers you could probably shorten ("relleno" to "r", menos relleno :P). I think you can drop the imports for standard lib if it's only a function or code snippet too. It doesn't ask for trailing newline on output, so maybe you can change the last EscribirLinea to Escribir. Can you assign functions to shorter names(adquirir e``fijar p a Escribir)? – fede s. – 2016-09-10T21:59:36.717

2

Octave, 51 bytes

x=input('');[("-~"'*[1:abs(x)>0])((x<0)+1:end),'0']

At first blatantly copying the Matlab approach by @pajonk and then modifying some details, rewriting as an "outer product" between a vector of ones and the characters "-~" and abusing on-the-fly-indexing (or what it could be called) lets us save some bytes. It still pains me slightly that I can't get the index expression to take fewer bytes.

Octave allows a(i1)(i2) or even (...)(i1)(i2) for indexing where Matlab would want us to store variables in between the indexings.

((x<0)+1:end)

is far too long to describe "skip first if". There must be a better way.

mathreadler

Posted 2016-09-07T18:49:16.050

Reputation: 141

1

PHP, 61 bytes

if(0>$n=$argv[1]){echo"~";$n=~$n;}echo str_repeat("-~",$n),0;

Jörg Hülsermann

Posted 2016-09-07T18:49:16.050

Reputation: 13 026

1

PHP, 58 bytes

<?=((0<$a=$argv[1])?'-':'').str_pad('0',2*abs($a),'~-',0);

Crypto

Posted 2016-09-07T18:49:16.050

Reputation: 862

1

Labyrinth, 25 bytes

`?+#~.
.  ; 6
54_"#2
  @!

Try it online!

Explanation

I really like the control flow in this one. The IP runs in a figure 8 (or actually a ∞, I guess) through the code to reduce the input slowly to 0 while printing the corresponding characters.

The code starts in the upper left corner going right. The ` doesn't do anything right now. ? reads the input and + adds it to the implicit zero below. Of course that doesn't do anything either, but when we run over this code again, ? will push a zero (because we're at EOF), and + will then get rid of that zero.

Next the # pushes the stack depth, simply to ensure that there's a positive value on the stack to make the IP turn south, and ; discards it again.

The " is a no-op and acts as the main branch of the code. There are three cases to distinguish:

  • If the current value is positive, the IP turns right (west) and completes one round of the left loop:

    _45.`?+
    _45      Push 45.
       .     Print as character '-'.
        `    Negate the current value (thereby applying the unary minus).
         ?+  Does nothing.
    
  • If the current value is negative, the IP turns left (east) and the following code is run:

    #26.~
    #        Push stack depth, 1.
     26      Turn it into a 126.
       .     Print as character '~'.
        ~    Bitwise NOT of the current value (applying the ~).
    

    Note that these two will alternate (since both change the sign of the input) until the input value is reduced to zero. At that point...

  • When the current value is zero, the IP simply keeps moving south, and executes the ! and then turns west onto the @. ! prints the 0 and @ terminates the program.

Martin Ender

Posted 2016-09-07T18:49:16.050

Reputation: 184 808

1

GolfScript

, 30 24 20 bytes

  • Saved 6 bytes thanks to xnor.
  • Saved 4 bytes thanks to Dennis.

~."-~"\abs*\0<{(;}*0

Input: -5

Output: -5 = ~-~-~-~-~0

Explanation

~.     # Input to integer and duplicate
"-~"   # We shall output a repetition of this string
\abs   # Move the input onto the stack and computes abs
*      # Multiply "-~" for abs(input) times
\      # Copy onto the stack the input
0<     # Is it less than 0?
{(;}*  # Yes: remove first '-' from the output
0      # Push 0

Try it online!

FedeWar

Posted 2016-09-07T18:49:16.050

Reputation: 271

1You don't have to print the 2 =, just the -~-~0. – xnor – 2016-09-11T07:21:48.200

1You can use {(;}*0 instead of {(;}{}if 0. – Dennis – 2016-09-11T07:47:48.780