26
\$\begingroup\$

Simple task today. Given a string whose length is one less than a whole power of 2, divide it into segments with doubling length.

For example for the string abcdefghijklmno, the result should be a, bc, defg, hijklmno:

abcdefghijklmno  (length 15)

a                 length 1
 bc               length 2
   defg           length 4
       hijklmno   length 8

The input will not be the empty string.

This is ; shortest solution per language wins.

\$\endgroup\$
1

39 Answers 39

1
2
2
\$\begingroup\$

PowerShell, 43 bytes

%{for($i=1;$_[$i];$i*=2){$_|% S*g($i-1)$i}}

Try it online!

Straightforward: extract substrings of doubling length at doubling start indexes.
Relevant golfing:

  • The loop exit condition $_[$i] tests just whether there is still a character at the current index; way shorter than $i-lt$_.Length
  • $_|% S*g($i-1)$i takes the input string in $_, pipes it to % (an alias for ForEach-Object), calls the string object's member 'Substring' (the only member matching S*g), passing the start index and the length of the substring to retrieve. Shorter than $_.Substring($i-1,$i)
\$\endgroup\$
2
\$\begingroup\$

MathGolf, 12 11 bytes

hâΣÆïó‼<≥;]

Try it online.

Explanation:

Step 1: Calculate the amount of parts we need to output, basically \$\log_2(length+1)\$ manually:

          #  (e.g. input = "abcdefghijklmno")
h         # Push the length of the (implicit) input-string
          #  → 15
 â        # Convert it to a binary list
          #  → [1,1,1,1]
  Σ       # Sum this list of 1-bits
          #  → 4

Step 2: Actually split the input into the power of 2 parts:

Æ         # Loop in the range [0,value],
          # using 5 characters as inner code-block:
 ï        #  Push the current 0-based loop-index
  ó       #  Pop and convert it to 2 to the power this index
   ‼      #  Apply the next two operators separately on the current stack:
    <     #   Slice to substring [0,val)
     ≥    #   Slice to substring [val,length)
      ;   # After the loop: discard the trailing no-op part
       ]  # Wrap all correct parts on the stack into a list
          # (after which the entire stack is output implicitly as result)
\$\endgroup\$
4
  • 1
    \$\begingroup\$ I'm surprised that a language with "Math" in the name doesn't have logarithm built-in and chose instead to have "5-character block" built-in, lol. (h╥(âΣ would just be ceiling of log_2) \$\endgroup\$ Commented Jul 3 at 13:12
  • \$\begingroup\$ @noodleperson ikr.. I've been missing a lot of Math-related builtins besides logarithm in the past in this language, like sine/cosine/tangent; rounding; base conversion besides binary/hexadecimal; bitwise operations like AND/OR/XOR; etc. \$\endgroup\$ Commented Jul 3 at 13:17
  • \$\begingroup\$ Wow, why on earth is it called MathGolf?! Is it just the fact that it uses Σ to mean sum? :P \$\endgroup\$ Commented Jul 3 at 13:18
  • \$\begingroup\$ @noodleperson I think the idea was to eventually add all the other stuff, but it was mostly abandoned. It does have 59 different 1-byte numeral constants, though (but no way to actually push other numbers consistently). xD \$\endgroup\$ Commented Jul 3 at 13:21
2
\$\begingroup\$

Julia 1.0, 54 bytes

~s=[s[2^i:2*2^i-1] for i=0:floor(Int,log2(length(s)))]

Try it online!

Uses array comprehension to generate pairs of indices. The related solution with map takes the same number of bytes:

Julia 1.0, 54 bytes

~s=map(i->s[2^i:2*2^i-1],0:floor(Int,log2(length(s))))

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Brachylog, 12 bytes

{Ẹg|ḍgᵗ↰ʰc}b

Try it online!

Explanation

We rely on ḍ - dichotomize to split the string in 2. When the length is odd, the first string is shorter which is what we want. We then recurse dichotomization on the first string. The tricky part is then to flatten the list recursively up in the same predicate. We use the same idea as @Dlosc answer here, integrated directly in the predicate thas splits the string instead of applied after (which is longer).

{         }     Apply the following predicate on the input string:
 Ẹ                If the input is the empty string ""…
  g                …output [""]
   |              Else
    ḍ             Dichotomize the string [<first half>, <second half>]
     gᵗ           Wrap the second half in a list
       ↰ʰ         Recursive call on the first half
         c        Concatenate to flatten the current level

           b    Remove the first element which is the empty string at the end
\$\endgroup\$
2
\$\begingroup\$

GolfScript, 20 19 bytes

1/.,,{).)&!n*}%]zip

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ -1 byte: dammit. \$\endgroup\$ Commented Jul 4 at 13:27
2
\$\begingroup\$

Julia 1.0, 36 bytes

!s=keys(s).|>k->show(s[2^~-k:~-2^k])

Try it online!

Ends with an error. Substrings are printed in quotes. Cleaner output with println instead of show (+3 bytes)

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Very nice! Good use of letting it just error out so you don't have to worry about just taking log2 of the length or some shenanigans \$\endgroup\$ Commented Jul 6 at 13:16
2
\$\begingroup\$

JavaScript (Node.js), 44 bytes

x=>[...x].reduce((a,c,i)=>i&++i?a+c:a+' '+c)

Try it online!

New contributor
Andrew Bayly is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
\$\endgroup\$
1
  • \$\begingroup\$ Nice solution! In case you didn't see, @l4m2 posted a JavaScript solution earlier in the thread at 38 bytes: l4m2's solution \$\endgroup\$ Commented Jul 14 at 23:37
1
\$\begingroup\$

J, 16 12 bytes

</.~2<.@^.#\

Attempt This Online!

This is my first time trying to golf in J! I got a lot of help golfing the forks and whatnot. I tried a different method from Bubbler's way and it ended 4 bytes shorter :)

Thanks to ovs for telling me about #\ which is a much shorter way of getting the length-one-range.

Explanation:

</.~2<.@^.#\
</.~          NB. Group the items of the input by
    2<.@^.    NB. floors of the base-2 logarithms of
          #\  NB. the range of 1 to the input's length.
              NB.   (Literally: length of prefixes)
\$\endgroup\$
2
  • \$\begingroup\$ This can actually be 12 bytes borrowing #\ -: 1+i.@# from Bubbler's solution. \$\endgroup\$
    – ovs
    Commented Jul 3 at 23:38
  • \$\begingroup\$ Thanks @ovs, I didn't know about #\ to get the indices :) \$\endgroup\$ Commented Jul 4 at 0:51
-1
\$\begingroup\$

Here's a short solution in Python for your problem:

s=input()
i=1
while s:
    print(s[:i])
    s=s[i:]
    i*=2

Explanation:

  1. s=input(): Reads the input string.
  2. i=1: Initializes the segment length to 1.
  3. while s:: Loops while there are characters left in the string.
  4. print(s[:i]): Prints the first i characters of the string.
  5. s=s[i:]: Updates the string by removing the first i characters.
  6. i*=2: Doubles the segment length for the next iteration.
\$\endgroup\$
1
  • 5
    \$\begingroup\$ You can remove those spaces, the whole loop body can all be on one line with semicolons. Is this AI output? \$\endgroup\$ Commented Jul 5 at 13:23
1
2

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