Look-and-say sequence

From Rosetta Code
Jump to: navigation, search
Task
Look-and-say sequence
You are encouraged to solve this task according to the task description, using any language you may know.

Sequence Definition

  • Take a decimal number
  • Look at the number, visually grouping consecutive runs of the same digit.
  • Say the number, from left to right, group by group; as how many of that digit there are - followed by the digit grouped.
This becomes the next number of the sequence.

The sequence is from John Conway, of Conway's Game of Life fame.

An example:

  • Starting with the number 1, you have one 1 which produces 11.
  • Starting with 11, you have two 1's i.e. 21
  • Starting with 21, you have one 2, then one 1 i.e. (12)(11) which becomes 1211
  • Starting with 1211 you have one 1, one 2, then two 1's i.e. (11)(12)(21) which becomes 111221

Task description

Write a program to generate successive members of the look-and-say sequence.

See also

  • This task is related to, and an application of, the Run-length encoding task.
  • Sequence A005150 on The On-Line Encyclopedia of Integer Sequences.

Contents

[edit] Ada

with Ada.Text_IO, Ada.Strings.Fixed;
use Ada.Text_IO, Ada.Strings, Ada.Strings.Fixed;
 
function "+" (S : String) return String is
Item : constant Character := S (S'First);
begin
for Index in S'First + 1..S'Last loop
if Item /= S (Index) then
return Trim (Integer'Image (Index - S'First), Both) & Item & (+(S (Index..S'Last)));
end if;
end loop;
return Trim (Integer'Image (S'Length), Both) & Item;
end "+";

This function can be used as follows:

Put_Line (+"1");
Put_Line (+(+"1"));
Put_Line (+(+(+"1")));
Put_Line (+(+(+(+"1"))));
Put_Line (+(+(+(+(+"1")))));
Put_Line (+(+(+(+(+(+"1"))))));
Put_Line (+(+(+(+(+(+(+"1")))))));
Put_Line (+(+(+(+(+(+(+(+"1"))))))));
Put_Line (+(+(+(+(+(+(+(+(+"1")))))))));
Put_Line (+(+(+(+(+(+(+(+(+(+"1"))))))))));

Sample output:

11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221

[edit] ALGOL 68

Translation of: Ada
Works with: ALGOL 68 version Standard - no extensions to language used
Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9.i386
Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386
OP + = (STRING s)STRING:
BEGIN
CHAR item = s[LWB s];
STRING out;
FOR index FROM LWB s + 1 TO UPB s DO
IF item /= s [index] THEN
out := whole(index - LWB s, 0) + item + (+(s [index:UPB s]));
GO TO return out
FI
OD;
out := whole (UPB s, 0) + item;
return out: out
END # + #;
 
OP + = (CHAR s)STRING:
+ STRING(s);
 
print ((+"1", new line));
print ((+(+"1"), new line));
print ((+(+(+"1")), new line));
print ((+(+(+(+"1"))), new line));
print ((+(+(+(+(+"1")))), new line));
print ((+(+(+(+(+(+"1"))))), new line));
print ((+(+(+(+(+(+(+"1")))))), new line));
print ((+(+(+(+(+(+(+(+"1"))))))), new line));
print ((+(+(+(+(+(+(+(+(+"1")))))))), new line));
print ((+(+(+(+(+(+(+(+(+(+"1"))))))))), new line))

Output:

11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221

[edit] AutoHotkey

AutoExecute:
Gui, -MinimizeBox
Gui, Add, Edit, w500 r20 vInput, 1
Gui, Add, Button, x155 w100 Default, &Calculate
Gui, Add, Button, xp+110 yp wp, E&xit
Gui, Show,, Look-and-Say sequence
Return
 
 
ButtonCalculate:
Gui, Submit, NoHide
GuiControl,, Input, % LookAndSay(Input)
Return
 
 
GuiClose:
ButtonExit:
ExitApp
Return
 
 
;---------------------------------------------------------------------------
LookAndSay(Input) {
;---------------------------------------------------------------------------
; credit for this function goes to AutoHotkey forum member Laslo
; http://www.autohotkey.com/forum/topic44657-161.html
;-----------------------------------------------------------------------
Loop, Parse, Input ; look at every digit
If (A_LoopField = d) ; I've got another one! (of the same value)
c += 1 ; Let's count them ...
Else { ; No, this one is different!
r .= c d ; remember what we've got so far
c := 1 ; It is the first one in a row
d := A_LoopField ; Which one is it?
}
Return, r c d
}

[edit] APL

 
⎕IO←0
d←{(1↓⍵)-¯1↓⍵}
f←{m←(0≠d ⍵),1 ⋄ ,(d ¯1,m/⍳⍴⍵),[.5](m/⍵)}
{(f⍣⍵) ,1}¨⍳10
 

[edit] AWK

function lookandsay(a)
{
s = ""
c = 1
p = substr(a, 1, 1)
for(i=2; i <= length(a); i++) {
if ( p == substr(a, i, 1) ) {
c++
} else {
s = s sprintf("%d%s", c, p)
p = substr(a, i, 1)
c = 1
}
}
s = s sprintf("%d%s", c, p)
return s
}
 
BEGIN {
b = "1"
print b
for(k=1; k <= 10; k++) {
b = lookandsay(b)
print b
}
}

[edit] BBC BASIC

      number$ = "1"
FOR i% = 1 TO 10
number$ = FNlooksay(number$)
PRINT number$
NEXT
END
 
DEF FNlooksay(n$)
LOCAL i%, j%, c$, o$
i% = 1
REPEAT
c$ = MID$(n$,i%,1)
j% = i% + 1
WHILE MID$(n$,j%,1) = c$
j% += 1
ENDWHILE
o$ += STR$(j%-i%) + c$
i% = j%
UNTIL i% > LEN(n$)
= o$

Output:

11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221

[edit] C

This program will not stop until killed or running out of memory.

#include <stdio.h>
#include <stdlib.h>
 
int main()
{
char *a = malloc(2), *b = 0, *x, c;
int cnt, len = 1;
 
for (sprintf(a, "1"); (b = realloc(b, len * 2 + 1)); a = b, b = x) {
puts(x = a);
for (len = 0, cnt = 1; (c = *a); ) {
if (c == *++a)
cnt++;
else if (c) {
len += sprintf(b + len, "%d%c", cnt, c);
cnt = 1;
}
}
}
 
return 0;
}

[edit] C++

#include <string>
#include <sstream>
 
std::string lookandsay(const std::string &s)
{
std::ostringstream r;
 
for (unsigned int i = 0; i != s.length(); ) {
unsigned int new_i = s.find_first_not_of(s[i], i+1);
if (new_i == std::string::npos)
new_i = s.length();
 
r << new_i - i << s[i];
i = new_i;
}
return r.str();
}
 
#include <iostream>
 
int main()
{
std::string laf = "1";
 
std::cout << laf << std::endl;
for (int i = 0; i < 10; i++) {
laf = lookandsay(laf);
std::cout << laf << std::endl;
}
 
return 0;
}

[edit] C#

using System;
using System.Text;
using System.Linq;
 
class Program
{
static string lookandsay(string number)
{
StringBuilder result = new StringBuilder();
 
char repeat = number[0];
number = number.Substring(1, number.Length-1)+" ";
int times = 1;
 
foreach (char actual in number)
{
if (actual != repeat)
{
result.Append(Convert.ToString(times)+repeat);
times = 1;
repeat = actual;
}
else
{
times += 1;
}
}
return result.ToString();
}
 
static void Main(string[] args)
{
string num = "1";
 
foreach (int i in Enumerable.Range(1, 10)) {
Console.WriteLine(num);
num = lookandsay(num);
}
}
}

Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

Alternate version using Regex (C#2 syntax only):

 
using System;
using System.Text.RegularExpressions;
 
namespace RosettaCode_Cs_LookAndSay
{
public class Program
{
public static int Main(string[] args)
{
Array.Resize<string>(ref args, 2);
string ls = args[0] ?? "1";
int n;
if (!int.TryParse(args[1], out n)) n = 10;
do {
Console.WriteLine(ls);
if (--n <= 0) break;
ls = say(look(ls));
} while(true);
 
return 0;
}
 
public static string[] look(string input)
{
int i = -1;
return Array.FindAll(Regex.Split(input, @"((\d)\2*)"),
delegate(string p) { ++i; i %= 3; return i == 1; }
);
}
 
public static string say(string[] groups)
{
return string.Concat(
Array.ConvertAll<string, string>(groups,
delegate(string p) { return string.Concat(p.Length, p[0]); }
)
);
}
}
}

Output (with args: 1 15):

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221
3113112221232112111312211312113211
1321132132111213122112311311222113111221131221
11131221131211131231121113112221121321132132211331222113112211
311311222113111231131112132112311321322112111312211312111322212311322113212221

[edit] Clojure

No ugly int-to-string-and-back conversions.

(defn digits-seq
"Returns a seq of the digits of a number (L->R)."
[n]
(loop [digits (), number n]
(if (zero? number) (seq digits)
(recur (cons (mod number 10) digits)
(quot number 10)))))
 
(defn join-digits
"Converts a digits-seq back in to a number."
[ds]
(reduce (fn [n d] (+ (* 10 n) d)) ds))
 
(defn look-and-say [n]
(->> n digits-seq (partition-by identity)
(mapcat (juxt count first)) join-digits))

Example output:

user> (take 8 (iterate look-and-say 1))
(1 11 21 1211 111221 312211 13112221 1113213211)

[edit] Common Lisp

(defun compress (array &key (test 'eql) &aux (l (length array)))
"Compresses array by returning a list of conses each of whose car is
a number of occurrences and whose cdr is the element occurring. For
instance, (compress \"abb\") produces ((1 . #\a) (2 . #\b))."

(if (zerop l) nil
(do* ((i 1 (1+ i))
(segments (acons 1 (aref array 0) '())))
((eql i l) (nreverse segments))
(if (funcall test (aref array i) (cdar segments))
(incf (caar segments))
(setf segments (acons 1 (aref array i) segments))))))
 
(defun next-look-and-say (number)
(reduce #'(lambda (n pair)
(+ (* 100 n)
(* 10 (car pair))
(parse-integer (string (cdr pair)))))
(compress (princ-to-string number))
:initial-value 0))

Example use:

(next-look-and-say 9887776666) ;=> 19283746

Straight character counting:

(defun look-and-say (s)
(let ((out (list (char s 0) 0)))
(loop for x across s do
(if (char= x (first out))
(incf (second out))
(setf out (list* x 1 out))))
(format nil "~{~a~^~}" (nreverse out))))
 
(loop for s = "1" then (look-and-say s)
repeat 10
do (write-line s))

[edit] D

[edit] Short Functional Version

import std.stdio, std.algorithm, std.range;
 
enum say = (in string s) pure => s.group.map!q{ text(a[1],a[0]) }.join;
 
void main() {
"1".recurrence!((t, n) => t[n - 1].say).take(8).writeln;
}
Output:
["1", "11", "21", "1211", "111221", "312211", "13112221", "1113213211"]

[edit] Fast Imperative Version

Same output.

import core.stdc.stdio, std.math, std.conv, std.algorithm, std.array;
 
void showLookAndSay(bool showArrays)(in uint n) nothrow {
if (n == 0) // No sequences to generate and show.
return;
 
enum Digit : char { nil = '\0', one = '1', two = '2', thr = '3' }
 
// Allocate an approximate upper bound size for the array.
static Digit* allocBuffer(in uint m) nothrow {
immutable len = cast(size_t)(100 + 1.05 *
exp(0.269 * m + 0.2686)) + 1;
auto a = len.uninitializedArray!(Digit[]);
printf("Allocated %d bytes.\n", a.length * Digit.sizeof);
return a.ptr;
}
 
// Can't be expressed in the D type system:
// a1 and a2 are immutable pointers to mutable data.
auto a1 = allocBuffer(n % 2 ? n : n - 1);
auto a2 = allocBuffer(n % 2 ? n - 1 : n);
printf("\n");
 
a1[0] = Digit.one;
size_t len1 = 1;
a1[len1] = Digit.nil;
 
foreach (immutable i; 0 .. n - 1) {
static if (showArrays)
printf("%2u: %s\n", i + 1, a1);
else
printf("%2u: n. digits: %u\n", i + 1, len1);
auto p1 = a1,
p2 = a2;
 
S0: final switch (*p1++) with (Digit) { // Initial state.
case nil: goto END;
case one: goto S1;
case two: goto S2;
case thr: goto S3;
}
S1: final switch (*p1++) with (Digit) {
case nil: *p2++ = one; *p2++ = one; goto END;
case one: goto S11;
case two: *p2++ = one; *p2++ = one; goto S2;
case thr: *p2++ = one; *p2++ = one; goto S3;
}
S2: final switch (*p1++) with (Digit) {
case nil: *p2++ = one; *p2++ = two; goto END;
case one: *p2++ = one; *p2++ = two; goto S1;
case two: goto S22;
case thr: *p2++ = one; *p2++ = two; goto S3;
}
S3: final switch (*p1++) with (Digit) {
case nil: *p2++ = one; *p2++ = thr; goto END;
case one: *p2++ = one; *p2++ = thr; goto S1;
case two: *p2++ = one; *p2++ = thr; goto S2;
case thr: goto S33;
}
S11: final switch (*p1++) with (Digit) {
case nil: *p2++ = two; *p2++ = one; goto END;
case one: *p2++ = thr; *p2++ = one; goto S0;
case two: *p2++ = two; *p2++ = one; goto S2;
case thr: *p2++ = two; *p2++ = one; goto S3;
}
S22: final switch (*p1++) with (Digit) {
case nil: *p2++ = two; *p2++ = two; goto END;
case one: *p2++ = two; *p2++ = two; goto S1;
case two: *p2++ = thr; *p2++ = two; goto S0;
case thr: *p2++ = two; *p2++ = two; goto S3;
}
S33: final switch (*p1++) with (Digit) {
case nil: *p2++ = two; *p2++ = thr; goto END;
case one: *p2++ = two; *p2++ = thr; goto S1;
case two: *p2++ = two; *p2++ = thr; goto S2;
case thr: *p2++ = thr; *p2++ = thr; goto S0;
}
END:
immutable len2 = p2 - a2;
a2[len2] = Digit.nil;
a1.swap(a2);
len1 = len2;
}
 
static if (showArrays)
printf("%2u: %s\n", n, a1);
else
printf("%2u: n. digits: %u\n", n, len1);
}
 
void main(in string[] args) {
immutable n = (args.length == 2) ? args[1].to!uint : 10;
n.showLookAndSay!true;
}
Output:
Allocated 116 bytes.
Allocated 121 bytes.

 1: 1
 2: 11
 3: 21
 4: 1211
 5: 111221
 6: 312211
 7: 13112221
 8: 1113213211
 9: 31131211131221
10: 13211311123113112211

With:

70.showLookAndSay!false;
Output:
Allocated 158045069 bytes.
Allocated 206826462 bytes.

 1: n. digits: 1
 2: n. digits: 2
 3: n. digits: 2
 4: n. digits: 4
 5: n. digits: 6
...
60: n. digits: 12680852
61: n. digits: 16530884
62: n. digits: 21549544
63: n. digits: 28091184
64: n. digits: 36619162
65: n. digits: 47736936
66: n. digits: 62226614
67: n. digits: 81117366
68: n. digits: 105745224
69: n. digits: 137842560
70: n. digits: 179691598

Using the LDC2 compiler with n=70 the run-time is about 3.74 seconds.

[edit] Intermediate Version

This mostly imperative version is intermediate in both speed and code size:

void main(in string[] args) {
import std.stdio, std.conv, std.algorithm, std.array, std.string;
 
immutable n = (args.length == 2) ? args[1].to!uint : 10;
if (n == 0)
return;
 
auto seq = ['1'];
writefln("%2d: n. digits: %d", 1, seq.length);
foreach (immutable i; 2 .. n + 1) {
Appender!(typeof(seq)) result;
foreach (const digit, const count; seq.representation.group) {
result ~= "123"[count - 1];
result ~= digit;
}
seq = result.data;
writefln("%2d: n. digits: %d", i, seq.length);
}
}

The output is the same as the second version.

If you modify the first program to print only the lengths of the strings (with a .map!(s => s.length)), compiling with LDC2 the run-times of the three versions with n=55 are about 31.1, 0.10 and 0.23 seconds.

[edit] E

def lookAndSayNext(number :int) {
var seen := null
var count := 0
var result := ""
def put() {
if (seen != null) {
result += count.toString(10) + E.toString(seen)
}
}
for ch in number.toString(10) {
if (ch != seen) {
put()
seen := ch
count := 0
}
count += 1
}
put()
return __makeInt(result, 10)
}
 
var number := 1
for _ in 1..20 {
println(number)
number := lookAndSayNext(number)
}

[edit] Elixir

defmodule LookAndSay do
def next(n) do
Enum.chunks_by(to_char_list(n), &(&1))
|> Enum.map(fn cl=[h|_] ->
Enum.concat(to_char_list(length cl), [h]) end)
|> Enum.concat
|> list_to_integer
end
 
def sequence_from(n) do
Stream.iterate n, &(LookAndSay.next/1)
end
 
def main([start_str|_]) do
{start_val,_} = Integer.parse(start_str)
 :io.format("~w~n", [LookAndSay.sequence_from(start_val) |> Enum.take 9] )
exit 0
end
 
def main([]) do
main(["1"])
end
end
 
LookAndSay.main(System.argv)
Output:
[1,11,21,1211,111221,312211,13112221,1113213211,31131211131221]


[edit] Erlang

-module(str).
-export([look_and_say/1, look_and_say/2]).
 
%% converts a single number
look_and_say([H|T]) -> lists:reverse(look_and_say(T,H,1,"")).
 
%% converts and accumulates as a loop
look_and_say(_, 0) -> [];
look_and_say(Start, Times) when Times > 0 ->
[Start | look_and_say(look_and_say(Start), Times-1)].
 
%% does the actual conversion for a number
look_and_say([], Current, N, Acc) ->
[Current, $0+N | Acc];
look_and_say([H|T], H, N, Acc) ->
look_and_say(T, H, N+1, Acc);
look_and_say([H|T], Current, N, Acc) ->
look_and_say(T, H, 1, [Current, $0+N | Acc]).

output:

1> c(str).
{ok,str}
2> str:look_and_say("1").
"11"
3> str:look_and_say("111221").
"312211"
4> str:look_and_say("1",10).
["1","11","21","1211","111221","312211","13112221",
 "1113213211","31131211131221","13211311123113112211"]

[edit] Factor

: (look-and-say) ( str -- )
unclip-slice swap [ 1 ] 2dip [
2dup = [ drop [ 1 + ] dip ] [
[ [ number>string % ] dip , 1 ] dip
] if
] each [ number>string % ] [ , ] bi* ;
 
: look-and-say ( str -- str' ) [ (look-and-say) ] "" make ;
 
"1" 10 [ dup print look-and-say ] times print

[edit] Forth

create buf1 256 allot
create buf2 256 allot
buf1 value src
buf2 value dest
 
s" 1" src place
 
: append-run ( digit run -- )
dest count +
tuck c! 1+ c!
dest c@ 2 + dest c! ;
 
: next-look-and-say
0 dest c!
src 1+ c@ [char] 0 ( digit run )
src count bounds do
over i c@ =
if 1+
else append-run i c@ [char] 1
then
loop
append-run
src dest to src to dest ;
 
: look-and-say ( n -- )
0 do next-look-and-say cr src count type loop ;
 
10 look-and-say

[edit] Fortran

module LookAndSay
implicit none
 
contains
 
subroutine look_and_say(in, out)
character(len=*), intent(in) :: in
character(len=*), intent(out) :: out
 
integer :: i, c
character(len=1) :: x
character(len=2) :: d
 
out = ""
c = 1
x = in(1:1)
do i = 2, len(trim(in))
if ( x == in(i:i) ) then
c = c + 1
else
write(d, "(I2)") c
out = trim(out) // trim(adjustl(d)) // trim(x)
c = 1
x = in(i:i)
end if
end do
write(d, "(I2)") c
out = trim(out) // trim(adjustl(d)) // trim(x)
end subroutine look_and_say
 
end module LookAndSay
program LookAndSayTest
use LookAndSay
implicit none
 
integer :: i
character(len=200) :: t, r
t = "1"
print *,trim(t)
call look_and_say(t, r)
print *, trim(r)
do i = 1, 10
call look_and_say(r, t)
r = t
print *, trim(r)
end do
 
end program LookAndSayTest

[edit] GAP

LookAndSay := function(s)
local c, r, cur, ncur, v;
v := "123";
r := "";
cur := 0;
ncur := 0;
for c in s do
if c = cur then
ncur := ncur + 1;
else
if ncur > 0 then
Add(r, v[ncur]);
Add(r, cur);
fi;
cur := c;
ncur := 1;
fi;
od;
Add(r, v[ncur]);
Add(r, cur);
return r;
end;
 
LookAndSay("1"); # "11"
LookAndSay(last); # "21"
LookAndSay(last); # "1211"
LookAndSay(last); # "111221"
LookAndSay(last); # "312211"
LookAndSay(last); # "13112221"
LookAndSay(last); # "1113213211"
LookAndSay(last); # "31131211131221"
LookAndSay(last); # "13211311123113112211"
LookAndSay(last); # "11131221133112132113212221"
LookAndSay(last); # "3113112221232112111312211312113211"
LookAndSay(last); # "1321132132111213122112311311222113111221131221"
LookAndSay(last); # "11131221131211131231121113112221121321132132211331222113112211"
LookAndSay(last); # "311311222113111231131112132112311321322112111312211312111322212311322113212221"

[edit] Go

package main
 
import (
"fmt"
"strconv"
)
 
func lss(s string) (r string) {
c := s[0]
nc := 1
for i := 1; i < len(s); i++ {
d := s[i]
if d == c {
nc++
continue
}
r += strconv.Itoa(nc) + string(c)
c = d
nc = 1
}
return r + strconv.Itoa(nc) + string(c)
}
 
func main() {
s := "1"
fmt.Println(s)
for i := 0; i < 8; i++ {
s = lss(s)
fmt.Println(s)
}
}

Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221

[edit] Groovy

def lookAndSay(sequence) {
def encoded = new StringBuilder()
(sequence.toString() =~ /(([0-9])\2*)/).each { matcher ->
encoded.append(matcher[1].size()).append(matcher[2])
}
encoded.toString()
}

Test Code

def sequence = "1"
(1..12).each {
println sequence
sequence = lookAndSay(sequence)
}

Output

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221
3113112221232112111312211312113211

[edit] Haskell

import Control.Monad (liftM2)
import Data.List (group)
 
-- this function is composed out of many functions; data flows from the bottom up
lookAndSay :: Integer -> Integer
lookAndSay = read -- convert digits to integer
. concatMap -- concatenate for each run,
(liftM2 (++) (show . length) -- the length of it
(take 1)) -- and an example member
. group -- collect runs of the same digit
. show -- convert integer to digits
 
-- less comments
lookAndSay2 :: Integer -> Integer
lookAndSay2 = read . concatMap (liftM2 (++) (show . length)
(take 1))
. group . show
 
 
-- same thing with more variable names
lookAndSay3 :: Integer -> Integer
lookAndSay3 n = read (concatMap describe (group (show n)))
where describe run = show (length run) ++ take 1 run
 
main = mapM_ print (iterate lookAndSay 1) -- display sequence until interrupted

[edit] Haxe

using Std;
 
class Main
{
 
static function main()
{
var test = "1";
for (i in 0...11) {
Sys.println(test);
test = lookAndSay(test);
}
}
 
static function lookAndSay(s:String)
{
if (s == null || s == "") return "";
 
var results = "";
var repeat = s.charAt(0);
var amount = 1;
for (i in 1...s.length)
{
var actual = s.charAt(i);
if (actual != repeat)
{
results += amount.string();
results += repeat;
repeat = actual;
amount = 0;
}
amount++;
}
results += amount.string();
results += repeat;
 
return results;
}
}

[edit] Icon and Unicon

procedure main()
every 1 to 10 do
write(n := nextlooknsayseq(\n | 1))
end
 
procedure nextlooknsayseq(n) #: return next element in look and say sequence
n2 := ""
n ? until pos(0) do {
i := tab(any(&digits)) | fail # or fail if not digits
move(-1)
n2 ||:= *tab(many(i)) || i # accumulate count+digit
}
return n2
end
Output:
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221

[edit] J

Solution:

las=: ,@((# , {.);.1~ 1 , 2 ~:/\ ])&.(10x&#.inv)@]^:(1+i.@[)

Example:

   10 las 1
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221

Note the result is an actual numeric sequence (cf. the textual solutions given in other languages).

[edit] Java

Translation of: C#
Works with: Java version 1.5+
public static String lookandsay(String number){
StringBuilder result= new StringBuilder();
 
char repeat= number.charAt(0);
number= number.substring(1) + " ";
int times= 1;
 
for(char actual: number.toCharArray()){
if(actual != repeat){
result.append(times + "" + repeat);
times= 1;
repeat= actual;
}else{
times+= 1;
}
}
return result.toString();
}

Testing:

public static void main(String[] args){
String num = "1";
 
for (int i=1;i<=10;i++) {
System.out.println(num);
num = lookandsay(num);
}
}

Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

[edit] JavaScript

Translation of: Perl
function lookandsay(str) {
return str.replace(/(.)\1*/g, function(seq, p1){return seq.length.toString() + p1})
}
 
var num = "1";
for (var i = 10; i > 0; i--) {
alert(num);
num = lookandsay(num);
}

[edit] K

  las: {x{0$,//$(#:'n),'*:'n:(&1,~=':x)_ x:0$'$x}\1}
las 8
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221


[edit] Lasso

The Look-and-say sequence is a recursive RLE, so the solution can leverage the same method as used for RLE.

define rle(str::string)::string => {
local(orig = #str->values->asCopy,newi=array, newc=array, compiled=string)
while(#orig->size) => {
if(not #newi->size) => {
#newi->insert(1)
#newc->insert(#orig->first)
#orig->remove(1)
else
if(#orig->first == #newc->last) => {
#newi->get(#newi->size) += 1
else
#newi->insert(1)
#newc->insert(#orig->first)
}
#orig->remove(1)
}
}
loop(#newi->size) => {
#compiled->append(#newi->get(loop_count)+#newc->get(loop_count))
}
return #compiled
}
define las(n::integer,run::integer) => {
local(str = #n->asString)
loop(#run) => { #str = rle(#str) }
return #str
}
loop(15) => {^ las(1,loop_count) + '\r' ^}
Output:
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221
3113112221232112111312211312113211
1321132132111213122112311311222113111221131221
11131221131211131231121113112221121321132132211331222113112211
311311222113111231131112132112311321322112111312211312111322212311322113212221
132113213221133112132113311211131221121321131211132221123113112221131112311332111213211322211312113211

[edit]

to look.and.say.loop :in :run :c :out
if empty? :in [output (word :out :run :c)]
if equal? first :in :c [output look.and.say.loop bf :in :run+1 :c :out]
output look.and.say.loop bf :in 1 first :in (word :out :run :c)
end
to look.and.say :in
if empty? :in [output :in]
output look.and.say.loop bf :in 1 first :in "||
end
 
show cascade 10 [print ? look.and.say ?] 1

[edit] Lua

--returns an iterator over the first n copies of the look-and-say sequence
function lookandsayseq(n)
local t = {1}
return function()
local ret = {}
for i, v in ipairs(t) do
if t[i-1] and v == t[i-1] then
ret[#ret - 1] = ret[#ret - 1] + 1
else
ret[#ret + 1] = 1
ret[#ret + 1] = v
end
end
t = ret
n = n - 1
if n > 0 then return table.concat(ret) end
end
end
for i in lookandsayseq(10) do print(i) end

Alternative solution, using LPeg:

require "lpeg"
local P, C, Cf, Cc = lpeg.P, lpeg.C, lpeg.Cf, lpeg.Cc
lookandsay = Cf(Cc"" * C(P"1"^1 + P"2"^1 + P"3"^1)^1, function (a, b) return a .. #b .. string.sub(b,1,1) end)
t = "1"
for i = 1, 10 do
print(t)
t = lookandsay:match(t)
end

[edit] M4

Using regular expressions:

Translation of: Perl
divert(-1)
define(`for',
`ifelse($#,0,``$0'',
`ifelse(eval($2<=$3),1,
`pushdef(`$1',$2)$4`'popdef(`$1')$0(`$1',incr($2),$3,`$4')')')')
 
define(`las',
`patsubst(`$1',`\(\(.\)\2*\)',`len(\1)`'\2')')
 
 
define(`v',1)
divert
for(`x',1,10,
`v
define(`v',las(v))')dnl
v

[edit] Mathematica

Custom Functions:

RunLengthEncode[x_List]:=(Through[{First,Length}[#]]&)/@Split[x]
LookAndSay[n_,d_:1]:=NestList[Flatten[Reverse/@RunLengthEncode[#]]&,{d},n-1]

If second argument is omitted the sequence is started with 1. Second argument is supposed to be a digits from 0 to 9. If however a larger number is supplied it will be seen as 1 number, not multiple digits. However if one wants to start with a 2 or more digit number, one could reverse the sequence to go back to a single digit start. First example will create the first 13 numbers of the sequence starting with 1, the next example starts with 7:

FromDigits /@ LookAndSay[13] // Column
FromDigits /@ LookAndSay[13, 7] // Column

gives back:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221
3113112221232112111312211312113211
1321132132111213122112311311222113111221131221

7
17
1117
3117
132117
1113122117
311311222117
13211321322117
1113122113121113222117
31131122211311123113322117
132113213221133112132123222117
11131221131211132221232112111312111213322117
31131122211311123113321112131221123113111231121123222117 

[edit] Maxima

collect(a) := block(
[n: length(a), b: [ ], x: a[1], m: 1],
for i from 2 thru n do
(if a[i] = x then m: m + 1 else (b: endcons([x, m], b), x: a[i], m: 1)),
b: endcons([x, m], b)
)$
 
look_and_say(s) := apply(sconcat, map(lambda([p], sconcat(string(p[2]), p[1])), collect(charlist(s))))$
 
block([s: "1"], for i from 1 thru 10 do (disp(s), s: look_and_say(s)));
/* "1"
"11"
"21"
"1211"
"111221"
"312211"
"13112221"
"1113213211"
"31131211131221"
"13211311123113112211" */

[edit] MAXScript

fn lookAndSay num =
(
local result = ""
num += " "
local current = num[1]
local numReps = 1
 
for digit in 2 to num.count do
(
if num[digit] != current then
(
result += (numReps as string) + current
numReps = 1
current = num[digit]
)
else
(
numReps += 1
)
)
result
)
 
local num = "1"
 
for i in 1 to 10 do
(
print num
num = lookAndSay num
)

[edit] Metafont

vardef lookandsay(expr s) =
string r; r := "";
if string s:
i := 0;
forever: exitif not (i < length(s));
c := i+1;
forever: exitif ( (substring(c,c+1) of s) <> (substring(i,i+1) of s) );
c := c + 1;
endfor
r := r & decimal (c-i) & substring(i,i+1) of s;
i := c;
endfor
fi
r
enddef;
 
string p; p := "1";
for el := 1 upto 10:
message p;
p := lookandsay(p);
endfor
 
end

[edit] Nimrod

proc NextInLookAndSaySequence (current: string): string =
assert(len(current) > 0)
Result = ""
var ch = current[0]
var count = 1
for i in countup(1, len(current)-1):
if current[i] != ch:
Result &= $count & ch
ch = current[i]
count = 1
else:
count += 1
Result &= $count & ch
 
proc LookAndSay (n = 10) =
var next = "1"
for i in countup(1, n):
next = NextInLookAndSaySequence(next)
echo next
 
LookAndSay()
 

[edit] Objective-C

#import <Foundation/Foundation.h>
 
-(NSString*)lookAndSay:(NSString *)word{
if (!word) {
return nil;
}
NSMutableString *result = [NSMutableString new];
 
char repeat = [word characterAtIndex:0];
int times = 1;
word = [NSString stringWithFormat:@"%@ ",[word substringFromIndex:1] ];
 
for (NSInteger index = 0; index < word.length; index++) {
char actual = [word characterAtIndex:index];
if (actual != repeat) {
[result appendFormat:@"%d%c", times, repeat];
times = 1;
repeat = actual;
} else {
times ++;
}
}
 
return [result copy];
}
 
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSString *num = @"1";
for (int i=1;i<=10;i++) {
NSLog(@"%@", num);
 
num = [self lookAndSay:num];
}
}
 

[edit] OCaml

[edit] Functional

let aux s =
let len = String.length s in
let rec aux c i n acc =
if i >= len
then List.rev((n,c)::acc)
else
if c = s.[i]
then aux c (succ i) (succ n) acc
else aux s.[i] (succ i) 1 ((n,c)::acc)
in
aux s.[0] 1 1 []
 
let lookandsay num =
let l = aux num in
let s =
List.map (fun (n,c) ->
(string_of_int n) ^ (String.make 1 c)) l
in
String.concat "" s
 
let fold_loop f ini n =
let rec aux i acc =
if i >= n
then (acc)
else aux (succ i) (f acc i)
in
aux 0 ini
 
let _ =
fold_loop
(fun num _ ->
let next = lookandsay num in
print_endline next;
(next))
(string_of_int 1) 10

[edit] With regular expressions in the Str library

#load "str.cma";;
 
let lookandsay =
Str.global_substitute (Str.regexp "\\(.\\)\\1*")
(fun s -> string_of_int (String.length (Str.matched_string s)) ^
Str.matched_group 1 s)
 
let () =
let num = ref "1" in
print_endline !num;
for i = 1 to 10 do
num := lookandsay !num;
print_endline !num;
done

[edit] With regular expressions in the Pcre library

open Pcre
 
let lookandsay str =
let rex = regexp "(.)\\1*" in
let subs = exec_all ~rex str in
let ar = Array.map (fun sub -> get_substring sub 0) subs in
let ar = Array.map (fun s -> String.length s, s.[0]) ar in
let ar = Array.map (fun (n,c) -> (string_of_int n) ^ (String.make 1 c)) ar in
let res = String.concat "" (Array.to_list ar) in
(res)
 
let () =
let num = ref(string_of_int 1) in
for i = 1 to 10 do
num := lookandsay !num;
print_endline !num;
done

run this example with 'ocaml -I +pcre pcre.cma script.ml'

[edit] Imperative

(* see http://oeis.org/A005150 *)
 
let look_and_say s =
let n = String.length s
and buf = Buffer.create 0
and prev = ref s.[0]
and count = ref 0 in
let append () = Buffer.add_char buf (char_of_int (48 + !count));
Buffer.add_char buf !prev in
String.iter (fun c ->
if c = !prev then incr count else
begin
append ();
prev := c;
count := 1
end
) s;
append ();
Buffer.contents buf;;
 
(* what about length of successive strings ? *)
let iter f a n =
let rec aux r n v = if n = 0
then List.rev(r::v)
else aux (f r) (n - 1) (r::v) in
aux a n [];;
 
let las = iter look_and_say "1";;
 
(* the first sixty terms *)
 
List.map (String.length) (las 59);;
(*
[1; 2; 2; 4; 6; 6; 8; 10; 14; 20; 26; 34; 46; 62; 78; 102; 134; 176; 226;
302; 408; 528; 678; 904; 1182; 1540; 2012; 2606; 3410; 4462; 5808; 7586;
9898; 12884; 16774; 21890; 28528; 37158; 48410; 63138; 82350; 107312;
139984; 182376; 237746; 310036; 403966; 526646; 686646; 894810; 1166642;
1520986; 1982710; 2584304; 3369156; 4391702; 5724486; 7462860; 9727930;
12680852]
*)

 
(* see http://oeis.org/A005341 *)


[edit] Oz

declare
%% e.g. "21" -> "1211"
fun {LookAndSayString S}
for DigitGroup in {Group S} append:Add do
{Add {Int.toString {Length DigitGroup}}}
{Add [DigitGroup.1]}
end
end
 
%% lazy sequence of integers starting with N
fun {LookAndSay N}
fun lazy {Loop S}
{String.toInt S}|{Loop {LookAndSayString S}}
end
in
{Loop {Int.toString N}}
end
 
%% like Haskell's "group"
fun {Group Xs}
case Xs of nil then nil
[] X|Xr then
Ys Zs
{List.takeDropWhile Xr fun {$ W} W==X end ?Ys ?Zs}
in
(X|Ys) | {Group Zs}
end
end
in
{ForAll {List.take {LookAndSay 1} 10} Show}

[edit] PARI/GP

step(n)={
my(v=eval(Vec(Str(n))),cur=v[1],ct=1,out="");
v=concat(v,99);
for(i=2,#v,
if(v[i]==cur,
ct++
,
out=Str(out,ct,cur);
cur=v[i];
ct=1
)
);
eval(out)
};
n=1;for(i=1,20,print(n);n=step(n))

[edit] Pascal

Works with: Free_Pascal
Library: SysUtils
program LookAndSayDemo(input, output);
 
uses
SysUtils;
 
function LookAndSay (s: string): string;
var
item: char;
index: integer;
count: integer;
begin
LookAndSay := '';
item := s[1];
count := 1;
for index:= 2 to length(s) do
if item = s[index] then
inc(count)
else
begin
LookAndSay := LookAndSay + intTostr(count) + item;
item := s[index];
count := 1;
end;
LookAndSay := LookAndSay + intTostr(count) + item;
end;
 
var
number: string;
 
begin
writeln('Press RETURN to continue and ^C to stop.');
number := '1';
while not eof(input) do
begin
write(number);
readln;
number := LookAndSay(number);
end;
end.

Output:

% ./LookAndSay 
Press RETURN to continue and ^C to stop.

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221
3113112221232112111312211312113211
1321132132111213122112311311222113111221131221
11131221131211131231121113112221121321132132211331222113112211^C

[edit] Perl

sub lookandsay {
my $str = shift;
$str =~ s/((.)\2*)/length($1) . $2/ge;
return $str;
}
 
my $num = "1";
foreach (1..10) {
print "$num\n";
$num = lookandsay($num);
}

Using string as a cyclic buffer:

for (my $_ = "1\n"; s/((.)\2*)//s;) {
print $1;
$_ .= ($1 ne "\n" and length($1)).$2
}

[edit] Perl 6

In Perl 6 it is natural to avoid explicit loops; rather we use the sequence operator to define a lazy sequence, then just use a slice subscript to pull off the first 10 values:

my @look-and-say := (
'1',
*.comb(/(.)$0*/).map({ .chars ~ .substr(0,1) }).join
...
*
);
 
.say for @look-and-say[^10];

[edit] PHP

<?php
function lookandsay($str) {
return preg_replace('/(.)\1*/e', 'strlen($0) . $1', $str);
}
 
$num = "1";
foreach (range(1,10) as $i) {
echo "$num\n";
$num = lookandsay($num);
}
?>

[edit] PicoLisp

(de las (Lst)
(make
(while Lst
(let (N 1 C)
(while (= (setq C (pop 'Lst)) (car Lst))
(inc 'N) )
(link N C) ) ) ) )

Usage:

: (las (1))
-> (1 1)
: (las @)
-> (2 1)
: (las @)
-> (1 2 1 1)
: (las @)
-> (1 1 1 2 2 1)
: (las @)
-> (3 1 2 2 1 1)
: (las @)
-> (1 3 1 1 2 2 2 1)
: (las @)
-> (1 1 1 3 2 1 3 2 1 1)
: (las @)
-> (3 1 1 3 1 2 1 1 1 3 1 2 2 1)

[edit] PowerBASIC

This uses the RLEncode function from the PowerBASIC Run-length encoding entry.

FUNCTION RLEncode (i AS STRING) AS STRING
DIM tmp1 AS STRING, tmp2 AS STRING, outP AS STRING
DIM Loop0 AS LONG, count AS LONG
 
FOR Loop0 = 1 TO LEN(i)
tmp1 = MID$(i, Loop0, 1)
IF tmp1 <> tmp2 THEN
IF count > 1 THEN
outP = outP & TRIM$(STR$(count)) & tmp2
tmp2 = tmp1
count = 1
ELSEIF 0 = count THEN
tmp2 = tmp1
count = 1
ELSE
outP = outP & "1" & tmp2
tmp2 = tmp1
END IF
ELSE
INCR count
END IF
NEXT
 
outP = outP & TRIM$(STR$(count)) & tmp2
FUNCTION = outP
END FUNCTION
 
FUNCTION lookAndSay(BYVAL count AS LONG) AS STRING
DIM iii AS STRING, tmp AS STRING
 
IF count > 1 THEN
iii = lookAndSay(count - 1)
ELSEIF count < 2 THEN
iii = "1"
END IF
 
tmp = RLEncode(iii)
lookAndSay = tmp
END FUNCTION
 
FUNCTION PBMAIN () AS LONG
DIM v AS LONG
v = VAL(INPUTBOX$("Enter a number."))
MSGBOX lookAndSay(v)
END FUNCTION

[edit] PowerShell

function Get-LookAndSay ($n = 1) {
$re = [regex] '(.)\1*'
$ret = ""
foreach ($m in $re.Matches($n)) {
$ret += [string] $m.Length + $m.Value[0]
}
return $ret
}
 
function Get-MultipleLookAndSay ($n) {
if ($n -eq 0) {
return @()
} else {
$a = 1
$a
for ($i = 1; $i -lt $n; $i++) {
$a = Get-LookAndSay $a
$a
}
}
}

Output:

PS> Get-MultipleLookAndSay 8
1
11
21
1211
111221
312211
13112221
1113213211

[edit] Prolog

Works with SWI-Prolog.

look_and_say(L) :-
maplist(write, L), nl,
encode(L, L1),
look_and_say(L1).
 
% This code is almost identical to the code of "run-length-encoding"
encode(In, Out) :-
packList(In, R1),
append(R1,Out).
 
 
% use of library clpfd allows packList(?In, ?Out) to works
% in both ways In --> Out and In <-- Out.
 
:- use_module(library(clpfd)).
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ?- packList([a,a,a,b,c,c,c,d,d,e], L).
% L = [[3,a],[1,b],[3,c],[2,d],[1,e]] .
% ?- packList(R, [[3,a],[1,b],[3,c],[2,d],[1,e]]).
% R = [a,a,a,b,c,c,c,d,d,e] .
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
packList([],[]).
 
packList([X],[[1,X]]) :- !.
 
 
packList([X|Rest],[XRun|Packed]):-
run(X,Rest, XRun,RRest),
packList(RRest,Packed).
 
 
run(Var,[],[1,Var],[]).
 
run(Var,[Var|LRest],[N1, Var],RRest):-
N #> 0,
N1 #= N + 1,
run(Var,LRest,[N, Var],RRest).
 
 
run(Var,[Other|RRest], [1,Var],[Other|RRest]):-
dif(Var,Other).
 

Output :

 ?- look_and_say([1]).
1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221
..........................

[edit] Pure

using system;
 
// Remove the trailing "L" from the string representation of bigints.
__show__ x::bigint = init (str x);
 
say x = val $ strcat $ map (sprintf "%d%s") $ look $ chars $ str x with
look [] = [];
look xs@(x:_) = (#takewhile (==x) xs,x) : look (dropwhile (==x) xs);
end;
 
iteraten 5 say 1; // [1,11,21,1211,111221]
 
// This prints the entire sequence, press Ctrl-C to abort.
do (puts.str) (iterate say 1);

[edit] PureBasic

If OpenConsole()
Define i, j, cnt, txt$, curr$, result$
Print("Enter start sequence: "): txt$=Input()
Print("How many repetitions: "): i=Val(Input())
;
PrintN(#CRLF$+"Sequence:"+#CRLF$+txt$)
Repeat
j=1
result$=""
Repeat
curr$=Mid(txt$,j,1)
cnt=0
Repeat
cnt+1
j+1
Until Mid(txt$,j,1)<>curr$
result$+Str(cnt)+curr$
Until j>Len(txt$)
PrintN(result$)
txt$=result$
i-1
Until i<=0
;
PrintN(#CRLF$+"Press ENTER to exit."): Input()
CloseConsole()
EndIf

Output

Enter start sequence: 1
How many repetitions: 7

Sequence:
1
11
21
1211
111221
312211
13112221
1113213211

[edit] Python

Translation of: C sharp
def lookandsay(number):
result = ""
 
repeat = number[0]
number = number[1:]+" "
times = 1
 
for actual in number:
if actual != repeat:
result += str(times)+repeat
times = 1
repeat = actual
else:
times += 1
 
return result
 
num = "1"
 
for i in range(10):
print num
num = lookandsay(num)

Functional

Works with: Python version 2.4+
>>> from itertools import groupby
>>> def lookandsay(number):
return ''.join( str(len(list(g))) + k
for k,g in groupby(number) )
 
>>> numberstring='1'
>>> for i in range(10):
print numberstring
numberstring = lookandsay(numberstring)

Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

As a generator

>>> from itertools import groupby, islice
>>>
>>> def lookandsay(number='1'):
while True:
yield number
number = ''.join( str(len(list(g))) + k
for k,g in groupby(number) )
 
 
>>> print('\n'.join(islice(lookandsay(), 10)))
1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

Using regular expressions

Translation of: Perl
import re
 
def lookandsay(str):
return re.sub(r'(.)\1*', lambda m: str(len(m.group(0))) + m.group(1), str)
 
num = "1"
for i in range(10):
print num
num = lookandsay(num)

[edit] R

Returning the value as an integer limits how long the sequence can get, so the option for integer or character return values are provided.

look.and.say <- function(x, return.an.int=FALSE)
{
#convert number to character vector
xstr <- unlist(strsplit(as.character(x), ""))
#get run length encoding
rlex <- rle(xstr)
#form new string
odds <- as.character(rlex$lengths)
evens <- rlex$values
newstr <- as.vector(rbind(odds, evens))
#collapse to scalar
newstr <- paste(newstr, collapse="")
#convert to number, if desired
if(return.an.int) as.integer(newstr) else newstr
}

Example usage.

x <- 1
for(i in 1:10)
{
x <- look.and.say(x)
print(x)
}

[edit] Racket

 
#lang racket
 
(define (encode str)
(regexp-replace* #px"(.)\\1*" str (lambda (m c) (~a (string-length m) c))))
 
(define (look-and-say-sequence n)
(reverse (for/fold ([r '("1")]) ([n n]) (cons (encode (car r)) r))))
 
(for-each displayln (look-and-say-sequence 10))
 

Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221

[edit] REXX

Programming note:   this version works with any string   (a null is assumed, which causes   1   to be used).

If a negative number is specified (the number of iterations to be used for the calculations), only the length of
the number (or character string) is shown.

[edit] simple version

/*REXX pgm displays the sequence (or lengths) for the look & say series.*/
parse arg N ! .; if N=='' then N=20 /*No nums given? Then use default*/
if !=='' then !=1 /*Null? Then assume 1st number.*/
 
do j=1 for abs(N) /*repeat a # times to show NUMS.*/
if j\==1 then !=$lookAndSay(!) /*invoke sub to calculate next #.*/
if N<0 then say 'length['j"]:" length(!) /*show its length.*/
else say  ! /*show the number to the screen. */
end /*j*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────$LOOKANDSAY subroutine──────────────*/
$lookAndSay: procedure; parse arg x,,$ /*define the argument passed {X}.*/
fin = '0'x /*use unique char to end scanning*/
x=x || fin /*append FIN character to string.*/
do k=1 by 0 /*now, process the given sequence*/
y=substr(x,k,1) /*pick off one char to examine. */
if y==fin then return $ /*if we're at the end, then done.*/
_=verify(x,y,,k) - k /*see how many chars we have of Y*/
$=$ || _ || y /*build the "say" thingy list. */
k=k + _ /*now, point to the next char. */
end /*k*/

output when using the default value of 20

[1]: 1
[2]: 11
[3]: 21
[4]: 1211
[5]: 111221
[6]: 312211
[7]: 13112221
[8]: 1113213211
[9]: 31131211131221
[10]: 13211311123113112211
[11]: 11131221133112132113212221
[12]: 3113112221232112111312211312113211
[13]: 1321132132111213122112311311222113111221131221
[14]: 11131221131211131231121113112221121321132132211331222113112211
[15]: 311311222113111231131112132112311321322112111312211312111322212311322113212221
[16]: 132113213221133112132113311211131221121321131211132221123113112221131112311332111213211322211312113211
[17]: 11131221131211132221232112111312212321123113112221121113122113111231133221121321132132211331121321231231121113122113322113111221131221
[18]: 31131122211311123113321112131221123113112211121312211213211321322112311311222113311213212322211211131221131211132221232112111312111213111213211231131122212322211331222113112211
[19]: 1321132132211331121321231231121113112221121321132122311211131122211211131221131211132221121321132132212321121113121112133221123113112221131112311332111213122112311311123112111331121113122112132113213211121332212311322113212221
[20]: 11131221131211132221232112111312111213111213211231132132211211131221131211221321123113213221123113112221131112311332211211131221131211132211121312211231131112311211232221121321132132211331121321231231121113112221121321133112132112312321123113112221121113122113121113123112112322111213211322211312113211

output   when the following is specified:   17 ggg

[1]: ggg
[2]: 3g
[3]: 131g
[4]: 1113111g
[5]: 3113311g
[6]: 132123211g
[7]: 11131211121312211g
[8]: 31131112311211131122211g
[9]: 132113311213211231132132211g
[10]: 11131221232112111312211213211312111322211g
[11]: 3113112211121312211231131122211211131221131112311332211g
[12]: 1321132122311211131122211213211321322112311311222113311213212322211g
[13]: 1113122113121122132112311321322112111312211312111322211213211321322123211211131211121332211g
[14]: 31131122211311122122111312211213211312111322211231131122211311123113322112111312211312111322111213122112311311123112112322211g
[15]: 132113213221133122112231131122211211131221131112311332211213211321322113311213212322211231131122211311123113223112111311222112132113311213211221121332211g
[16]: 11131221131211132221231122212213211321322112311311222113311213212322211211131221131211132221232112111312111213322112132113213221133112132113221321123113213221121113122123211211131221222112112322211g
[17]: 31131122211311123113321112132132112211131221131211132221121321132132212321121113121112133221123113112221131112311332111213122112311311123112112322211211131221131211132221232112111312211322111312211213211312111322211231131122111213122112311311221132211221121332211g

output   when the following is specified:   -60

length[1]: 1
length[2]: 2
length[3]: 2
length[4]: 4
length[5]: 6
length[6]: 6
length[7]: 8
length[8]: 10
length[9]: 14
length[10]: 20
length[11]: 26
length[12]: 34
length[13]: 46
length[14]: 62
length[15]: 78
length[16]: 102
length[17]: 134
length[18]: 176
length[19]: 226
length[20]: 302
length[21]: 408
length[22]: 528
length[23]: 678
length[24]: 904
length[25]: 1182
length[26]: 1540
length[27]: 2012
length[28]: 2606
length[29]: 3410
length[30]: 4462
length[31]: 5808
length[32]: 7586
length[33]: 9898
length[34]: 12884
length[35]: 16774
length[36]: 21890
length[37]: 28528
length[38]: 37158
length[39]: 48410
length[40]: 63138
length[41]: 82350
length[42]: 107312
length[43]: 139984
length[44]: 182376
length[45]: 237746
length[46]: 310036
length[47]: 403966
length[48]: 526646
length[49]: 686646
length[50]: 894810
length[51]: 1166642
length[52]: 1520986
length[53]: 1982710
length[54]: 2584304
length[55]: 3369156
length[56]: 4391702
length[57]: 5724486
length[58]: 7462860
length[59]: 9727930
length[60]: 12680852

[edit] faster version

This version appends the generated parts of the sequence, and after it gets to a certain size (chunkSize),
it appends the sequence generated (so far) to the primary sequence, and starts with a null sequence.
This avoids appending a small character string to a growing larger and larger character string.

/*REXX pgm displays the sequence (or lengths) for the look & say series.*/
parse arg N ! .; if N=='' then N=20 /*No nums given? Then use default*/
if !=='' then !=1 /*Null? Then assume 1st number.*/
 
do j=1 for abs(N) /*repeat a # times to show NUMS.*/
if j\==1 then !=$lookAndSay(!) /*invoke sub to calculate next #.*/
if N<0 then say 'length['j"]:" length(!) /*show its length.*/
else say '['j"]:" ! /*show the number to the screen. */
end /*j*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────$LOOKANDSAY subroutine──────────────*/
$lookAndSay: procedure; parse arg x,,$ ! /*define argument passed {X}.*/
chunkSize=1000 /*define a sensible chunk size. */
fin = '0'x /*use unique char to end scanning*/
x=x || fin /*append FIN character to string.*/
do k=1 by 0 /*now, process the given sequence*/
y=substr(x,k,1) /*pick off one char to examine. */
if y==fin then leave /*if we're at the end, then done.*/
_=verify(x,y,,k) - k /*see how many chars we have of Y*/
$=$ || _ || y /*build the "say" thingy list. */
k=k + _ /*now, point to the next char. */
if length($)<chunkSize then iterate /*OK, keep going.*/
 !=! || $ /*append $ to the  ! string.*/
chunkSize=chunkSize+100 /*chunkSize is an increasing #. */
$= /*now, start $ from scratch.*/
end /*k*/
return ! || $ /*return the  ! string plus $. */

output   is the same as version 1   (the simple version).

[edit] Ruby

Translation of: Perl
def lookandsay(str)
str.gsub(/(.)\1*/) {$&.length.to_s + $1}
end
 
num = "1"
10.times do
puts num
num = lookandsay(num)
end
Output:
1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

Using Enumerable#chunk

def lookandsay(str)
str.chars.chunk{|c| c}.map{|c,x| [x.size, c]}.join
end
 
puts num = "1"
9.times do
puts num = lookandsay(num)
end

The output is the same above.

Without regular expression:

# Adding clusterization (http://apidock.com/rails/Enumerable/group_by)
module Enumerable
# clumps adjacent elements together
# >> [2,2,2,3,3,4,2,2,1].cluster
# => [[2, 2, 2], [3, 3], [4], [2, 2], [1]]
def cluster
cluster = []
each do |element|
if cluster.last && cluster.last.last == element
cluster.last << element
else
cluster << [element]
end
end
cluster
end
end

Using Array#cluster defined above:

def print_sequence(input_sequence, seq=10)
return unless seq > 0
puts input_sequence.join
result_array = input_sequence.cluster.map do |cluster|
[cluster.count, cluster.first]
end
print_sequence(result_array.flatten, seq-1)
end
 
print_sequence([1])

The output is the same above.

[edit] Rust

use std::iter;
 
fn next_sequence(in_seq: &[int]) -> ~[int] {
assert!(!in_seq.is_empty());
 
let mut result = ~[];
let mut current_number = in_seq[0];
let mut current_runlength = 1;
 
for i in in_seq.slice_from(1).iter() {
if current_number == *i {
current_runlength += 1;
} else {
result.push(current_runlength);
result.push(current_number);
current_runlength = 1;
current_number = *i;
}
}
result.push(current_runlength);
result.push(current_number);
 
result
}
 
fn main() {
let mut seq = ~[1];
 
for i in iter::range(0, 10) {
println!("Sequence {}: {:?}", i, seq);
seq = next_sequence(seq);
}
}

Works as of 2013-01-05.

[edit] Scala

def lookAndSay(seed: BigInt) = {
val s = seed.toString
( 1 until s.size).foldLeft((1, s(0), new StringBuilder)) {
case ((len, c, sb), index) if c != s(index) => sb.append(len); sb.append(c); (1, s(index), sb)
case ((len, c, sb), _) => (len + 1, c, sb)
} match {
case (len, c, sb) => sb.append(len); sb.append(c); BigInt(sb.toString)
}
}
 
def lookAndSayIterator(seed: BigInt) = Iterator.iterate(seed)(lookAndSay)

[edit] Seed7

$ include "seed7_05.s7i";
 
const func string: lookAndSay (in integer: level, in string: stri) is func
result
var string: lookAndSay is "";
local
var integer: index is 2;
begin
if level = 1 then
if stri <> "" then
while index <= length(stri) and stri[index] = stri[1] do
incr(index);
end while;
lookAndSay := str(pred(index)) & stri[1 len 1] & lookAndSay(level, stri[index ..]);
end if;
else
lookAndSay := lookAndSay(1, lookAndSay(pred(level), stri));
end if;
end func;
 
const proc: main is func
local
var integer: level is 0;
begin
for level range 1 to 14 do
writeln(lookAndSay(level, "1"));
end for;
end func;

Output:

11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221
3113112221232112111312211312113211
1321132132111213122112311311222113111221131221
11131221131211131231121113112221121321132132211331222113112211
311311222113111231131112132112311321322112111312211312111322212311322113212221

[edit] Smalltalk

Works with: GNU Smalltalk
String extend [
lookAndSay [ |anElement nextElement counter coll newColl|
coll := (self asOrderedCollection).
newColl := OrderedCollection new.
counter := 0.
anElement := (coll first).
[ coll size > 0 ]
whileTrue: [
nextElement := coll removeFirst.
( anElement == nextElement ) ifTrue: [
counter := counter + 1.
] ifFalse: [
newColl add: (counter displayString).
newColl add: (anElement asString).
anElement := nextElement.
counter := 1.
]
].
newColl add: (counter displayString).
newColl add: (anElement asString).
^(newColl join)
]
].
 
|r|
r := '1'.
10 timesRepeat: [
r displayNl.
r := r lookAndSay.
]

[edit] SNOBOL4

Works with: Macro Spitbol
Works with: Snobol4+
Works with: CSnobol

The look-and-say sequence is an iterative run-length string encoding. So looksay( ) is just a wrapper around the Run-length Encoding task. This is by far the easiest solution.

*       # Encode RLE
define('rle(str)c,n') :(rle_end)
rle str len(1) . c :f(return)
str span(c) @n =
rle = rle n c :(rle)
rle_end
 
* # First m members of sequence with seed n
define('looksay(n,m)') :(looksay_end)
looksay output = n; m = gt(m,1) m - 1 :f(return)
n = rle(n) :(looksay)
looksay_end
 
* Test and display
looksay(1,10)
end

Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

[edit] SQL

DROP VIEW delta;
CREATE VIEW delta AS
SELECT sequence1.v AS x,
(sequence1.v<>sequence2.v)*sequence1.c AS v,
sequence1.c AS c
FROM SEQUENCE AS sequence1,
SEQUENCE AS sequence2
WHERE sequence1.c = sequence2.c+1;
 
DROP VIEW rle0;
CREATE VIEW rle0 AS
SELECT delta2.x AS x,
SUM(delta2.v) AS v,
delta2.c AS c
FROM delta AS delta1,
delta AS delta2
WHERE delta1.c >= delta2.c
GROUP BY delta1.c;
 
DROP VIEW rle1;
CREATE VIEW rle1 AS
SELECT SUM(x)/x AS a,
x AS b,
c AS c
FROM rle0
GROUP BY v;
 
DROP VIEW rle2;
CREATE VIEW rle2 AS
SELECT a AS v, 1 AS o, 2*c+0 AS c FROM rle1 UNION
SELECT b AS v, 1 AS o, 2*c+1 AS c FROM rle1;
 
DROP VIEW normed;
CREATE VIEW normed AS
SELECT r1.v AS v, SUM(r2.o) AS c
FROM rle2 AS r1,
rle2 AS r2
WHERE r1.c >= r2.c
GROUP BY r1.c;
 
DROP TABLE rle;
CREATE TABLE rle(v INT, c INT);
INSERT INTO rle SELECT * FROM normed ORDER BY c;
 
DELETE FROM SEQUENCE;
INSERT INTO SEQUENCE VALUES(-1,0);
INSERT INTO SEQUENCE SELECT * FROM rle;

Usage:

% sqlite3 
SQLite version 3.4.0
Enter ".help" for instructions
sqlite> CREATE TABLE sequence(v int, c int);
sqlite> INSERT INTO sequence VALUES(-1,0);
sqlite> INSERT INTO sequence VALUES(1,1);
sqlite> SELECT * FROM sequence;
-1|0
1|1
sqlite> .read look.sql
sqlite> SELECT * FROM sequence;
-1|0
1|1
1|2
sqlite> .read look.sql
sqlite> SELECT * FROM sequence;
-1|0
2|1
1|2
sqlite> .read look.sql
sqlite> SELECT * FROM sequence;
-1|0
1|1
2|2
1|3
1|4
sqlite> .read look.sql
sqlite> SELECT * FROM sequence;
-1|0
1|1
1|2
1|3
2|4
2|5
1|6

[edit] Tcl

proc lookandsay n {
set new ""
while {[string length $n] > 0} {
set char [string index $n 0]
for {set count 1} {[string index $n $count] eq $char} {incr count} {}
append new $count $char
set n [string range $n $count end]
}
interp alias {} next_lookandsay {} lookandsay $new
return $new
}
 
puts 1 ;# ==> 1
puts [lookandsay 1] ;# ==> 11
puts [next_lookandsay] ;# ==> 21
puts [next_lookandsay] ;# ==> 1211
puts [next_lookandsay] ;# ==> 111221
puts [next_lookandsay] ;# ==> 312211

Alternatively, with coroutines:

Works with: Tcl version 8.6
proc seq_lookandsay {n {coroName next_lookandsay}} {
coroutine $coroName apply {n {
for {} {[yield $n] ne "stop"} {set n $new} {
set new ""
foreach subseq [regexp -all -inline {0+|1+|2+|3+|4+|5+|6+|7+|8+|9+} $n] {
append new [string length $subseq] [string index $subseq 0]
}
}
}} $n
}
 
puts [seq_lookandsay 1]
puts [next_lookandsay]
puts [next_lookandsay]
puts [next_lookandsay]
puts [next_lookandsay]
puts [next_lookandsay]
puts [next_lookandsay]
puts [next_lookandsay]
puts [next_lookandsay]
puts [next_lookandsay]

Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

[edit] TUSCRIPT

 
$$ MODE TUSCRIPT,{}
num=1,say=""
LOOP look
digits=STRINGS (num," ? ")
digitgrouped=ACCUMULATE (digits,howmany)
LOOP/CLEAR h=howmany,digit=digitgrouped
say=JOIN (say,"",h,digit)
ENDLOOP
PRINT say
num=VALUE(say),say=""
IF (look==14) EXIT
ENDLOOP
 

Output:

11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221
3113112221232112111312211312113211
1321132132111213122112311311222113111221131221
11131221131211131231121113112221121321132132211331222113112211
311311222113111231131112132112311321322112111312211312111322212311322113212221  

[edit] Ursala

The look_and_say function returns the first n results by iterating the function that maps a given sequence to its successor.

#import std
#import nat
 
look_and_say "n" = ~&H\'1' next"n" rlc~&E; *= ^lhPrT\~&hNC %nP+ length
 
#show+
 
main = look_and_say 10

output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

[edit] VBA

 
Public Sub LookAndSay(Optional Niter As Integer = 10)
'generate "Niter" members of the look-and-say sequence
'(argument is optional; default is 10)
 
Dim s As String 'look-and-say number
Dim news As String 'next number in sequence
Dim curdigit As String 'current digit in s
Dim newdigit As String 'next digit in s
Dim curlength As Integer 'length of current run
Dim p As Integer 'position in s
Dim L As Integer 'length of s
 
On Error GoTo Oops 'to catch overflow, i.e. number too long
 
'start with "1"
s = "1"
For i = 1 To Niter
'initialise
L = Len(s)
p = 1
curdigit = Left$(s, 1)
curlength = 1
news = ""
For p = 2 To L
'check next digit in s
newdigit = Mid$(s, p, 1)
If curdigit = newdigit Then 'extend current run
curlength = curlength + 1
Else ' "output" run and start new run
news = news & CStr(curlength) & curdigit
curdigit = newdigit
curlength = 1
End If
Next p
' "output" last run
news = news & CStr(curlength) & curdigit
Debug.Print news
s = news
Next i
Exit Sub
 
Oops:
Debug.Print
If Err.Number = 6 Then 'overflow
Debug.Print "Oops - number too long!"
Else
Debug.Print "Error: "; Err.Number, Err.Description
End If
End Sub
 

Output:

LookAndSay 7
11
21
1211
111221
312211
13112221
1113213211

(Note: overflow occurs at 38th iteration!)

[edit] Vedit macro language

This implementation generates look-and-say sequence starting from the sequence on cursor line in edit buffer. Each new sequence is inserted as a new line. 10 sequences are created in this example.

Repeat(10) {
BOL
Reg_Empty(20)
While (!At_EOL) {
Match("(.)\1*", REGEXP+ADVANCE)
Num_Str(Chars_Matched, 20, LEFT+APPEND)
Reg_Copy_Block(20, CP-1, CP, APPEND)
}
Ins_Newline Reg_Ins(20)
}

Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221

[edit] VBScript

[edit] Implementation
function looksay( n )
dim i
dim accum
dim res
dim c
res = vbnullstring
do
if n = vbnullstring then exit do
accum = 0
c = left( n,1 )
do while left( n, 1 ) = c
accum = accum + 1
n = mid(n,2)
loop
if accum > 0 then
res = res & accum & c
end if
loop
looksay = res
end function
[edit] Invocation
dim m 
m = 1
for i = 0 to 13
m = looksay(m)
wscript.echo m
next
[edit] Output
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221
3113112221232112111312211312113211
1321132132111213122112311311222113111221131221
11131221131211131231121113112221121321132132211331222113112211
311311222113111231131112132112311321322112111312211312111322212311322113212221

[edit] Yorick

func looksay(input) {
// Special case: one digit
if(strlen(input) == 1)
return "1" + input;
// Convert string into an array of digits
digits = strchar(input)(:-1);
// Find indices where each run starts
w = where(digits(dif));
start = numberof(w) ? grow(1, w+1) : [1];
// Find length of each run
len = grow(start, numberof(digits)+1)(dif);
// Find digits for each run
run = digits(start);
// Construct output array
result = array(string, numberof(start)*2);
// Fill in lengths
result(1::2) = swrite(format="%d", len);
// Fill in digits; first must add trailing nulls to coerce single string
// into an array of strings.
run = transpose([run, array(char(0), numberof(run))])(*);
result(2::2) = strchar(run);
// Merge string array into single string
return result(sum);
}
 
val = "1";
do {
write, val;
val = looksay(val);
} while(strlen(val) < 80);

Output:

 1
 11
 21
 1211
 111221
 312211
 13112221
 1113213211
 31131211131221
 13211311123113112211
 11131221133112132113212221
 3113112221232112111312211312113211
 1321132132111213122112311311222113111221131221
 11131221131211131231121113112221121321132132211331222113112211
 311311222113111231131112132112311321322112111312211312111322212311322113212221
Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox