Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

The input is a word of lowercase letters not separated by whitespace. A newline at the end is optional.

The same word must be output in a modified version: For each character, double it the second time it appears in the original word, triple it the third time etc.

Example input:

bonobo

Example output:

bonoobbooo

Standard I/O rules apply. The shortest code in bytes wins.

Tests provided by @Neil :

tutu -> tuttuu
queue -> queuuee
bookkeeper -> boookkkeeepeeer
repetitive -> repeetittiiveee
uncopyrightables -> uncopyrightables
abracadabra -> abraacaaadaaaabbrraaaaa
mississippi -> misssiisssssssiiipppiiii
share|improve this question

28 Answers 28

Jelly, 4 bytes

;\f"

Try it online!

How it works

;\f"  Main link. Argument: S (string)

;\    Cumulatively reduce by concatenation.
      This yields the array of all prefixes of S.
  f"  Vectorized filter.
      Keep only occurrences of the nth letter in the nth prefix.
share|improve this answer
11  
Well then... rip Pyth. – Adnan 20 hours ago
    
This site is becoming a competition for the best general-purpose golfing language... not that that's a bad thing. – shelvacu 11 hours ago
    
@shelvacu The latter is debatable, 2 friends I've shown PPCG to have said something along the lines of "all the top answers are just using golf languages" as a first impression. – Insane 4 hours ago

Pyth, 6 bytes

Thanks to @Doorknob for taking off 1 byte.

Thanks to @Maltysen for taking off 5 bytes.

s@VQ._

Try it online!

How it works


For example, take the string "bonobo".

._ makes a list: ['b', 'bo', 'bon', 'bono', 'bonob', 'bonobo']

VQ means for N in Q, which means Q (the input evaluated) will be treated as a list: ['b', 'o', 'n', 'o', 'b', 'o'], and then they will be paired by the @ like this:

     Q      ._         @ (intersect)
0:  'b'     'b'       'b'
1:  'o'     'bo'      'o'
2:  'n'     'bon'     'n'
3:  'o'     'bono'    'oo'
4:  'b'     'bonob'   'bb'
5:  'o'     'bonobo'  'ooo'

Therefore, @VQ._ will produce ['b', 'o', 'n', 'oo', 'bb', 'ooo'].

The s then joins them all together, creating a string 'bonoobbooo', which is then implicitly printed out to become bonoobbooo.

share|improve this answer
    
Kenny, your explanation is wrong. VQ only means for N in Q when it is not inside a function. In this case, what's actually going on is that @V means the @ function vectorized (applied in parallel) over its next two arguments, Q and ._. This is missing from the docs, so I'll fix it. – isaacg 4 hours ago

Retina, 34 19 bytes

Saved 15 bytes by taking some inspiration from isaacg's solution.

Byte count assumes ISO 8859-1 encoding.


$`¶
(\D)(?!.*\1¶)

The leading and trailing empty lines are significant.

Try it online!

Explanation


$`¶

This is a replace stage which matches the empty regex (i.e. every zero-width position in the string) and substitutes $`¶ for it, where $` is the prefix of the match and inserts a linefeed. This basically computes all the prefixes and puts them on a separate line together with the last character of that prefix:

bb
obo
oboo
kbook
kbookk
ebookke
ebookkee
pbookkeep
ebookkeepe
rbookkeeper

There will be some leading and trailing linefeeds, but we can ignore them.

From each of these prefixes we want to keep the characters that are equal to the last character. For that we use another replace stage:

(\D)(?!.*\1¶)

This matches everything we don't want to keep and replaces it with a nothing. We match any character (using \D since we know there won't be digits in the input) and then make sure that there isn't another copy of that character at the end of the line.

share|improve this answer

><>, 27 bytes

>i:0g1+:\
:{-1v!?:<}o
/p${/

Requires the official interpreter which exits with an error when trying to print code point -1. Try it online!

The code reads input one char at a time and uses the first row of the codebox as a large array which stores the number of times each char has been seen so far (><> initialises non-program cells to 0). The second row is a loop for outputting a char multiple times.

Alternatively, here's a version which exits cleanly (37 bytes, not properly golfed):

>i:0(?;:0g1+:\
}o:{-1v!?:   <
v  p${<
share|improve this answer
    
Damn that's good ! I should stop relying so heavily on the online interpreter, I would never have thought about simply using such a huge codebox, and I didn't even knew the official interpreter exited on -1 print – Aaron 21 hours ago
2  
@Aaron Yeah, it's a corollary of Python erroring when trying to do chr(-1). The animated interpreter's great for visualisations, but unfortunately some of the discrepancies with the official interpreter are a bit annoying :/ – Sp3000 21 hours ago

Python, 56 bytes

I seem to be stuck with two answers of the same length:

f=lambda x,*y:x and-~y.count(x[0])*x[0]+f(x[1:],x[0],*y)
f=lambda x,y=0:x[y:]and-~x[:y].count(x[y])*x[y]+f(x,y+1)

Edit: See @pacholik's answer for a shorter, alternative Python approach.

share|improve this answer
    
I'm not used to beating you with my ><> answers, I'm waiting for a Gol><> answer to fix that ;) – Aaron 21 hours ago
    
@Aaron Too bad, I was actually going to beat you back with ><> :P – Sp3000 21 hours ago

Pyth, 7 bytes

s@Led._

Test suite

Test suite thanks to DenkerAffe

Explanation:

s@Led._
     ._    All prefixes, implicitly applied to the input.
 @L        Filter each prefix for characters equal to
   ed      the last character of the prefix
s          Concatenate and implicitly print.
share|improve this answer

Perl, 17

(16 bytes code, +1 for -p)

s/./${$&}.=$&/ge

Usage:

perl -pe 's/./${$&}.=$&/ge' <<< 'bonobo'
bonoobbooo
share|improve this answer

Haskell, 50 42 41 bytes

Saved 8 bytes thanks to Lynn

f t=[c|(i,c)<-zip[1..]t,x<-take i t,c==x]
share|improve this answer
1  
How about: f t=[c|(i,c)<-zip[0..]t,j<-[0..i],c==t!!j] – Lynn 22 hours ago
    
Nice, thank you. – Damien 20 hours ago

Haskell, 39 bytes

f""=""
f x=f(init x)++filter(==last x)x

Usage example: f "bonobo" -> "bonoobbooo".

Different enough from @Damien's answer. Builds the string from the right by extracting all occurrences of the last character from the string and prepending a recursive call with all but the last character.

share|improve this answer

JavaScript (ES6), 48 45 bytes

s=>s.replace(n=/./g,c=>c.repeat(n[c]=-~n[c]))

Edit: Saved 3 bytes thanks to @user81655.

share|improve this answer

Labyrinth, 54 bytes

 ^
}(
="
}
;"({
 { .
 }}:
):
{
;~{{
 ` =
 "=}
"`
:,
@v

Another collab with @MartinBüttner, who actually did most of the golfing for this one. The program's surprisingly small considering what's going on, and it's very... vertical. Both of us are pretty convinced this isn't optimal though, but optimality in Labyrinth is finnicky since there's so many possible layouts to try.

Try it online!

Explanation

Labyrinth only has two stacks of arbitrary-precision integers, which isn't much flexibility in terms of memory options. To perform the counting, this program actually uses the two stacks as a tape, with shifting a value from one stack to the other being akin to moving a memory pointer left/right by a cell. It's not quite the same as that though, since we also need to drag a few values along with us.

Here's a brief explanation of the code:

enter image description here

  1. Input/termination: Read an input char , and duplicate : it. The duplicated char will be used as a loop counter to determine how many elements to shift from the auxiliary stack to the main stack. If EOF, turn left at the : and halt @, otherwise turn right and move up to section 2.

  2. Stack shift loop: Shift elements from the auxiliary stack to the main stack [input char] number of times, dragging the input char and loop counter along with us. This is a loop that happens until the counter is decremented to 0.

  3. Increment count: Pop the counter ; and pull the next element of the auxiliary stack {. This is the number of times we've seen the char so far (popping/shifting from empty stacks yield 0 in Labyrinth, which is perfect for initalising counters). Increment this counter ), make a copy of it : then shift it back to aux }.

  4. Output loop: Output the [input char], [updated times-seen counter] number of times. This loop happens until the duplicated times-seen counter reaches 0. The stack ends with the zeroed times-seen counter on top, with the [input char] beneath it (since we make a copy before outputting at each iteration).

  5. Unshift setup: Pop the zeroed times-seen counter ; and shift [input char] to aux, as setup for section 6.

  6. Stack unshift loop: Using the remaining [input char] as a loop counter, shift [input char] elements back from main to aux, i.e. the inverse of section 2.

Additionally, ^ and v (which rotate a column of code) are used to move the instruction pointer from the very top to the very bottom at the start of the program and after every input iteration.

Some golfing details

Most of the loops are a bit more complex than their simple explanation above. In particular:

  • To enter section 2 correctly, the input char is negated. To handle the negated char in the loop, bitwise negation ~ and unary negation ` are used instead of ( for decrementing.

  • For golfing purposes, a } from section 3 made its way to section 4. To compensate, there's an additional corresponding { in the loop.

  • At the end of each input iteration, the instruction pointer is facing upwards at the top ^, and thus when it is at the bottom again it is ready to read input, since the IP is facing upwards towards the ,. However, on the first iteration the IP starts off facing rightwards, but luckily this doesn't matter since the v at the bottom is not at a junction, and a left turn is made like at any other corner.

share|improve this answer

05AB1E, 10 bytes

Code:

$vy«Dy¢y×?

Explanation:

$           # Push the number 1 and input
 v          # Map over the input string
  y«        # Concat the letter to the previous string (initial 1)
    D       # Duplicate this string
     y¢     # Count the occurences of the current character in the string
       y×   # Multiply this number with the current character
         ?  # Pop and print without a newline

Uses the CP-1252 encoding. Try it online!

share|improve this answer

Pyth, 11 bytes

s.e*b/<Qhkb

Try it here!

Explanation

s.e*b/<Qhkb    # Q = input

 .e            # map over input with b as value and k as index (Q get appended at the end inplicitly)
      <Qhk     # take the first k+1 chars of Q
     /    b    # count occurences of b in there
   *b          # repeat b that many times
s              # join resulting list into one string
share|improve this answer

PowerShell v2+, 52 bytes

$b=,0*26;-join([char[]]$args[0]|%{"$_"*++$b[$_-97]})

Constructs a 26-element array consisting of only zeros, stores it in $b. This is our "counter" of what letters we've seen. We then take input $args[0], cast it as a char-array, and send it through a loop. Each iteration, we take the current character "$_" and multiply it by the pre-incremented counter at the given value, which will make the first occurrence be multiplied by 1, the second by 2 and so on. We encapsulate that with a -join so it's all one word being output.

share|improve this answer

J, 11 bytes

#~+/@(={:)\

This is a monadic verb. Try it here. Usage:

   f =: #~+/@(={:)\
   f 'tutu'
'tuttuu'

Explanation

#~+/@(={:)\
     (   )\  For each non-empty prefix:
       {:      Take last element,
      =        compare for equality to the others and itself
  +/@          and take sum (number of matches).
#~           Replicate original elements wrt the resulting array.
share|improve this answer

CJam, 14

q:A,{)A<_)--}/

Try it online

Explanation:

q:A      read the input and store in A
,        get the string length
{…}/     for each number from 0 to length-1
  )      increment the number
  A<     get the prefix of A with that length
  _      duplicate it
  )      separate the last character
  -      remove it from the rest of the prefix
  -      remove all the remaining characters (different from the last one)
          from the prefix
share|improve this answer

MATL, 8 bytes

tt!=RsY"

Try it online! Or verify all test cases at once.

Explanation

t    % take input string implictly. Duplicate
t!   % duplicate and transpose into a column
=    % test for equality with broadcast. Gives an NxN array, where N is
     % input string length
R    % upper triangular part: set entries below the diagonal to 0
s    % sum of each column. For each postion in the input, gives how many
     % times that letter has appeared up to that position
Y"   % replicate elements (run-length decoding). Display implicitly
share|improve this answer

Perl 6, 37 bytes

{.split('').map({$_ x++%.{$_}}).join}
share|improve this answer

><>, 52 bytes

i:0(?;&l:?!v1-$:&:&=?\}70.>
6f+0.00o:&~/         \:o

It stacks every letter read, prints them once and once again for every similar letter in the stack.
It uses the & register, because having to handle 3 variables on the stack (current read letter, position in the stack, letter at this position) is a pain.

You can try it here!

share|improve this answer

Python 3, 52

def f(s):*s,x=s;return s and f(s)+x+x*s.count(x)or x
share|improve this answer
2  
Ah, going from the end makes so much more sense! You can do this shorter in a lambda, without the need for Python 3 specifically: f=lambda s:s and f(s[:-1])+s[-1]*s.count(s[-1]) – Sp3000 21 hours ago
    
I though it could be done that way. But I don't like subscripting in Python :P – pacholik 21 hours ago

PHP, 54 bytes

for(;$c=$argv[1][+$x++];)echo str_repeat($c,++$o[$c]);

Run like this (-d added for aesthetics only):

php -d error_reporting=30709 -r 'for(;$c=$argv[1][+$x++];)echo str_repeat($c,++$o[$c]); echo"\n";' abracadabra
share|improve this answer

Mathematica, 57 bytes

StringReplace[Clear@c;c@_=0;#,x_:>x~StringRepeat~++c[x]]&

We use c[x] as a lookup table of how often character x has already occurred. This is incremented each time it's retrieved in x~StringRepeat~++c[x]. Unfortunately, to make the function reusable, we need to reset the lookup table each time with Clear@c;c@_=0;, which is quite expensive.

share|improve this answer

Rust, 176 Bytes

fn s(w:&str)->String{let mut m=std::collections::HashMap::new();w.chars().map(|c|{let mut s=m.remove(&c).unwrap_or(String::new());s.push(c);m.insert(c,s.clone());s}).collect()}

This uses a map to store a string for every character in the input. For each character, the string will be removed from the map, concatenated with the character, inserted back into the map and appended to the output.

I would have liked to use get(...) instead of remove(...), but the borrow checker had me change my mind.

share|improve this answer

awk, 72 bytes

BEGIN{FS=""}{for(i=1;i<=NF;i++){a[$i]++;for(j=0;j<a[$i];j++)printf $i}}

The idea is to store the count of the appearing character in an associative array and print the character this count times.

share|improve this answer

Beam, 33 42 bytes

This should have been smaller, but I lost some bytes initializing the memory slots to 0. Swapping some flow directions managed to eliminate a lot of empty space.

 >+\
vus/
>rnH
  >g'\
(@v's/
^`<'

Try it in this snippet

General explanation.

  • Set all the memory slots from 0-255 to 0
  • Read in the input ascii value into the beam
  • If beam is 0 halt (beam = store)
  • Get the memory[beam] value into the store, increment it and save back
  • Decrement the store to 0 printing out the beam character
  • Repeat
share|improve this answer

Python, 66 bytes

Try it here

Golfed

def s(w,o=[],n=""):
 for x in w:n+=x*(o.count(x)+1);o+=x
 return n

Ungolfed

def stretch(word):
    occurrences = []
    newWord = ""
    for w in word:
        newWord += w * (occurrences.count(w) + 1)
        occurrences.append(w)
    return newWord
share|improve this answer

Ruby, 50 48 bytes

Anonymous function.

->s{i=0
s.chars.map{|c|c*s[0,i+=1].count(c)}*''}
share|improve this answer

Javascript ES6 47 bytes

q=>[...q].map(a=>x[a]=(x[a]||'')+a,x=[]).join``
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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