Golf: tabs to bullets

Given:
an outline list, with each line indented by a series of tabs
a list of bullets (assume a circular list, for simplicity)

Write a function that replaces every tab with two spaces, except for
the last one, which is replaced by a bullet.

example:

input file:
foo
\t bar
\t \t baz
\t \t \t hello
\t \t world

bullets: %w(* - o x)

output (view in fixed width):
foo

  • bar
    • baz
      o hello
    • world

martin

On Tue, Mar 25, 2008 at 2:02 PM, Martin DeMello
[email protected] wrote:

Given:
an outline list, with each line indented by a series of tabs
a list of bullets (assume a circular list, for simplicity)

Write a function that replaces every tab with two spaces, except for
the last one, which is replaced by a bullet.

Code is worth a thousand descriptions:

#!/usr/bin/ruby

file = ARGV[0]
MARKERS = “*-ox”.split(//)

def bullet(n)
MARKERS[n % MARKERS.length]
end

IO.foreach(file) {|line|
a = line.gsub(/^\t+/, “”)
n = line.length - a.length - 1
replace = n == -1 ? “” : " "*(n)+ bullet(n) + " "
out = line.gsub(/^\t+/, replace)
puts out
}

martin

On Mar 25, 2008, at 4:02 PM, Martin DeMello wrote:

foo

  • baz
    o hello
  • world

I didn’t really golf it, but my answer is:

#!/usr/bin/env ruby -wKU

input = <<END_INPUT
foo
\t bar
\t \t baz
\t \t \t hello
\t \t world
END_INPUT

bullets = %w[* - o x]
input.gsub!(/^(\t ?)+/) do |indent|
tabs = indent.count("\t") - 1
" " * tabs + bullets[tabs] + " "
end

puts input

END

James Edward G. II

Hi –

On Wed, 26 Mar 2008, Martin DeMello wrote:

On Tue, Mar 25, 2008 at 2:16 PM, James G. [email protected] wrote:

I didn’t really golf it, but my answer is:

You have a point - I wasn’t looking for golf so much as for neat
and/or offbeat approaches to the problem of counting the tabs.

Darn, I took you literally :slight_smile:

def t(s)b=‘*-ox’;s.map{|l|c=l.count(“\t”)
(c-1).times{l.sub!(/\t/,’ ')}
l.sub(/\t/,b[c-1,1])}end

t(some_string)

(Thanks to JEG2 for reminding me of count, which I had hypercorrected
in my mind into thinking only existed in 1.9 because of Array#count
:slight_smile:

David

On Tue, Mar 25, 2008 at 2:16 PM, James G. [email protected]
wrote:

I didn’t really golf it, but my answer is:

You have a point - I wasn’t looking for golf so much as for neat
and/or offbeat approaches to the problem of counting the tabs.

martin

A slightly different approach (count the tabs once!), starting from
James’s code:

input = <<END_INPUT
foo
\t bar
\t \t baz
\t \t \t hello
\t \t world
END_INPUT

bullets = %w[* - o x]

h = Hash.new {|h, k|
bullet = bullets[(k.count("\t")-1) % bullets.size]
h[k] = k.gsub(/(\t )(?=\t )/, " ").sub(/\t/, bullet)
}

input.gsub!(/^(\t ?)+/) do |indent|
h[indent]
end

puts input

END

foo

  • bar
    • baz
      o hello
    • world

Similar to Joel’s approach…

#bullets.rb
h={}
%w(\ * - o x).each_with_index{|b, i| h["\t" * i]= " " * i + "#{b} " }
puts gets.gsub(/^(\t*)/){ h[$1]} until $stdin.eof?

C:\ruby\scripts>cat input_file | ruby bullets.rb
foo

  • bar
  • baz
    o hello
  • world

Joel VanderWerf wrote:

h[k] = k.gsub(/(\t )(?=\t )/, " ").sub(/\t/, bullet)

a little more robust:

h[k] = k.gsub(/(\t ?)(?=\t)/, " ").sub(/\t/, bullet)

On Tue, Mar 25, 2008 at 5:11 PM, Gordon T. [email protected]
wrote:

foo

  • bar
  • baz
    o hello
  • world

Except it was broken. I’ll try it again.

#bullets.rb
h={‘’=>‘’}
%w(* - o x).each_with_index{|b, i| h[“\t” * (i+1)]= "#{’ ’ * i}#{b} " }
puts gets.gsub(/^(\t*)/){ h[$1] } until $stdin.eof?

On Mar 25, 2008, at 3:02 PM, Martin DeMello wrote:

foo
\t bar
\t \t baz
\t \t \t hello
\t \t world

bullets: %w(* - o x)

cfp2:~ > cat a.rb
DATA.read.gsub(%r/(?:\t\ ?)+/){|s|’ ‘(n=s.count(“\t”)-1)+%w( - o x)
[n]+’ '}.display

END
foo
bar
baz
hello
world

cfp2:~ > ruby a.rb
foo

  • bar
    • baz
      o hello
    • world

a @ http://drawohara.com/

Hi –

On Wed, 26 Mar 2008, David A. Black wrote:

and/or offbeat approaches to the problem of counting the tabs.

Darn, I took you literally :slight_smile:

def t(s)b=’*-ox’;s.map{|l|c=l.count("\t")
(c-1).times{l.sub!(/\t/,’ ')}

Whoops, that should be ’ ’ (two spaces).

David

Hi –

On Wed, 26 Mar 2008, ara howard wrote:

example:
cfp2:~ > cat a.rb
DATA.read.gsub(%r/(?:\t\ ?)+/){|s|’ ‘(n=s.count("\t")-1)+%w( - o x)[n]+’
'}.display

I don’t think that does the two-space thing:

david-blacks-macbook:hacking dblack$ cat ara.rb
<<EOM.gsub(%r/(?:\t\ ?)+/){|s|’ ‘(n=s.count("\t")-1)+%w( - o x)[n]+’
'}.display
\t\t\ta
\t\tb
\t\t\t\tc
EOM
david-blacks-macbook:hacking dblack$ ruby ara.rb
o a

  • b
    x c

Then again, mine didn’t either…

David

On Mar 25, 2008, at 4:58 PM, David A. Black wrote:

Then again, mine didn’t either…

neither did the OPs - my gives back the sample data, which actually
required one - easy to change though.

a @ http://codeforpeople.com/

On Mar 25, 2008, at 5:22 PM, David A. Black wrote:

I’m seeing it differently; I see Martin’s like this:

oh yeah - interesting. the fix:

cfp2:~ > cat a.rb
DATA.read.gsub(%r/(?:\t\ ?)+/){|s|’ ‘(n=s.count(“\t”)-1)+%w( - o x)
[n]+’ '}.display

END
foo
bar
baz
hello
world

cfp2:~ > ruby a.rb
foo

  • bar
    • baz
      o hello
    • world

a @ http://codeforpeople.com/

Hi –

On Wed, 26 Mar 2008, ara howard wrote:

On Mar 25, 2008, at 4:58 PM, David A. Black wrote:

Then again, mine didn’t either…

neither did the OPs - my gives back the sample data, which actually required
one - easy to change though.

I’m seeing it differently; I see Martin’s like this:

foo

  • bar
    • baz
      o hello
    • world

and yours like this:

foo

  • bar
    • baz
      o hello
    • world

That’s what I was referring to.

David

On Mar 25, 3:02 pm, Martin DeMello [email protected] wrote:

foo

  • baz
    o hello
  • world

martin

bullets = %w(. * - o x)

“foo
\t bar
\t \t baz
\t \t \t hello
\t \t world
“.each{|x| puts x.reverse.sub(”\t”,bullets[x.count(“\t”)]).
reverse.gsub(“\t”," ") }

On 3/25/08, ara howard [email protected] wrote:

    bar
             baz
                     hello
             world

(86 bytes of code)

Here’s one that shaves 9 bytes of Ara’s while adding 2 fixes to match
the original spec:
use modulo for a circular list of bullets, and take an input filename
from the command line, instead of imbedding it.

$><<$<.read.gsub(/(?:\t\ ?)+/){|s|’
(n=s.chop.size-1)+'-ox’[n%4].chr+’ '}

(77 bytes)

2008/3/25, David A. Black [email protected]:

Darn, I took you literally :slight_smile:

def t(s)b=‘*-ox’;s.map{|l|c=l.count(“\t”)
(c-1).times{l.sub!(/\t/,’ ')}
l.sub(/\t/,b[c-1,1])}end

t(some_string)

You forgot the modulo :

with c = l.count("\t’)-1, it gives :

def t(s)b=‘*-ox’;d=b.size;s.map{|l|c=l.count(“\t”)-1
c.times{l.sub! /\t/,’ '}
l.sub /\t/,b[c%d,1]}end

input :

input = <<END_INPUT
foo
\t bar
\t \t baz
\t \t \t hello
\t \t \t \t ciao
\t \t \t \t \t bye
\t \t \t \t \t \t konnichiwa
\t \t world
END_INPUT

James has also forgotten :

bullets = %w[* - o x]
length = bullets.size
input.gsub!(/^(\t ?)+/) do |indent|
tabs = indent.count(“\t”) - 1
" " * tabs + bullets[tabs%length] + " "
end

– Jean-François.