# Challenge

Write a program or function that converts a 32 bit binary number to its quad-dotted decimal notation (often used for representing IPv4)

A quad-dotted decimal is formed like so:

1. Split the binary representation into its 4 individual bytes
2. Convert each byte into denary
3. place "." between each number

Example:

input:  10001011111100010111110001111110
step 1: 10001011 11110001 01111100 01111110
step 2:    139      241      124      126
step 3: 139.241.124.126


# I/O examples

input --> output

10001011111100010111110001111110 --> 139.241.124.126
00000000000000000000000000000000 --> 0.0.0.0
01111111000000000000000000000001 --> 127.0.0.1
11000000101010000000000111111111 --> 192.168.1.255


# Rules

• Input will always be a 32 bit binary number but your examples are binary lists. Is that also an acceptable input form? – Adám Jan 10 at 12:49
• Is it allowed to use a string as input instead of a list of binary digits? – Galen Ivanov Jan 10 at 13:31
• I have added a brief description of how the qaud-dotted notation is formed @LuisMendo. – mabel Jan 10 at 13:31
• @Adám this is actually how I meant for the challenge to be interpreted, but I guess I couldn't find the right word. I have added it as an acceptable input form, but left the 32 bit binary number as valid input also. – mabel Jan 10 at 13:33
• I'm not clear, can we take in an actual number as input, like 2130706433 to give 127.0.0.1? – xnor Jan 11 at 4:00

# 05AB1E, 6 bytes

4äC'.ý


Explanation:

4ä       # Convert the (implicit) input-string into 4 equal-sized parts
C      # Convert each part from binary to an integer
'.ý  '# Join this list by "."
# (after which the result is output implicitly)


# x86-16 machine code, IBM PC DOS, 5447 45 bytes

Binary:

00000000: be82 00b3 04b1 08ac d0d8 d0d4 e2f9 8ac4  ................
00000010: 41d4 0a50 8ac4 84c0 75f6 580c 30b4 0ecd  A..P....u.X.0...
00000020: 10e2 f74b 7406 b02e cd10 ebd9 c3         ...Kt........


Build and test BIN2IP.COM using xxd -r from above.

Unassembled listing:

BE 0082     MOV  SI, 82H        ; command line input address
B3 04       MOV  BL, 4          ; loop 4 bytes
BYTE_LOOP:
B1 08       MOV  CL, 8          ; loop 8 bits
BIT_LOOP:
AC          LODSB               ; load next bit char into AL
D0 D8       RCR  AL, 1          ; put LSB of char into CF
D0 D4       RCL  AH, 1          ; put CF into LSB of byte value, then shift left
E2 F9       LOOP BIT_LOOP       ; continue bit loop
8A C4       MOV  AL, AH         ; put byte result into AL
GET_DIGIT:
D4 0A       AAM                 ; byte divide by 10, AH = AL / 10, AL = AL % 10
50          PUSH AX             ; save remainder in AL on stack
8A C4       MOV  AL, AH         ; put quotient back into AL
41          INC  CX             ; increment decimal digit count
D4 C0       TEST AL, AL         ; quotient = 0?
75 F6       JNZ  GET_DIGIT      ; if not, continue looping
PRINT_DIGIT:
58          POP  AX             ; restore digit in AL
0C 30       OR   AL, '0'        ; ASCII convert
B4 0E       MOV  AH, 0EH        ; BIOS write char function
CD 10       INT  10H            ; write to console
E2 F7       LOOP PRINT_DIGIT    ; loop until done
4B          DEC  BX             ; is last byte?
74 06       JZ   END_LOOP       ; if so, don't display a '.'
B0 2E       MOV  AL, '.'        ; otherwise display '.'
CD 10       INT  10H            ; write to console
END_LOOP:
75 D7       JNZ  BYTE_LOOP      ; continue byte loop
C3          RET                 ; exit to DOS


Output:

A standalone PC DOS executable. Input is command line, output to console.

Notes:

The "interesting part" (converting binary string to bytes) is about 15 bytes, whereas the rest of code is writing the itoa() function to convert binary bytes into a decimal string representation for display.

• -2 bytes eliminating unnecessary PUSH/POP thx to @PeterCordes!
• dec cx / jz end_loop could be re-arranged using a loop instruction that either falls through to a ret or jumps forward to mov al/int 10h/jmp byte_loop, for a net saving of I think 1 byte, from replacing dec cx/jcc with loop. Or maybe use DI for that loop counter instead of CX, avoiding push/pop? – Peter Cordes Jan 11 at 20:13
• BTW, several size-neutral changes that would make it more efficient (especially on modern CPUs): shr al,1 to shift the low bit into CF, not RCR. You don't need an input dependency on FLAGS. (Or hmm, possibly even scasb with AL='1' instead of loading, but that would invert). adc ah,ah can be 1 uop, RCL isn't. Also, test reg,reg/jcc is more efficient than or reg,reg, and the same size. I think the inefficient or idiom comes from 8080 ORA A, which didn't have an opcode that only set flags. – Peter Cordes Jan 11 at 20:24
• The question allows input as a 32-bit binary integer so you could just write a function that takes that (in memory pointed to by DS:SI if you want), instead of converting from a base 2 string. Also, instead of push/pop for digit-order, you could maybe store backwards into a buffer, creating a $-terminated string, and when you're done you have a pointer to the first byte. How do I print an integer in Assembly Level Programming without printf from the c library? shows the algorithm (and using a Linux write system call on it). – Peter Cordes Jan 11 at 20:27 • @PeterCordes yes, I just tried and that's what's happening. I was doing two different LOOPs on the "inner" loop, and since I can count on CX being 0 at the end of the first, I used it as the counter for decimal digits and looped again. Unfortunately DEC / JNZ is 1 byte more than LOOP so my gain there offsets the BX outer loop gain. So, yes, BX would seem to win but it was a great idea and fun exercise to go through! – 640KB Jan 11 at 21:10 • @PeterCordes I experimented with writing in reverse to a string buffer, and was only able to get it down to 48 bytes. Here's the scratchpad (godbolt.org/z/6853--) if you have any thoughts or ideas. – 640KB Jan 13 at 17:22 # C (gcc), 48 bytes i;f(n){for(i=4;i--;)printf(".%hhu"+i/3,n>>i*8);}  Takes as input a 32-bit integer. Thanks to ceilingcat and gastropner for getting this answer where it is now! Try it online! • Missing semicolon in for loop. 48 bytes – girobuz Jan 12 at 6:38 # Jelly, 10 6 bytes s8Ḅj“.  Try it online! s Slice input list 8 into size 8 chunks Ḅ Convert from binary list to integer j“. Join with dots as the separator Implicit output  • If you use ” (character) rather than “ (start list of characters) this would be a Link rather than a full program (although submission may want to ba a full-program anyway, since the Link result is not just a list of characters, so we may prefer the implicit printing) – Jonathan Allan Jan 10 at 14:52 • Are you counting Ḅ as a single byte? – chrylis -on strike- Jan 11 at 7:13 • @chrylis-onstrike- Jelly uses a custom code page to encode its characters. So, in this instance, yes, it's one byte. – AdmBorkBork Jan 12 at 15:59 # PHP, 26 bytes <?=long2ip(bindec($argn));


Try it online!

# PHP, 7 bytes

long2ip


Try it online!

• No need for bindec, $argn will be an integer. – Kerkouch Jan 18 at 3:23 • @kerkouch yes, that's true. I think that option was allowed after I posted the original answer. That simplifies this quite a bit. :) – 640KB Jan 18 at 14:05 # PowerShell, 46 bytes ""+[IPAddress]"$([Convert]::ToInt64($args,2))"  Try it online! First takes input $args binary string and [System.Convert]s it into Int64. Uses the .NET type call [System.Net.Ipaddress] to parse that Int64 into an IPAddress object, then coerces the .IPAddressToString() method by prepending ""+.

• Unfortunately on systems that are LittleEndian (like TIO and most computers... I think?) this parses the binary backwards so the IP in your TIO link has the quads in reverse order. – Malivil Jan 10 at 15:45
• @Malivil Dang, that's a side-effect of removing the "$( )" that I golfed. I'll put that back in. Thanks for the bug catch! – AdmBorkBork Jan 10 at 16:06 # Python 2, 47 bytes f=lambda n,k=-2:k*nor f(n>>8,k+1)+'.'+n%256  Try it online! # Python 3, 46 bytes lambda n:('.%d'*4%(*n.to_bytes(4,"big"),))[1:]  Try it online! Shaving a byte from David Foerster's to_bytes solution using string formatting. # MathGolf, 6 bytes 8/å'.u  Try it online. Explanation: 8/ # Split the (implicit) input-string into parts of size 8 å # Convert each part from a binary-string to an integer '.u '# Join by "." # (after which the entire stack joined together is output implicitly)  # APL (Dyalog Unicode), 20 19 bytesSBCS -1 thanks to Kritixi Lithos. Full program. Prompts for 32-bit integer, optionally as list of bits. ' '⎕R'.'⍕256|83⎕DR⎕  Try it online! ⎕ console prompt for numeric input 83⎕DR interpret the bits of that data as 8-bit integers (internal Data Representation type 3) 256| convert to unsigned integers (lit. 256-mod of that) ⍕ stringify (makes space-separated string) ' '⎕R'.'Replace spaces with dots • Using ⎕r on ⍕'ing the entire list saves a byte – user41805 Jan 12 at 7:57 • @KritixiLithos How? – Adám Jan 12 at 8:16 • ' '⎕r'.'⍕256|... tio.run/… – user41805 Jan 12 at 8:20 • @KritixiLithos Oh right, for some reason I thought it was nested and would give too many spaces. – Adám Jan 12 at 8:21 # JavaScript (V8), 49 44 bytes -5 bytes thanks to Arnauld s=>s.match(/.{8}/g).map(x=>'0b'+x|0).join.  Try it online! # C#7+, 117 73 bytes s=>string.Join('.',(new System.Net.IPAddress(s)+"").Split('.').Reverse())  Accepts the bit representation of an IP address to transform it into a four-number notation, converts it to a string array, reverses the elements to account for the endianness differences of machines, then joins them together again with a dot. Try it online! • Reduced to 73 bytes by utilizing the string hack and chaining (c/o @Expired Data) # Initial answer, 117 bytes string I(long b){var x=new System.Net.IPAddress(b).ToString().Split('.');Array.Reverse(x);return string.Join(".",x);}  Use it like: void Main() { Console.WriteLine(I(0b_10001011111100010111110001111110)); } public string I(long b) { var x = new System.Net.IPAddress(b).ToString().Split('.'); Array.Reverse(x); return string.Join(".", x); }  • by using lambdas, chaining and a hack for ToString() you can reduce it to 73 bytes – Expired Data Jan 13 at 11:47 • Thanks, @ExpiredData, totally forgot the string hack. – terrible-coder Jan 13 at 15:59 # Japt, 7 bytes ò8 mÍq.  Try it here # k4, 18 17 bytes saved a byte by expressing in composed form instead of as a lambda: ("."/:$2/:'4 0N#)


original explanation: output is string, quad-dot decimal not supported by k

{"."/:$2/:'4 0N#x} { } /lambda with implicit arg x 4 0N#x /cut x into 4 pieces 2/:' /convert each piece to decimal$            /stringify
"."/:             /join with .


called on 2 binaries:

{"."/:$2/:'4 0N#x}'(10001011111100010111110001111110b;11000000101010000000000111111111b) ("139.241.124.126";"192.168.1.255")  # Java 9, 979492 81 bytes s->{for(int i=0;i<32;)System.out.print((i>0?".":"")+Long.parseLong(s,i,i+=8,2));}  -2 bytes thanks to @AZTECCO. -11 bytes thanks to @Holger by combining the Long.parseLong(s.substring(i,i+=8),2) into Long.parseLong(s,i,i+=8,2). Try it online. Explanation: s->{ // Method with String parameter and no return-type for(int i=0;i<32;) // Loop i in the range [0, 32): System.out.print( // Print: (i>0? // If i is larger than 0 (so it's not the first iteration): "." // Print a dot : // Else: "") // Print nothing instead + // Appended with: Long.parseLong(s,i,i+=8,2));} // A substring of the input s from index i to i+8, // (and increase i by 8 for the next loop iteration) // Converted from binary-String to integer  • Since Java 9, you can use Long.parseLong(s,i,i+=8,2) which will not only improve it from a golfing point of view, even the performance will be better as it saves the substring operations. – Holger Jan 13 at 15:12 • @Holger Oh, I didn't knew that. Thanks! :) – Kevin Cruijssen Jan 13 at 16:56 ## Excel. 96 bytes =BIN2DEC(LEFT(A1,8))&"."&BIN2DEC(MID(A1,9,8))&"."&BIN2DEC(MID(A1,17,8))&"."&BIN2DEC(RIGHT(A1,8))  # Python 3 (125 bytes) def f(x): y='' for j in range(4): y+=str(int(x[j*8:j*8+8],2)) if j<4: y+="." return y  Try it online • Hi. Small problem in that this outputs an extra "." at the end. Easily fixed by changing j<4 to j<3. Also we normally count bytes and not characters and according to TIO this is 125 bytes. – ElPedro Jan 11 at 8:28 • Here are a few hints for 80 bytes Try it online! – ElPedro Jan 11 at 8:50 • Thank you @ElPedro for the knowledge. – Merin Nakarmi Jan 15 at 17:43 • My pleasure, however there are a couple more golfs that I didn't mention. I'll leave those for you to find. Since OP has said that trailing space is alowed then you can save at least 6 more. Have fun :) – ElPedro Jan 15 at 21:59 • BTW, even if you don't use the hints, you should really update the answer to correct the identified problem and please feel free to post my suggestions as an improved answer. – ElPedro Jan 15 at 22:00 # Red, 33 bytes func[n][to 1.1.1 debase/base n 2]  Try it online! Takes the input as strings. # Burlesque, 13 bytes 8co{b2}]m'.IC  Try it online! 8co #Break into chunks 8 long {b2}]m #Read each chunk as base-2 and turn to string '.IC #Intercalate "." between each and collapse  # Stax, 8 bytes Ç∩0&→Ö¡  Run and debug it at staxlang.xyz! ### Unpacked (9 bytes) and explanation: 8/{|Bm'.* 8/ Split into length-8 chunks. 4M would work just as well. {|Bm Convert each chunk to decimal '.* Join with .  # Python 2, 81 $$\\cdots$/extract_tex] 58 55 bytes lambda s:'.'.join(int(s[i:i+8],2)for i in(0,8,16,24))  Try it online! Saved 3 bytes thanks to ElPedro!!! Lambda function that takes a string of 32 "0"s and "1"s. • Ha, just came up wth the same thing! If you switch to Python 2 you can use backticks instead of str() to save 3 more Try it online! – ElPedro Jan 11 at 7:50 • @ElPedro Awesome, great minds think alike! Good idea switching to 2 for str() to backticks save. :-) – Noodle9 Jan 11 at 8:31 # C (clang), 66 61 bytes i;g(*m){for(i=32;i--;)*++m+=i%8?*m*2:!printf(".%d"+i/24,*m);}  Try it online! Input as an array of integers (bits) Adds current number shifted to the next. Every 8 bits it prints instead of adding. Saved 5 thanks to @gastropner and @ceilingcat # CJam, 10 bytes l~8/2fb'.*  Try it online! ### Explanation l~ e# Read a line and evaluate it. Pushes list to the stack 8/ e# Split into sublists of 8 elements each. Gives list of sublists 2fb e# Map "base conversion" with extra parameter 2 over the list of sublists '.* e# Join sublists with character ".". Implicitly display  # Python 3, 47 bytes lambda n:".".join(map(str,n.to_bytes(4,"big")))  Try it online! # PowerShell, 45 44 bytes args|%{r+=+r+"_"} [ipaddress]::Parse(r)  Try it online! # PowerShell, 45 bytes Pure PowerShell. It does not use external libs. (args|%{(r=2*r%256+"_")[++i%8]})-join'.'  Try it online! Unrolled and commented: bytes = args|%{ # args is array on character 48 or 49 (bits) r = 2 * r # one bit shift left # the first operand is integer, so Powershell converts the second operand to an integer r = r % 256 # bitwise and 0xFF digit = "_" # convert a char 48, 49 to string "0" or "1" respectively r = r + digit # add a digit # the first operand is integer, so Powershell converts the second operand to an integer # now r is a byte containing 8 bits to the left of the current one index = ++i % 8 # 1,2,3,4,5,6,7,0, 1,2,3,4,5,6,7,0, ... (r)[index] # represent r as an array; take an element of this array # index 0 will give r, other indexes will give null # Powershell outputs non null values only # Compare to Wrtie-Output (r)[index] } # now bytes is array of not null elements Write-Output (bytes -join '.')  • Witchcraft! I can't even begin to understand how the second one works -- can you add an explanation? – AdmBorkBork Jan 12 at 16:09 • Thanks, O' Valley of Plenty. I've added explanation. – mazzy Jan 13 at 8:17 # Perl 5, 30 bytes s/.{8}/oct("0b&").'.'/ge;chop  Try it online! Search-replaces with regexp that takes eight bits (0 or 1) at a time and converts them to their decimal representation with . placed after each, but chops off the last . char. Using a function named oct here seems counter-intuitive since the input string isn't octal. But when the given string starts with 0b the rest is read as the binary string it is. # Ruby, 37 34 bytes ->b{(-3..0).map{|w|255&b<<w*8}*?.}  Try it online! # Perl 6, 28 27 bytes -1 byte thanks to Jo King {chop S:g/.**8/{:2(~/)}./}  Try it online! # J, 18 bytes ' .'rplc~&":_8#.$  Try it online! ## Old answer -2 thanks to Kritixi Lithos ' .'rplc~&":2#.4 8$]


Try it online!

My first answer in a non-esolang! (kinda). The way this answer works is pretty simple. Let's look first at a non-tacit form of this expression:

(":#.(4 8 $n))rplc' .'  Assuming that (for instance) n is: n =: 1 0 0 0 1 0 1 1 1 1 1 1 0 0 0 1 0 1 1 1 1 1 0 0 0 1 1 1 1 1 1 0  The expression 4 8$ n is equal to:

1 0 0 0 1 0 1 1
1 1 1 1 0 0 0 1
0 1 1 1 1 1 0 0
0 1 1 1 1 1 1 0


Then, the #. verb is applied over the matrix, yielding the following result:

139 241 124 126


The resulting list is stringified using ":, and using rplc every space in the string representation of list is swapped to a dot, yielding the final form:

139.241.124.126

• [:#. can become 2#., and you can also remove the cap in rplc~[:": with rplc~&":. Also 2#.4 8\$] can become shorter with the adverb infix jsoftware.com/help/dictionary/d430.htm – user41805 Jan 16 at 20:26
• I can't spot the the possibility of using adverb infix in the code – Krzysztof Szewczyk Jan 17 at 9:04

# REXX, 91 bytes

PARSE ARG WITH 1 A 9 B 17 C 25 D
SAY X2D(B2X(A))'.'X2D(B2X(B))'.'X2D(B2X(C))'.'X2D(B2X(D))


Online REXX interpreter

• If REXX had a function that would go directly from binary to decimal I could chop 20 bytes off of this. – abricker Jan 17 at 23:24

# Forth (gforth), 130 bytes.

Requires a Forth that starts in decimal mode, works with gforth.

: p . 8 emit ." ." ;
: d dup 255 and swap ;
: r 8 rshift d ;
: q 32 2 base ! word number drop d r r r drop decimal p p p . ;


Try it online!

Usage: q 10001011111100010111110001111110 [enter]

Deobfuscated version (or how I would really do it)

\ Forth program to convert a binary IP address to dotted decimal notation.

decimal
: binary   2 base ! ;

\ Get the binary string and convert to a number.
: getbin   32 binary word number drop ;

\ Shift and mask the byte we are interested in. Put all 4 on the stack.
hex
: mask   rshift dup ff and ;
: quad4   dup ff and swap ;