Sign up ×
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.

Your objective is to take input like

Pie is good.  I just ate a bunch of pies early this morning.  Actually, it was closer to the afternoon.  Mornings are good.

and create an array of the indexes of the string where the letters that make up the word "Llama" appear (one of each in order). For example, let me show the letters pointed at with carets to show the indexes:

Pie is good.  I just ate a bunch of pies early this morning.  Actually, it was closer to the afternoon.  Mornings are good.
                                            ^                      ^        ^                            ^        ^

So the array would look like:

[44, 67, 76, 105, 114]

(If your application uses a indexing that's not 0-based, the numbers will look different. That's fine.)

If the text has no llama, then the array should be empty, nil, null, or undefined.

Any code language is accepted. This is a contest, so the least characters win!

share|improve this question
@TheWobbuffet You keep changing your username and picture. There was a time when you were "Doorknob" and had his picture. Now, your pic is a sheep. You should change it to a llama. – Justin May 4 '14 at 23:11
What about 0-based vs 1-based indexing? Can we just use the indexing used by our language or do all submissions have to conform to one convention (which one)? – Martin Büttner May 4 '14 at 23:37
@Quincunx The sheep says '42' on it! – Doorhandle May 5 '14 at 0:34
@m.buettner I really don't care about that. Whichever one you want. Also, which programming languages use 1-based indexing? :P – Doorhandle May 5 '14 at 0:37
Do you just want the function that does it or the whole program? Do you want the input/output code as well? – malik May 5 '14 at 2:17

22 Answers 22

up vote 10 down vote accepted

CJam - 33


It gets the 1-based indexes (2 more bytes for 0-based)


l reads a line from the input (replace with q for whole input)
el converts to lowercase
"llama"{...}/ executes the block for each "llama" letter
1$ copies the current string
# finds the index of the letter
)_ increments and duplicates
T+:T adds T (initially 0), updates T and leaves it on the stack
\@ swaps items around, now we have current-T, index, string
> slices the string starting at the index
; pops the remaining string
] gathers the indexes in an array
At this point we have all the 1-based indexes; iff any letter was not found, the array will have duplicates.
___ makes 3 more copies of the array
| (with 2 array copies) removes duplicates
= compares, resulting in 0 if there were duplicates or 1 if not
* multiplies the array 0 or 1 times accordingly

share|improve this answer for more info on the language. New to me. – TankorSmash May 5 '14 at 14:43

Perl, 52 bytes

The solution is provided as function that takes the string as argument and returns a list of positions.

  • One-based positions, case-sensitive search, without newlines: 52 bytes

    sub l{pop=~/(l).*?(l).*?(a).*?(m).*?(a)/;@+[1..$#+]}

    The case-sensitive search returns an empty array in the example of the question, because after matching the first three letters the lowercase letter m is missing in the input text.

  • Support of newlines: + 1 byte = 53 bytes

    sub l{pop=~/(l).*?(l).*?(a).*?(m).*?(a)/s;@+[1..$#+]}

    The text can now span several lines.

  • Case-insensitive search: + 1 byte = 54 bytes

    sub l{pop=~/(l).*?(l).*?(a).*?(m).*?(a)/si;@+[1..$#+]}

    Now the example in the question reports a list of index positions, they are one-based numbers:

    [45 68 77 106 115]
  • Zero-based positions: + 9 bytes = 63 bytes

    sub l{pop=~/(l).*?(l).*?(a).*?(m).*?(a)/si;map{$_-1}@+[1..$#+]}

    Result for the example in the question:

    [44 67 76 105 114]


The latter variant includes more or less the other variants.

sub l {
    # pop() gets the last argument 
    pop() =~ /(l).*?(l).*?(a).*?(m).*?(a)/si;
    # the letters inbetween are matched against ".*?",
    # the non-greedy variant of ".*". Thus ".*?"
    # matches only as few as possible characters.
    # The modifier /i controls the case-sensitivity
    # and means ignore case. Without the case matters.
    # Modifier /s treats the string as single line,
    # even if it contains newlines.
    map { $_-1 }   # subtract 1 for zero-based positions
    # Array @+ contains the end-positions of the last
    # submatches, and of the whole match in the first position.
    # Therefore the first value is sliced away.
    # @+ is available since Perl 5.6.

# test
my @result = l(<<"END_STR");
Pie is good.  I just ate a bunch of pies early this morning.  Actually, it was closer to the afternoon.  Mornings are good.
print "[@result]\n";
share|improve this answer
This also assumes that the input is ASCII, or at least not full Unicode. Unless Perl's regexes correctly respect grapheme boundaries these days (they certainly did not back when I had the misfortune of using it.) – Trejkaz May 5 '14 at 13:06
@Trejkaz: Unicode does not matter at all here: (a) "llama" is ASCII and its letters does not collide with any non-ASCII Unicode character or its byte representation in UTF-8. (b) With multi-byte encodings in mind, the term "index" in the question would be underspecified. Index can relate to the character position or the byte (storage) position. (c) Supporting any encoding with characters positions would mean, that the encoding should be known and needs to be provided as additional argument. – Heiko Oberdiek May 5 '14 at 15:38
Your first two solutions print [] and the third prints [ ] for me (the longer ones work correctly). I'm running "perl, v5.8.8 built for msys-64int". Do you have a bug, or does it work on a different version of perl? – Tim S. May 5 '14 at 17:48
@TimS.: [] is correct for the first solution, M is not matched in a case-sensitive search. The question is quite unclear regarding case-sensitivity. – Heiko Oberdiek May 5 '14 at 17:52
Ok, so [] is acceptable for the first two. But the first three solutions are still not working right for me: if you give it input that should return indexes, it returns [ ] – Tim S. May 5 '14 at 17:55

C# - 119

Takes string, outputs array. Null if no llama in string.

int[]a(string s){var i=0;var o="llama".Select((x,y)=>i=s.IndexOf(x,y>0?i+1:0));return o.All(x=>x>=0)?o.ToArray():null;}
share|improve this answer
+1 for x=>x>=0 – ClickRick May 5 '14 at 6:25
I am impressed. Way smaller than any of my ideas for this one. I did find you could make it smaller by initializing i to -1 and putting the .ToArray() on the .Select statement, like so int[]a(string s){var i=-1;var o="llama".Select(x=>i=s.IndexOf(x,i+1)).ToArray();return o.All(x=>x>=0)?o:null;} – Grax Jul 31 '14 at 15:24

Ruby, 56 65 63

Edit: +9 characters so that it is case-insensitive.

Defines a function (lambda, technically) f.


Returns nil if there is no llama. If it has to be [] (empty array), then just add ||[] before the last } for a total of 4 extra characters.

Readable version:

innerLlama = -> str{
    index = 0;
    arr = 'llama'{|char|
        index = str.index(char, index + 1)
        break unless index
    # uncomment this line for empty array on failure
    #arr || []
share|improve this answer
I apologize for editing my question after some time, but I just added that the array, if no llama, can be nil,null,empty, or undefined. – Doorhandle May 5 '14 at 0:41
So you did it with a llambda? – Mason Wheeler May 5 '14 at 3:31
@Doorknob would be two bytes shorter by using upcase instead of downcase no? – dstarh May 5 '14 at 14:24
@dstarh Yep, thanks – Doorknob May 5 '14 at 17:10
Think you can get case-insensitivity a byte cheaper by doing index(/#{c}/i instead of upcase. – histocrat May 7 '14 at 15:10

Fortran - 154 148

Fortran sucks at golfing, but just to prove that parsing strings can be done in a math-based language, I did it:

function f result(r);integer::r(5),j=1;do i=1,len(s);if(s(i:i)==a(j:j).or.s(i:i)==b(j:j)) then;r(j)=i;j=j+1;endif;enddo;if(any(r==0))r=0;endfunction

I saved a few characters by eliminating the not-required f at the end of endfunction and used if(any(r==0)) instead of if(.not.all(r>0)).

This requires:

  1. s to be the string with text
  2. a to be the lower-case test (i.e., llama)
  3. b to be the upper-case test (i.e., LLAMA)

The full, un-golfed program is

program find_llama
   character(len=123) :: s = "Pie is good.  I just ate a bunch of pies early this morning.  Actually, it was closer to the afternoon.  Mornings are good."
   character(len=5) :: a="llama",b="LLAMA"

   print *,f()
   function f result(r)
     do i=1,len(s)
        if(s(i:i)==a(j:j).or.s(i:i)==b(j:j)) then
     if(any(r==0)) r=0
   end function
end program find_llama
share|improve this answer
Modern Fortran is at least allowed on the pitch & putt areas. FORTRAN IV would still be playing crazy golf. – ClickRick May 5 '14 at 6:30
@ClickRick: Fortran IV is something I have not learned. Not sure that I want to. Something about forced indentation and capitalization disturbs me. – Kyle Kanos May 5 '14 at 10:52

C - 53

Compile with:

gcc -D L=\"llama\" -D W=\"Lie\ is\ good.\ \ I\ just\ ate\ a\ bunch\ of\ pies\ early\ this\ morning.\ \ Actually,\ it\ was\ closer\ to\ the\ afternoon.\ \ Mornings\ are\ good.\"

I tested this compile command with cygwin's gcc. Other environments might handle spaces, and other special characters differently.

The 0-based result is stored into array r. Its contents are undefined if there is no llama in the string.

  • Case-sensitive (53)


  • Case-insensitive (58)


share|improve this answer

JavaScript (ECMAScript 6) - 68 Characters


Assumes that the string to test is in the variable s. If you want to turn it into a function then prepend f=s=> (for an additional 5 characters).



Case Insensitive - 69 Characters



[68, 80, 93, 105, 114]

Case Insensitive & First Match - 74 Characters



[44, 67, 76, 105, 114]
share|improve this answer

Python, 100

I am the worst golfer ever. :P

Thanks to @xnor for shaving off 6 bytes.

for i in s:
 if g:exec("o+=[n];g=g[1:];"*(i.lower()==g[0])+"n+=1")

o contains the array after.

EDIT: Fixed.

EDIT 2: len(g) to g, o==5 to o>4 as per @xnor's suggestions.

EDIT 3: @WolframH fixed it.

share|improve this answer
o*=(len(o)==5) is excellent. It's horrible, but I love it! – kevinsa5 May 5 '14 at 5:30
I don't think the outer parentheses on that line are necessary. You could save two characters by removing them. – user2357112 May 5 '14 at 6:46
@user2357112 On that second last line? I'll remove 'em. – cjfaure May 5 '14 at 8:59
I assume s is the input string, right? Shouldn't then s.lower be i.lower? However, that doe – WolframH May 5 '14 at 19:56
@WolframH ah, yes, will fix tomorrow. – cjfaure May 5 '14 at 19:59

sed, 299+1

Yes, sed can find a llama. No, sed can't do math. This is the longest answer so far, at 299+1 characters, because I had to teach sed to count.

This answer requires a sed with extended regular expressions (sed -E or sed -r). I used OpenBSD sed(1). Input is one string per line. (Therefore, the string may not contain a newline.) Output is a line of numbers, or nothing.

Usage (+1 character for -r):

$ echo 'All arms on all shoulders may ache.' | sed -rf llama.sed
1 2 12 26 30 

Source code (299 characters):

s/(z*)%/\10 z\1/

The program first replaces the llama with five %. (All % in this program are literal.) The first command s/%/z/g changes any % to z in the input line. The next five commands find the llama, so All arms on all shoulders may ache. becomes A%% arms on %ll shoulders %ay %che. Because each .* is greedy, I always finds the llama on the right: llama llama would become llama %%%%%. If I can't get five %, then /(.*%){5}/!d deletes the input line and skips the next commands.

s/[^%]/z/g changes every character but % to z. Then I enter a loop. s/(z*)%/\10 z\1/ changes the first % to 0, copies zero or more z from left to right, and adds one more z to right. This is so the number of z will equal the index. For example, zz%zzz%... becomes zz0 zzzzzzzz%... because the first % was at index 2, and the next % is at index 8. s/z*$// removes extra z from the end of the string.

The next eleven commands count z by removing each z and counting up from 0. It counts like zzz0, zz1, z2, 3. Also, 1zzzz9 becomes z1zzz0 (later 23), or zzzz9 becomes 1zzz0 (later 13). This loop continues until there are no more % or z.

share|improve this answer

Python 71

Assumes input in s. Output in o.

for c in'lama':o+=F(c,o[-1]+1),

Edit: Changed from lists to tuples to save 2 bytes.

share|improve this answer
Multiplying lists by booleans is fun, isn't it? ;D – cjfaure May 6 '14 at 6:10
I like how you dodge the problem of o needing to start nonempty to take o[-1]. Maybe it's shorter though to just start o as [-1] and later do o=o[1:]? Annoyingly, the initial -1 trips up checking if o contains -1. – xnor May 8 '14 at 7:24
@xnor: I don't think the -1-Idea can be made to work. At least, I didn't succeed :-( However, I changed lists to tuples to save 2 bytes. :-) – WolframH May 12 '14 at 18:11

Python 100

import re
print["l.*?(l).*?(a).*?(m).*?(a)",x,re.I).start(i) for i in range(5)]


in  = Pie is good.  I just ate a bunch of pies early this morning.  Actually, it was closer to the afternoon.  Mornings are good.
out = [44, 67, 76, 105, 114]
in[out] = ['l', 'l', 'a', 'M', 'a']
share|improve this answer

Haskell, 111

import Data.Char
l i(a:as)t@(b:bs)|a==b=i:l(i+1)as bs|True=l(i+1)as t
l _ _ _=[]
r s=l 0(map toUpper s)"LLAMA"


import Data.Char

llama :: Int -> String -> String -> [Int]
llama i (a:as) t@(b:bs)
  | a==b      = i : llama (i+1) as bs
  | otherwise = llama (i+1) as t
llama _ _ _ = []

runme :: String -> [Int]
runme s = llama 0 (map toUpper s) "LLAMA"


*Main> r "Pie is good.  I just ate a bunch of pies early this morning.  Actually, it was closer to the afternoon.  Mornings are good."
share|improve this answer

Matlab, 61 96

Searches the string and replaces everything up to each match with gibberish before searching for next character. Will leave s undefined if an the word does not occur.

t='llama';for q=1:5;s(q)=min(regexpi(z,t(q))),z(1:s(q))=0;end

Note that the charcount could be reduced if case sensitivity is allowed.

Previous versions

 try;t='llama';for q=1:length(t);s(q)=find(lower(z)==t(q),1);z(1:s(q))=ones(1,s(q));end;catch;end

Searches the string and replaces everything up to each match with gibberish before searching for next character. Error handling (try-catch-end) could maybe be dropped, then the program would crash (but s would be undefined as required) if llama not found.


>> z='Pie is good.  I just ate a bunch of pies early this morning.  Actually, it was closer to the afternoon.  Mornings are good.';
>> try;t='llama';for q=1:length(t);s(q)=find(lower(z)==t(q),1);z(1:s(q))=ones(1,s(q));end;catch;end
>> s
s =

    45    68    77   106   115

Without error handling:

t='llama';for q=1:length(t);s(q)=find(lower(z)==t(q),1);z(1:s(q))=ones(1,s(q));end
share|improve this answer
Like the idea, have reduced charcount a bit. – Dennis Jaheruddin May 6 '14 at 12:15

Language Java

 final int[] wordIndexInSentence(String sentence, String word)
    final int[] returnArr = new int[word.length()];
    int fromIndex = 0;
    word = word.toUpperCase();
    sentence = sentence.toUpperCase();
    for (int i = 0; i < word.length(); i++)
      final char c = word.charAt(i);
      returnArr[i] = sentence.indexOf(c, fromIndex);
      fromIndex = returnArr[i] > 0 ? returnArr[i] + 1 : fromIndex;
    return returnArr;
share|improve this answer

Python (70)

for x in'llama':c=s.lower().find(x,c+1);r+=[c]
r*=1-(-1in r)

We search of each character in 'llama' in turn, starting after the location of the previously-found character. If no character is found, c becomes the default value of -1, in which case the last line turns r into the empty list.

Edit: Found out that str.find(s,...) can be invoked as s.find(...), saving 4 characters.

share|improve this answer

OpenEuphoria, 147128

I have two examples. First, the shortest:

object t=and_bits(gets(0),#DF),L="LLAMA",i=0,X={}for j=1 to 5 do 
end for 
if find(0,X) then X={} end if?X

I can get it down to 126 characters if I use "or" instead of "and" like the C version does up above. However, this also matches the string ''!-! as llama. Uncommon, but still a possible error.

object t=or_bits(gets(0),96),L="llama",i=0,X={}for j=1 to 5 do 
end for 
if find(0,X) then X={} end if?X

And then the version using regular expressions:

include std/regex.e
include std/sequence.e
include std/utils.e
object X=regex:find(new("(?i)(l).*?(l).*?(a).*?(m).*?(a)"),gets(0))
? iff(atom(X),{},vslice(X[2..6],2))

Both take input from STDIN and post to STDOUT.

EDIT: Shorter regex example:

include std/regex.e
include std/sequence.e
object X=regex:find(new("(?i)(l).*?(l).*?(a).*?(m).*?(a)"),gets(0))
if atom(X)then?{}else?vslice(X[2..6],2)end if
share|improve this answer
Is it possible to save a few by building the regex with split/join or explode/implode, or does OpenEuphoria not have short versions of those? – Peter Taylor May 8 '14 at 9:09
OpenEuphoria can do split/join with strings of characters, but I don't see a way to do it in a shorter manner. I'm not very good with regular expressions; the regex used here was "inspired" (shamelessly stolen) from one of the other examples on this page. – TinSoldier May 8 '14 at 13:44

Powershell - 121 85

I'm still practicing with Powershell, expect this could be improved

$s contains the string, result is in array $a

Original version

$a=@();$w="llama";$n=$c=0;foreach ($i in $s.tochararray()) {if ($i -eq $w[$n]) {$a+=$c;$n+=1} $c+=1};$a*=$a.length -gt 4


foreach ($i in $s.tochararray()) {
 if ($i -eq $w[$n]) {
 } $c+=1
$a*=$a.length -gt 4

New version, with massive thanks to @goric

share|improve this answer
You can remove a lot of spaces in there to shorten things up to 112: $a=@();$w="llama";$n=$c=0;foreach($i in $s.tochararray()){if($i-eq$w[$n]){$a+=$c;$n+=1}$c+=1};$a*=$a.length-gt4 – goric May 9 '14 at 19:05
Also, you can replace foreach($i in $s.tochararray()) with [char[]]$s|%, as long as you change the subsequent $i to a $_. That shaves it down to 93: $a=@();$w="llama";$n=$c=0;[char[]]$s|%{if($_-eq$w[$n]){$a+=$c;$n+=1}$c+=1};$a*=‌​$a.length-gt4 – goric May 9 '14 at 19:08
Save 5 more chars by removing the $w variable altogether, since its only used once. Just inline it into the if: if($i-eq"llama"[$n]) – goric May 9 '14 at 19:14
..and, of course, replace your +=1s with ++s – goric May 9 '14 at 19:25


no PHP answer yet? I think a language heavily string-oriented can beat at least a math-based one

function x($s){$i=$j=0;$r=str_split('llama');$s=strtolower($s);while($i<strlen($s)){if($s[$i]==$r[$j]){$r[$j]=$i;$j++;if($j>4)return$r;}$i++;}return[];}

152 against fortran 154, job done :P


function x($s){
        if ($s[$i]==$r[$j]){
                return $r;

if the caller always passes a lowercase string, it lowers to 137

share|improve this answer
You need to add <? at the beginning of your code to make it valid. Sorry... – avall May 8 '14 at 7:40

JavaScript, 122 115

function(s,b){z=[];for(i=0;i<5;i++){z.push(b=s.toLowerCase().indexOf("llama"[i],++b))};return z.indexOf(-1)<0?z:[]}

Defines a function that takes a string as its only argument (second arg is a cheap var) and returns either an empty array or a 5-element array.

Drops to 108 if I take the input on a single char variable (s) and leave the output in another (b):

var b=((z="llama".split('').map(function(a){return (b=s.toLowerCase().indexOf(a,++b))})).indexOf(-1)<0?z:[])

Edit: Swapped out map for for loop.

share|improve this answer
ECMAScript 6 version (81 characters) - b=(z=[]"llama",a=>b=s.toLowerCase().indexOf(a,++b))).indexOf(-1)<0?z:‌​[] – MT0 May 5 '14 at 22:31

Rebol, 97

f: func[s][a: copy[]foreach n"llama"[if none? s: find s n[return[]]append a index? s s: next s]a]

Usage example in Rebol console:

>> f "Pie is good.  I just ate a bunch of pies early this morning.  Actually, it was closer to the afternoon.  Mornings are good." 
== [45 68 77 106 115]

>> f "nearly llami"       
== []

>> f "Llama"
== [1 2 3 4 5]

>> f reverse "llama"
== []

Rebol uses 1-based indexing. Returns empty list [] if no llama sequence found (case insensitive).


f: func [s] [
    a: copy []
    foreach n "llama" [
        if none? s: find s n [return []]
        append a index? s
        s: next s
share|improve this answer

APL, 47

+\↑⊃{a s←⍵⋄~⍺∊s:⍬⍬⋄a,←n←s⍳⍺⋄a(n↓s)}/'amall',⊂⍬⍞

Not the shortest code, but quite warped, in an APL way.


'amall',⊂⍬⍞ Make an array of 6 elements: the letters 'amall' and a subarray of 2 elements, themselves subarrays: the empty array and a line of characters read from input.

{...}/... Reduce (right-fold) the 6-element array using the provided function.

a s←⍵ Decompose the right argument into the array of indices and the remaining substring (initially the empty array and the full string.)

~⍺∊s:⍬⍬ If the substring does not contain the next letter stop the computation and return the empty array.

a,←n←s⍳⍺ Otherwise, find its position, call it n, and append it to the array of indices.

a(n↓s) Make and return an array of 2 elements: the extended array of indices and the remaining substring.

+\↑⊃... Unpack the output of the folding, take the first element (the array of indices) and scan it with addition, to turn relative offsets into absolute ones.


      +\↑⊃{a s←⍵⋄~⍺∊s:⍬⍬⋄a,←n←s⍳⍺⋄a(n↓s)}/'amall',⊂⍬⍞
All cats meow aloud.
2 3 6 10 15


      +\↑⊃{a s←⍵⋄~⍺∊s:⍬⍬⋄a,←n←s⍳⍺⋄a(n↓s)}/'amall',⊂⍬⍞
Some cats purr instead.
share|improve this answer

Julia, 76

Another regex example using Julia language.

share|improve this answer

Your Answer


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.