1. Euphoria sucks at golfing

It's been a while since we've discussed code golf. I think it's a good mental exercise and quite a bit of fun. Unfortunately, due to its verbose nature, Euphoria results tend to be a worse than other languages, especially curly bracket languages that lack "end <construct>" type statements.

Here's a fun problem: Bring out the inner llama of a sentence

The Wobbuffet said...

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 code-golf contest, so the least characters win!

Here is my solution...

include std/text.e 
 
object T = gets(0), 
    t = lower(T), 
    L = "llama", 
    X = repeat(0,5) 
 
for i = 1 to length(L) do 
    if i = 1 then 
        X[i] = find(L[i],t) 
    else 
        X[i] = find(L[i],t,X[i-1]+1) 
    end if 
    if X[i] = 0 then 
        X = {} 
        exit 
    end if 
end for 
 
? X 

Output:

{45,68,77,106,115} 

Total of 180 characters (worst by far according to other answers). It accepts a string via STDIN, e.g.

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

-Greg

new topic     » topic index » view message » categorize

2. Re: Euphoria sucks at golfing

Without rethinking your algorithm, I've managed to trim some off your code.

include std/text.e  
 
object t = lower(gets(0)), 
    L = "llama",  
    X = {0}, 
    c 
  
for i = 1 to length(L) do  
   c = find(L[i],t,X[$]+1)  
   if c then  
      X &= c 
   else 
      X = {0} 
      exit 
   end if 
end for  
  
? X[2..$] 

A better way to count it would be to count tokens rather than characters. That would make language to language comparisons more meaningful.

new topic     » goto parent     » topic index » view message » categorize

3. Re: Euphoria sucks at golfing

Here's my attempt:

include std/text.e 
 
object t = lower(gets(0)), 
    L = "llama", 
    X = 0&"     " 
 
for i = 1 to length(L) do 
    X[i+1] = find(L[i],t,X[i]+1) 
    if X[i+1] = 0 then 
        X = {0} 
        exit 
    end if 
end for 
 
? X[2..$] 
new topic     » goto parent     » topic index » view message » categorize

4. Re: Euphoria sucks at golfing

Well, it's more descriptive than others. If the include makes up the count, you could compare in uppercase by transforming the input with

t=and_bits(gets(0),#DF) 

And here's my entry without much thinking on how to remove the duplicate if

object t=and_bits(gets(0),#DF),s="LLAMA",z=1,r={} 
for i=1 to length(t) do 
	if t[i]=s[z] then 
		r&=i 
		z+=1 
		if z=6 then 
			exit 
		end if 
	end if 
end for	 
if z<6 then r={} end if 
?r 

Edit: removed unused var

object t=and_bits(gets(0),#DF),s="LLAMA",z=1,r={} 
for i=1 to length(t) do 
	if and_bits(t[i]=s[z],z<6) then 
		r&=i 
		z+=1 
	end if 
end for	 
if z<6 then r={} end if 
?r 

Edit2: one if removed :)

new topic     » goto parent     » topic index » view message » categorize

5. Re: Euphoria sucks at golfing

I got it down to 150 characters (after whitespace removed). Here's the whitespace version:

object t=and_bits(gets(0),#DF),L="LLAMA",X={},i=1 
 
while length(L) do 
  i=find(L[1],t,i) 
  if i=0 then 
    X={} 
    exit 
  else 
    L=L[2..$] 
    X&=i 
    i+=1 
  end if 
end while 
?X 

Edit: Shortened to 148:

object t=and_bits(gets(0),#DF),L="LLAMA",X={},i=1 
 
while length(L)do 
  i=find(L[1],t,i) 
  if i then 
    L=L[2..$] 
    X&=i 
    i+=1 
  else 
    X={} 
    exit 
  end if 
end while 
?X 

Edit2 Got it down to 147. Here is the short version:

object t=and_bits(gets(0),#DF),L="LLAMA",X={},i=1 
while length(L)do 
i=find(L[1],t,i)if i then L=L[2..$]X&=i i+=1 
else X={}exit 
end if 
end while 
?X 
new topic     » goto parent     » topic index » view message » categorize

6. Re: Euphoria sucks at golfing

Not tested this one ...

object T = lower(gets(0)), 
       X = {} 
	    
X &= find('l', T) 
X &= find('l', T, X[$]+1) 
X &= find('a', T, X[$]+1) 
X &= find('m', T, X[$]+1) 
X &= find('a', T, X[$]+1) 
 
if find(0, X) then 
   X = {} 
end if 
return X 
new topic     » goto parent     » topic index » view message » categorize

7. Re: Euphoria sucks at golfing

Whittled down to 141:

object t=and_bits(gets(0),#DF),L="LLAMA",i=0,X={} 
 
while length(L) do 
  i=find(L[1],t,i+1) 
  X&=i 
  L=L[2..$] 
end while 
 
if find(0,X) then 
  X={} 
end if 
?X 
new topic     » goto parent     » topic index » view message » categorize

8. Re: Euphoria sucks at golfing

jaygade said...

Whittled down to 141:

object t=and_bits(gets(0),#DF),L="LLAMA",i=0,X={} 
 
while length(L) do 
  i=find(L[1],t,i+1) 
  X&=i 
  L=L[2..$] 
end while 
 
if find(0,X) then 
  X={} 
end if 
?X 

Nice! You can make it even shorter using or to convert to lowercase instead of and to upper, here's one i was using to test:

object t=or_bits(gets(0),32),s="llama",z=1,r={} 
for i=1 to length(t) do 
	if z<6 and t[i]=s[z] then 
		r&=i 
		z+=1 
	end if 
end for	 
if z<6 then r={} end if 
new topic     » goto parent     » topic index » view message » categorize

9. Re: Euphoria sucks at golfing

I'm not sure that or_bits would work. Aren't you only setting bit 4 and not masking any others?

Hmm, testing finds that you could get some errors, although it should work most of the time.

Edit: My testing finds an off-by-one error, but you might be able to correct for that.

new topic     » goto parent     » topic index » view message » categorize

10. Re: Euphoria sucks at golfing

Not the shortest, but probably the most terse:

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)) 

Shorter:

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 
new topic     » goto parent     » topic index » view message » categorize

11. Re: Euphoria sucks at golfing

This gets down to 130:

object o=and_bits(gets(0),#DF),l="LLAMA",x=0,y={} 
for i=1 to 5 do 
x=find(l[i],o,x+1)if x=0 then 
?{}abort(0)end if 
y&=x 
end for 
?y 

Readable:

object 
	o = and_bits(gets(0),#DF), 
	l="LLAMA", 
	x=0, 
	y={} 
for i=1 to 5 do 
	x=find(l[i],o,x+1) 
	if x=0 then 
		?{} 
		abort(0) 
	end if 
	y &= x 
end for 
?y 
new topic     » goto parent     » topic index » view message » categorize

12. Re: Euphoria sucks at golfing

I got it down to 129 126. Are there any more gains to be had?

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

Edit: Stole the "or_bits" idea from gbonhevi above the C example (58 bytes) on the page, using '96' instead of '32'. I'm still afraid of getting false positives, but so far it has proven to be correct.

Edit again: Found the failing sequence: ",,!-!" = "llama".

new topic     » goto parent     » topic index » view message » categorize

13. Re: Euphoria sucks at golfing

jaygade said...

Are there any more gains to be had?

if find(0,X) then X={} end if 
?X 

could be replaced with

?X[1..$*not find(0,X)] 
new topic     » goto parent     » topic index » view message » categorize

14. Re: Euphoria sucks at golfing

Oooh.

Thanks, Pete! That works great. 117 characters. I never think of using $ as an actual number.

new topic     » goto parent     » topic index » view message » categorize

15. Re: Euphoria sucks at golfing

This works in Phix (105 characters)

object t=lower(gets(0)),L="llama",i=0for j=1to 5do i=find(L[j],t,i+1)L[j]=i end for?L[1..-not find(0,L)] 

Notes: lower() is an autoinclude, I overwrite L with the result as we go, and finally use negative indexes.

Pete

new topic     » goto parent     » topic index » view message » categorize

16. Re: Euphoria sucks at golfing

petelomax said...

This works in Phix (105 characters)

object t=lower(gets(0)),L="llama",i=0for j=1to 5do i=find(L[j],t,i+1)L[j]=i end for?L[1..-not find(0,L)] 

Notes: lower() is an autoinclude, I overwrite L with the result as we go, and finally use negative indexes.

Pete

I don't have Phix or OpenEuphoria installed anywhere these days, but the "i" object isn't needed just put the initial start index value in L[1]. Try the code below to verify it works. (103 characters)

object t=lower(gets(0)),L=1&"llama"for j=2to 6do L[j]=find(L[j],t,L[j-1]) end for?L[2..-not find(0,L)] 
new topic     » goto parent     » topic index » view message » categorize

17. Re: Euphoria sucks at golfing

mindwalker said...

I don't have Phix or OpenEuphoria installed anywhere these days, but the "i" object isn't needed just put the initial start index value in L[1]. Try the code below to verify it works. (103 characters)

object t=lower(gets(0)),L=1&"llama"for j=2to 6do L[j]=find(L[j],t,L[j-1]) end for?L[2..-not find(0,L)] 

The first two 'L's will have the same position, since the find starts at the same position as the last letter found. Also when a letter is not found, the slice length will be negative L[2..0] resulting in an error.

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu