1
\$\begingroup\$

Okay, so I saw this in a meme and decided it'd be the perfect code golf challenge:

I prefer to increase the side of my indents according to the Fibonacci sequence:

class Kls
 def method
  t = Time.now
  if t.hour >= 12
    puts "It's afternoon"
    if t.hour == 18
       puts "It's time for your meal of:"
       %w(bread sausage brocolli milk).each do |food|
            "Some #{food}"
       end
    end
  else
    puts "It's not afternoon"
  end
 end
end 

This means each line is indented by the sum of the spaces indented in the previous indentation-level. The first indention-level is indented by one space, then subsequent indention-levels are indented by 1, 2, 3, 5, 8, 13, 21, etc additional spaces.

The challenge

Given a multi-line string with multiples of 2 spaces as indentation, convert it to a Fibonacci indented multi-line string instead.
This means every line with 0 indented spaces will remain 0 spaces; every line with 2 indented spaces will become 1 instead (sum of the first two Fibonacci numbers 0+1 = 1); every line with 4 indented spaces will becomes 2 instead (sum of the first three Fibonacci numbers 0+1+1 = 2); etc. So the number of indentations can be calculated as follows:

  • Get the current amount of leading spaces (guaranteed to be a multiple of 2, so [0,2,4,6,8,...])
  • Divide this by 2, so we have our 0-indexed numbers (let's call it n)
  • Get the first [0,n] (0-indexed) Fibonacci numbers
  • Sum that sub-sequence together, and use that amount of leading spaces instead in the output

For example, for the output above, the input would have been:

class Kls
  def method
    t = Time.now
    if t.hour >= 12
      puts "It's afternoon"
      if t.hour == 18
        puts "It's time for your meal of:"
        %w(bread sausage brocolli milk).each do |food|
          "Some #{food}"
        end
      end
    else
      puts "It's not afternoon"
    end
  end 
end

If we take a look at the line containing "Some #{food}":

In the input it has 10 amount of leading spaces, so n will be 10/2 = 5. The first [0,5] Fibonacci numbers are: [0,1,1,2,3,5]. When we take the sum of that list (0+1+1+2+3+5) the new amount of leading spaces in the output would be 12.

The amount of indented spaces in the output for every 2 indented spaces in the input will be [0, 1, 2, 4, 7, 12, 20, 33, 54, 88, ...] A000071 on oeis.org (except for the first 0).

Challenge rules:

  • The space-indentation of the input is guaranteed to be multiples of 2 ([0,2,4,6,8,...])
  • The input is guaranteed to not contain more than 1 consecutive space elsewhere (except for the leading indentation of course)
  • Use whatever language you like
  • Please include a link to an online interpreter
  • Input should be a multi-line string (so no, string-lists/arrays aren't allowed)
  • Output should also be a multi-line string (either printed or returned as string)
  • Your method should work for deeper-indented Fibonacci indented multi-line strings than the example
  • This is , so try to do it in the fewest bytes possible.

Additional test cases:

Input:

this
  is
    one
      of
        the
          tests
            !

Output:

this
 is
  one
    of
       the
            tests
                    !

Input:

      And
  how
               about
        this ?

Output:

    And
 how
                                 about
       this ?

Input:

                    20 spaces?

Output:

                                                                                                                                               20 spaces?
\$\endgroup\$
  • 1
    \$\begingroup\$ What if there's 2 or more spaces in the code that aren't part of the indentation? \$\endgroup\$ – Blue Aug 22 '18 at 11:21
  • 3
    \$\begingroup\$ @AJFaraday I took the liberty of editing your challenge so it can be re-opened. The challenge in general is a nice idea and I personally like it; it was just not properly explained. If you see anything incorrect in what I've edited, let me know. \$\endgroup\$ – Kevin Cruijssen Aug 23 '18 at 9:19

10 Answers 10

4
\$\begingroup\$

05AB1E (legacy), 22 21 bytes

|εDgsðÛ©g-;LÅfOð*®J}»

Try it online.

21 bytes alternative using the formula \$Fib(\frac{n}{2}+2)-1\$ instead of \$\sum_{i=1}^{i=\frac{n}{2}}{Fib(i)}\$ :
(Credit to @JonathanAllan's Jelly answer for this formula.)

|εDgsðÛ©g-;ÌÅf<ð*®J}»

Try it online.

Explanation:

|                        # Take the input split by newlines
 ε                  }    # Map each line to:
  Dg                     #  Duplicate the line and take its length
    s                    #  Swap so the duplicated line is at the top of the stack again
     ðÛ                  #  Remove all leading spaces
       ©                 #  Store the result in the register (without popping)
        g                #  Take its length as well
         -               #  Subtract both lengths from each other
          ;              #  Halve it, because they are multiples of 2 indented spaces
           L             #  Create a list in the range [1, n]
            Åf           #  Get the i'th Fibonacci number for each
              O          #  And sum them together
               ð*        #  Have that many space characters
                 ®J      #  And join them with the saved string from the register
                    »    # And finally print the mapped list with new-lines
\$\endgroup\$
3
\$\begingroup\$

Python 2, 111 109 100 95 bytes

g=lambda n:n<1or g(n-2)+g(n-4)
def f(I):
 for l in I:L=l.lstrip();print~-g(len(l)-len(L))*' '+L

Try it online!


Saved:

  • -5 bytes, thanks to ovs.
\$\endgroup\$
  • 1
    \$\begingroup\$ g can be g=lambda n:n<1or g(n-2)+g(n-4). \$\endgroup\$ – ovs Aug 22 '18 at 11:53
  • \$\begingroup\$ and you can use strip instead of lstrip as trailing whitespace is insignificant. \$\endgroup\$ – ovs Aug 22 '18 at 11:56
  • \$\begingroup\$ @ovs But it would affect len(l)-len(L). \$\endgroup\$ – user202729 Aug 22 '18 at 11:58
  • \$\begingroup\$ @ovs, Thanks :) \$\endgroup\$ – TFeld Aug 22 '18 at 12:16
3
\$\begingroup\$

Husk, 23 bytes

mȯF+M(R' !∫Θİf→½L)↕=' ¶

Try it online!

Explanation

m(F+M(R' !∫Θİf→½L)↕=' )¶  -- full program
                       ¶  -- lines
m(                    )   -- map
                  ↕='     -- | split on first non-space
    M(           )        -- | with the spaces
                L         -- | | length
               ½          -- | | halve
              →           -- | | increment
            İf            -- | | Fibonacci numbers: [1,1,2,3,5..]
           Θ              -- | | prepend 0: [0,1,1,2,3,5..]
          ∫               -- | | cumulative sums: [0,1,2,4,7,12..]
         !                -- | | 1-based index
      R'                  -- | | replicate that many spaces
  F+                      -- | join
\$\endgroup\$
  • 1
    \$\begingroup\$ This answer appears to have three levels of indent with only 1 space, then continuing in Fibonacci. \$\endgroup\$ – AJFaraday Aug 22 '18 at 12:29
  • \$\begingroup\$ I had the same mistake at first. Instead of having the indexed Fibonacci amount of spaces in the result, it's actually the sum of the first [1,n] amount of Fibonacci numbers. So instead of [0,1,1,2,3,5,8,...] indented spaces, it's (sum_each([0,[0,1],[0,1,1],[0,1,1,2],[0,1,1,2,3],[0,1,1,2,3,5],[0,1,1,2,3,5,8],...]) -> [0,1,2,4,7,12,20,...] indented spaces instead. \$\endgroup\$ – Kevin Cruijssen Aug 22 '18 at 12:35
  • 1
    \$\begingroup\$ @KevinCruijssen: I was able to fix it w/o additional bytes, thanks a lot! \$\endgroup\$ – ბიმო Aug 22 '18 at 13:21
2
\$\begingroup\$

Retina 0.8.2, 37 bytes

m`^
 	 	
+`( +	)( +)	  
$2$1$1
 	 *	

Try it online! Warning: Lots of white space. Explanation:

m`^
 	 	

Prefix each line with space tab space tab. These keep track of the previous and current Fibonacci number.

+`( +   )( +)     
$2$1$1

For each two spaces of the original indentation, compute the next Fibonacci number by summing the previous two.

 	 *	

Subtract 1 from the result and delete the previous Fibonacci number.

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

Jelly, 20 bytes

Ỵµ=⁶i0‘H‘ÆḞ’⁶ẋ;t⁶$)Y

Try it online!


Explanation

Let \$x\$ be the 1-indexing index of the first non-whitespace character (\$1,3,5,7,\dots\$).

Then the new indent is

$$F_{(x+1)/2+1}-1$$

where \$F\$ is the Fibonacci function.

\$\endgroup\$
  • \$\begingroup\$ Save 1 from both with Ỵµ...)Y \$\endgroup\$ – Jonathan Allan Aug 22 '18 at 14:24
2
\$\begingroup\$

Jelly, 17 bytes

Ỵµwt©⁶$HÆḞ€⁶ẋ;®)Y

A full program which prints the result.

Try it online!

How?

The indentations required for a line of the output is \$Fib(\frac{s}{2}+2)-1\$ where \$s\$ is the number of spaces in the line of the input, and:

$$Fib(\frac{s}{2}+2)-1=\sum_{i=1}^{i=\frac{s}{2}}{Fib(i)}$$

(\$i\$ could also start at \$0\$ since \$Fib(0)=0\$)

Ỵµwt©⁶$HÆḞ€⁶ẋ;®)Y - Main Link: list of characters
Ỵ                 - split at newlines
 µ             )  - for each line:
      $           -   last 2 links as a monad:
     ⁶            -     literal space character
   t              -     trim from both sides
    ©             -     (copy to register)
  w               -   first index of that substring in the line
       H          -   halve (this is (s+1)/2)
        ÆḞ€       -   Fibonacci of €ach (using an implicit range [1,2,...,s/2]
                  -                      where the (s+1)/2 is floored to s/2)
           ⁶      -   literal space character
            ẋ     -   repeat (vectorises) (e.g. [1,1,2,3,5] -> [[' '],[' '],[' ',' '],[' ',' ',' '],[' ',' ',' ',' ',' ']]
              ®   -   recall from register
             ;    -   concatenate
                Y - join with newline characters 
                  - implicit print
                  -  ...smashes, so e.g. [[' '],[' '],[' ',' '],['x']] is just "    x"
\$\endgroup\$
2
\$\begingroup\$

Java 11, 150 bytes

s->{for(var l:s.split("\n"))System.out.println(" ".repeat(f(l.length()-(l=l.stripLeading()).length())-1)+l);};int f(int n){return n<1?1:f(n-2)+f(n-4);}

Try it online (NOTE: Both String.repeat(int) and String.stripLeading() are emulated as repeat(String,int) and stripLeadingE(String) respectively, because Java 11 isn't on TIO yet.)

Explanation:

s->{                   // Method with String parameter and no return-type
  for(var l:s.split("\n"))
                       //  Loop over the lines of the input:
    System.out.println(//   Print with trailing new-line:
      " ".repeat(      //    Repeat a space this many times:
           f(          //     Call the separated (recursive) method `f` with the parameter:
             l.length()//      The length of the line,
             -(l=l.stripLeading()).length()
                       //      minus the length of the line without leading spaces
           )-1         //     minus 1
      )+l);};          //    And append the line without leading spaces

int f(int n){          // Separated method with integer as both parameter and return-type
  return n<1?          //  If the input is 0 or lower:
          1            //   Return 1
         :             //  Else:
          f(n-2)+f(n-4);}
                       //   Return a recursive call to `n-2` plus a recursive call to `n-4`
\$\endgroup\$
2
\$\begingroup\$

Japt v2.0a0, 20 19 bytes

r/^ +/m@ÓMgXÊz ÄÄ)ç

Try it


Explanation

r                        :Replace
 /^ +/m                  :Global, multiline regular expression matching one or more spaces at the start of each line
       _                 :Pass each match through a function
        Ê                :  Length
         z               :  (Floor) divide by 2
           õ             :  Range [0,result]
              @          :  Map each X
               MgX       :    Xth Fibonacci number
                  Ã      :  End mapping
             x           :  Reduce by addition
                   ç     :  Repeat <space> that many times
\$\endgroup\$
1
\$\begingroup\$

JavaScript (Node.js), 87 81 bytes

x=>x.replace(/^ */gm,s=>" ".repeat((g=(n,a=b=1)=>n?g(n-2,b,b+=a):b-1)(s.length)))

Try it online!

For small indent levels (up to 15), 61 bytes using approximation:

x=>x.replace(/^ */gm,s=>" ".repeat(1.272**s.length*1.171-.5))

Use 1.27202 ** s.length * 1.17082 - .5 for indents up to 21 levels

\$\endgroup\$
1
\$\begingroup\$

Perl 6, 62 bytes

*.trans(/[\n|^]' '+/=>{"\n"~' 'x(1,1,*+*...*)[$/.ords/2+1]-1})

Try it online!

\$\endgroup\$

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.