Bitflip and negate

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>

• So... you want us to put our thing down, flip it and reverse it? Commented Sep 7, 2016 at 20:42
• whitespace between ~ and 0 allowed?
Commented Sep 7, 2016 at 20:54
• No, output the strings exactly.
– xnor
Commented Sep 7, 2016 at 21:54
• Obligatory xkcd.com/153 Commented Sep 8, 2016 at 20: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.

• Aw, beat me to it. Commented Sep 7, 2016 at 19:43
• I just wrote the same too - with n in the place of x and ' in the place of " :) Commented Sep 7, 2016 at 23:30
• @JonathanAllan Then you can safely consider it a dupe. Commented Sep 8, 2016 at 12:03

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.


Pyth, 1413 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.

• Use implicit input at the end to save one byte: >0 instead of <Q0 Commented Sep 7, 2016 at 20:21
• @StevenH. Thank you! Now we're in a tie with the shortest answer! Commented Sep 7, 2016 at 20:31
• Very different solution (that, unfortunately, doesn't save any bytes): tW>0Q_+0sm"~- Commented Sep 7, 2016 at 20:45
• @StevenH. Golfed your solution down to 12: _<>0Q+0sm"~- I hope your okay with me adding this to my solution. Commented Sep 7, 2016 at 22:44

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.

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!

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) • Commented Sep 7, 2016 at 20:26 Perl 38 35 33 (23 + 1 for -p) 24 s/\d+/"-~"x$&.0/e;s;--;


-13 thanks to Dada

• You probably meant -p instead of -r. Also you can get rid of those last parenthesis and semicolon : if$h<0 is enough. – Dada Commented Sep 7, 2016 at 21:03 • I did, thanks. I've been writing too many answers in sed I guess. Commented Sep 7, 2016 at 21:05 • Probably, yea. (Get rid of the last 2 parenthesis too) – Dada Commented Sep 7, 2016 at 21:09 • 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 Commented Sep 7, 2016 at 21:19 • Thanks, I didn't know -p added a ; too. Commented Sep 7, 2016 at 21:22 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 2× two times | the absolute value + plus 0∘< positiveness (i.e 1 for numbers over 0) TryAPL online! 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 • tail fails for n=0. You can use drop 1 instead. – nimi Commented Sep 7, 2016 at 20:25 • @nimi Thanks; I have no idea how I missed that.. Commented Sep 7, 2016 at 20:31 • Don't waste the otherwise guard: f n|n<0=tail.f$abs n|x<-[1..n]>>"-~"=x++"0".
– nimi
Commented Sep 7, 2016 at 20:42
• 2 bytes to save: ...|n<0=tail$f(-n)|.... – nimi Commented Sep 7, 2016 at 21:02 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  JavaScript (ES6), 39 37 bytes x=>"-~".repeat(x<0?-x:x).slice(x<0)+0  Saved 2 bytes thanks to @Neil 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.  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  • Hi, and welcome to PPCG! Nice first post! Commented Sep 8, 2016 at 10:59 • Welcome to PPCG! Hmm, that's a shorter solution than mine, so I will delete my answer and upvote yours instead. :) Commented Sep 8, 2016 at 11:42 Ruby, 34 bytes ->x{("-~"*x.abs+?0)[2[0<=>x]..-1]}  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. • I don't think it works for negative numbers... Commented Sep 9, 2016 at 5:09 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)  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.  Vim - 31 keystrokes First vim golf, prolly missed a ton of stuff. i-~<esc>:s/-\~-/\~-/dwp<left>ii<esc><left>d$@"<esc>a0

• Nice, welcome to the club! :) You could do :s/^- instead of :s/-\~/\~- and D instead of d$ Commented Sep 8, 2016 at 21:33 • 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. Commented Sep 8, 2016 at 22:17 • @DJMcMayhem oh, 0i doesn't work? Commented Sep 9, 2016 at 1:37 • 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. Commented Sep 9, 2016 at 1:39 Matlab, 61 bytes x=input('');A=repmat('-~',1,abs(x));disp([A((x<0)+1:end) 48])  Pyke, 14 13 bytes X,"-~"*Q0<>0+  Try it here! 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 > $_ }  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  ><>, 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)  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. PseudoD, 688579 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  • Welcome 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 efijar p a Escribir)? Commented Sep 10, 2016 at 21:59 PHP, 61 bytes if(0>$n=$argv[1]){echo"~";$n=~$n;}echo str_repeat("-~",$n),0;


PHP, 58 bytes

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


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.

GolfScript, 3024 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!

• You don't have to print the 2 = , just the -~-~0.
– xnor
Commented Sep 11, 2016 at 7:21
• You can use {(;}*0 instead of {(;}{}if 0. Commented Sep 11, 2016 at 7:47