Look-and-say sequence

Revision as of 16:44, 16 November 2013 by Angus (talk | contribs) (order)

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.
Task
Look-and-say sequence
You are encouraged to solve this task according to the task description, using any language you may know.
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.

Ada

<lang 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 "+";</lang> This function can be used as follows: <lang ada>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"))))))))));</lang> Sample output:

11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221

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

<lang algol68>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))</lang> Output:

11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221

AutoHotkey

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

}</lang>

APL

<lang apl>

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

</lang>

AWK

<lang 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
 }

}</lang>

BBC BASIC

<lang bbcbasic> 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$</lang>

Output:

11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221

C

This program will not stop until killed or running out of memory. <lang c>#include <stdio.h>

  1. 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; }</lang>

C++

<lang cpp>#include <string>

  1. 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();

}

  1. 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;

}</lang>

C#

<lang csharp>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);             
       }
   }

}</lang>

Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

Alternate version using Regex (C#2 syntax only): <lang csharp> 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]); }
               )
           );
       }
   }

}</lang> Output (with args: 1 15):

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

Clojure

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

<lang clojure>(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))</lang>

Example output: <lang clojure>user> (take 8 (iterate look-and-say 1)) (1 11 21 1211 111221 312211 13112221 1113213211)</lang>

Common Lisp

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

Example use:

<lang lisp>(next-look-and-say 9887776666) ;=> 19283746</lang>

Straight character counting: <lang lisp>(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))</lang>

D

Short Functional Version

<lang d>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;

}</lang>

Output:
["1", "11", "21", "1211", "111221", "312211", "13112221", "1113213211"]

Fast Imperative Version

Same output. <lang d>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;

}</lang>

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: <lang d>70.showLookAndSay!false;</lang>

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.

Intermediate Version

This mostly imperative version is intermediate in both speed and code size: <lang d>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);
   }

}</lang> 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.

E

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

}</lang>

Erlang

<lang 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]).</lang>

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"]

Factor

<lang 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</lang>

Forth

<lang 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</lang>

Fortran

<lang 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</lang>

<lang fortran>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</lang>

GAP

<lang 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"</lang>

Go

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

}</lang> Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221

Groovy

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

}</lang> Test Code <lang groovy>def sequence = "1" (1..12).each {

   println sequence
   sequence = lookAndSay(sequence)

}</lang> Output

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

Haskell

<lang 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</lang>

Haxe

<lang 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; } }</lang>

Icon and Unicon

<lang Icon>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</lang>

Output:

11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221

J

Solution:

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

Example: <lang j> 10 las 1 1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221</lang>

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

Java

Translation of: C#
Works with: Java version 1.5+

<lang java5>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(); }</lang> Testing: <lang java5>public static void main(String[] args){ String num = "1";

for (int i=1;i<=10;i++) { System.out.println(num); num = lookandsay(num); } }</lang> Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

JavaScript

Translation of: Perl

<lang javascript>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);

}</lang>

K

<lang k> las: {x{0$,//$(#:'n),'*:'n:(&1,~=':x)_ x:0$'$x}\1}

 las 8

1 11 21 1211 111221 312211 13112221 1113213211 31131211131221</lang>


Lasso

The Look-and-say sequence is a recursive RLE, so the solution can leverage the same method as used for RLE. <lang Lasso>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' ^}</lang>

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

<lang logo>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</lang>

Lua

<lang 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</lang>

Alternative solution, using LPeg: <lang lua>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</lang>

M4

Using regular expressions:

Translation of: Perl

<lang M4>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</lang>

Mathematica

Custom Functions: <lang Mathematica>RunLengthEncode[x_List]:=(Through[{First,Length}[#]]&)/@Split[x]

LookAndSay[n_,d_:1]:=NestList[Flatten[Reverse/@RunLengthEncode[#]]&,{d},n-1]</lang>

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:

<lang Mathematica>FromDigits /@ LookAndSay[13] // Column FromDigits /@ LookAndSay[13, 7] // Column</lang>

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 

Maxima

<lang 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" */</lang>

MAXScript

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

)</lang>

Metafont

<lang 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</lang>

Nimrod

<lang 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() </lang>

OCaml

Functional

<lang ocaml>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</lang>

With regular expressions in the Str library

<lang ocaml>#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</lang>

With regular expressions in the Pcre library

<lang ocaml>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</lang>

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

Imperative

<lang ocaml>(* 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 *)</lang>


Oz

<lang 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}</lang>

PARI/GP

<lang parigp>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))</lang>

Pascal

Works with: Free_Pascal
Library: SysUtils

<lang pascal>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.</lang> 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

Perl

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

}</lang>

Using string as a cyclic buffer: <lang perl>for (my $_ = "1\n"; s/((.)\2*)//s;) { print $1; $_ .= ($1 ne "\n" and length($1)).$2 }</lang>

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: <lang perl>my @look-and-say := (

   '1',
   *.comb(/(.)$0*/).map({ .chars ~ .substr(0,1) }).join
   ...
   *

);

.say for @look-and-say[^10];</lang>

PHP

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

} ?></lang>

PicoLisp

<lang PicoLisp>(de las (Lst)

  (make
     (while Lst
        (let (N 1  C)
           (while (= (setq C (pop 'Lst)) (car Lst))
              (inc 'N) )
           (link N C) ) ) ) )</lang>

Usage: <lang PicoLisp>: (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)</lang>

PowerBASIC

This uses the RLEncode function from the PowerBASIC Run-length encoding entry. <lang powerbasic>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</lang>

PowerShell

<lang 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
       }
   }

}</lang> Output:

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

Prolog

Works with SWI-Prolog.

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

</lang>

Output :

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

Pure

<lang 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);</lang>

PureBasic

<lang 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</lang>

Output

Enter start sequence: 1
How many repetitions: 7

Sequence:
1
11
21
1211
111221
312211
13112221
1113213211

Python

Translation of: C sharp – C#

<lang python>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)</lang>

Functional

Works with: Python version 2.4+

<lang python>>>> 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)</lang>

Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

As a generator
<lang python>>>> 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</lang>

Using regular expressions

Translation of: Perl

<lang python>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)</lang>

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. <lang R>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

}</lang> Example usage. <lang R>x <- 1 for(i in 1:10) {

  x <- look.and.say(x)
  print(x)

}</lang>

Racket

<lang Racket>

  1. 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)) </lang>

Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221

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. <lang rexx>/*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   /*forever*/</lang>

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:   -44

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

Ruby

Translation of: Perl

<lang ruby>def lookandsay(str)

 str.gsub(/(.)\1*/) {$&.length.to_s + $1}

end

num = "1" 10.times do

 puts num
 num = lookandsay(num)

end</lang>

Output:
1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

Using Enumerable#chunk <lang ruby>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</lang> The output is the same above.

Without regular expression:

<lang ruby># 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</lang>

Using Array#cluster defined above:

<lang ruby>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])</lang> The output is the same above.

Scala

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

Seed7

<lang 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;</lang>

Output:

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

Smalltalk

Works with: GNU Smalltalk

<lang 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.

]</lang>

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.

<lang SNOBOL4>* # 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</lang>

Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

SQL

<lang 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;</lang>

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

Tcl

<lang 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</lang>

Alternatively, with coroutines:

Works with: Tcl version 8.6

<lang tcl>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]</lang> Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

TUSCRIPT

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

</lang> Output:

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

Ursala

The look_and_say function returns the first n results by iterating the function that maps a given sequence to its successor. <lang Ursala>#import std

  1. import nat

look_and_say "n" = ~&H\'1' next"n" rlc~&E; *= ^lhPrT\~&hNC %nP+ length

  1. show+

main = look_and_say 10</lang> output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211

VBA

<lang 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 </lang>

Output:

LookAndSay 7
11
21
1211
111221
312211
13112221
1113213211

(Note: overflow occurs at 38th iteration!)

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.

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

}</lang>

Output:

1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
11131221133112132113212221

VBScript

Implementation

<lang vb>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</lang>

Invocation

<lang vb>dim m m = 1 for i = 0 to 13 m = looksay(m) wscript.echo m next</lang>

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

Yorick

<lang 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);</lang>

Output:

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