Look-and-say sequence: Difference between revisions
Added Uiua solution |
|||
(308 intermediate revisions by more than 100 users not shown) | |||
Line 1: | Line 1: | ||
{{task|Text processing}} |
{{task|Text processing}} |
||
The [[wp:Look and say sequence|Look and say sequence]] is a recursively defined sequence of numbers studied most notably by [[wp:John Horton Conway|John Conway]]. |
|||
The '''look-and-say sequence''' is also known as the '''Morris Number Sequence''', after cryptographer Robert Morris, and the puzzle ''What is the next number in the sequence 1, 11, 21, 1211, 111221?'' is sometimes referred to as the ''Cuckoo's Egg'', from a description of Morris in Clifford Stoll's book ''The Cuckoo's Egg''. |
|||
'''Sequence Definition''' |
'''Sequence Definition''' |
||
* Take a decimal number |
* Take a decimal number |
||
* ''Look'' at the number, visually grouping consecutive runs of the same digit. |
* ''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. |
* ''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. |
: This becomes the next number of the sequence. |
||
The [[wp:Look_and_say_sequence|sequence]] is from [[wp:John Horton Conway|John Conway]], of [[Conway's Game of Life]] fame. |
|||
'''An example:''' |
'''An example:''' |
||
* Starting with the number 1, you have ''one'' 1 which produces 11 |
* Starting with the number 1, you have ''one'' 1 which produces 11 |
||
* Starting with 11, you have ''two'' 1's |
* Starting with 11, you have ''two'' 1's. I.E.: 21 |
||
* Starting with 21, you have ''one'' 2, then ''one'' 1 |
* 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 |
* Starting with 1211, you have ''one'' 1, ''one'' 2, then ''two'' 1's. I.E.: (11)(12)(21) which becomes 111221 |
||
'''Write a program to generate successive members of the look-and-say sequence.''' |
|||
;Task: |
|||
Write a program to generate successive members of the look-and-say sequence. |
|||
;Related tasks: |
|||
* [[Fours is the number of letters in the ...]] |
|||
* [[Number names]] |
|||
* [[Self-describing numbers]] |
|||
* [[Self-referential sequence]] |
|||
* [[Spelling of ordinal numbers]] |
|||
;See also: |
|||
* [https://www.youtube.com/watch?v=ea7lJkEhytA Look-and-Say Numbers (feat John Conway)], A Numberphile Video. |
|||
* This task is related to, and an application of, the [[Run-length encoding]] task. |
|||
* Sequence [https://oeis.org/A005150 A005150] on The On-Line Encyclopedia of Integer Sequences. |
|||
<br><br> |
|||
=={{header|11l}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="11l">F lookandsay(=number) |
|||
V result = ‘’ |
|||
V repeat = number[0] |
|||
number = number[1..]‘ ’ |
|||
V times = 1 |
|||
L(actual) number |
|||
I actual != repeat |
|||
result ‘’= String(times)‘’repeat |
|||
times = 1 |
|||
repeat = actual |
|||
E |
|||
times++ |
|||
R result |
|||
V num = ‘1’ |
|||
L 10 |
|||
print(num) |
|||
num = lookandsay(num)</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
</pre> |
|||
=={{header|8080 Assembly}}== |
|||
<syntaxhighlight lang="8080asm">bdos: equ 5 ; CP/M calls |
|||
puts: equ 9 |
|||
nmemb: equ 15 ; Change this to print more or fewer members |
|||
org 100h |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; Generate and output members of the sequence |
|||
mvi b,nmemb ; Counter |
|||
outloop: push b ; Preserve counter across calls |
|||
mvi c,puts ; Output current member |
|||
lxi d,memb |
|||
call bdos ; And newline |
|||
mvi c,puts |
|||
lxi d,newline |
|||
call bdos |
|||
lxi h,memb ; Generate next member |
|||
call looksay |
|||
pop b ; Restore counter |
|||
dcr b ; Done yet? |
|||
jnz outloop |
|||
rst 0 |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; Given a $-terminated string under HL, representing |
|||
;; a member of the look and say sequence, generate |
|||
;; the next one in place (ish). The memory after the |
|||
;; string is assumed to be free. |
|||
looksay: push h ; Save start of string on stack |
|||
mov d,h ; And in DE |
|||
mov e,l |
|||
mvi a,'$' ; Find end of string |
|||
findend: cmp m |
|||
inx h |
|||
jnz findend |
|||
xchg ; HL=string, DE=destination |
|||
push d ; Save start of new string on stack |
|||
lookchar: mvi b,0 ; Zero counter |
|||
lookloop: mov a,m ; Get current character |
|||
inr b ; Compare next character |
|||
inx h |
|||
cmp m ; While it is the same, keep going |
|||
jz lookloop |
|||
mov c,a ; Keep character |
|||
mvi a,'0' ; There are B amount of these characters |
|||
add b |
|||
stax d ; Store the amount |
|||
inx d ; And in the next location |
|||
mov a,c ; Store the character |
|||
stax d |
|||
inx d |
|||
mvi a,'$' ; Are we done? |
|||
cmp m |
|||
jnz lookchar ; If not, do next character |
|||
stax d ; If yes, terminate new string |
|||
;; Free up memory by copying the new string to where the old |
|||
;; string began. |
|||
pop d ; Start of new string |
|||
pop h ; Start of old string |
|||
copyloop: ldax d ; Get char from new string |
|||
mov m,a ; Store char where old string was |
|||
cpi '$' ; are we done yet? |
|||
inx d |
|||
inx h |
|||
jnz copyloop |
|||
ret |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
newline: db 13,10,'$' |
|||
;; This is where the string will be stored. |
|||
memb: db '1$' ; First item |
|||
; Due to how CP/M loads programs, the memory after here |
|||
; is free until we hit the stack. |
|||
</syntaxhighlight> |
|||
=={{header|8086 Assembly}}== |
|||
<syntaxhighlight lang="asm"> bits 16 |
|||
cpu 8086 |
|||
puts: equ 9h ; MS/DOS system call to print a string |
|||
nmemb: equ 15 ; Change this to print more or fewer members |
|||
section .text |
|||
org 100h |
|||
mov cx,nmemb ; CX = how many members to print |
|||
outloop: mov dx,memb ; Print current member |
|||
mov ah,puts |
|||
int 21h |
|||
mov dx,newline ; Print newline |
|||
int 21h |
|||
mov di,memb ; Generate next member |
|||
call looksay |
|||
loop outloop ; Decrease CX, and loop until zero. |
|||
ret ; Go back to DOS. |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;;; Given a look and say string in ES:DI, generate the next |
|||
;;; one in place. Assumption: DS = ES. |
|||
looksay: push cx ; Keep the counter register |
|||
mov si,di ; Store pointer to string begin in SI |
|||
mov bx,di ; And another in BX |
|||
mov al,'$' ; Find the end of the string |
|||
xor cx,cx ; Max. 65535 tries |
|||
dec cx |
|||
repne scasb ; The 8086 has dedicated string search |
|||
mov dx,di ; Store copy of start of new str in DX |
|||
;;; Process one character |
|||
.procchar: mov al,'0' ; Set counter to ASCII 0 |
|||
mov ah,[bx] ; Get current character of string |
|||
cmp ah,'$' ; Done? |
|||
je .done |
|||
.samechar: inc bx ; Increment pointer |
|||
inc al ; Increment counter |
|||
cmp ah,[bx] ; Still the same character? |
|||
je .samechar ; If yes, test next character |
|||
mov [di],ax ; Store counter and character |
|||
inc di ; Move ahead two characters |
|||
inc di |
|||
jmp .procchar ; Do next character |
|||
;;; Copy new string into old location |
|||
.done: mov byte [di],'$' ; Terminate the string |
|||
mov cx,di ; Calculate how many bytes to copy |
|||
sub cx,dx ; end + 1 - start, so one too few here |
|||
shr cx,1 ; Divide by 2 = words |
|||
inc cx ; Compensate for the missing +1 |
|||
mov di,dx ; Pointer to begin of new string |
|||
xchg si,di ; Set SI = new string and DI = old |
|||
rep movsw ; Copy 16 bits at a time |
|||
pop cx ; Restore counter register |
|||
ret |
|||
section .data |
|||
newline: db 13,10,'$' ; Newline to print in between members |
|||
memb: db '1$' ; This is where the current member is stored</syntaxhighlight> |
|||
=={{header|ABC}}== |
|||
<syntaxhighlight lang="abc">HOW TO RETURN look.and.say seq: |
|||
PUT "" IN result |
|||
PUT 0 IN n |
|||
PUT "" IN c |
|||
FOR ch IN seq: |
|||
SELECT: |
|||
c=ch: |
|||
PUT n+1 IN n |
|||
ELSE: |
|||
IF n>0: PUT result^"`n`"^c IN result |
|||
PUT 1 IN n |
|||
PUT ch IN c |
|||
RETURN result^"`n`"^c |
|||
PUT "1" IN item |
|||
FOR i IN {1..14}: |
|||
WRITE item/ |
|||
PUT look.and.say item IN item</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211</pre> |
|||
=={{header|Action!}}== |
|||
<syntaxhighlight lang="action!">BYTE FUNC GetLength(CHAR ARRAY s BYTE pos) |
|||
CHAR c |
|||
BYTE len |
|||
c=s(pos) |
|||
len=1 |
|||
DO |
|||
pos==+1 |
|||
IF pos<=s(0) AND s(pos)=c THEN |
|||
len==+1 |
|||
ELSE |
|||
EXIT |
|||
FI |
|||
OD |
|||
RETURN (len) |
|||
PROC Append(CHAR ARRAY text,suffix) |
|||
BYTE POINTER srcPtr,dstPtr |
|||
BYTE len |
|||
len=suffix(0) |
|||
IF text(0)+len>255 THEN |
|||
len=255-text(0) |
|||
FI |
|||
IF len THEN |
|||
srcPtr=suffix+1 |
|||
dstPtr=text+text(0)+1 |
|||
MoveBlock(dstPtr,srcPtr,len) |
|||
text(0)==+suffix(0) |
|||
FI |
|||
RETURN |
|||
PROC LookAndSay(CHAR ARRAY in,out) |
|||
BYTE pos,len |
|||
CHAR ARRAY tmp(5) |
|||
pos=1 len=0 out(0)=0 |
|||
WHILE pos<=in(0) |
|||
DO |
|||
len=GetLength(in,pos) |
|||
StrB(len,tmp) |
|||
Append(out,tmp) |
|||
out(0)==+1 |
|||
out(out(0))=in(pos) |
|||
pos==+len |
|||
OD |
|||
RETURN |
|||
PROC Main() |
|||
CHAR ARRAY s1(256),s2(256) |
|||
BYTE i |
|||
SCopy(s1,"1") |
|||
PrintE(s1) |
|||
FOR i=1 TO 11 |
|||
DO |
|||
IF (i&1)=0 THEN |
|||
LookAndSay(s2,s1) |
|||
PrintE(s1) |
|||
ELSE |
|||
LookAndSay(s1,s2) |
|||
PrintE(s2) |
|||
FI |
|||
OD |
|||
RETURN</syntaxhighlight> |
|||
{{out}} |
|||
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Look-and-say_sequence.png Screenshot from Atari 8-bit computer] |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
</pre> |
|||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
< |
<syntaxhighlight lang="ada">with Ada.Text_IO, Ada.Strings.Fixed; |
||
use Ada.Text_IO, Ada.Strings, Ada.Strings.Fixed; |
use Ada.Text_IO, Ada.Strings, Ada.Strings.Fixed; |
||
Line 29: | Line 356: | ||
end loop; |
end loop; |
||
return Trim (Integer'Image (S'Length), Both) & Item; |
return Trim (Integer'Image (S'Length), Both) & Item; |
||
end "+"; |
end "+";</syntaxhighlight> |
||
This function can be used as follows: |
This function can be used as follows: |
||
< |
<syntaxhighlight lang="ada">Put_Line (+"1"); |
||
Put_Line (+(+"1")); |
Put_Line (+(+"1")); |
||
Put_Line (+(+(+"1"))); |
Put_Line (+(+(+"1"))); |
||
Line 40: | Line 367: | ||
Put_Line (+(+(+(+(+(+(+(+"1")))))))); |
Put_Line (+(+(+(+(+(+(+(+"1")))))))); |
||
Put_Line (+(+(+(+(+(+(+(+(+"1"))))))))); |
Put_Line (+(+(+(+(+(+(+(+(+"1"))))))))); |
||
Put_Line (+(+(+(+(+(+(+(+(+(+"1")))))))))); |
Put_Line (+(+(+(+(+(+(+(+(+(+"1"))))))))));</syntaxhighlight> |
||
{{out}} |
|||
Sample output: |
|||
<pre> |
<pre> |
||
11 |
11 |
||
Line 54: | Line 381: | ||
11131221133112132113212221 |
11131221133112132113212221 |
||
</pre> |
</pre> |
||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
{{trans|Ada}} |
{{trans|Ada}} |
||
{{works with|ALGOL 68|Standard - no extensions to language used}} |
{{works with|ALGOL 68|Standard - no extensions to language used}} |
||
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386}} |
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386}} |
||
{{works with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386}} |
{{works with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386}} |
||
< |
<syntaxhighlight lang="algol68">OP + = (STRING s)STRING: |
||
BEGIN |
BEGIN |
||
CHAR item = s[LWB s]; |
CHAR item = s[LWB s]; |
||
Line 86: | Line 413: | ||
print ((+(+(+(+(+(+(+(+"1"))))))), new line)); |
print ((+(+(+(+(+(+(+(+"1"))))))), new line)); |
||
print ((+(+(+(+(+(+(+(+(+"1")))))))), new line)); |
print ((+(+(+(+(+(+(+(+(+"1")))))))), new line)); |
||
print ((+(+(+(+(+(+(+(+(+(+"1"))))))))), new line))</ |
print ((+(+(+(+(+(+(+(+(+(+"1"))))))))), new line))</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
11 |
11 |
||
Line 100: | Line 427: | ||
11131221133112132113212221 |
11131221133112132113212221 |
||
</pre> |
</pre> |
||
=={{header|ALGOL-M}}== |
|||
<syntaxhighlight lang="algolm">begin |
|||
string(1) function digit(n); |
|||
integer n; |
|||
case n of begin |
|||
digit := "0"; digit := "1"; digit := "2"; |
|||
digit := "3"; digit := "4"; digit := "5"; |
|||
digit := "6"; digit := "7"; digit := "8"; |
|||
digit := "9"; |
|||
end; |
|||
string(1) array cur[1:128]; |
|||
string(1) array next[1:128]; |
|||
integer curlen, i, cnt, j, n; |
|||
cur[1] := "1"; |
|||
curlen := 1; |
|||
for n := 1 step 1 until 15 do begin |
|||
write(""); |
|||
for i := 1 step 1 until curlen do |
|||
writeon(cur[i]); |
|||
i := j := 1; |
|||
while i <= curlen do begin |
|||
cnt := 1; |
|||
while cur[i + cnt] = cur[i] do |
|||
cnt := cnt + 1; |
|||
next[j] := digit(cnt); |
|||
next[j + 1] := cur[i]; |
|||
j := j + 2; |
|||
i := i + cnt; |
|||
end; |
|||
for i := 1 step 1 until j-1 do |
|||
cur[i] := next[i]; |
|||
curlen := j - 1; |
|||
end; |
|||
end</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221</pre> |
|||
=={{header|APL}}== |
|||
<syntaxhighlight lang="apl"> |
|||
⎕IO←0 |
|||
d←{(1↓⍵)-¯1↓⍵} |
|||
f←{m←(0≠d ⍵),1 ⋄ ,(d ¯1,m/⍳⍴⍵),[.5](m/⍵)} |
|||
{(f⍣⍵) ,1}¨⍳10 |
|||
</syntaxhighlight> |
|||
This is an ugly little APL2 function that accepts a numeric vector (or scalar) and returns the result. |
|||
Apologies for the labeled loop... |
|||
<syntaxhighlight lang="apl2"> |
|||
R←LNS V;T |
|||
R←0⍴0 ⍝ initiate empty reply |
|||
LOOP:T←↑⍴↑(=\V)⊂V←,V ⍝ t is the length of the 1st digit's run |
|||
R←R,T,↑V ⍝ append t and the 1st digit |
|||
→(0≠↑⍴V←T↓V)/LOOP ⍝ drop t digits and iterate |
|||
</syntaxhighlight> |
|||
=={{header|AppleScript}}== |
|||
<syntaxhighlight lang="applescript">on lookAndSay(startNumber, howMany) |
|||
if (howMany < 1) then return {} |
|||
-- The numbers are handled as lists of digit-value integers for efficiency and output as a list of strings. |
|||
script o |
|||
property previousNumber : {} |
|||
property newNumber : {} |
|||
property output : {} |
|||
end script |
|||
-- "Digitise" the start number. |
|||
repeat |
|||
set beginning of o's newNumber to startNumber mod 10 as integer |
|||
set startNumber to startNumber div 10 |
|||
if (startNumber is 0) then exit repeat |
|||
end repeat |
|||
-- Add it to the output as text and successively derive the remaining numbers. |
|||
set astid to AppleScript's text item delimiters |
|||
set AppleScript's text item delimiters to "" |
|||
set end of o's output to o's newNumber as text |
|||
repeat (howMany - 1) times |
|||
set o's previousNumber to o's newNumber |
|||
set o's newNumber to {} |
|||
set i to 1 |
|||
set previousLength to (o's previousNumber's length) |
|||
set currentDigit to beginning of o's previousNumber |
|||
repeat with j from 2 to previousLength |
|||
set thisDigit to item j of o's previousNumber |
|||
if (thisDigit is not currentDigit) then |
|||
set end of o's newNumber to j - i |
|||
set end of o's newNumber to currentDigit |
|||
set i to j |
|||
set currentDigit to thisDigit |
|||
end if |
|||
end repeat |
|||
set end of o's newNumber to previousLength - i + 1 |
|||
set end of o's newNumber to currentDigit |
|||
set end of o's output to o's newNumber as text |
|||
end repeat |
|||
set AppleScript's text item delimiters to astid |
|||
return o's output |
|||
end lookAndSay |
|||
-- Test code: |
|||
return lookAndSay(1, 10)</syntaxhighlight> |
|||
{{output}} |
|||
<syntaxhighlight lang="applescript">{"1", "11", "21", "1211", "111221", "312211", "13112221", "1113213211", "31131211131221", "13211311123113112211"}</syntaxhighlight> |
|||
=={{header|Arturo}}== |
|||
<syntaxhighlight lang="rebol">lookAndSay: function [n][ |
|||
if n=0 -> return "1" |
|||
previous: lookAndSay n-1 |
|||
result: new "" |
|||
currentCounter: 0 |
|||
currentCh: first previous |
|||
loop previous 'ch [ |
|||
if? currentCh <> ch [ |
|||
if not? zero? currentCounter -> |
|||
'result ++ (to :string currentCounter) ++ currentCh |
|||
currentCounter: 1 |
|||
currentCh: ch |
|||
] |
|||
else -> |
|||
currentCounter: currentCounter + 1 |
|||
] |
|||
'result ++ (to :string currentCounter) ++ currentCh |
|||
return result |
|||
] |
|||
loop 0..10 'x [ |
|||
print [x "->" lookAndSay x] |
|||
]</syntaxhighlight> |
|||
{{out}} |
|||
<pre>0 -> 1 |
|||
1 -> 11 |
|||
2 -> 21 |
|||
3 -> 1211 |
|||
4 -> 111221 |
|||
5 -> 312211 |
|||
6 -> 13112221 |
|||
7 -> 1113213211 |
|||
8 -> 31131211131221 |
|||
9 -> 13211311123113112211 |
|||
10 -> 11131221133112132113212221</pre> |
|||
=={{header|AutoHotkey}}== |
|||
<syntaxhighlight 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 |
|||
}</syntaxhighlight> |
|||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
< |
<syntaxhighlight lang="awk">function lookandsay(a) |
||
{ |
{ |
||
s = "" |
s = "" |
||
Line 128: | Line 664: | ||
print b |
print b |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header| |
=={{header|BASIC}}== |
||
{{works with|QBasic}} |
|||
{{works with|QuickBasic}} |
|||
{{works with|BASICA}} |
|||
{{works with|Chipmunk Basic}} |
|||
{{works with|GW-BASIC}} |
|||
{{works with|MSX BASIC|any}} |
|||
{{works with|Run BASIC}} |
|||
{{works with|Just BASIC}} |
|||
<syntaxhighlight lang="basic">10 DEFINT A-Z: I$="1" |
|||
20 FOR Z=1 TO 15 |
|||
30 PRINT I$ |
|||
40 O$="" |
|||
50 FOR I=1 TO LEN(I$) |
|||
60 C=1 |
|||
70 IF MID$(I$,I,1)=MID$(I$,I+C,1) THEN C=C+1: GOTO 70 |
|||
80 O$=O$+CHR$(C+48)+MID$(I$,I,1) |
|||
90 I=I+C-1 |
|||
100 NEXT I |
|||
110 I$=O$ |
|||
120 NEXT Z</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221</pre> |
|||
==={{header|Applesoft BASIC}}=== |
|||
There are no checks for memory allocation failure or "''out of bound''" in case more than the worst case happens. |
|||
{{trans|BASIC}} |
|||
<syntaxhighlight lang="vb">10 I$="1" |
|||
20 FOR Z=1 TO 15 |
|||
30 PRINT I$ |
|||
40 O$="" |
|||
50 FOR I=1 TO LEN(I$) |
|||
60 C=1 |
|||
70 IF MID$(I$,I,1)=MID$(I$,I+C,1) THEN C=C+1: GOTO 70 |
|||
80 O$=O$+CHR$(C+48)+MID$(I$,I,1) |
|||
90 I=I+C-1 |
|||
100 NEXT I |
|||
110 I$=O$ |
|||
120 NEXT Z</syntaxhighlight> |
|||
==={{header|Chipmunk Basic}}=== |
|||
<lang c>#include <stdio.h> |
|||
{{works with|Chipmunk Basic|3.6.4}} |
|||
#include <stdlib.h> |
|||
<syntaxhighlight lang="qbasic">100 cls |
|||
#include <string.h> |
|||
110 dim x$(2) |
|||
120 i = 0 ' índice de cadena de entrada |
|||
130 x$(i) = "1" |
|||
140 input "Indica cuantas repeticiones: ",r |
|||
150 print "Secuencia:" |
|||
160 print x$(i) |
|||
170 for n = 1 to r-1 |
|||
180 j = 1-i ' índice de cadena de salida |
|||
190 x$(j) = "" |
|||
200 k = 1 |
|||
210 while k <= len(x$(i)) |
|||
220 k0 = k+1 |
|||
230 while ((k0 <= len(x$(i))) and (mid$(x$(i),k,1) = mid$(x$(i),k0,1))) |
|||
240 k0 = k0+1 |
|||
250 wend |
|||
260 x$(j) = x$(j)+str$(k0-k)+mid$(x$(i),k,1) |
|||
270 k = k0 |
|||
280 wend |
|||
290 i = j |
|||
300 print x$(j) |
|||
310 next n |
|||
320 end</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Similar to FreeBASIC entry.</pre> |
|||
==={{header|GW-BASIC}}=== |
|||
char *lookandsay(const char *s) |
|||
The [[#BASIC|BASIC]] solution works without any changes. |
|||
{ |
|||
int i, c, l, fi; |
|||
char *r = NULL; |
|||
char p; |
|||
==={{header|MSX Basic}}=== |
|||
l = strlen(s); |
|||
{{works with|MSX BASIC|any}} |
|||
if ( l == 0 ) return NULL; |
|||
The [[#BASIC|BASIC]] solution works without any changes. |
|||
r = malloc(l*3); /* worst case considered: each number gets a two digit counter */ |
|||
memset(r, 0, l*3); |
|||
p = s[0]; |
|||
fi = 0; |
|||
c = 1; |
|||
for(i=1; i < l; i++) { |
|||
if ( p == s[i] ) { |
|||
c++; |
|||
} else { |
|||
fi += sprintf(&r[fi], "%d%c", c, p); |
|||
c = 1; |
|||
p = s[i]; |
|||
} |
|||
} |
|||
fi += sprintf(&r[fi], "%d%c", c, p); |
|||
r[fi] = 0; |
|||
free(s); |
|||
return r; |
|||
} |
|||
==={{header|True BASIC}}=== |
|||
int main() |
|||
<syntaxhighlight lang="qbasic">LET i$ = "1" |
|||
{ |
|||
FOR z = 1 TO 15 |
|||
int i; |
|||
PRINT i$ |
|||
const char *laf = "1"; |
|||
LET o$ = "" |
|||
FOR i = 1 TO LEN(i$) |
|||
LET c = 1 |
|||
DO WHILE (i$)[i:i+1-1] = (i$)[i+c:i+c+1-1] |
|||
LET c = c+1 |
|||
LOOP |
|||
LET o$ = o$ & CHR$(c+48) & (i$)[i:i+1-1] |
|||
LET i = i+c-1 |
|||
NEXT i |
|||
LET i$ = o$ |
|||
NEXT z |
|||
END</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Similar to FreeBASIC entry.</pre> |
|||
=={{header|BASIC256}}== |
|||
printf("%s\n", laf); |
|||
<syntaxhighlight lang="basic256"> |
|||
for(i=0; i < 10; i++) { |
|||
# look and say |
|||
laf = lookandsay(laf); |
|||
printf("%s\n", laf); |
|||
} |
|||
free(laf); |
|||
dim a$(2) |
|||
return 0; |
|||
}</lang> |
|||
i = 0 # input string index |
|||
=={{header|C++}}== |
|||
a$[i] = "1" |
|||
<lang cpp>#include <string> |
|||
#include <sstream> |
|||
print a$[i] |
|||
std::string lookandsay(const std::string &s) |
|||
{ |
|||
std::ostringstream r; |
|||
for n=1 to 10 |
|||
for (unsigned int i = 0; i != s.length(); ) { |
|||
j = 1 - i # output string index |
|||
unsigned int new_i = s.find_first_not_of(s[i], i+1); |
|||
a$[j] = "" |
|||
if (new_i == std::string::npos) |
|||
k = 1 |
|||
new_i = s.length(); |
|||
while (k <= length(a$[i])) |
|||
k0 = k + 1 |
|||
while ((k0 <= length(a$[i])) and (mid(a$[i], k, 1) = mid(a$[i], k0, 1))) |
|||
k0 = k0 + 1 |
|||
end while |
|||
a$[j] += string(k0 - k) + mid(a$[i], k, 1) |
|||
k = k0 |
|||
end while |
|||
i = j |
|||
print a$[j] |
|||
next n |
|||
</syntaxhighlight> |
|||
=={{header|BBC BASIC}}== |
|||
r << new_i - i << s[i]; |
|||
<syntaxhighlight lang="bbcbasic"> number$ = "1" |
|||
i = new_i; |
|||
FOR i% = 1 TO 10 |
|||
} |
|||
number$ = FNlooksay(number$) |
|||
return r.str(); |
|||
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$</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
</pre> |
|||
=={{header|BCPL}}== |
|||
#include <iostream> |
|||
<syntaxhighlight lang="bcpl">get "libhdr" |
|||
manifest $( |
|||
amount = 15 |
|||
bufsize = 128 |
|||
$) |
|||
let move(dest,src) be |
|||
$( until !src = 0 do |
|||
$( !dest := !src |
|||
dest := dest + 1 |
|||
src := src + 1 |
|||
$) |
|||
!dest := 0 |
|||
$) |
|||
let count(v) = valof |
|||
$( let i=1 |
|||
while v!i = !v do i := i + 1 |
|||
resultis i |
|||
$) |
|||
let looksay(in,out) be |
|||
$( until !in = 0 do |
|||
$( let n = count(in) |
|||
out!0 := n |
|||
out!1 := !in |
|||
out := out + 2 |
|||
in := in + n |
|||
$) |
|||
!out := 0 |
|||
$) |
|||
let show(v) be |
|||
$( until !v = 0 do |
|||
$( writen(!v) |
|||
v := v + 1 |
|||
$) |
|||
wrch('*N') |
|||
$) |
|||
let start() be |
|||
$( let buf1 = vec bufsize and buf2 = vec bufsize |
|||
buf1!0 := 1 |
|||
buf1!1 := 0 |
|||
for n = 1 to amount do |
|||
$( show(buf1) |
|||
looksay(buf1,buf2) |
|||
move(buf1,buf2) |
|||
$) |
|||
$)</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221</pre> |
|||
=={{header|BQN}}== |
|||
<syntaxhighlight lang="bqn">LookSay ← ∾´((⊑∾˜ ≠+'0'˙)¨1↓((+`»≠⊢)⊸⊔)) |
|||
>((⌈´≠¨)↑¨⊢) LookSay⍟(↕15)"1"</syntaxhighlight> |
|||
{{out}} |
|||
<pre>┌─ |
|||
╵"1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221" |
|||
┘</pre> |
|||
=={{header|Bracmat}}== |
|||
In this example we use a non-linear pattern and a negation of a pattern: the end of e sequence of equal digits is (1) the end of the string or (2) the start of a sequence starting with a different digit. |
|||
<syntaxhighlight lang="bracmat">( 1:?number |
|||
& 0:?lines |
|||
& whl |
|||
' ( 1+!lines:~>10:?lines |
|||
& :?say { This will accumulate all that has to be said after one iteration. } |
|||
& 0:?begin |
|||
& ( @( !number { Pattern matching. The '@' indicates we're looking in a string rather than a tree structure. } |
|||
: ? |
|||
( [!begin |
|||
%@?digit |
|||
? |
|||
[?end |
|||
( (|(%@:~!digit) ?) { The %@ guarantees we're testing one character - not less (%) and not more (@). The ? takes the rest. } |
|||
& !say !end+-1*!begin !digit:?say |
|||
& !end:?begin { When backtracking, 'begin' advances to the begin of the next sequence, or to the end of the string. } |
|||
) |
|||
& ~ { fail! This forces backtracking. Backtracking stops when all begin positions have been tried. } |
|||
) |
|||
) |
|||
| out$(str$!say:?number) { After backtracking, output string and set number to string for next iteration. } |
|||
) |
|||
) |
|||
);</syntaxhighlight> |
|||
{{out}} |
|||
<pre>11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221</pre> |
|||
=={{header|C}}== |
|||
This program will not stop until killed or running out of memory. |
|||
<syntaxhighlight lang="c">#include <stdio.h> |
|||
#include <stdlib.h> |
|||
int main() |
int main() |
||
{ |
{ |
||
char *a = malloc(2), *b = 0, *x, c; |
|||
std::string laf = "1"; |
|||
int cnt, len = 1; |
|||
std::cout << laf << std::endl; |
|||
for (int i = 0; i < 10; i++) { |
|||
laf = lookandsay(laf); |
|||
std::cout << laf << std::endl; |
|||
} |
|||
for (sprintf(a, "1"); (b = realloc(b, len * 2 + 1)); a = b, b = x) { |
|||
return 0; |
|||
puts(x = a); |
|||
}</lang> |
|||
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; |
|||
=={{header|C sharp|C#}}== |
|||
}</syntaxhighlight> |
|||
=={{header|C sharp|C#}}== |
|||
<lang csharp>using System; |
|||
<syntaxhighlight lang="csharp">using System; |
|||
using System.Text; |
using System.Text; |
||
using System.Linq; |
using System.Linq; |
||
Line 257: | Line 1,031: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Output: |
|||
{{out}} |
|||
<pre>1 |
<pre>1 |
||
11 |
11 |
||
Line 272: | Line 1,045: | ||
13211311123113112211</pre> |
13211311123113112211</pre> |
||
Alternate version using Regex (C#2 syntax only): |
|||
=={{header|Common Lisp}}== |
|||
<syntaxhighlight lang="csharp"> |
|||
using System; |
|||
using System.Text.RegularExpressions; |
|||
namespace RosettaCode_Cs_LookAndSay |
|||
<lang lisp>(defun compress (array &key (test 'eql) &aux (l (length array))) |
|||
{ |
|||
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]); } |
|||
) |
|||
); |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} (with args: 1 15): |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221</pre> |
|||
=={{header|C++}}== |
|||
<syntaxhighlight lang="cpp">#include <iostream> |
|||
#include <sstream> |
|||
#include <string> |
|||
std::string lookandsay(const std::string& s) |
|||
{ |
|||
std::ostringstream r; |
|||
for (std::size_t i = 0; i != s.length();) { |
|||
auto 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(); |
|||
} |
|||
int main() |
|||
{ |
|||
std::string laf = "1"; |
|||
std::cout << laf << '\n'; |
|||
for (int i = 0; i < 10; ++i) { |
|||
laf = lookandsay(laf); |
|||
std::cout << laf << '\n'; |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|Ceylon}}== |
|||
<syntaxhighlight lang="ceylon">shared void run() { |
|||
function lookAndSay(Integer|String input) { |
|||
variable value digits = if (is Integer input) then input.string else input; |
|||
value builder = StringBuilder(); |
|||
while (exists currentChar = digits.first) { |
|||
if (exists index = digits.firstIndexWhere((char) => char != currentChar)) { |
|||
digits = digits[index...]; |
|||
builder.append("``index````currentChar``"); |
|||
} |
|||
else { |
|||
builder.append("``digits.size````currentChar``"); |
|||
break; |
|||
} |
|||
} |
|||
return builder.string; |
|||
} |
|||
variable String|Integer result = 1; |
|||
print(result); |
|||
for (i in 1..14) { |
|||
result = lookAndSay(result); |
|||
print(result); |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|Clojure}}== |
|||
No ugly int-to-string-and-back conversions. |
|||
<syntaxhighlight 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))</syntaxhighlight> |
|||
{{out}} |
|||
<syntaxhighlight lang="clojure">user> (take 8 (iterate look-and-say 1)) |
|||
(1 11 21 1211 111221 312211 13112221 1113213211)</syntaxhighlight> |
|||
----- |
|||
The math above is lovely, Clojure using Java's regular expressions is also powerful: |
|||
<syntaxhighlight lang="clojure">(defn look-and-say |
|||
[n] |
|||
(->> (re-seq #"(.)\1*" n) |
|||
(mapcat (comp (juxt count first) first)) |
|||
(apply str))) |
|||
(take 12 (iterate look-and-say "1"))</syntaxhighlight> |
|||
{{out}} |
|||
<syntaxhighlight lang="clojure">("1" |
|||
"11" |
|||
"21" |
|||
"1211" |
|||
"111221" |
|||
"312211" |
|||
"13112221" |
|||
"1113213211" |
|||
"31131211131221" |
|||
"13211311123113112211" |
|||
"11131221133112132113212221" |
|||
"3113112221232112111312211312113211")</syntaxhighlight> |
|||
=={{header|CLU}}== |
|||
<syntaxhighlight lang="clu">look_and_say = proc (s: string) returns (string) |
|||
out: array[char] := array[char]$[] |
|||
count: int := 0 |
|||
last: char := '\000' |
|||
for c: char in string$chars(s) do |
|||
if c ~= last then |
|||
if count ~= 0 then |
|||
array[char]$addh(out, char$i2c(count + 48)) |
|||
array[char]$addh(out, last) |
|||
end |
|||
last := c |
|||
count := 1 |
|||
else |
|||
count := count + 1 |
|||
end |
|||
end |
|||
array[char]$addh(out, char$i2c(count + 48)) |
|||
array[char]$addh(out, last) |
|||
return (string$ac2s(out)) |
|||
end look_and_say |
|||
start_up = proc () |
|||
lines = 15 |
|||
po: stream := stream$primary_output() |
|||
cur: string := "1" |
|||
for i: int in int$from_to(1, lines) do |
|||
stream$putl(po, cur) |
|||
cur := look_and_say(cur) |
|||
end |
|||
end start_up</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221</pre> |
|||
=={{header|COBOL}}== |
|||
<syntaxhighlight lang="cobol"> IDENTIFICATION DIVISION. |
|||
PROGRAM-ID. LOOK-AND-SAY-SEQ. |
|||
DATA DIVISION. |
|||
WORKING-STORAGE SECTION. |
|||
01 SEQUENCES. |
|||
02 CUR-SEQ PIC X(80) VALUE "1". |
|||
02 CUR-CHARS REDEFINES CUR-SEQ |
|||
PIC X OCCURS 80 TIMES INDEXED BY CI. |
|||
02 CUR-LENGTH PIC 99 COMP VALUE 1. |
|||
02 NEXT-SEQ PIC X(80). |
|||
02 NEXT-CHARS REDEFINES NEXT-SEQ |
|||
PIC X OCCURS 80 TIMES INDEXED BY NI. |
|||
01 ALG-STATE. |
|||
02 STEP-AMOUNT PIC 99 VALUE 14. |
|||
02 ITEM-COUNT PIC 9. |
|||
PROCEDURE DIVISION. |
|||
LOOK-AND-SAY. |
|||
DISPLAY CUR-SEQ. |
|||
SET CI TO 1. |
|||
SET NI TO 1. |
|||
MAKE-NEXT-ENTRY. |
|||
MOVE 0 TO ITEM-COUNT. |
|||
IF CI IS GREATER THAN CUR-LENGTH GO TO STEP-DONE. |
|||
TALLY-ITEM. |
|||
ADD 1 TO ITEM-COUNT. |
|||
SET CI UP BY 1. |
|||
IF CI IS NOT GREATER THAN CUR-LENGTH |
|||
AND CUR-CHARS(CI) IS EQUAL TO CUR-CHARS(CI - 1) |
|||
GO TO TALLY-ITEM. |
|||
INSERT-ENTRY. |
|||
MOVE ITEM-COUNT TO NEXT-CHARS(NI). |
|||
MOVE CUR-CHARS(CI - 1) TO NEXT-CHARS(NI + 1). |
|||
SET NI UP BY 2. |
|||
GO TO MAKE-NEXT-ENTRY. |
|||
STEP-DONE. |
|||
MOVE NEXT-SEQ TO CUR-SEQ. |
|||
SET NI DOWN BY 1. |
|||
SET CUR-LENGTH TO NI. |
|||
SUBTRACT 1 FROM STEP-AMOUNT. |
|||
IF STEP-AMOUNT IS NOT EQUAL TO ZERO GO TO LOOK-AND-SAY. |
|||
STOP RUN.</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211</pre> |
|||
=={{header|Common Lisp}}== |
|||
<syntaxhighlight 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 |
"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 |
a number of occurrences and whose cdr is the element occurring. For |
||
Line 292: | Line 1,347: | ||
(parse-integer (string (cdr pair))))) |
(parse-integer (string (cdr pair))))) |
||
(compress (princ-to-string number)) |
(compress (princ-to-string number)) |
||
:initial-value 0))</ |
:initial-value 0))</syntaxhighlight> |
||
Example use: |
Example use: |
||
< |
<syntaxhighlight lang="lisp">(next-look-and-say 9887776666) ;=> 19283746</syntaxhighlight> |
||
Straight character counting: |
|||
<syntaxhighlight 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))</syntaxhighlight> |
|||
=={{header|Cowgol}}== |
|||
<syntaxhighlight lang="cowgol">include "cowgol.coh"; |
|||
include "strings.coh"; |
|||
# Given a string with a member of the look-and-say sequence, |
|||
# generate the next member of the sequence. |
|||
sub LookSay(cur: [uint8], next: [uint8]) is |
|||
while [cur] != 0 loop |
|||
var count: uint8 := 1; |
|||
var curch: uint8 := [cur]; |
|||
# count how many of this character we have |
|||
loop |
|||
cur := @next cur; |
|||
if [cur] != curch then break; end if; |
|||
count := count + 1; |
|||
end loop; |
|||
# add it and its count to the next sequence |
|||
[next] := '0' + count; |
|||
next := @next next; |
|||
[next] := curch; |
|||
next := @next next; |
|||
end loop; |
|||
[next] := 0; |
|||
end sub; |
|||
# amount of members to print |
|||
# (don't forget to enlarge the buffers if you make this bigger) |
|||
var members: uint8 := 15; |
|||
# define two buffers |
|||
var curbuf: uint8[255]; |
|||
var nextbuf: uint8[255]; |
|||
# start with "1" |
|||
CopyString("1", &curbuf as [uint8]); |
|||
# generate and print successive members |
|||
while members > 0 loop |
|||
print(&curbuf as [uint8]); |
|||
print_nl(); |
|||
LookSay(&curbuf as [uint8], &nextbuf as [uint8]); |
|||
CopyString(&nextbuf as [uint8], &curbuf as [uint8]); |
|||
members := members - 1; |
|||
end loop;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221</pre> |
|||
=={{header|Crystal}}== |
|||
{{trans|Ruby}} |
|||
The simplest one: |
|||
<syntaxhighlight lang="ruby">class String |
|||
def lookandsay |
|||
gsub(/(.)\1*/){ |s| s.size.to_s + s[0] } |
|||
end |
|||
end |
|||
ss = '1' |
|||
12.times { puts ss; ss = ss.to_s.lookandsay }</syntaxhighlight> |
|||
{{trans|Ruby from Perl}} |
|||
<syntaxhighlight lang="ruby">def lookandsay(str) |
|||
str.gsub(/(.)\1*/) { |s| s.size.to_s + $1 } |
|||
end |
|||
num = "1" |
|||
12.times { puts num; num = lookandsay(num) }</syntaxhighlight> |
|||
{{trans|Ruby}} |
|||
Using Enumerable#chunks |
|||
<syntaxhighlight lang="ruby">def lookandsay(str) |
|||
str.chars.chunks(&.itself).map{ |(c, x)| x.size.to_s + c }.join |
|||
end |
|||
num = "1" |
|||
12.times { puts num; num = lookandsay(num) }</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211</pre> |
|||
=={{header|D}}== |
=={{header|D}}== |
||
===Short Functional Version=== |
|||
<lang d>import std.stdio; |
|||
<syntaxhighlight lang="d">import std.stdio, std.algorithm, std.range; |
|||
import std.string; |
|||
enum say = (in string s) pure => s.group.map!q{ text(a[1],a[0]) }.join; |
|||
void main() { |
void main() { |
||
"1".recurrence!((t, n) => t[n - 1].say).take(8).writeln; |
|||
char[]las = "1"; |
|||
}</syntaxhighlight> |
|||
writefln("%s",las); |
|||
{{out}} |
|||
las = lookandsay(las); |
|||
<pre>["1", "11", "21", "1211", "111221", "312211", "13112221", "1113213211"]</pre> |
|||
writefln("%s",las); |
|||
las = lookandsay(las); |
|||
===Beginner Imperative Version=== |
|||
writefln("%s",las); |
|||
<syntaxhighlight lang="d">import std.stdio, std.conv, std.array; |
|||
las = lookandsay(las); |
|||
writefln("%s",las); |
|||
pure string lookAndSay(string s){ |
|||
las = lookandsay(las); |
|||
auto result = appender!string; |
|||
writefln("%s",las); |
|||
auto i=0, j=i+1; |
|||
while(i<s.length){ |
|||
while(j<s.length && s[i]==s[j]) j++; |
|||
result.put( text(j-i) ~ s[i] ); |
|||
i = j++; |
|||
} |
|||
return result.data; |
|||
} |
} |
||
void main(){ |
|||
auto s="1"; |
|||
for(auto i=0; i<10; i++) |
|||
(s = s.lookAndSay).writeln; |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221</pre> |
|||
===Fast Imperative Version=== |
|||
char[]lookandsay(char[]input) { |
|||
<syntaxhighlight lang="d">import core.stdc.stdio, std.math, std.conv, std.algorithm, std.array; |
|||
char last = input[$-1]; |
|||
char[]output; |
|||
void showLookAndSay(bool showArrays)(in uint n) nothrow { |
|||
int count = 0; |
|||
if (n == 0) // No sequences to generate and show. |
|||
foreach_reverse(i;input) { |
|||
return; |
|||
count++; |
|||
enum Digit : char { nil = '\0', one = '1', two = '2', thr = '3' } |
|||
output = toString(count)~last~output; |
|||
// Allocate an approximate upper bound size for the array. |
|||
count = 1; |
|||
static Digit* allocBuffer(in uint m) nothrow { |
|||
last = i; |
|||
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; |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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</pre> |
|||
With: |
|||
<syntaxhighlight lang="d">70.showLookAndSay!false;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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</pre> |
|||
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: |
|||
<syntaxhighlight 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); |
|||
return output; |
|||
} |
|||
} </lang> |
|||
}</syntaxhighlight> |
|||
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 <code>.map!(s => s.length)</code>), |
|||
compiling with LDC2 the run-times of the three versions |
|||
with n=55 are about 31.1, 0.10 and 0.23 seconds. |
|||
===More Direct Version=== |
|||
Translated and modified from C code by Reddit user "skeeto": |
|||
http://www.reddit.com/r/dailyprogrammer/comments/2ggy30/9152014_challenge180_easy_looknsay/ |
|||
Using ideas from: |
|||
http://www.njohnston.ca/2010/10/a-derivation-of-conways-degree-71-look-and-say-polynomial/ |
|||
This recursive version is able to generate very large sequences in a short time without memory for the intermediate sequence (and with stack space proportional to the sequence order). |
|||
<syntaxhighlight lang="d">import core.stdc.stdio, std.conv; |
|||
// On Windows this uses the printf from the Microsoft C runtime, |
|||
// that doesn't handle real type and some of the C99 format |
|||
// specifiers, but it's faster for bulk printing. |
|||
version (LDC) version (Windows) |
|||
extern(C) nothrow @nogc int printf(const char*, ...); |
|||
// http://www.njohnston.ca/2010/10/a-derivation-of-conways-degree-71-look-and-say-polynomial/ |
|||
struct Sequence { |
|||
string seq; |
|||
uint[6] next; |
|||
} |
|||
immutable Sequence[93] sequences = [ |
|||
{"", []}, |
|||
{"1112", [63]}, |
|||
{"1112133", [64, 62]}, |
|||
{"111213322112", [65]}, |
|||
{"111213322113", [66]}, |
|||
{"1113", [68]}, |
|||
{"11131", [69]}, |
|||
{"111311222112", [84, 55]}, |
|||
{"111312", [70]}, |
|||
{"11131221", [71]}, |
|||
{"1113122112", [76]}, |
|||
{"1113122113", [77]}, |
|||
{"11131221131112", [82]}, |
|||
{"111312211312", [78]}, |
|||
{"11131221131211", [79]}, |
|||
{"111312211312113211", [80]}, |
|||
{"111312211312113221133211322112211213322112", [81, 29, 91]}, |
|||
{"111312211312113221133211322112211213322113", [81, 29, 90]}, |
|||
{"11131221131211322113322112", [81, 30]}, |
|||
{"11131221133112", [75, 29, 92]}, |
|||
{"1113122113322113111221131221", [75, 32]}, |
|||
{"11131221222112", [72]}, |
|||
{"111312212221121123222112", [73]}, |
|||
{"111312212221121123222113", [74]}, |
|||
{"11132", [83]}, |
|||
{"1113222", [86]}, |
|||
{"1113222112", [87]}, |
|||
{"1113222113", [88]}, |
|||
{"11133112", [89, 92]}, |
|||
{"12", [1]}, |
|||
{"123222112", [3]}, |
|||
{"123222113", [4]}, |
|||
{"12322211331222113112211", [2, 61, 29, 85]}, |
|||
{"13", [5]}, |
|||
{"131112", [28]}, |
|||
{"13112221133211322112211213322112", [24, 33, 61, 29, 91]}, |
|||
{"13112221133211322112211213322113", [24, 33, 61, 29, 90]}, |
|||
{"13122112", [7]}, |
|||
{"132", [8]}, |
|||
{"13211", [9]}, |
|||
{"132112", [10]}, |
|||
{"1321122112", [21]}, |
|||
{"132112211213322112", [22]}, |
|||
{"132112211213322113", [23]}, |
|||
{"132113", [11]}, |
|||
{"1321131112", [19]}, |
|||
{"13211312", [12]}, |
|||
{"1321132", [13]}, |
|||
{"13211321", [14]}, |
|||
{"132113212221", [15]}, |
|||
{"13211321222113222112", [18]}, |
|||
{"1321132122211322212221121123222112", [16]}, |
|||
{"1321132122211322212221121123222113", [17]}, |
|||
{"13211322211312113211", [20]}, |
|||
{"1321133112", [6, 61, 29, 92]}, |
|||
{"1322112", [26]}, |
|||
{"1322113", [27]}, |
|||
{"13221133112", [25, 29, 92]}, |
|||
{"1322113312211", [25, 29, 67]}, |
|||
{"132211331222113112211", [25, 29, 85]}, |
|||
{"13221133122211332", [25, 29, 68, 61, 29, 89]}, |
|||
{"22", [61]}, |
|||
{"3", [33]}, |
|||
{"3112", [40]}, |
|||
{"3112112", [41]}, |
|||
{"31121123222112", [42]}, |
|||
{"31121123222113", [43]}, |
|||
{"3112221", [38, 39]}, |
|||
{"3113", [44]}, |
|||
{"311311", [48]}, |
|||
{"31131112", [54]}, |
|||
{"3113112211", [49]}, |
|||
{"3113112211322112", [50]}, |
|||
{"3113112211322112211213322112", [51]}, |
|||
{"3113112211322112211213322113", [52]}, |
|||
{"311311222", [47, 38]}, |
|||
{"311311222112", [47, 55]}, |
|||
{"311311222113", [47, 56]}, |
|||
{"3113112221131112", [47, 57]}, |
|||
{"311311222113111221", [47, 58]}, |
|||
{"311311222113111221131221", [47, 59]}, |
|||
{"31131122211311122113222", [47, 60]}, |
|||
{"3113112221133112", [47, 33, 61, 29, 92]}, |
|||
{"311312", [45]}, |
|||
{"31132", [46]}, |
|||
{"311322113212221", [53]}, |
|||
{"311332", [38, 29, 89]}, |
|||
{"3113322112", [38, 30]}, |
|||
{"3113322113", [38, 31]}, |
|||
{"312", [34]}, |
|||
{"312211322212221121123222113", [36]}, |
|||
{"312211322212221121123222112", [35]}, |
|||
{"32112", [37]} |
|||
]; |
|||
void evolve(in uint seq, in uint n) nothrow @nogc { |
|||
if (n <= 0) { |
|||
printf(sequences[seq].seq.ptr); |
|||
} else { |
|||
foreach (immutable next; sequences[seq].next) { |
|||
if (next == 0) |
|||
break; |
|||
evolve(next, n - 1); |
|||
} |
|||
} |
|||
} |
|||
void main(in string[] args) { |
|||
immutable uint n = (args.length != 2) ? 10 : args[1].to!uint; |
|||
immutable base = 8; |
|||
immutable string[base] results = ["", "1", "11", "21", "1211", |
|||
"111221", "312211", "13112221"]; |
|||
if (n < base) { |
|||
printf("%s\n", results[n].ptr); |
|||
return; |
|||
} |
|||
evolve(24, n - base); |
|||
evolve(39, n - base); |
|||
'\n'.putchar; |
|||
}</syntaxhighlight> |
|||
=={{header|Delphi}}== |
|||
See [https://rosettacode.org/wiki/Look-and-say_sequence#Pascal Pascal]. |
|||
=={{header|Draco}}== |
|||
<syntaxhighlight lang="draco">\util.g |
|||
proc nonrec look_and_say(*char inp, outp) void: |
|||
char cur; |
|||
byte count; |
|||
channel output text outch; |
|||
open(outch, outp); |
|||
while cur := inp*; cur ~= '\e' do |
|||
count := 1; |
|||
while |
|||
inp := inp + 1; |
|||
inp* = cur |
|||
do |
|||
count := count + 1 |
|||
od; |
|||
write(outch; count, cur) |
|||
od; |
|||
close(outch) |
|||
corp |
|||
proc nonrec main() void: |
|||
[256] char buf1, buf2; |
|||
byte i; |
|||
byte LINES = 14; |
|||
CharsCopy(&buf1[0], "1"); |
|||
for i from 1 upto LINES do |
|||
writeln(&buf1[0]); |
|||
look_and_say(&buf1[0], &buf2[0]); |
|||
CharsCopy(&buf1[0], &buf2[0]) |
|||
od |
|||
corp</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211</pre> |
|||
=={{header|E}}== |
=={{header|E}}== |
||
< |
<syntaxhighlight lang="e">def lookAndSayNext(number :int) { |
||
var seen := null |
var seen := null |
||
var count := 0 |
var count := 0 |
||
Line 357: | Line 1,906: | ||
println(number) |
println(number) |
||
number := lookAndSayNext(number) |
number := lookAndSayNext(number) |
||
}</ |
}</syntaxhighlight> |
||
=={{header|EasyLang}}== |
|||
{{trans|AWK}} |
|||
<syntaxhighlight> |
|||
proc lookandsay . a$ . |
|||
c = 1 |
|||
p$ = substr a$ 1 1 |
|||
for i = 2 to len a$ |
|||
if p$ = substr a$ i 1 |
|||
c += 1 |
|||
else |
|||
s$ &= c & p$ |
|||
p$ = substr a$ i 1 |
|||
c = 1 |
|||
. |
|||
. |
|||
s$ &= c & p$ |
|||
swap a$ s$ |
|||
. |
|||
b$ = 1 |
|||
print b$ |
|||
for k = 1 to 10 |
|||
lookandsay b$ |
|||
print b$ |
|||
. |
|||
</syntaxhighlight> |
|||
=={{header|EchoLisp}}== |
|||
<syntaxhighlight lang="scheme"> |
|||
(lib 'math) ;; for (number->list) = explode function |
|||
(lib 'list) ;; (group) |
|||
(define (next L) |
|||
(for/fold (acc null) ((g (group L))) |
|||
(append acc (list (length g) (first g))))) |
|||
(define (task n starter) |
|||
(for/fold (L (number->list starter)) ((i n)) |
|||
(writeln (list->string L)) |
|||
(next L))) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<syntaxhighlight lang="scheme"> |
|||
(task 10 1) |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
</syntaxhighlight> |
|||
=={{header|Elixir}}== |
|||
<syntaxhighlight lang="elixir">defmodule LookAndSay do |
|||
def next(n) do |
|||
Enum.chunk_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, &(next/1) |
|||
end |
|||
def main([start_str|_]) do |
|||
{start_val,_} = Integer.parse(start_str) |
|||
IO.inspect sequence_from(start_val) |> Enum.take 9 |
|||
end |
|||
def main([]) do |
|||
main(["1"]) |
|||
end |
|||
end |
|||
LookAndSay.main(System.argv)</syntaxhighlight> |
|||
{{out}} |
|||
<pre>[1, 11, 21, 1211, 111221, 312211, 13112221, 1113213211, 31131211131221]</pre> |
|||
'''Regex version:''' |
|||
<syntaxhighlight lang="elixir">defmodule RC do |
|||
def look_and_say(n) do |
|||
Regex.replace(~r/(.)\1*/, to_string(n), fn x,y -> [to_string(String.length(x)),y] end) |
|||
|> String.to_integer |
|||
end |
|||
end |
|||
IO.inspect Enum.reduce(1..9, [1], fn _,acc -> [RC.look_and_say(hd(acc)) | acc] end) |> Enum.reverse</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
[1, 11, 21, 1211, 111221, 312211, 13112221, 1113213211, 31131211131221, |
|||
13211311123113112211] |
|||
</pre> |
|||
=={{header|Erlang}}== |
|||
<syntaxhighlight 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]).</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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"] |
|||
</pre> |
|||
=={{header|ERRE}}== |
|||
<syntaxhighlight lang="text"> |
|||
PROGRAM LOOK |
|||
PROCEDURE LOOK_AND_SAY(N$->N$) |
|||
LOCAL I%,J%,C$,O$ |
|||
I%=1 |
|||
REPEAT |
|||
C$=MID$(N$,I%,1) |
|||
J%=I%+1 |
|||
WHILE MID$(N$,J%,1)=C$ DO |
|||
J%+=1 |
|||
END WHILE |
|||
O$+=MID$(STR$(J%-I%),2)+C$ |
|||
I%=J% |
|||
UNTIL I%>LEN(N$) |
|||
N$=O$ |
|||
END PROCEDURE |
|||
BEGIN |
|||
NUMBER$="1" |
|||
FOR I%=1 TO 10 DO |
|||
LOOK_AND_SAY(NUMBER$->NUMBER$) |
|||
PRINT(NUMBER$) |
|||
END FOR |
|||
END PROGRAM |
|||
</syntaxhighlight> |
|||
<pre> |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
</pre> |
|||
=={{header|F Sharp|F#}}== |
|||
Library functions somehow missing in F# out of the box (but present in haskell) |
|||
<syntaxhighlight lang="fsharp"> |
|||
let rec brk p lst = |
|||
match lst with |
|||
| [] -> (lst, lst) |
|||
| x::xs -> |
|||
if p x |
|||
then ([], lst) |
|||
else |
|||
let (ys, zs) = brk p xs |
|||
(x::ys, zs) |
|||
let span p lst = brk (not << p) lst |
|||
let rec groupBy eq lst = |
|||
match lst with |
|||
| [] -> [] |
|||
| x::xs -> |
|||
let (ys,zs) = span (eq x) xs |
|||
(x::ys)::groupBy eq zs |
|||
let group lst : list<list<'a>> when 'a : equality = groupBy (=) lst |
|||
</syntaxhighlight> |
|||
Implementation |
|||
<syntaxhighlight lang="fsharp"> |
|||
let lookAndSay = |
|||
let describe (xs: char list) = |
|||
List.append (List.ofSeq <| (List.length xs).ToString()) [List.head xs] |
|||
let next xs = List.collect describe (group xs) |
|||
let toStr xs = String (Array.ofList xs) |
|||
Seq.map toStr <| Seq.unfold (fun xs -> Some (xs, next xs)) ['1'] |
|||
let getNthLookAndSay n = Seq.nth n lookAndSay |
|||
Seq.take 10 lookAndSay |
|||
</syntaxhighlight> |
|||
=={{header|Factor}}== |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
=={{header|Fennel}}== |
|||
<syntaxhighlight lang="fennel">(fn look-and-say [t] |
|||
(let [lst t |
|||
ret []] |
|||
(while (> (length lst) 0) |
|||
(var (num cnt) (values (table.remove lst 1) 1)) |
|||
(while (= num (. lst 1)) |
|||
(set cnt (+ cnt 1)) |
|||
(when (> (length lst) 0) |
|||
(set num (table.remove lst 1)))) |
|||
(tset ret (+ (length ret) 1) cnt) |
|||
(tset ret (+ (length ret) 1) num)) |
|||
ret)) |
|||
(var lst [1]) |
|||
(for [i 1 10] |
|||
(print (table.concat lst)) |
|||
(set lst (look-and-say lst)))</syntaxhighlight> |
|||
Alternative solution |
|||
<syntaxhighlight lang="fennel">(fn look-and-say [s] |
|||
(var ret []) |
|||
(var (num cnt) (values (s:sub 1 1) 1)) |
|||
(for [i 2 (length s)] |
|||
(var cur-num (s:sub i i)) |
|||
(if (= num cur-num) |
|||
(set cnt (+ cnt 1)) |
|||
(do |
|||
(table.insert ret (.. cnt num)) |
|||
(set cnt 1) |
|||
(set num cur-num)))) |
|||
(table.insert ret (.. cnt num)) |
|||
(table.concat ret)) |
|||
(var str "1") |
|||
(for [i 1 10] |
|||
(print str) |
|||
(set str (look-and-say str)))</syntaxhighlight> |
|||
=={{header|FOCAL}}== |
|||
<syntaxhighlight lang="focal">01.10 A "HOW MANY",M |
|||
01.20 S B(0)=1;S B(1)=0 |
|||
01.30 F Z=1,M;D 4;D 2 |
|||
01.40 Q |
|||
02.10 S X=0;S Y=0 |
|||
02.15 I (B(X)),2.5 |
|||
02.17 S CN=0 |
|||
02.20 S CN=CN+1 |
|||
02.25 S X=X+1 |
|||
02.30 I (FABS(B(X)-B(X-1))),2.2 |
|||
02.35 S C(Y)=CN;S C(Y+1)=B(X-1) |
|||
02.40 S Y=Y+2 |
|||
02.45 G 2.15 |
|||
02.50 S C(Y)=0 |
|||
02.55 F X=0,Y;S B(X)=C(X) |
|||
03.10 I (A-9)3.2;T "9";R |
|||
03.20 I (A-8)3.3;T "8";R |
|||
03.30 I (A-7)3.4;T "7";R |
|||
03.40 I (A-6)3.5;T "6";R |
|||
03.50 I (A-5)3.6;T "5";R |
|||
03.60 I (A-4)3.7;T "4";R |
|||
03.70 I (A-3)3.8;T "3";R |
|||
03.80 I (A-2)3.9;T "2";R |
|||
03.90 T "1" |
|||
04.10 S X=0 |
|||
04.20 S A=B(X) |
|||
04.30 I (-A)4.4;T !;R |
|||
04.40 D 3 |
|||
04.50 S X=X+1 |
|||
04.60 G 4.2</syntaxhighlight> |
|||
{{out}} |
|||
<pre>HOW MANY:12 |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211</pre> |
|||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
< |
<syntaxhighlight lang="forth">create buf1 256 allot |
||
create buf2 256 allot |
create buf2 256 allot |
||
buf1 value src |
buf1 value src |
||
Line 387: | Line 2,248: | ||
0 do next-look-and-say cr src count type loop ; |
0 do next-look-and-say cr src count type loop ; |
||
10 look-and-say |
10 look-and-say</syntaxhighlight> |
||
=={{header|Fortran}}== |
=={{header|Fortran}}== |
||
< |
<syntaxhighlight lang="fortran">module LookAndSay |
||
implicit none |
implicit none |
||
Line 420: | Line 2,281: | ||
end subroutine look_and_say |
end subroutine look_and_say |
||
end module LookAndSay</ |
end module LookAndSay</syntaxhighlight> |
||
< |
<syntaxhighlight lang="fortran">program LookAndSayTest |
||
use LookAndSay |
use LookAndSay |
||
implicit none |
implicit none |
||
Line 438: | Line 2,299: | ||
end do |
end do |
||
end program LookAndSayTest |
end program LookAndSayTest</syntaxhighlight> |
||
=={{header| |
=={{header|FreeBASIC}}== |
||
{{trans|BASIC256}} |
|||
<syntaxhighlight lang="freebasic"> |
|||
Dim As Integer n, j, k, k0, r |
|||
Dim As String X(2) |
|||
Dim As Integer i = 0 ' índice de cadena de entrada |
|||
X(0) = "1" |
|||
Input "Indica cuantas repeticiones: ", r |
|||
<lang haskell>import Control.Monad (liftM2) |
|||
Print Chr(10) & "Secuencia:" |
|||
Print X(i) |
|||
For n = 1 To r-1 |
|||
j = 1 - i ' índice de cadena de salida |
|||
X(j) = "" |
|||
k = 1 |
|||
While k <= Len(X(i)) |
|||
k0 = k + 1 |
|||
While ((k0 <= Len(X(i))) And (Mid(X(i), k, 1) = Mid(X(i), k0, 1))) |
|||
k0 += 1 |
|||
Wend |
|||
X(j) += Str(k0 - k) + Mid(X(i), k, 1) |
|||
k = k0 |
|||
Wend |
|||
i = j |
|||
Print X(j) |
|||
Next n |
|||
End |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Indica cuantas repeticiones: 10 |
|||
Secuencia: |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
</pre> |
|||
=={{header|Frink}}== |
|||
<syntaxhighlight lang="frink"> |
|||
LookAndSay = "12211123" |
|||
println["Starting Value: " + LookAndSay] |
|||
LASStr = { |LaS| |
|||
length[LaS@0] + length[LaS@1] + LaS@0 |
|||
/* |
|||
The returned results from the Regex are divided between a distinct matching |
|||
character and any following identical characters. For example, a string |
|||
of 2222 would be returned from this function as [2,222]. |
|||
The function adds the length of both elements (1 and 3 in the example |
|||
above) and returns that value with the matching character. |
|||
i.e. Length of 1st element = 1, Length of 2nd element = 3, value of 1st element = 2 |
|||
1 + 3 = 4 & value 2. Returned result is "42" i.e. "Four 2s." |
|||
*/ |
|||
} |
|||
// Calculate the next 10 Look and Say Sequence Values |
|||
for i = 1 to 10 |
|||
{ |
|||
LookAndSayReg = LookAndSay =~ %r/(\d)(\1{0,})/g |
|||
LookAndSay = join["",mapList[LASStr,LookAndSayReg]] |
|||
println["$i - $LookAndSay"] |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Starting Value: 1 |
|||
1 - 11 |
|||
2 - 21 |
|||
3 - 1211 |
|||
4 - 111221 |
|||
5 - 312211 |
|||
6 - 13112221 |
|||
7 - 1113213211 |
|||
8 - 31131211131221 |
|||
9 - 13211311123113112211 |
|||
10 - 11131221133112132113212221 |
|||
</pre> |
|||
=={{header|FutureBasic}}== |
|||
<syntaxhighlight lang="futurebasic"> |
|||
include "NSLog.incl" |
|||
local fn LookAndSay( testWord as CFStringRef ) as CFStringRef |
|||
NSUInteger i, length, times |
|||
CFMutableStringRef result = fn MutableStringWithCapacity(0) |
|||
unichar repeat = fn StringCharacterAtIndex( testWord, 0 ) |
|||
times = 1 |
|||
testWord = fn StringWithFormat( @"%@ ", fn StringSubstringFromIndex( testWord, 1 ) ) |
|||
length = len(testWord) |
|||
for i = 0 to length - 1 |
|||
unichar actual = fn StringCharacterAtIndex( testWord, i ) |
|||
if ( actual != repeat ) |
|||
MutableStringAppendFormat( result, @"%d%c", times, repeat ) |
|||
times = 1 |
|||
repeat = actual |
|||
else |
|||
times++ |
|||
end if |
|||
next |
|||
end fn = fn StringWithString( result ) |
|||
void local fn DoIt |
|||
NSUInteger i |
|||
CFStringRef numStr = @"1" |
|||
for i = 1 to i <= 15 |
|||
NSLog( @"%@", numStr ) |
|||
numStr = fn LookAndSay( numStr ) |
|||
next |
|||
end fn |
|||
fn DoIt |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
{{output}} |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221 |
|||
</pre> |
|||
=={{header|Gambas}}== |
|||
'''Code is modified from the [[http://rosettacode.org/wiki/Look-and-say_sequence#PureBasic PureBasic]] example''' |
|||
'''[https://gambas-playground.proko.eu/?gist=83d63e1706fa1dc3c7468b1e9d7bcf05 Click this link to run this code]''' |
|||
<syntaxhighlight lang="gambas">Public Sub Main() |
|||
Dim i, j, cnt As Integer |
|||
Dim txt$, curr$, result$ As String |
|||
txt$ = "1211" |
|||
i = 1 |
|||
Print "Sequence: " & txt$ & " = "; |
|||
Repeat |
|||
j = 1 |
|||
result$ = "" |
|||
Repeat |
|||
curr$ = Mid(txt$, j, 1) |
|||
cnt = 0 |
|||
Repeat |
|||
Inc cnt |
|||
Inc j |
|||
Until Mid(txt$, j, 1) <> curr$ |
|||
result$ &= Str(cnt) & curr$ |
|||
Until j > Len(txt$) |
|||
Print result$ |
|||
txt$ = result$ |
|||
Dec i |
|||
Until i <= 0 |
|||
End</syntaxhighlight> |
|||
Output: |
|||
<pre> |
|||
Sequence: 1211 = 111221 |
|||
</pre> |
|||
=={{header|GAP}}== |
|||
<syntaxhighlight 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"</syntaxhighlight> |
|||
=={{header|Go}}== |
|||
<syntaxhighlight 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) |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
</pre> |
|||
=={{header|Groovy}}== |
|||
<syntaxhighlight 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() |
|||
}</syntaxhighlight> |
|||
Test Code |
|||
<syntaxhighlight lang="groovy">def sequence = "1" |
|||
(1..12).each { |
|||
println sequence |
|||
sequence = lookAndSay(sequence) |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211</pre> |
|||
=={{header|Haskell}}== |
|||
<syntaxhighlight lang="haskell">import Control.Monad (liftM2) |
|||
import Data.List (group) |
import Data.List (group) |
||
Line 466: | Line 2,621: | ||
where describe run = show (length run) ++ take 1 run |
where describe run = show (length run) ++ take 1 run |
||
main = mapM_ print (iterate lookAndSay 1) -- display sequence until interrupted |
main = mapM_ print (iterate lookAndSay 1) -- display sequence until interrupted</syntaxhighlight> |
||
=={{header|Haxe}}== |
|||
<syntaxhighlight 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; |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|Icon}} and {{header|Unicon}}== |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
{{out}} |
|||
<pre>11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221</pre> |
|||
=={{header|Insitux}}== |
|||
<syntaxhighlight lang="insitux">(function look-and-say n x |
|||
(return-when (empty? n) x) |
|||
(let digit (0 n) |
|||
[before after] (part-before (!= digit) n)) |
|||
(recur after (strn x (len before) digit))) |
|||
(var result "1") |
|||
(loop 10 i |
|||
(print (var! result look-and-say)))</syntaxhighlight> |
|||
=={{header|J}}== |
=={{header|J}}== |
||
'''Solution''': |
'''Solution''': |
||
<syntaxhighlight lang="j">las=: ,@((# , {.);.1~ 1 , 2 ~:/\ ])&.(10x&#.inv)@]^:(1+i.@[)</syntaxhighlight> |
|||
'''Example''': |
'''Example''': |
||
10 las 1 |
<syntaxhighlight lang="j"> 10 las 1 |
||
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221</syntaxhighlight> |
|||
Note the result is an actual numeric sequence (cf. the textual solutions given in other languages). |
Note the result is an actual numeric sequence (cf. the textual solutions given in other languages). |
||
Line 481: | Line 2,716: | ||
=={{header|Java}}== |
=={{header|Java}}== |
||
{{trans|C#}} |
{{trans|C#}} |
||
{{works with|Java|1.5+}} |
{{works with|Java|1.5+}} |
||
< |
<syntaxhighlight lang="java5">public static String lookandsay(String number){ |
||
StringBuilder result= new StringBuilder(); |
StringBuilder result= new StringBuilder(); |
||
Line 500: | Line 2,734: | ||
} |
} |
||
return result.toString(); |
return result.toString(); |
||
}</ |
}</syntaxhighlight> |
||
Testing: |
Testing: |
||
< |
<syntaxhighlight lang="java5">public static void main(String[] args){ |
||
String num = "1"; |
String num = "1"; |
||
Line 509: | Line 2,743: | ||
num = lookandsay(num); |
num = lookandsay(num); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre>1 |
<pre>1 |
||
11 |
11 |
||
Line 523: | Line 2,757: | ||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
=== With RegExp === |
|||
{{trans|Perl}} |
{{trans|Perl}} |
||
< |
<syntaxhighlight lang="javascript">function lookandsay(str) { |
||
return str.replace(/(.)\1*/g, function(seq, p1){return seq.length.toString() + p1}) |
return str.replace(/(.)\1*/g, function(seq, p1){return seq.length.toString() + p1}) |
||
} |
} |
||
Line 532: | Line 2,767: | ||
alert(num); |
alert(num); |
||
num = lookandsay(num); |
num = lookandsay(num); |
||
}</ |
}</syntaxhighlight> |
||
=== Imperative version === |
|||
<syntaxhighlight lang="javascript">function lookAndSay( s="" ){ |
|||
var tokens=[] |
|||
var i=0, j=1 |
|||
while( i<s.length ) { |
|||
while( j<s.length && s[j]===s[i] ) j++ |
|||
tokens.push( `${j-i}${s[i]}` ) |
|||
i=j++ |
|||
} |
|||
return tokens.join("") |
|||
} |
|||
var phrase="1" |
|||
for(var n=0; n<10; n++ ) |
|||
console.log( phrase = lookAndSay( phrase ) )</syntaxhighlight> |
|||
{{Output}} |
|||
<pre>11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221</pre> |
|||
=={{header|jq}}== |
|||
{{Works with|jq|1.4}} |
|||
<syntaxhighlight lang="jq">def look_and_say: |
|||
def head(c; n): if .[n:n+1] == c then head(c; n+1) else n end; |
|||
tostring |
|||
| if length == 0 then "" |
|||
else head(.[0:1]; 1) as $len |
|||
| .[0:$len] as $head |
|||
| ($len | tostring) + $head[0:1] + (.[$len:] | look_and_say) |
|||
end ; |
|||
# look and say n times |
|||
def look_and_say(n): |
|||
if n == 0 then empty |
|||
else look_and_say as $lns |
|||
| $lns, ($lns|look_and_say(n-1)) |
|||
end ;</syntaxhighlight> |
|||
'''Example''' |
|||
1 | look_and_say(10) |
|||
{{Out}} |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
=={{header|Julia}}== |
|||
{{Works with|Julia|1.1}} |
|||
<syntaxhighlight lang="julia">function lookandsay(s::String) |
|||
rst = IOBuffer() |
|||
c = 1 |
|||
for i in 1:length(s) |
|||
if i != length(s) && s[i] == s[i+1] |
|||
c += 1 |
|||
else |
|||
print(rst, c, s[i]) |
|||
c = 1 |
|||
end |
|||
end |
|||
String(take!(rst)) |
|||
end |
|||
function lookandsayseq(n::Integer) |
|||
rst = Vector{String}(undef, n) |
|||
rst[1] = "1" |
|||
for i in 2:n |
|||
rst[i] = lookandsay(rst[i-1]) |
|||
end |
|||
rst |
|||
end |
|||
println(lookandsayseq(10))</syntaxhighlight> |
|||
{{out}} |
|||
<pre>String["1", "11", "21", "1211", "111221", "312211", "13112221", "1113213211", "31131211131221", "13211311123113112211"]</pre> |
|||
=={{header|K}}== |
|||
<syntaxhighlight lang="k"> las: {x{0$,//$(#:'n),'*:'n:(&1,~=':x)_ x:0$'$x}\1} |
|||
las 8 |
|||
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221</syntaxhighlight> |
|||
=={{header|Kotlin}}== |
|||
<syntaxhighlight lang="scala">// version 1.0.6 |
|||
fun lookAndSay(s: String): String { |
|||
val sb = StringBuilder() |
|||
var digit = s[0] |
|||
var count = 1 |
|||
for (i in 1 until s.length) { |
|||
if (s[i] == digit) |
|||
count++ |
|||
else { |
|||
sb.append("$count$digit") |
|||
digit = s[i] |
|||
count = 1 |
|||
} |
|||
} |
|||
return sb.append("$count$digit").toString() |
|||
} |
|||
fun main(args: Array<String>) { |
|||
var las = "1" |
|||
for (i in 1..15) { |
|||
println(las) |
|||
las = lookAndSay(las) |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221 |
|||
</pre> |
|||
=={{header|Lasso}}== |
|||
The Look-and-say sequence is a recursive RLE, so the solution can leverage the same method as used for RLE. |
|||
<syntaxhighlight 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' ^}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221 |
|||
132113213221133112132113311211131221121321131211132221123113112221131112311332111213211322211312113211</pre> |
|||
=={{header|LiveCode}}== |
|||
This function takes a string and returns the next Look-And-Say iteration of it: |
|||
<syntaxhighlight lang="lua">function lookAndSay S |
|||
put 0 into C |
|||
put char 1 of S into lastChar |
|||
repeat with i = 2 to length(S) |
|||
add 1 to C |
|||
if char i of S is lastChar then next repeat |
|||
put C & lastChar after R |
|||
put 0 into C |
|||
put char i of S into lastChar |
|||
end repeat |
|||
return R & C + 1 & lastChar |
|||
end lookAndSay |
|||
on demoLookAndSay |
|||
put 1 into x |
|||
repeat 10 |
|||
put x & cr after message |
|||
put lookAndSay(x) into x |
|||
end repeat |
|||
put x after message |
|||
end demoLookAndSay</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221</pre> |
|||
=={{header|Logo}}== |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
=={{header|Lua}}== |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
Alternative solution, using LPeg: |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
Alternative solution, using Lua Pattern: |
|||
<syntaxhighlight lang="lua">function lookandsay(t) |
|||
return t:gsub("(1*)(2*)(3*)", function (...) |
|||
local ret = {} |
|||
for i = 1, select("#", ...) do |
|||
local v = select(i, ...) |
|||
if #v > 0 then |
|||
ret[#ret + 1] = #v |
|||
ret[#ret + 1] = v:sub(1,1) |
|||
end |
|||
end |
|||
return table.concat(ret) |
|||
end) |
|||
end |
|||
local t = "1" |
|||
for i = 1, 10 do |
|||
print(t) |
|||
t = lookandsay(t) |
|||
end</syntaxhighlight> |
|||
<syntaxhighlight lang="lua">function lookandsay2(t) |
|||
return t:gsub("(1*)(2*)(3*)", function (x, y, z) |
|||
return (x == "" and x or (#x .. x:sub(1, 1))) .. |
|||
(y == "" and y or (#y .. y:sub(1, 1))) .. |
|||
(z == "" and z or (#z .. z:sub(1, 1))) |
|||
end) |
|||
end |
|||
local t = "1" |
|||
for i = 1, 10 do |
|||
print(t) |
|||
t = lookandsay2(t) |
|||
end</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211</pre> |
|||
=={{header|M4}}== |
=={{header|M4}}== |
||
Using regular expressions: |
Using regular expressions: |
||
{{trans|Perl}} |
{{trans|Perl}} |
||
< |
<syntaxhighlight lang="m4">divert(-1) |
||
define(`for', |
define(`for', |
||
`ifelse($#,0,``$0'', |
`ifelse($#,0,``$0'', |
||
Line 552: | Line 3,101: | ||
`v |
`v |
||
define(`v',las(v))')dnl |
define(`v',las(v))')dnl |
||
v</syntaxhighlight> |
|||
v </lang> |
|||
=={{header| |
=={{header|MACRO-11}}== |
||
<syntaxhighlight lang="macro11"> .TITLE LOKSAY |
|||
Custom Functions: |
|||
.MCALL .TTYOUT,.EXIT |
|||
<lang Mathematica>RunLengthEncode[x_List]:=(Through[{First,Length}[#]]&)/@Split[x] |
|||
LOKSAY::MOV #START,R0 |
|||
LookAndSay[n_,d_:1]:=NestList[Flatten[Reverse/@RunLengthEncode[#]]&,{d},n-1] </lang> |
|||
MOV #BUFR1,R1 |
|||
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: |
|||
JSR PC,COPY |
|||
<lang Mathematica> FromDigits /@ LookAndSay[13] // Column |
|||
MOV #^D14,R5 |
|||
FromDigits /@ LookAndSay[13, 7] // Column </lang> |
|||
$1: MOV #BUFR1,R1 |
|||
gives back: |
|||
JSR PC,PRINT |
|||
<pre style='height:15em;overflow:scroll'>1 |
|||
MOV #NEWLIN,R1 |
|||
JSR PC,PRINT |
|||
JSR PC,STEP |
|||
SOB R5,$1 |
|||
.EXIT |
|||
STEP: MOV #BUFR1,R0 |
|||
MOV #BUFR2,R1 |
|||
BR 2$ |
|||
1$: INC R3 |
|||
CMPB (R0)+,R4 |
|||
BEQ 1$ |
|||
ADD #60,R3 |
|||
MOVB R3,(R1)+ |
|||
MOVB R4,(R1)+ |
|||
DEC R0 |
|||
2$: CLR R3 |
|||
MOVB (R0)+,R4 |
|||
BNE 1$ |
|||
MOV #BUFR2,R0 |
|||
MOV #BUFR1,R1 |
|||
COPY: MOVB (R0)+,(R1)+ |
|||
BNE COPY |
|||
RTS PC |
|||
PRINT: MOVB (R1)+,R0 |
|||
.TTYOUT |
|||
BNE PRINT |
|||
RTS PC |
|||
NEWLIN: .BYTE 15,12,0,0 |
|||
START: .ASCIZ /1/ |
|||
BUFR1: .BLKB 400 |
|||
BUFR2: .BLKB 400 |
|||
.END LOKSAY</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
11 |
||
21 |
21 |
||
Line 575: | Line 3,158: | ||
3113112221232112111312211312113211 |
3113112221232112111312211312113211 |
||
1321132132111213122112311311222113111221131221 |
1321132132111213122112311311222113111221131221 |
||
11131221131211131231121113112221121321132132211331222113112211</pre> |
|||
=={{header|Maple}}== |
|||
<syntaxhighlight lang="maple">generate_seq := proc(s) |
|||
local times, output, i; |
|||
times := 1; |
|||
output := ""; |
|||
for i from 2 to StringTools:-Length(s) do |
|||
if (s[i] <> s[i-1]) then |
|||
output := cat(output, times, s[i-1]); |
|||
times := 1; # re-assign |
|||
else |
|||
times ++; |
|||
end if; |
|||
end do; |
|||
cat(output, times, s[i - 1]); |
|||
end proc: |
|||
Look_and_Say :=proc(n) |
|||
7 |
|||
local value, i; |
|||
value := "1"; |
|||
print(value); |
|||
for i from 2 to n do |
|||
value := generate_seq(value); |
|||
print(value); |
|||
end do; |
|||
end proc: |
|||
#Test: |
|||
Look_and_Say(10);</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
"1" |
|||
"11" |
|||
"21" |
|||
"1211" |
|||
"111221" |
|||
"312211" |
|||
"13112221" |
|||
"1113213211" |
|||
"31131211131221" |
|||
"13211311123113112211" |
|||
</pre> |
|||
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
|||
The function: |
|||
<syntaxhighlight lang="mathematica"> LookAndSay[n_Integer?Positive]:= Reverse @@@ Tally /@ Split @ IntegerDigits @ n // Flatten // FromDigits</syntaxhighlight> |
|||
takes as input an <em>arbitrary</em> positive integer and generates the next member of the ‘Look and Say’ sequence. |
|||
The first example returns the next 12 numbers of the sequence starting with 1: |
|||
<syntaxhighlight lang="mathematica">NestList[LookAndSay, 1, 12] // Column</syntaxhighlight> |
|||
<pre style='height:15em;overflow:scroll'>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221</pre> |
|||
The second example returns the next 12 numbers of the sequence starting with 7: |
|||
<syntaxhighlight lang="mathematica">NestList[LookAndSay, 7, 12] // Column</syntaxhighlight> |
|||
<pre style='height:15em;overflow:scroll'>7 |
|||
17 |
17 |
||
1117 |
1117 |
||
Line 589: | Line 3,243: | ||
11131221131211132221232112111312111213322117 |
11131221131211132221232112111312111213322117 |
||
31131122211311123113321112131221123113111231121123222117 </pre> |
31131122211311123113321112131221123113111231121123222117 </pre> |
||
=={{header|Maxima}}== |
|||
<syntaxhighlight 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" */</syntaxhighlight> |
|||
Implementation treating the sequence as numbers |
|||
<syntaxhighlight lang="maxima"> |
|||
ciphers(n):=block(makelist(floor(mod(n, 10^(k+1)) / 10^k), k, 0,floor(log(n)/log(10))),reverse(%%)); |
|||
collect(a) := block( |
|||
[n: length(ciphers(a)), b: [ ], x: ciphers(a)[1], m: 1], |
|||
for i from 2 thru n do |
|||
(if ciphers(a)[i] = x then m: m + 1 else (b: endcons([x, m], b), x: ciphers(a)[i], m: 1)), |
|||
b: endcons([x, m], b), |
|||
map(reverse,%%), |
|||
flatten(%%), |
|||
at(sum((part(%%,k))*y^(length(%%)-k),k,1,length(%%)),y=10) |
|||
)$ |
|||
block(i:1,append([i],makelist(i:collect(i),9)),table_form(%%)); |
|||
/* matrix( |
|||
[1], |
|||
[11], |
|||
[21], |
|||
[1211], |
|||
[111221], |
|||
[312211], |
|||
[13112221], |
|||
[1113213211], |
|||
[31131211131221], |
|||
[13211311123113112211] |
|||
) */ |
|||
</syntaxhighlight> |
|||
=={{header|MAXScript}}== |
=={{header|MAXScript}}== |
||
< |
<syntaxhighlight lang="maxscript">fn lookAndSay num = |
||
( |
( |
||
local result = "" |
local result = "" |
||
Line 620: | Line 3,326: | ||
print num |
print num |
||
num = lookAndSay num |
num = lookAndSay num |
||
)</ |
)</syntaxhighlight> |
||
=={{header|Metafont}}== |
=={{header|Metafont}}== |
||
<syntaxhighlight lang="metafont">vardef lookandsay(expr s) = |
|||
<lang metafont>vardef lookandsay(expr s) = |
|||
string r; r := ""; |
string r; r := ""; |
||
if string s: |
if string s: |
||
Line 646: | Line 3,351: | ||
endfor |
endfor |
||
end</ |
end</syntaxhighlight> |
||
=={{header| |
=={{header|Miranda}}== |
||
<syntaxhighlight lang="miranda">main :: [sys_message] |
|||
<lang ocaml>let aux s = |
|||
main = [Stdout (lay (take 15 (iterate looksay "1")))] |
|||
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 [] |
|||
looksay :: [char]->[char] |
|||
let lookandsay num = |
|||
looksay = concat . map f . split |
|||
let l = aux num in |
|||
where f xs = show (#xs) ++ [hd xs] |
|||
let s = |
|||
List.map (fun (n,c) -> |
|||
(string_of_int n) ^ (String.make 1 c)) l |
|||
in |
|||
String.concat "" s |
|||
split :: [*]->[[*]] |
|||
let fold_loop f ini n = |
|||
split = foldr f [] |
|||
let rec aux i acc = |
|||
where f x [] = [[x]] |
|||
f x (ys:yss) = (x:ys):yss, if x = hd ys |
|||
then (acc) |
|||
= [x]:ys:yss, otherwise</syntaxhighlight> |
|||
else aux (succ i) (f acc i) |
|||
{{out}} |
|||
in |
|||
<pre>1 |
|||
aux 0 ini |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221</pre> |
|||
=={{header|MiniScript}}== |
|||
<syntaxhighlight lang="miniscript">// Look and Say Sequence |
|||
repeats = function(digit, string) |
|||
count = 0 |
|||
for c in string |
|||
if c != digit then break |
|||
count = count + 1 |
|||
end for |
|||
return str(count) |
|||
end function |
|||
numbers = "1" |
|||
print numbers |
|||
for i in range(1,10) // warning, loop size > 15 gets long numbers very quickly |
|||
number = "" |
|||
position = 0 |
|||
while position < numbers.len |
|||
repeatCount = repeats(numbers[position], numbers[position:]) |
|||
number = number + repeatCount + numbers[position] |
|||
position = position + repeatCount.val |
|||
end while |
|||
print number |
|||
numbers = number |
|||
end for</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
</pre> |
|||
=={{header|Modula-2}}== |
|||
let _ = |
|||
<syntaxhighlight lang="modula2">MODULE LookAndSay; |
|||
fold_loop |
|||
FROM InOut IMPORT WriteString, WriteLn; |
|||
(fun num _ -> |
|||
FROM Strings IMPORT Assign, Length; |
|||
let next = lookandsay num in |
|||
print_endline next; |
|||
(next)) |
|||
(string_of_int 1) 10</lang> |
|||
CONST |
|||
Alternately, using the included Str library: |
|||
MaxSize = 128; |
|||
Steps = 14; |
|||
VAR |
|||
<lang ocaml>#load "str.cma";; |
|||
buf1, buf2: ARRAY [0..MaxSize-1] OF CHAR; |
|||
step: CARDINAL; |
|||
PROCEDURE LookSay(in: ARRAY OF CHAR; VAR out: ARRAY OF CHAR); |
|||
VAR count, inIdx, outIdx: CARDINAL; |
|||
curChar: CHAR; |
|||
BEGIN |
|||
inIdx := 0; |
|||
outIdx := 0; |
|||
WHILE in[inIdx] # CHR(0) DO |
|||
curChar := in[inIdx]; |
|||
count := 0; |
|||
REPEAT |
|||
INC(inIdx); |
|||
INC(count); |
|||
UNTIL in[inIdx] # curChar; |
|||
out[outIdx] := CHR(ORD('0') + count); |
|||
out[outIdx+1] := curChar; |
|||
outIdx := outIdx + 2; |
|||
END; |
|||
out[outIdx] := CHR(0); |
|||
END LookSay; |
|||
BEGIN |
|||
Assign("1", buf1); |
|||
FOR step := 1 TO Steps DO |
|||
WriteString(buf1); |
|||
WriteLn(); |
|||
LookSay(buf1, buf2); |
|||
Assign(buf2, buf1); |
|||
END; |
|||
END LookAndSay.</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
1113122113121113123112111311222112132113213221133122211311221</pre> |
|||
=={{header|NewLisp}}== |
|||
<syntaxhighlight lang="newlisp"> |
|||
;;; Compute the following number in the sequence |
|||
(define (next-number s) |
|||
(let (n 0 c (first s) res "") |
|||
(dostring (x s) |
|||
(if (= (char x) c) ; the iteration variable is the ASCII code |
|||
(++ n) |
|||
(begin |
|||
(setq res (string res n c)) |
|||
(setq n 1 c (char x))))) |
|||
(setq res (string res n c)) |
|||
res)) |
|||
; |
|||
;;; Print out the first n+1 numbers, starting from 1 |
|||
(define (go n) |
|||
(let (s "1") |
|||
(println s) |
|||
(dotimes (x n) |
|||
(setq s (next-number s)) |
|||
(println s)))) |
|||
; |
|||
(go 10) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
</pre> |
|||
=={{header|Nim}}== |
|||
<syntaxhighlight lang="nim">iterator lookAndSay(n: int): string = |
|||
var current = "1" |
|||
yield current |
|||
for round in 2..n: |
|||
var ch = current[0] |
|||
var count = 1 |
|||
var next = "" |
|||
for i in 1..current.high: |
|||
if current[i] == ch: |
|||
inc count |
|||
else: |
|||
next.add $count & ch |
|||
ch = current[i] |
|||
count = 1 |
|||
current = next & $count & ch |
|||
yield current |
|||
for s in lookAndSay(12): |
|||
echo s</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211</pre> |
|||
=={{header|Objective-C}}== |
|||
<syntaxhighlight lang="objc">#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]; |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|OCaml}}== |
|||
=== Functional === |
|||
This function computes a see-and-say sequence from the previous one: |
|||
<syntaxhighlight lang="ocaml">let rec seeAndSay = function |
|||
| [], nys -> List.rev nys |
|||
| x::xs, [] -> seeAndSay(xs, [x; 1]) |
|||
| x::xs, y::n::nys when x=y -> seeAndSay(xs, y::1+n::nys) |
|||
| x::xs, nys -> seeAndSay(xs, x::1::nys)</syntaxhighlight> |
|||
It can be used like this: |
|||
<syntaxhighlight lang="ocaml">> let gen n = |
|||
let xs = Array.create n [1] in |
|||
for i=1 to n-1 do |
|||
xs.(i) <- seeAndSay(xs.(i-1), []) |
|||
done; |
|||
xs;; |
|||
val gen : int -> int list array = <fun> |
|||
> gen 10;; |
|||
- : int list array = |
|||
[|[1]; [1; 1]; [2; 1]; [1; 2; 1; 1]; [1; 1; 1; 2; 2; 1]; [3; 1; 2; 2; 1; 1]; |
|||
[1; 3; 1; 1; 2; 2; 2; 1]; [1; 1; 1; 3; 2; 1; 3; 2; 1; 1]; |
|||
[3; 1; 1; 3; 1; 2; 1; 1; 1; 3; 1; 2; 2; 1]; |
|||
[1; 3; 2; 1; 1; 3; 1; 1; 1; 2; 3; 1; 1; 3; 1; 1; 2; 2; 1; 1]|]</syntaxhighlight> |
|||
=== With regular expressions in the Str library === |
|||
<syntaxhighlight lang="ocaml">#load "str.cma";; |
|||
let lookandsay = |
let lookandsay = |
||
Line 700: | Line 3,631: | ||
num := lookandsay !num; |
num := lookandsay !num; |
||
print_endline !num; |
print_endline !num; |
||
done</ |
done</syntaxhighlight> |
||
=== With regular expressions in the Pcre library === |
|||
Another solution using the pcre bindings: |
|||
<syntaxhighlight lang="ocaml">open Pcre |
|||
<lang ocaml>open Pcre |
|||
let lookandsay str = |
let lookandsay str = |
||
Line 720: | Line 3,650: | ||
num := lookandsay !num; |
num := lookandsay !num; |
||
print_endline !num; |
print_endline !num; |
||
done</ |
done</syntaxhighlight> |
||
run this example with 'ocaml -I +pcre pcre.cma script.ml' |
|||
=== Imperative === |
|||
<syntaxhighlight 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 *)</syntaxhighlight> |
|||
=={{header|Oforth}}== |
|||
<syntaxhighlight lang="oforth">import: mapping |
|||
: lookAndSay ( n -- ) |
|||
[ 1 ] #[ dup .cr group map( [#size, #first] ) expand ] times( n ) ;</syntaxhighlight> |
|||
{{out}} for n = 10 : |
|||
<pre> |
|||
[1] |
|||
[1, 1] |
|||
[2, 1] |
|||
[1, 2, 1, 1] |
|||
[1, 1, 1, 2, 2, 1] |
|||
[3, 1, 2, 2, 1, 1] |
|||
[1, 3, 1, 1, 2, 2, 2, 1] |
|||
[1, 1, 1, 3, 2, 1, 3, 2, 1, 1] |
|||
[3, 1, 1, 3, 1, 2, 1, 1, 1, 3, 1, 2, 2, 1] |
|||
[1, 3, 2, 1, 1, 3, 1, 1, 1, 2, 3, 1, 1, 3, 1, 1, 2, 2, 1, 1] |
|||
</pre> |
|||
=={{header|Oz}}== |
|||
<syntaxhighlight 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}</syntaxhighlight> |
|||
=={{header|PARI/GP}}== |
|||
<syntaxhighlight 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))</syntaxhighlight> |
|||
=={{header|Pascal}}== |
|||
{{works with|Free_Pascal}} |
|||
{{works with|Delphi}} |
|||
{{libheader|SysUtils}} |
|||
<syntaxhighlight lang="pascal">program LookAndSayDemo(input, output); |
|||
{$IFDEF FPC} |
|||
{$MODE DELPHI} |
|||
{$ENDIF} |
|||
uses |
|||
SysUtils; |
|||
function LookAndSay(s: string): string; |
|||
var |
|||
item: char; |
|||
index: integer; |
|||
count: integer; |
|||
begin |
|||
Result := ''; |
|||
item := s[1]; |
|||
count := 1; |
|||
for index := 2 to length(s) do |
|||
if item = s[index] then |
|||
inc(count) |
|||
else |
|||
begin |
|||
Result := Result + intTostr(count) + item; |
|||
item := s[index]; |
|||
count := 1; |
|||
end; |
|||
Result := Result + 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.</syntaxhighlight> |
|||
{{out}} |
|||
<pre>% ./LookAndSay |
|||
Press RETURN to continue and ^C to stop. |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211^C |
|||
</pre> |
|||
Even faster imperative Version |
|||
Improvement: |
|||
setlength of result,no inttoStr and using pChar |
|||
But the Code Alignment is very important. |
|||
{{works with|Free_Pascal}} |
|||
{{libheader|SysUtils}} |
|||
<syntaxhighlight lang="pascal"> |
|||
program LookAndSayDemo(input, output); |
|||
{$IFDEF FPC} |
|||
{$Mode Delphi} // using result |
|||
{$optimization ON} |
|||
// i3-4330 3.5 Ghz |
|||
// {$CodeAlign proc=16,loop=8} //2,6 secs |
|||
{$CodeAlign proc=16,loop=1} //1,6 secs so much faster ??? |
|||
{$ENDIF} |
|||
uses |
|||
SysUtils; |
|||
const |
|||
cntChar : array[1..9] of char = |
|||
('1','2','3','4','5','6','7','8','9'); |
|||
function LookAndSay2 (const s: string): string; |
|||
//using pChar for result |
|||
var |
|||
source, |
|||
destin : pChar; |
|||
len, |
|||
idxFrom, |
|||
idxTo : integer; |
|||
cnt: integer; |
|||
item: char; |
|||
begin |
|||
idxFrom := length(s); |
|||
source := @s[1]; |
|||
//adjust length of result |
|||
len := round(length(s)* 1.306+10); |
|||
setlength(result,len); |
|||
destin := @result[1]; |
|||
dec(destin); |
|||
idxto := 1; |
|||
item := source^; |
|||
inc(source); |
|||
cnt := 1; |
|||
for idxFrom := idxFrom downto 2 do |
|||
begin |
|||
if item <> source^ then |
|||
begin |
|||
destin[idxTo] := cntChar[cnt]; |
|||
destin[idxTo+1]:= item; |
|||
item := source^; |
|||
cnt := 1; |
|||
inc(idxto,2); |
|||
end |
|||
else |
|||
inc(cnt); |
|||
inc(source); |
|||
end; |
|||
destin[idxTo] := cntChar[cnt]; |
|||
destin[idxTo+1]:= item; |
|||
setlength(result,idxto+1); |
|||
end; |
|||
var |
|||
number: string; |
|||
l1,l2, |
|||
i : integer; |
|||
begin |
|||
number := '1'; |
|||
writeln(number); |
|||
writeln(1:4,length(number):16,1/1:10:6); |
|||
For i := 2 to 70 do |
|||
begin |
|||
l1 := length(number); |
|||
number := LookAndSay2(number); |
|||
l2 := length(number); |
|||
IF i <10 then |
|||
writeln(number); |
|||
writeln(i:4,length(number):16,l2/l1:10:6); |
|||
end; |
|||
end.</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
1 1 1.000000 |
|||
11 |
|||
2 2 2.000000 |
|||
21 |
|||
3 2 1.000000 |
|||
1211 |
|||
4 4 2.000000 |
|||
111221 |
|||
5 6 1.500000 |
|||
312211 |
|||
6 6 1.000000 |
|||
13112221 |
|||
7 8 1.333333 |
|||
1113213211 |
|||
8 10 1.250000 |
|||
31131211131221 |
|||
9 14 1.400000 |
|||
10 20 1.428571 |
|||
11 26 1.300000 |
|||
12 34 1.307692 |
|||
13 46 1.352941 |
|||
14 62 1.347826 |
|||
15 78 1.258065 |
|||
16 102 1.307692 |
|||
........ |
|||
67 81117366 1.303580 |
|||
68 105745224 1.303608 |
|||
69 137842560 1.303535 |
|||
70 179691598 1.303600 |
|||
real 0m1.639s |
|||
user 0m1.593s |
|||
sys 0m0.043s</pre> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
< |
<syntaxhighlight lang="perl">sub lookandsay { |
||
my $str = shift; |
my $str = shift; |
||
$str =~ s/((.)\2*)/length($1) . $2/ge; |
$str =~ s/((.)\2*)/length($1) . $2/ge; |
||
Line 733: | Line 3,967: | ||
print "$num\n"; |
print "$num\n"; |
||
$num = lookandsay($num); |
$num = lookandsay($num); |
||
}</ |
}</syntaxhighlight> |
||
Using string as a cyclic buffer: |
|||
<syntaxhighlight lang="perl">for (local $_ = "1\n"; s/((.)\2*)//s;) { |
|||
print $1; |
|||
$_ .= ($1 ne "\n" and length($1)).$2 |
|||
}</syntaxhighlight> |
|||
=={{header|Phix}}== |
|||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">lookandsay</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">=</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">c</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> |
|||
<span style="color: #008080;">else</span> |
|||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d%s"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> |
|||
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d%s"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"1"</span> |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">s</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lookandsay</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">s</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
|||
<pre> |
|||
"1" |
|||
"11" |
|||
"21" |
|||
"1211" |
|||
"111221" |
|||
"312211" |
|||
"13112221" |
|||
"1113213211" |
|||
"31131211131221" |
|||
"13211311123113112211" |
|||
"11131221133112132113212221" |
|||
</pre> |
|||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
< |
<syntaxhighlight lang="php"><?php |
||
function lookandsay($str) { |
|||
function lookAndSay($str) { |
|||
return preg_replace('/(.)\1*/e', 'strlen($0) . $1', $str); |
|||
return preg_replace_callback('#(.)\1*#', function($matches) { |
|||
return strlen($matches[0]).$matches[1]; |
|||
}, $str); |
|||
} |
} |
||
$num = "1"; |
$num = "1"; |
||
foreach (range(1,10) as $i) { |
|||
foreach(range(1,10) as $i) { |
|||
echo "$num\n"; |
|||
$num = lookandsay($num); |
|||
echo $num."<br/>"; |
|||
$num = lookAndSay($num); |
|||
} |
} |
||
?></lang> |
|||
?></syntaxhighlight> |
|||
=={{header|PowerBASIC}}== |
|||
=={{header|Picat}}== |
|||
This uses the PowerBASIC <code>RLEncode</code> function from [[Run-length encoding]]. |
|||
<syntaxhighlight lang="picat">go => |
|||
S1 = "1", |
|||
foreach(_ in 1..11) |
|||
println(S1), |
|||
S1 := runs(S1) |
|||
end, |
|||
println(S1), |
|||
nl. |
|||
runs(X) = V => |
|||
<lang powerbasic>FUNCTION RLEncode (i AS STRING) AS STRING |
|||
S = "", |
|||
Last = X[1], |
|||
C = 1, |
|||
foreach(I in 2..X.length) |
|||
if X[I] == Last then |
|||
C := C + 1 |
|||
else |
|||
S := S ++ C.to_string() ++ [X[I-1]], |
|||
C := 1, |
|||
Last := X[I] |
|||
end |
|||
end, |
|||
V = S ++ C.to_string() ++ [Last].</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211</pre> |
|||
=={{header|PicoLisp}}== |
|||
<syntaxhighlight lang="picolisp">(de las (Lst) |
|||
(make |
|||
(while Lst |
|||
(let (N 1 C) |
|||
(while (= (setq C (pop 'Lst)) (car Lst)) |
|||
(inc 'N) ) |
|||
(link N C) ) ) ) )</syntaxhighlight> |
|||
Usage: |
|||
<syntaxhighlight 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)</syntaxhighlight> |
|||
=={{header|PL/M}}== |
|||
<syntaxhighlight lang="plm">100H: |
|||
BDOS: PROCEDURE (FN, ARG); DECLARE FN BYTE, ARG ADDRESS; GO TO 5; END BDOS; |
|||
EXIT: PROCEDURE; CALL BDOS(0,0); END EXIT; |
|||
PRINT: PROCEDURE (S); DECLARE S ADDRESS; CALL BDOS(9,S); END PRINT; |
|||
COPY$STRING: PROCEDURE (SRC, DEST); |
|||
DECLARE (SRC, DEST, I) ADDRESS; |
|||
DECLARE (S BASED SRC, D BASED DEST) BYTE; |
|||
I = 0; |
|||
DO WHILE S(I) <> '$'; |
|||
D(I) = S(I); |
|||
I = I + 1; |
|||
END; |
|||
D(I) = '$'; |
|||
END COPY$STRING; |
|||
COUNT: PROCEDURE (POS) BYTE; |
|||
DECLARE POS ADDRESS, (I, P BASED POS) BYTE; |
|||
I = 1; |
|||
DO WHILE P(I) = P; |
|||
I = I + 1; |
|||
END; |
|||
RETURN I; |
|||
END COUNT; |
|||
LOOK$SAY: PROCEDURE (OLD, NEW); |
|||
DECLARE (OLD, NEW) ADDRESS; |
|||
DECLARE (O BASED OLD, N BASED NEW, C) BYTE; |
|||
DO WHILE O <> '$'; |
|||
C = COUNT(OLD); |
|||
N = O; |
|||
N(1) = C + '0'; |
|||
NEW = NEW + 2; |
|||
OLD = OLD + C; |
|||
END; |
|||
N = '$'; |
|||
END LOOK$SAY; |
|||
DECLARE STEPS LITERALLY '15'; |
|||
DECLARE BUF$SIZE LITERALLY '128'; |
|||
DECLARE BUFR1 (BUF$SIZE) BYTE INITIAL ('1$'); |
|||
DECLARE BUFR2 (BUF$SIZE) BYTE; |
|||
DECLARE I BYTE; |
|||
DO I=1 TO STEPS; |
|||
CALL PRINT(.BUFR1); |
|||
CALL PRINT(.(13,10,'$')); |
|||
CALL LOOK$SAY(.BUFR1, .BUFR2); |
|||
CALL COPY$STRING(.BUFR2, .BUFR1); |
|||
END; |
|||
CALL EXIT; |
|||
EOF</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
12 |
|||
1121 |
|||
122111 |
|||
112213 |
|||
12221131 |
|||
1123123111 |
|||
12213111213113 |
|||
11221131132111311231 |
|||
12221231123121133112213111 |
|||
1123112131122131112112321222113113 |
|||
1221311221113112221131132112213121112312311231 |
|||
11221131122213311223123112312112221131112113213111213112213111 |
|||
122212311223113212223111213112213111211223123113211231211131132111311222113113</pre> |
|||
=={{header|PowerBASIC}}== |
|||
This uses the <code>RLEncode</code> function from the [[Run-length encoding#PowerBASIC|PowerBASIC Run-length encoding entry]]. |
|||
<syntaxhighlight lang="powerbasic">FUNCTION RLEncode (i AS STRING) AS STRING |
|||
DIM tmp1 AS STRING, tmp2 AS STRING, outP AS STRING |
DIM tmp1 AS STRING, tmp2 AS STRING, outP AS STRING |
||
DIM Loop0 AS LONG, count AS LONG |
DIM Loop0 AS LONG, count AS LONG |
||
Line 796: | Line 4,218: | ||
v = VAL(INPUTBOX$("Enter a number.")) |
v = VAL(INPUTBOX$("Enter a number.")) |
||
MSGBOX lookAndSay(v) |
MSGBOX lookAndSay(v) |
||
END FUNCTION</ |
END FUNCTION</syntaxhighlight> |
||
=={{header|PowerShell}}== |
=={{header|PowerShell}}== |
||
< |
<syntaxhighlight lang="powershell">function Get-LookAndSay ($n = 1) { |
||
$re = [regex] '(.)\1*' |
$re = [regex] '(.)\1*' |
||
$ret = "" |
$ret = "" |
||
Line 819: | Line 4,241: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre>PS> Get-MultipleLookAndSay 8 |
<pre>PS> Get-MultipleLookAndSay 8 |
||
1 |
1 |
||
Line 830: | Line 4,252: | ||
13112221 |
13112221 |
||
1113213211</pre> |
1113213211</pre> |
||
=={{header|Prolog}}== |
|||
Works with SWI-Prolog. |
|||
<syntaxhighlight 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). |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> ?- look_and_say([1]). |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
..........................</pre> |
|||
=={{header|Pure}}== |
|||
<syntaxhighlight 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);</syntaxhighlight> |
|||
=={{header|PureBasic}}== |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Enter start sequence: 1 |
|||
How many repetitions: 7 |
|||
Sequence: |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211</pre> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
{{trans|C sharp|C#}} |
{{trans|C sharp|C#}} |
||
<syntaxhighlight lang="python">def lookandsay(number): |
|||
<lang python>def lookandsay(number): |
|||
result = "" |
result = "" |
||
Line 855: | Line 4,399: | ||
for i in range(10): |
for i in range(10): |
||
print num |
print num |
||
num = lookandsay(num)</ |
num = lookandsay(num)</syntaxhighlight> |
||
Functional |
Functional |
||
{{works with|Python|2.4+}} |
{{works with|Python|2.4+}} |
||
< |
<syntaxhighlight lang="python">>>> from itertools import groupby |
||
>>> def lookandsay(number): |
>>> def lookandsay(number): |
||
return ''.join( str(len(list(g))) + k |
return ''.join( str(len(list(g))) + k |
||
Line 867: | Line 4,411: | ||
>>> for i in range(10): |
>>> for i in range(10): |
||
print numberstring |
print numberstring |
||
numberstring = lookandsay(numberstring)</ |
numberstring = lookandsay(numberstring)</syntaxhighlight> |
||
Output: |
|||
{{out}} |
|||
<pre>1 |
<pre>1 |
||
11 |
11 |
||
Line 882: | Line 4,425: | ||
13211311123113112211</pre> |
13211311123113112211</pre> |
||
'''As a generator'''<br> |
|||
Using regular expressions: |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
'''Using regular expressions'''<br> |
|||
{{trans|Perl}} |
{{trans|Perl}} |
||
< |
<syntaxhighlight lang="python">import re |
||
def lookandsay(str): |
def lookandsay(str): |
||
Line 892: | Line 4,457: | ||
for i in range(10): |
for i in range(10): |
||
print num |
print num |
||
num = lookandsay(num)</ |
num = lookandsay(num)</syntaxhighlight> |
||
=={{header|Q}}== |
|||
<syntaxhighlight lang="q">las:{{raze string[count@'x],'@'[;0]x:where[differ x]_x}\[x;1#"1"]} |
|||
las 8</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
,"1" |
|||
"11" |
|||
"21" |
|||
"1211" |
|||
"111221" |
|||
"312211" |
|||
"13112221" |
|||
"1113213211" |
|||
"31131211131221" |
|||
</pre> |
|||
=={{header|Quackery}}== |
|||
<syntaxhighlight lang="quackery"> [ stack ] is instances |
|||
[ 1 instances put |
|||
$ "" swap |
|||
behead swap space join |
|||
witheach |
|||
[ 2dup != iff |
|||
[ rot instances share |
|||
number$ join |
|||
rot join swap |
|||
1 instances replace ] |
|||
else |
|||
[ drop |
|||
1 instances tally ] ] |
|||
drop instances release ] is lookandsay ( $ --> $ ) |
|||
$ "1" |
|||
15 times |
|||
[ dup echo$ cr |
|||
lookandsay ] |
|||
echo$ cr</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221 |
|||
132113213221133112132113311211131221121321131211132221123113112221131112311332111213211322211312113211 |
|||
</pre> |
|||
=={{header|R}}== |
=={{header|R}}== |
||
Returning the value as an integer limits how long the sequence can get, |
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) |
|||
<syntaxhighlight lang="r">look.and.say <- function(x, return.an.int=FALSE) |
|||
{ |
{ |
||
#convert number to character vector |
#convert number to character vector |
||
Line 910: | Line 4,536: | ||
#convert to number, if desired |
#convert to number, if desired |
||
if(return.an.int) as.integer(newstr) else newstr |
if(return.an.int) as.integer(newstr) else newstr |
||
}</syntaxhighlight> |
|||
} </lang> |
|||
Example usage |
Example usage: |
||
< |
<syntaxhighlight lang="r">x <- 1 |
||
for(i in 1:10) |
for(i in 1:10) |
||
{ |
{ |
||
x <- look.and.say(x) |
x <- look.and.say(x) |
||
print(x) |
print(x) |
||
}</syntaxhighlight> |
|||
} </lang> |
|||
=={{header|Racket}}== |
|||
<syntaxhighlight lang="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)) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
</pre> |
|||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
{{works with|rakudo|2018.03}} |
|||
In Raku it is natural to avoid explicit loops; rather we use the sequence operator to define a lazy infinite sequence. We'll print the first 15 values here. |
|||
<syntaxhighlight lang="raku" line>.say for ('1', *.subst(/(.)$0*/, { .chars ~ .[0] }, :g) ... *)[^15];</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221</pre> |
|||
=={{header|REXX}}== |
|||
Programming note: this version works with any string (a '''null''' is assumed, which causes '''1''' to be used). |
|||
<br><br>If a negative number is specified (the number of iterations |
|||
to be used for the calculations), only the length of<br> |
|||
the number (or character string) is shown. |
|||
===simple version=== |
|||
<syntaxhighlight lang="rexx">/*REXX program displays the sequence (and/or lengths) for the look and say series.*/ |
|||
parse arg N ! . /*obtain optional arguments from the CL*/ |
|||
if N=='' | N=="," then N= 20 /*Not specified? Then use the default.*/ |
|||
if !=='' | !=="," then != 1 /* " " " " " " */ |
|||
do j=1 for abs(N) /*repeat a number of times to show NUMS*/ |
|||
if j\==1 then != lookNsay(!) /*invoke function to calculate next #. */ |
|||
if N<0 then say 'length['j"]:" length(!) /*Also, display the sequence's length.*/ |
|||
else say '['j"]:" ! /*display the number to the terminal. */ |
|||
end /*j*/ |
|||
exit 0 /*stick a fork in it, we're all done. */ |
|||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
|||
lookNsay: procedure; parse arg x,,$ /*obtain the (passed) argument {X}. */ |
|||
fin = '0'x /*use unique character to end scanning.*/ |
|||
x= x || fin /*append the FIN character to string.*/ |
|||
do k=1 by 0 /*now, process the given sequence. */ |
|||
y= substr(x, k, 1) /*pick off one character to examine. */ |
|||
if y== fin then return $ /*if we're at the end, then we're done.*/ |
|||
_= verify(x, y, , k) - k /*see how many characters we have of Y.*/ |
|||
$= $ || _ || y /*build the "look and say" sequence. */ |
|||
k= k + _ /*now, point to the next character. */ |
|||
end /*k*/</syntaxhighlight> |
|||
{{out|output|text= when using the default input values of: <tt> 20 1 </tt>}} |
|||
<pre> |
|||
[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 |
|||
</pre> |
|||
{{out|output|text= when using the input values of: <tt> 17 ggg </tt>}} |
|||
<pre> |
|||
[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 |
|||
</pre> |
|||
{{out|output|text= when using the input value of: <tt> -60 </tt>}} |
|||
(Shown at three-quarter size.) |
|||
<pre style="font-size:75%"> |
|||
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 |
|||
</pre> |
|||
===faster version=== |
|||
This version appends the generated parts of the sequence, and after it gets to a certain size (chunkSize), |
|||
<br>it appends the sequence generated (so far) to the primary sequence, and starts with a null sequence. |
|||
<br>This avoids appending a small character string to a growing larger and larger character string. |
|||
<syntaxhighlight lang="rexx">/*REXX program displays the sequence (and/or lengths) for the look and say series.*/ |
|||
parse arg N ! . /*obtain optional arguments from the CL*/ |
|||
if N=='' | N=="," then N= 20 /*Not specified? Then use the default.*/ |
|||
if !=='' | !=="," then != 1 /* " " " " " " */ |
|||
/* [↑] !: starting char for the seq.*/ |
|||
do j=1 for abs(N) /*repeat a number of times to show NUMS*/ |
|||
if j\==1 then != lookNsay(!) /*invoke function to calculate next #. */ |
|||
if N<0 then say 'length['j"]:" length(!) /*Also, display the sequence's length.*/ |
|||
else say '['j"]:" ! /*display the number to the terminal. */ |
|||
end /*j*/ |
|||
exit 0 /*stick a fork in it, we're all done. */ |
|||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
|||
lookNsay: procedure; parse arg x,,$ ! /*obtain the (passed) argument {X}. */ |
|||
chSize= 1000 /*define a sensible chunk size. */ |
|||
fin = '0'x /*use unique character to end scanning.*/ |
|||
x= x || fin /*append the FIN character to string.*/ |
|||
do k=1 by 0 /*now, process the given sequence. */ |
|||
y= substr(x, k, 1) /*pick off one character to examine. */ |
|||
if y==fin then return $ /*if we're at the end, then we're done.*/ |
|||
_= verify(x, y, , k) - k /*see how many characters we have of Y.*/ |
|||
$= $ || _ || y /*build the "look and say" sequence. */ |
|||
k= k + _ /*now, point to the next character. */ |
|||
if length($)<chSize then iterate /*Less than chunkSize? Then keep going*/ |
|||
!= ! || $ /*append $ to the ! string. */ |
|||
$= /*now, start $ from scratch. */ |
|||
chSize= chSize + 100 /*bump the chunkSize (length) counter.*/ |
|||
end /*k*/ |
|||
return ! || $ /*return the ! string plus the $ string*/</syntaxhighlight> |
|||
{{out|output|text= is identical to the 1<sup>st</sup> REXX version (the simple version).}}<br><br> |
|||
=={{header|Refal}}== |
|||
<syntaxhighlight lang="refal">$ENTRY Go { |
|||
= <Prout <Sequence 10 1>>; |
|||
}; |
|||
Sequence { |
|||
0 e.seq = ; |
|||
s.N e.seq = <Prout e.seq> |
|||
<Sequence <- s.N 1> <LookSay e.seq>>; |
|||
} |
|||
LookSay { |
|||
= ; |
|||
e.1, |
|||
<First <Group e.1> e.1>: (e.group) e.rest, |
|||
<Lenw e.group>: s.num s.item e.discard = |
|||
s.num s.item <LookSay e.rest>; |
|||
} |
|||
Group { |
|||
s.1 s.1 e.rest = <+ 1 <Group s.1 e.rest>>; |
|||
s.1 e.rest = 1; |
|||
};</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
1 1 |
|||
2 1 |
|||
1 2 1 1 |
|||
1 1 1 2 2 1 |
|||
3 1 2 2 1 1 |
|||
1 3 1 1 2 2 2 1 |
|||
1 1 1 3 2 1 3 2 1 1 |
|||
3 1 1 3 1 2 1 1 1 3 1 2 2 1 |
|||
1 3 2 1 1 3 1 1 1 2 3 1 1 3 1 1 2 2 1 1</pre> |
|||
=={{header|Ring}}== |
|||
<syntaxhighlight lang="ring"> |
|||
number = "1" |
|||
for nr = 1 to 10 |
|||
number = lookSay(number) |
|||
see number + nl |
|||
next |
|||
func lookSay n |
|||
i = 0 j = 0 c="" o="" |
|||
i = 1 |
|||
while i <= len(n) |
|||
c = substr(n,i,1) |
|||
j = i + 1 |
|||
while substr(n,j,1) = c |
|||
j += 1 |
|||
end |
|||
o += string(j-i) + c |
|||
i = j |
|||
end |
|||
return o |
|||
</syntaxhighlight> |
|||
=={{header|RPL}}== |
|||
{{works with|Halcyon Calc|4.2.7}} |
|||
{| class="wikitable" |
|||
! Code |
|||
! Comments |
|||
|- |
|||
| |
|||
≪ DUP 1 DUP SUB → str char |
|||
≪ 2 '''WHILE''' str OVER DUP SUB char == '''REPEAT''' 1 + '''END''' |
|||
DUP 1 - →STR char + |
|||
str ROT OVER SIZE SUB |
|||
≫ ≫ 'CountCut' STO |
|||
≪ |
|||
"" 1 CF SWAP |
|||
'''WHILE''' 1 FC? '''REPEAT''' |
|||
CountCut '''IF''' DUP "" == '''THEN''' 1 SF '''END''' |
|||
ROT ROT + SWAP |
|||
'''END''' DROP |
|||
≫ 'LKSAY' STO |
|||
| |
|||
''( "####" -- "n#" "remainder" )'' |
|||
Count occurences of 1st char |
|||
Build "n#" |
|||
Extract remaining string |
|||
''("M(n)" -- "M(n+1)" )'' |
|||
Initialize M(n+1) and flag |
|||
set flag if at end of "M(n)" |
|||
build "M(n+1)" |
|||
Forget "M(n)" |
|||
|} |
|||
The following line of code delivers what is required: |
|||
≪ {} 1 "1" 12 START SWAP OVER + SWAP LKSAY NEXT DROP ≫ |
|||
{{out}} |
|||
<pre> |
|||
1: { "1" "11" "21" "1211" "111221" "312211" "13112221" "1113213211" "31131211131221" "13211311123113112211" "11131221133112132113212221" "3113112221232112111312211312113211" } |
|||
</pre> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
The simplest one: |
|||
<syntaxhighlight lang="ruby"> |
|||
class String |
|||
def look_and_say |
|||
gsub(/(.)\1*/){|s| s.size.to_s + s[0]} |
|||
end |
|||
end |
|||
ss = '1' |
|||
12.times {puts ss; ss = ss.look_and_say} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
</pre> |
|||
{{trans|Perl}} |
{{trans|Perl}} |
||
< |
<syntaxhighlight lang="ruby">def lookandsay(str) |
||
str.gsub(/(.)\1*/) {$&.length.to_s + $1} |
|||
end |
end |
||
num = "1" |
num = "1" |
||
10.times do |
10.times do |
||
puts num |
|||
num = lookandsay(num) |
|||
end</ |
end</syntaxhighlight> |
||
{{out}} |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
</pre> |
|||
Using Enumerable#chunk |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
The '''output''' is the same above. |
|||
Without regular expression: |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
Using Array#cluster defined above: |
|||
<syntaxhighlight 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])</syntaxhighlight> |
|||
The '''output''' is the same above. |
|||
=={{header|Rust}}== |
|||
<syntaxhighlight lang="rust">fn next_sequence(in_seq: &[i8]) -> Vec<i8> { |
|||
assert!(!in_seq.is_empty()); |
|||
let mut result = Vec::new(); |
|||
let mut current_number = in_seq[0]; |
|||
let mut current_runlength = 1; |
|||
for i in &in_seq[1..] { |
|||
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 = vec![1]; |
|||
for i in 0..10 { |
|||
println!("Sequence {}: {:?}", i, seq); |
|||
seq = next_sequence(&seq); |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Sequence 0: [1] |
|||
Sequence 1: [1, 1] |
|||
Sequence 2: [2, 1] |
|||
Sequence 3: [1, 2, 1, 1] |
|||
Sequence 4: [1, 1, 1, 2, 2, 1] |
|||
Sequence 5: [3, 1, 2, 2, 1, 1] |
|||
Sequence 6: [1, 3, 1, 1, 2, 2, 2, 1] |
|||
Sequence 7: [1, 1, 1, 3, 2, 1, 3, 2, 1, 1] |
|||
Sequence 8: [3, 1, 1, 3, 1, 2, 1, 1, 1, 3, 1, 2, 2, 1] |
|||
Sequence 9: [1, 3, 2, 1, 1, 3, 1, 1, 1, 2, 3, 1, 1, 3, 1, 1, 2, 2, 1, 1]</pre> |
|||
=={{header|Sather}}== |
|||
<syntaxhighlight lang="sather">class MAIN is |
|||
look_and_say!: STR is |
|||
current ::= "1"; |
|||
loop |
|||
yield current; |
|||
buf ::= #FSTR; |
|||
last ::= current[0]; |
|||
count ::= 0; |
|||
loop |
|||
ch ::= current.elt!; |
|||
if ch /= last then |
|||
buf := buf + count + last; |
|||
last := ch; count := 1; |
|||
else |
|||
count := count + 1; |
|||
end; |
|||
end; |
|||
current := (buf + count + last).str; |
|||
end; |
|||
end; |
|||
main is |
|||
loop 12.times!; |
|||
#OUT+ look_and_say! + "\n"; |
|||
end; |
|||
end; |
|||
end;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211</pre> |
|||
=={{header|Scala}}== |
|||
===Recursive=== |
|||
<syntaxhighlight lang="scala">import scala.annotation.tailrec |
|||
object LookAndSay extends App { |
|||
loop(10, "1") |
|||
@tailrec |
|||
private def loop(n: Int, num: String): Unit = { |
|||
println(num) |
|||
if (n <= 0) () else loop(n - 1, lookandsay(num)) |
|||
} |
|||
private def lookandsay(number: String): String = { |
|||
val result = new StringBuilder |
|||
@tailrec |
|||
def loop(numberString: String, repeat: Char, times: Int): String = |
|||
if (numberString.isEmpty) result.toString() |
|||
else if (numberString.head != repeat) { |
|||
result.append(times).append(repeat) |
|||
loop(numberString.tail, numberString.head, 1) |
|||
} else loop(numberString.tail, numberString.head, times + 1) |
|||
loop(number.tail + " ", number.head, 1) |
|||
} |
|||
}</syntaxhighlight> |
|||
{{Out}}See it running in your browser by [https://scalafiddle.io/sf/V5Jn5mf/0 (JavaScript, non JVM)] or by [https://scastie.scala-lang.org/7kn0fV3gTaqCDLIv4QGuMQ Scastie (JVM)]. |
|||
===using Iterator=== |
|||
{{libheader|Scala}}<syntaxhighlight 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)</syntaxhighlight> |
|||
===using Stream=== |
|||
<syntaxhighlight lang="scala">object Main extends App { |
|||
def lookAndSay(previous: List[BigInt]): Stream[List[BigInt]] = { |
|||
def next(num: List[BigInt]): List[BigInt] = num match { |
|||
case Nil => Nil |
|||
case head :: Nil => 1 :: head :: Nil |
|||
case head :: tail => |
|||
val size = (num takeWhile (_ == head)).size |
|||
List(BigInt(size), head) ::: next(num.drop(size)) |
|||
} |
|||
val x = next(previous) |
|||
x #:: lookAndSay(x) |
|||
} |
|||
(lookAndSay(1 :: Nil) take 10).foreach(s => println(s.mkString(""))) |
|||
}</syntaxhighlight> |
|||
=={{header|Seed7}}== |
|||
<syntaxhighlight 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;</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221 |
|||
</pre> |
|||
=={{header|SETL}}== |
|||
<syntaxhighlight lang="setl">program looksay; |
|||
s := "1"; |
|||
loop for i in [1..10] do |
|||
print(s); |
|||
s := looksay(s); |
|||
end loop; |
|||
proc looksay(s); |
|||
loop for c in s do; |
|||
if cur /= c then |
|||
if count /= om then |
|||
r +:= count + cur; |
|||
end if; |
|||
cur := c; |
|||
count := 1; |
|||
else |
|||
count +:= 1; |
|||
end if; |
|||
end loop; |
|||
r +:= count + cur; |
|||
return r; |
|||
end proc; |
|||
end looksay;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211</pre> |
|||
=={{header|Sidef}}== |
|||
{{trans|Perl}} |
|||
<syntaxhighlight lang="ruby">func lookandsay(str) { |
|||
str.gsub(/((.)\2*)/, {|a,b| a.len.to_s + b }); |
|||
} |
|||
var num = "1"; |
|||
{ |
|||
say num; |
|||
num = lookandsay(num); |
|||
} * 10;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211</pre> |
|||
=={{header|Smalltalk}}== |
=={{header|Smalltalk}}== |
||
{{works with|GNU Smalltalk}} |
{{works with|GNU Smalltalk}} |
||
< |
<syntaxhighlight lang="smalltalk">String extend [ |
||
lookAndSay [ |anElement nextElement counter coll newColl| |
lookAndSay [ |anElement nextElement counter coll newColl| |
||
coll := (self asOrderedCollection). |
coll := (self asOrderedCollection). |
||
Line 962: | Line 5,253: | ||
r displayNl. |
r displayNl. |
||
r := r lookAndSay. |
r := r lookAndSay. |
||
]</ |
]</syntaxhighlight> |
||
{{works with|Pharo}} |
|||
<syntaxhighlight lang="smalltalk">String compile: |
|||
'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). |
|||
^('''' join: newColl)' |
|||
classified: 'toys'. |
|||
result := OrderedCollection new. |
|||
r := '1'. |
|||
result add: r. |
|||
result addAll: ((1 to: 10) collect: [ :i | |
|||
r := r lookAndSay. |
|||
]). |
|||
result. |
|||
</syntaxhighlight> |
|||
Output: |
|||
an OrderedCollection('1' '11' '21' '1211' '111221' '312211' '13112221' '1113213211' '31131211131221' '13211311123113112211' '11131221133112132113212221') |
|||
=={{header|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. |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211</pre> |
|||
=={{header|SQL}}== |
|||
<syntaxhighlight 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;</syntaxhighlight> |
|||
Usage: |
|||
[[Category:SQLite]] |
|||
<pre>% 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</pre> |
|||
=={{header|SQL PL}}== |
|||
{{works with|Db2 LUW}} version 9.7 or higher. |
|||
With SQL PL: |
|||
<syntaxhighlight lang="sql pl"> |
|||
SET SERVEROUTPUT ON @ |
|||
BEGIN |
|||
DECLARE NMBR VARCHAR(100) DEFAULT '1'; |
|||
DECLARE J SMALLINT DEFAULT 1; |
|||
CALL DBMS_OUTPUT.PUT_LINE(NMBR); |
|||
WHILE (J < 10) DO |
|||
BEGIN |
|||
DECLARE I SMALLINT; |
|||
DECLARE SIZE SMALLINT; |
|||
DECLARE ACTUAL CHAR(1); |
|||
DECLARE REPEAT CHAR(1); |
|||
DECLARE RESULT VARCHAR(100); |
|||
DECLARE TIMES SMALLINT; |
|||
SET REPEAT = SUBSTR(NMBR, 1, 1); |
|||
SET NMBR = SUBSTR(NMBR, 2) || ' '; |
|||
SET TIMES = 1; |
|||
SET I = 1; |
|||
SET SIZE = LENGTH(NMBR); |
|||
WHILE (I <= SIZE) DO |
|||
SET ACTUAL = SUBSTR(NMBR, I, 1); |
|||
IF (ACTUAL <> REPEAT) THEN |
|||
SET RESULT = COALESCE(RESULT, '') || TIMES || '' || REPEAT; |
|||
SET TIMES = 1; |
|||
SET REPEAT = ACTUAL; |
|||
ELSE |
|||
SET TIMES = TIMES + 1; |
|||
END IF; |
|||
SET I = I + 1; |
|||
END WHILE; |
|||
CALL DBMS_OUTPUT.PUT_LINE(RESULT); |
|||
SET NMBR = RESULT; |
|||
END ; |
|||
SET J = J + 1; |
|||
END WHILE; |
|||
END @ |
|||
</syntaxhighlight> |
|||
Output: |
|||
<pre> |
|||
db2 => BEGIN |
|||
... |
|||
db2 (cont.) => END @ |
|||
DB20000I The SQL command completed successfully. |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
</pre> |
|||
=={{header|Swift}}== |
|||
{{trans|Rust}} |
|||
<syntaxhighlight lang="swift">func lookAndSay(_ seq: [Int]) -> [Int] { |
|||
var result = [Int]() |
|||
var cur = seq[0] |
|||
var curRunLength = 1 |
|||
for i in seq.dropFirst() { |
|||
if cur == i { |
|||
curRunLength += 1 |
|||
} else { |
|||
result.append(curRunLength) |
|||
result.append(cur) |
|||
curRunLength = 1 |
|||
cur = i |
|||
} |
|||
} |
|||
result.append(curRunLength) |
|||
result.append(cur) |
|||
return result |
|||
} |
|||
var seq = [1] |
|||
for i in 0..<10 { |
|||
print("Seq \(i): \(seq)") |
|||
seq = lookAndSay(seq) |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Seq 0: [1] |
|||
Seq 1: [1, 1] |
|||
Seq 2: [2, 1] |
|||
Seq 3: [1, 2, 1, 1] |
|||
Seq 4: [1, 1, 1, 2, 2, 1] |
|||
Seq 5: [3, 1, 2, 2, 1, 1] |
|||
Seq 6: [1, 3, 1, 1, 2, 2, 2, 1] |
|||
Seq 7: [1, 1, 1, 3, 2, 1, 3, 2, 1, 1] |
|||
Seq 8: [3, 1, 1, 3, 1, 2, 1, 1, 1, 3, 1, 2, 2, 1] |
|||
Seq 9: [1, 3, 2, 1, 1, 3, 1, 1, 1, 2, 3, 1, 1, 3, 1, 1, 2, 2, 1, 1]</pre> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
< |
<syntaxhighlight lang="tcl">proc lookandsay n { |
||
set new "" |
set new "" |
||
while {[string length $n] > 0} { |
while {[string length $n] > 0} { |
||
Line 982: | Line 5,541: | ||
puts [next_lookandsay] ;# ==> 1211 |
puts [next_lookandsay] ;# ==> 1211 |
||
puts [next_lookandsay] ;# ==> 111221 |
puts [next_lookandsay] ;# ==> 111221 |
||
puts [next_lookandsay] ;# ==> 312211</ |
puts [next_lookandsay] ;# ==> 312211</syntaxhighlight> |
||
Alternatively, with coroutines: |
|||
{{works with|Tcl|8.6}} |
|||
<syntaxhighlight 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]</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
</pre> |
|||
=={{header|TUSCRIPT}}== |
|||
<syntaxhighlight 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 |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre style='height:30ex;overflow:scroll'> |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221 |
|||
</pre> |
|||
=={{header|Uiua}}== |
|||
As noted on the [https://rosettacode.org/wiki/Run-length_encoding Run-length encoding page], this is just RLE gone bad. |
|||
<syntaxhighlight lang="uiua"> |
|||
Rle ← /◇⊂≡⍚(⊂⊃(°⋕⧻|⊢))⊜□⊸(+1⊛) |
|||
⇌[⍥(⍚Rle.)10□] "1" |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
{"1" "11" "21" "1211" "111221" "312211" "13112221" "1113213211" "31131211131221" "13211311123113112211" "11131221133112132113212221"} |
|||
</pre> |
|||
=={{header|UNIX Shell}}== |
|||
{{works with|bash}} |
|||
<syntaxhighlight lang="bash">lookandsay() { |
|||
local num=$1 char seq i |
|||
for ((i=0; i<=${#num}; i++)); do |
|||
char=${num:i:1} |
|||
if [[ $char == ${seq:0:1} ]]; then |
|||
seq+=$char |
|||
else |
|||
[[ -n $seq ]] && printf "%d%s" ${#seq} ${seq:0:1} |
|||
seq=$char |
|||
fi |
|||
done |
|||
} |
|||
for ((num=1, i=1; i<=10; i++)); do |
|||
echo $num |
|||
num=$( lookandsay $num ) |
|||
done</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211</pre> |
|||
=={{header|Ursala}}== |
=={{header|Ursala}}== |
||
The look_and_say function returns the first n results |
The look_and_say function returns the first n results |
||
that maps a given sequence to its successor. |
by iterating the function that maps a given sequence to its successor. |
||
< |
<syntaxhighlight lang="ursala">#import std |
||
#import nat |
#import nat |
||
Line 994: | Line 5,667: | ||
#show+ |
#show+ |
||
main = look_and_say 10</ |
main = look_and_say 10</syntaxhighlight> |
||
{{out}} |
|||
output: |
|||
<pre>1 |
<pre>1 |
||
11 |
11 |
||
Line 1,007: | Line 5,680: | ||
13211311123113112211</pre> |
13211311123113112211</pre> |
||
=={{header|VBA}}== |
|||
<syntaxhighlight 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 |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
LookAndSay 7 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
</pre> |
|||
(Note: overflow occurs at 38th iteration!) |
|||
=={{header|VBScript}}== |
|||
=====Implementation===== |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
=====Invocation===== |
|||
<syntaxhighlight lang="vb">dim m |
|||
m = 1 |
|||
for i = 0 to 13 |
|||
m = looksay(m) |
|||
wscript.echo m |
|||
next</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221 |
|||
</pre> |
|||
=={{header|Vedit macro language}}== |
=={{header|Vedit macro language}}== |
||
This implementation generates look-and-say sequence |
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. |
|||
< |
<syntaxhighlight lang="vedit">Repeat(10) { |
||
BOL |
BOL |
||
Reg_Empty(20) |
Reg_Empty(20) |
||
Line 1,021: | Line 5,811: | ||
} |
} |
||
Ins_Newline Reg_Ins(20) |
Ins_Newline Reg_Ins(20) |
||
}</syntaxhighlight> |
|||
} </lang> |
|||
{{out}} |
|||
Output: |
|||
1 |
1 |
||
11 |
11 |
||
Line 1,035: | Line 5,825: | ||
13211311123113112211 |
13211311123113112211 |
||
11131221133112132113212221 |
11131221133112132113212221 |
||
=={{header|V (Vlang)}}== |
|||
{{trans|Go}} |
|||
<syntaxhighlight lang="v (vlang)">fn lss(s string) string { |
|||
mut r := '' |
|||
mut c := s[0..1] |
|||
mut nc := 1 |
|||
for i := 1; i < s.len; i++ { |
|||
d := s[i..i+1] |
|||
if d == c { |
|||
nc++ |
|||
continue |
|||
} |
|||
r += nc.str() + c |
|||
c = d |
|||
nc = 1 |
|||
} |
|||
return r + nc.str() + c |
|||
} |
|||
fn main() { |
|||
mut s := "1" |
|||
println(s) |
|||
for i := 0; i < 8; i++ { |
|||
s = lss(s) |
|||
println(s) |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
</pre> |
|||
=={{header|Wren}}== |
|||
{{trans|Kotlin}} |
|||
<syntaxhighlight lang="wren">var lookAndSay = Fn.new { |s| |
|||
var res = "" |
|||
var digit = s[0] |
|||
var count = 1 |
|||
for (i in 1...s.count) { |
|||
if (s[i] == digit) { |
|||
count = count + 1 |
|||
} else { |
|||
res = res + "%(count)%(digit)" |
|||
digit = s[i] |
|||
count = 1 |
|||
} |
|||
} |
|||
return res + "%(count)%(digit)" |
|||
} |
|||
var las = "1" |
|||
for (i in 1..15) { |
|||
System.print(las) |
|||
las = lookAndSay.call(las) |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221 |
|||
</pre> |
|||
=={{header|XPL0}}== |
|||
<syntaxhighlight lang "XPL0">char Seq0(100), Seq1(100); |
|||
int Iter, Digit, Count, I0, I1, T; |
|||
string 0; |
|||
[Seq0(0):= ^1; Seq0(1):= 0; |
|||
Text(0, Seq0); CrLf(0); |
|||
for Iter:= 2 to 15 do |
|||
[I1:= 0; I0:= 0; |
|||
repeat Digit:= Seq0(I0); |
|||
Count:= ^1; |
|||
I0:= I0+1; |
|||
while Seq0(I0) = Digit do |
|||
[Count:= Count+1; |
|||
I0:= I0+1; |
|||
]; |
|||
Seq1(I1):= Count; I1:= I1+1; |
|||
Seq1(I1):= Digit; I1:= I1+1; |
|||
until Seq0(I0) = 0; |
|||
Seq1(I1):= 0; |
|||
T:= Seq0; Seq0:= Seq1; Seq1:= T; |
|||
Text(0, Seq0); CrLf(0); |
|||
]; |
|||
]</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221 |
|||
</pre> |
|||
=={{header|Yabasic}}== |
|||
<syntaxhighlight lang="yabasic"> |
|||
dim X$(2) |
|||
i = 0 // índice de cadena de entrada |
|||
X$(i) = "1" |
|||
input "Indica cuantas repeticiones: " r |
|||
print "\nSecuencia:" |
|||
print X$(i) |
|||
for n = 1 to r-1 |
|||
j = 1 - i // índice de cadena de salida |
|||
X$(j) = "" |
|||
k = 1 |
|||
while k <= len(X$(i)) |
|||
k0 = k + 1 |
|||
while ((k0 <= len(X$(i))) and (mid$(X$(i), k, 1) = mid$(X$(i), k0, 1))) |
|||
k0 = k0 + 1 |
|||
wend |
|||
X$(j) = X$(j) + str$(k0 - k) + mid$(X$(i), k, 1) |
|||
k = k0 |
|||
wend |
|||
i = j |
|||
print X$(j) |
|||
next n |
|||
print |
|||
</syntaxhighlight> |
|||
{{out}}La salida es similar a la de [[#FreeBASIC|FreeBASIC]], mostrada arriba. |
|||
=={{header|Yorick}}== |
|||
<syntaxhighlight 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);</syntaxhighlight> |
|||
{{out}} |
|||
<pre> 1 |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
3113112221232112111312211312113211 |
|||
1321132132111213122112311311222113111221131221 |
|||
11131221131211131231121113112221121321132132211331222113112211 |
|||
311311222113111231131112132112311321322112111312211312111322212311322113212221</pre> |
|||
=={{header|zkl}}== |
|||
Treating the task as a string manipulation problem. |
|||
{{trans|Scala}} |
|||
<syntaxhighlight lang="zkl">fcn lookAndSay(seed){ // numeric String --> numeric String |
|||
len,c:=[1..seed.len()-1].reduce(fcn([(len,c)]lc,index,s,sb){ |
|||
if(c!=s[index]) { sb.write(len); sb.write(c); lc.clear(1,s[index]) } |
|||
else lc.clear(len+1,c); |
|||
},L(1,seed[0]), seed,sb:=Sink(String)); |
|||
sb.write(len); sb.write(c); |
|||
sb.close(); |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
(0).reduce(10,fcn(seed,_){ lookAndSay(seed).println() },"1"); |
|||
11 |
|||
21 |
|||
1211 |
|||
111221 |
|||
312211 |
|||
13112221 |
|||
1113213211 |
|||
31131211131221 |
|||
13211311123113112211 |
|||
11131221133112132113212221 |
|||
</pre> |
Latest revision as of 22:07, 24 June 2024
You are encouraged to solve this task according to the task description, using any language you may know.
The Look and say sequence is a recursively defined sequence of numbers studied most notably by John Conway.
The look-and-say sequence is also known as the Morris Number Sequence, after cryptographer Robert Morris, and the puzzle What is the next number in the sequence 1, 11, 21, 1211, 111221? is sometimes referred to as the Cuckoo's Egg, from a description of Morris in Clifford Stoll's book The Cuckoo's Egg.
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.
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
Write a program to generate successive members of the look-and-say sequence.
- Related tasks
- Fours is the number of letters in the ...
- Number names
- Self-describing numbers
- Self-referential sequence
- Spelling of ordinal numbers
- See also
- Look-and-Say Numbers (feat John Conway), A Numberphile Video.
- This task is related to, and an application of, the Run-length encoding task.
- Sequence A005150 on The On-Line Encyclopedia of Integer Sequences.
11l
F lookandsay(=number)
V result = ‘’
V repeat = number[0]
number = number[1..]‘ ’
V times = 1
L(actual) number
I actual != repeat
result ‘’= String(times)‘’repeat
times = 1
repeat = actual
E
times++
R result
V num = ‘1’
L 10
print(num)
num = lookandsay(num)
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211
8080 Assembly
bdos: equ 5 ; CP/M calls
puts: equ 9
nmemb: equ 15 ; Change this to print more or fewer members
org 100h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Generate and output members of the sequence
mvi b,nmemb ; Counter
outloop: push b ; Preserve counter across calls
mvi c,puts ; Output current member
lxi d,memb
call bdos ; And newline
mvi c,puts
lxi d,newline
call bdos
lxi h,memb ; Generate next member
call looksay
pop b ; Restore counter
dcr b ; Done yet?
jnz outloop
rst 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Given a $-terminated string under HL, representing
;; a member of the look and say sequence, generate
;; the next one in place (ish). The memory after the
;; string is assumed to be free.
looksay: push h ; Save start of string on stack
mov d,h ; And in DE
mov e,l
mvi a,'$' ; Find end of string
findend: cmp m
inx h
jnz findend
xchg ; HL=string, DE=destination
push d ; Save start of new string on stack
lookchar: mvi b,0 ; Zero counter
lookloop: mov a,m ; Get current character
inr b ; Compare next character
inx h
cmp m ; While it is the same, keep going
jz lookloop
mov c,a ; Keep character
mvi a,'0' ; There are B amount of these characters
add b
stax d ; Store the amount
inx d ; And in the next location
mov a,c ; Store the character
stax d
inx d
mvi a,'$' ; Are we done?
cmp m
jnz lookchar ; If not, do next character
stax d ; If yes, terminate new string
;; Free up memory by copying the new string to where the old
;; string began.
pop d ; Start of new string
pop h ; Start of old string
copyloop: ldax d ; Get char from new string
mov m,a ; Store char where old string was
cpi '$' ; are we done yet?
inx d
inx h
jnz copyloop
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
newline: db 13,10,'$'
;; This is where the string will be stored.
memb: db '1$' ; First item
; Due to how CP/M loads programs, the memory after here
; is free until we hit the stack.
8086 Assembly
bits 16
cpu 8086
puts: equ 9h ; MS/DOS system call to print a string
nmemb: equ 15 ; Change this to print more or fewer members
section .text
org 100h
mov cx,nmemb ; CX = how many members to print
outloop: mov dx,memb ; Print current member
mov ah,puts
int 21h
mov dx,newline ; Print newline
int 21h
mov di,memb ; Generate next member
call looksay
loop outloop ; Decrease CX, and loop until zero.
ret ; Go back to DOS.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Given a look and say string in ES:DI, generate the next
;;; one in place. Assumption: DS = ES.
looksay: push cx ; Keep the counter register
mov si,di ; Store pointer to string begin in SI
mov bx,di ; And another in BX
mov al,'$' ; Find the end of the string
xor cx,cx ; Max. 65535 tries
dec cx
repne scasb ; The 8086 has dedicated string search
mov dx,di ; Store copy of start of new str in DX
;;; Process one character
.procchar: mov al,'0' ; Set counter to ASCII 0
mov ah,[bx] ; Get current character of string
cmp ah,'$' ; Done?
je .done
.samechar: inc bx ; Increment pointer
inc al ; Increment counter
cmp ah,[bx] ; Still the same character?
je .samechar ; If yes, test next character
mov [di],ax ; Store counter and character
inc di ; Move ahead two characters
inc di
jmp .procchar ; Do next character
;;; Copy new string into old location
.done: mov byte [di],'$' ; Terminate the string
mov cx,di ; Calculate how many bytes to copy
sub cx,dx ; end + 1 - start, so one too few here
shr cx,1 ; Divide by 2 = words
inc cx ; Compensate for the missing +1
mov di,dx ; Pointer to begin of new string
xchg si,di ; Set SI = new string and DI = old
rep movsw ; Copy 16 bits at a time
pop cx ; Restore counter register
ret
section .data
newline: db 13,10,'$' ; Newline to print in between members
memb: db '1$' ; This is where the current member is stored
ABC
HOW TO RETURN look.and.say seq:
PUT "" IN result
PUT 0 IN n
PUT "" IN c
FOR ch IN seq:
SELECT:
c=ch:
PUT n+1 IN n
ELSE:
IF n>0: PUT result^"`n`"^c IN result
PUT 1 IN n
PUT ch IN c
RETURN result^"`n`"^c
PUT "1" IN item
FOR i IN {1..14}:
WRITE item/
PUT look.and.say item IN item
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211
Action!
BYTE FUNC GetLength(CHAR ARRAY s BYTE pos)
CHAR c
BYTE len
c=s(pos)
len=1
DO
pos==+1
IF pos<=s(0) AND s(pos)=c THEN
len==+1
ELSE
EXIT
FI
OD
RETURN (len)
PROC Append(CHAR ARRAY text,suffix)
BYTE POINTER srcPtr,dstPtr
BYTE len
len=suffix(0)
IF text(0)+len>255 THEN
len=255-text(0)
FI
IF len THEN
srcPtr=suffix+1
dstPtr=text+text(0)+1
MoveBlock(dstPtr,srcPtr,len)
text(0)==+suffix(0)
FI
RETURN
PROC LookAndSay(CHAR ARRAY in,out)
BYTE pos,len
CHAR ARRAY tmp(5)
pos=1 len=0 out(0)=0
WHILE pos<=in(0)
DO
len=GetLength(in,pos)
StrB(len,tmp)
Append(out,tmp)
out(0)==+1
out(out(0))=in(pos)
pos==+len
OD
RETURN
PROC Main()
CHAR ARRAY s1(256),s2(256)
BYTE i
SCopy(s1,"1")
PrintE(s1)
FOR i=1 TO 11
DO
IF (i&1)=0 THEN
LookAndSay(s2,s1)
PrintE(s1)
ELSE
LookAndSay(s1,s2)
PrintE(s2)
FI
OD
RETURN
- Output:
Screenshot from Atari 8-bit computer
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211
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"))))))))));
- Output:
11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221
ALGOL 68
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
ALGOL-M
begin
string(1) function digit(n);
integer n;
case n of begin
digit := "0"; digit := "1"; digit := "2";
digit := "3"; digit := "4"; digit := "5";
digit := "6"; digit := "7"; digit := "8";
digit := "9";
end;
string(1) array cur[1:128];
string(1) array next[1:128];
integer curlen, i, cnt, j, n;
cur[1] := "1";
curlen := 1;
for n := 1 step 1 until 15 do begin
write("");
for i := 1 step 1 until curlen do
writeon(cur[i]);
i := j := 1;
while i <= curlen do begin
cnt := 1;
while cur[i + cnt] = cur[i] do
cnt := cnt + 1;
next[j] := digit(cnt);
next[j + 1] := cur[i];
j := j + 2;
i := i + cnt;
end;
for i := 1 step 1 until j-1 do
cur[i] := next[i];
curlen := j - 1;
end;
end
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221
APL
⎕IO←0
d←{(1↓⍵)-¯1↓⍵}
f←{m←(0≠d ⍵),1 ⋄ ,(d ¯1,m/⍳⍴⍵),[.5](m/⍵)}
{(f⍣⍵) ,1}¨⍳10
This is an ugly little APL2 function that accepts a numeric vector (or scalar) and returns the result.
Apologies for the labeled loop...
R←LNS V;T
R←0⍴0 ⍝ initiate empty reply
LOOP:T←↑⍴↑(=\V)⊂V←,V ⍝ t is the length of the 1st digit's run
R←R,T,↑V ⍝ append t and the 1st digit
→(0≠↑⍴V←T↓V)/LOOP ⍝ drop t digits and iterate
AppleScript
on lookAndSay(startNumber, howMany)
if (howMany < 1) then return {}
-- The numbers are handled as lists of digit-value integers for efficiency and output as a list of strings.
script o
property previousNumber : {}
property newNumber : {}
property output : {}
end script
-- "Digitise" the start number.
repeat
set beginning of o's newNumber to startNumber mod 10 as integer
set startNumber to startNumber div 10
if (startNumber is 0) then exit repeat
end repeat
-- Add it to the output as text and successively derive the remaining numbers.
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to ""
set end of o's output to o's newNumber as text
repeat (howMany - 1) times
set o's previousNumber to o's newNumber
set o's newNumber to {}
set i to 1
set previousLength to (o's previousNumber's length)
set currentDigit to beginning of o's previousNumber
repeat with j from 2 to previousLength
set thisDigit to item j of o's previousNumber
if (thisDigit is not currentDigit) then
set end of o's newNumber to j - i
set end of o's newNumber to currentDigit
set i to j
set currentDigit to thisDigit
end if
end repeat
set end of o's newNumber to previousLength - i + 1
set end of o's newNumber to currentDigit
set end of o's output to o's newNumber as text
end repeat
set AppleScript's text item delimiters to astid
return o's output
end lookAndSay
-- Test code:
return lookAndSay(1, 10)
- Output:
{"1", "11", "21", "1211", "111221", "312211", "13112221", "1113213211", "31131211131221", "13211311123113112211"}
Arturo
lookAndSay: function [n][
if n=0 -> return "1"
previous: lookAndSay n-1
result: new ""
currentCounter: 0
currentCh: first previous
loop previous 'ch [
if? currentCh <> ch [
if not? zero? currentCounter ->
'result ++ (to :string currentCounter) ++ currentCh
currentCounter: 1
currentCh: ch
]
else ->
currentCounter: currentCounter + 1
]
'result ++ (to :string currentCounter) ++ currentCh
return result
]
loop 0..10 'x [
print [x "->" lookAndSay x]
]
- Output:
0 -> 1 1 -> 11 2 -> 21 3 -> 1211 4 -> 111221 5 -> 312211 6 -> 13112221 7 -> 1113213211 8 -> 31131211131221 9 -> 13211311123113112211 10 -> 11131221133112132113212221
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
}
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
}
}
BASIC
10 DEFINT A-Z: I$="1"
20 FOR Z=1 TO 15
30 PRINT I$
40 O$=""
50 FOR I=1 TO LEN(I$)
60 C=1
70 IF MID$(I$,I,1)=MID$(I$,I+C,1) THEN C=C+1: GOTO 70
80 O$=O$+CHR$(C+48)+MID$(I$,I,1)
90 I=I+C-1
100 NEXT I
110 I$=O$
120 NEXT Z
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221
Applesoft BASIC
10 I$="1"
20 FOR Z=1 TO 15
30 PRINT I$
40 O$=""
50 FOR I=1 TO LEN(I$)
60 C=1
70 IF MID$(I$,I,1)=MID$(I$,I+C,1) THEN C=C+1: GOTO 70
80 O$=O$+CHR$(C+48)+MID$(I$,I,1)
90 I=I+C-1
100 NEXT I
110 I$=O$
120 NEXT Z
Chipmunk Basic
100 cls
110 dim x$(2)
120 i = 0 ' índice de cadena de entrada
130 x$(i) = "1"
140 input "Indica cuantas repeticiones: ",r
150 print "Secuencia:"
160 print x$(i)
170 for n = 1 to r-1
180 j = 1-i ' índice de cadena de salida
190 x$(j) = ""
200 k = 1
210 while k <= len(x$(i))
220 k0 = k+1
230 while ((k0 <= len(x$(i))) and (mid$(x$(i),k,1) = mid$(x$(i),k0,1)))
240 k0 = k0+1
250 wend
260 x$(j) = x$(j)+str$(k0-k)+mid$(x$(i),k,1)
270 k = k0
280 wend
290 i = j
300 print x$(j)
310 next n
320 end
- Output:
Similar to FreeBASIC entry.
GW-BASIC
The BASIC solution works without any changes.
MSX Basic
The BASIC solution works without any changes.
True BASIC
LET i$ = "1"
FOR z = 1 TO 15
PRINT i$
LET o$ = ""
FOR i = 1 TO LEN(i$)
LET c = 1
DO WHILE (i$)[i:i+1-1] = (i$)[i+c:i+c+1-1]
LET c = c+1
LOOP
LET o$ = o$ & CHR$(c+48) & (i$)[i:i+1-1]
LET i = i+c-1
NEXT i
LET i$ = o$
NEXT z
END
- Output:
Similar to FreeBASIC entry.
BASIC256
# look and say
dim a$(2)
i = 0 # input string index
a$[i] = "1"
print a$[i]
for n=1 to 10
j = 1 - i # output string index
a$[j] = ""
k = 1
while (k <= length(a$[i]))
k0 = k + 1
while ((k0 <= length(a$[i])) and (mid(a$[i], k, 1) = mid(a$[i], k0, 1)))
k0 = k0 + 1
end while
a$[j] += string(k0 - k) + mid(a$[i], k, 1)
k = k0
end while
i = j
print a$[j]
next n
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
BCPL
get "libhdr"
manifest $(
amount = 15
bufsize = 128
$)
let move(dest,src) be
$( until !src = 0 do
$( !dest := !src
dest := dest + 1
src := src + 1
$)
!dest := 0
$)
let count(v) = valof
$( let i=1
while v!i = !v do i := i + 1
resultis i
$)
let looksay(in,out) be
$( until !in = 0 do
$( let n = count(in)
out!0 := n
out!1 := !in
out := out + 2
in := in + n
$)
!out := 0
$)
let show(v) be
$( until !v = 0 do
$( writen(!v)
v := v + 1
$)
wrch('*N')
$)
let start() be
$( let buf1 = vec bufsize and buf2 = vec bufsize
buf1!0 := 1
buf1!1 := 0
for n = 1 to amount do
$( show(buf1)
looksay(buf1,buf2)
move(buf1,buf2)
$)
$)
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221
BQN
LookSay ← ∾´((⊑∾˜ ≠+'0'˙)¨1↓((+`»≠⊢)⊸⊔))
>((⌈´≠¨)↑¨⊢) LookSay⍟(↕15)"1"
- Output:
┌─ ╵"1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221" ┘
Bracmat
In this example we use a non-linear pattern and a negation of a pattern: the end of e sequence of equal digits is (1) the end of the string or (2) the start of a sequence starting with a different digit.
( 1:?number
& 0:?lines
& whl
' ( 1+!lines:~>10:?lines
& :?say { This will accumulate all that has to be said after one iteration. }
& 0:?begin
& ( @( !number { Pattern matching. The '@' indicates we're looking in a string rather than a tree structure. }
: ?
( [!begin
%@?digit
?
[?end
( (|(%@:~!digit) ?) { The %@ guarantees we're testing one character - not less (%) and not more (@). The ? takes the rest. }
& !say !end+-1*!begin !digit:?say
& !end:?begin { When backtracking, 'begin' advances to the begin of the next sequence, or to the end of the string. }
)
& ~ { fail! This forces backtracking. Backtracking stops when all begin positions have been tried. }
)
)
| out$(str$!say:?number) { After backtracking, output string and set number to string for next iteration. }
)
)
);
- Output:
11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221
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;
}
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 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221
C++
#include <iostream>
#include <sstream>
#include <string>
std::string lookandsay(const std::string& s)
{
std::ostringstream r;
for (std::size_t i = 0; i != s.length();) {
auto 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();
}
int main()
{
std::string laf = "1";
std::cout << laf << '\n';
for (int i = 0; i < 10; ++i) {
laf = lookandsay(laf);
std::cout << laf << '\n';
}
}
Ceylon
shared void run() {
function lookAndSay(Integer|String input) {
variable value digits = if (is Integer input) then input.string else input;
value builder = StringBuilder();
while (exists currentChar = digits.first) {
if (exists index = digits.firstIndexWhere((char) => char != currentChar)) {
digits = digits[index...];
builder.append("``index````currentChar``");
}
else {
builder.append("``digits.size````currentChar``");
break;
}
}
return builder.string;
}
variable String|Integer result = 1;
print(result);
for (i in 1..14) {
result = lookAndSay(result);
print(result);
}
}
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))
- Output:
user> (take 8 (iterate look-and-say 1))
(1 11 21 1211 111221 312211 13112221 1113213211)
The math above is lovely, Clojure using Java's regular expressions is also powerful:
(defn look-and-say
[n]
(->> (re-seq #"(.)\1*" n)
(mapcat (comp (juxt count first) first))
(apply str)))
(take 12 (iterate look-and-say "1"))
- Output:
("1"
"11"
"21"
"1211"
"111221"
"312211"
"13112221"
"1113213211"
"31131211131221"
"13211311123113112211"
"11131221133112132113212221"
"3113112221232112111312211312113211")
CLU
look_and_say = proc (s: string) returns (string)
out: array[char] := array[char]$[]
count: int := 0
last: char := '\000'
for c: char in string$chars(s) do
if c ~= last then
if count ~= 0 then
array[char]$addh(out, char$i2c(count + 48))
array[char]$addh(out, last)
end
last := c
count := 1
else
count := count + 1
end
end
array[char]$addh(out, char$i2c(count + 48))
array[char]$addh(out, last)
return (string$ac2s(out))
end look_and_say
start_up = proc ()
lines = 15
po: stream := stream$primary_output()
cur: string := "1"
for i: int in int$from_to(1, lines) do
stream$putl(po, cur)
cur := look_and_say(cur)
end
end start_up
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221
COBOL
IDENTIFICATION DIVISION.
PROGRAM-ID. LOOK-AND-SAY-SEQ.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 SEQUENCES.
02 CUR-SEQ PIC X(80) VALUE "1".
02 CUR-CHARS REDEFINES CUR-SEQ
PIC X OCCURS 80 TIMES INDEXED BY CI.
02 CUR-LENGTH PIC 99 COMP VALUE 1.
02 NEXT-SEQ PIC X(80).
02 NEXT-CHARS REDEFINES NEXT-SEQ
PIC X OCCURS 80 TIMES INDEXED BY NI.
01 ALG-STATE.
02 STEP-AMOUNT PIC 99 VALUE 14.
02 ITEM-COUNT PIC 9.
PROCEDURE DIVISION.
LOOK-AND-SAY.
DISPLAY CUR-SEQ.
SET CI TO 1.
SET NI TO 1.
MAKE-NEXT-ENTRY.
MOVE 0 TO ITEM-COUNT.
IF CI IS GREATER THAN CUR-LENGTH GO TO STEP-DONE.
TALLY-ITEM.
ADD 1 TO ITEM-COUNT.
SET CI UP BY 1.
IF CI IS NOT GREATER THAN CUR-LENGTH
AND CUR-CHARS(CI) IS EQUAL TO CUR-CHARS(CI - 1)
GO TO TALLY-ITEM.
INSERT-ENTRY.
MOVE ITEM-COUNT TO NEXT-CHARS(NI).
MOVE CUR-CHARS(CI - 1) TO NEXT-CHARS(NI + 1).
SET NI UP BY 2.
GO TO MAKE-NEXT-ENTRY.
STEP-DONE.
MOVE NEXT-SEQ TO CUR-SEQ.
SET NI DOWN BY 1.
SET CUR-LENGTH TO NI.
SUBTRACT 1 FROM STEP-AMOUNT.
IF STEP-AMOUNT IS NOT EQUAL TO ZERO GO TO LOOK-AND-SAY.
STOP RUN.
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211
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))
Cowgol
include "cowgol.coh";
include "strings.coh";
# Given a string with a member of the look-and-say sequence,
# generate the next member of the sequence.
sub LookSay(cur: [uint8], next: [uint8]) is
while [cur] != 0 loop
var count: uint8 := 1;
var curch: uint8 := [cur];
# count how many of this character we have
loop
cur := @next cur;
if [cur] != curch then break; end if;
count := count + 1;
end loop;
# add it and its count to the next sequence
[next] := '0' + count;
next := @next next;
[next] := curch;
next := @next next;
end loop;
[next] := 0;
end sub;
# amount of members to print
# (don't forget to enlarge the buffers if you make this bigger)
var members: uint8 := 15;
# define two buffers
var curbuf: uint8[255];
var nextbuf: uint8[255];
# start with "1"
CopyString("1", &curbuf as [uint8]);
# generate and print successive members
while members > 0 loop
print(&curbuf as [uint8]);
print_nl();
LookSay(&curbuf as [uint8], &nextbuf as [uint8]);
CopyString(&nextbuf as [uint8], &curbuf as [uint8]);
members := members - 1;
end loop;
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221
Crystal
The simplest one:
class String
def lookandsay
gsub(/(.)\1*/){ |s| s.size.to_s + s[0] }
end
end
ss = '1'
12.times { puts ss; ss = ss.to_s.lookandsay }
def lookandsay(str)
str.gsub(/(.)\1*/) { |s| s.size.to_s + $1 }
end
num = "1"
12.times { puts num; num = lookandsay(num) }
Using Enumerable#chunks
def lookandsay(str)
str.chars.chunks(&.itself).map{ |(c, x)| x.size.to_s + c }.join
end
num = "1"
12.times { puts num; num = lookandsay(num) }
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211
D
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"]
Beginner Imperative Version
import std.stdio, std.conv, std.array;
pure string lookAndSay(string s){
auto result = appender!string;
auto i=0, j=i+1;
while(i<s.length){
while(j<s.length && s[i]==s[j]) j++;
result.put( text(j-i) ~ s[i] );
i = j++;
}
return result.data;
}
void main(){
auto s="1";
for(auto i=0; i<10; i++)
(s = s.lookAndSay).writeln;
}
- Output:
11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221
Fast Imperative Version
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.
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.
More Direct Version
Translated and modified from C code by Reddit user "skeeto": http://www.reddit.com/r/dailyprogrammer/comments/2ggy30/9152014_challenge180_easy_looknsay/
Using ideas from: http://www.njohnston.ca/2010/10/a-derivation-of-conways-degree-71-look-and-say-polynomial/
This recursive version is able to generate very large sequences in a short time without memory for the intermediate sequence (and with stack space proportional to the sequence order).
import core.stdc.stdio, std.conv;
// On Windows this uses the printf from the Microsoft C runtime,
// that doesn't handle real type and some of the C99 format
// specifiers, but it's faster for bulk printing.
version (LDC) version (Windows)
extern(C) nothrow @nogc int printf(const char*, ...);
// http://www.njohnston.ca/2010/10/a-derivation-of-conways-degree-71-look-and-say-polynomial/
struct Sequence {
string seq;
uint[6] next;
}
immutable Sequence[93] sequences = [
{"", []},
{"1112", [63]},
{"1112133", [64, 62]},
{"111213322112", [65]},
{"111213322113", [66]},
{"1113", [68]},
{"11131", [69]},
{"111311222112", [84, 55]},
{"111312", [70]},
{"11131221", [71]},
{"1113122112", [76]},
{"1113122113", [77]},
{"11131221131112", [82]},
{"111312211312", [78]},
{"11131221131211", [79]},
{"111312211312113211", [80]},
{"111312211312113221133211322112211213322112", [81, 29, 91]},
{"111312211312113221133211322112211213322113", [81, 29, 90]},
{"11131221131211322113322112", [81, 30]},
{"11131221133112", [75, 29, 92]},
{"1113122113322113111221131221", [75, 32]},
{"11131221222112", [72]},
{"111312212221121123222112", [73]},
{"111312212221121123222113", [74]},
{"11132", [83]},
{"1113222", [86]},
{"1113222112", [87]},
{"1113222113", [88]},
{"11133112", [89, 92]},
{"12", [1]},
{"123222112", [3]},
{"123222113", [4]},
{"12322211331222113112211", [2, 61, 29, 85]},
{"13", [5]},
{"131112", [28]},
{"13112221133211322112211213322112", [24, 33, 61, 29, 91]},
{"13112221133211322112211213322113", [24, 33, 61, 29, 90]},
{"13122112", [7]},
{"132", [8]},
{"13211", [9]},
{"132112", [10]},
{"1321122112", [21]},
{"132112211213322112", [22]},
{"132112211213322113", [23]},
{"132113", [11]},
{"1321131112", [19]},
{"13211312", [12]},
{"1321132", [13]},
{"13211321", [14]},
{"132113212221", [15]},
{"13211321222113222112", [18]},
{"1321132122211322212221121123222112", [16]},
{"1321132122211322212221121123222113", [17]},
{"13211322211312113211", [20]},
{"1321133112", [6, 61, 29, 92]},
{"1322112", [26]},
{"1322113", [27]},
{"13221133112", [25, 29, 92]},
{"1322113312211", [25, 29, 67]},
{"132211331222113112211", [25, 29, 85]},
{"13221133122211332", [25, 29, 68, 61, 29, 89]},
{"22", [61]},
{"3", [33]},
{"3112", [40]},
{"3112112", [41]},
{"31121123222112", [42]},
{"31121123222113", [43]},
{"3112221", [38, 39]},
{"3113", [44]},
{"311311", [48]},
{"31131112", [54]},
{"3113112211", [49]},
{"3113112211322112", [50]},
{"3113112211322112211213322112", [51]},
{"3113112211322112211213322113", [52]},
{"311311222", [47, 38]},
{"311311222112", [47, 55]},
{"311311222113", [47, 56]},
{"3113112221131112", [47, 57]},
{"311311222113111221", [47, 58]},
{"311311222113111221131221", [47, 59]},
{"31131122211311122113222", [47, 60]},
{"3113112221133112", [47, 33, 61, 29, 92]},
{"311312", [45]},
{"31132", [46]},
{"311322113212221", [53]},
{"311332", [38, 29, 89]},
{"3113322112", [38, 30]},
{"3113322113", [38, 31]},
{"312", [34]},
{"312211322212221121123222113", [36]},
{"312211322212221121123222112", [35]},
{"32112", [37]}
];
void evolve(in uint seq, in uint n) nothrow @nogc {
if (n <= 0) {
printf(sequences[seq].seq.ptr);
} else {
foreach (immutable next; sequences[seq].next) {
if (next == 0)
break;
evolve(next, n - 1);
}
}
}
void main(in string[] args) {
immutable uint n = (args.length != 2) ? 10 : args[1].to!uint;
immutable base = 8;
immutable string[base] results = ["", "1", "11", "21", "1211",
"111221", "312211", "13112221"];
if (n < base) {
printf("%s\n", results[n].ptr);
return;
}
evolve(24, n - base);
evolve(39, n - base);
'\n'.putchar;
}
Delphi
See Pascal.
Draco
\util.g
proc nonrec look_and_say(*char inp, outp) void:
char cur;
byte count;
channel output text outch;
open(outch, outp);
while cur := inp*; cur ~= '\e' do
count := 1;
while
inp := inp + 1;
inp* = cur
do
count := count + 1
od;
write(outch; count, cur)
od;
close(outch)
corp
proc nonrec main() void:
[256] char buf1, buf2;
byte i;
byte LINES = 14;
CharsCopy(&buf1[0], "1");
for i from 1 upto LINES do
writeln(&buf1[0]);
look_and_say(&buf1[0], &buf2[0]);
CharsCopy(&buf1[0], &buf2[0])
od
corp
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211
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)
}
EasyLang
proc lookandsay . a$ .
c = 1
p$ = substr a$ 1 1
for i = 2 to len a$
if p$ = substr a$ i 1
c += 1
else
s$ &= c & p$
p$ = substr a$ i 1
c = 1
.
.
s$ &= c & p$
swap a$ s$
.
b$ = 1
print b$
for k = 1 to 10
lookandsay b$
print b$
.
EchoLisp
(lib 'math) ;; for (number->list) = explode function
(lib 'list) ;; (group)
(define (next L)
(for/fold (acc null) ((g (group L)))
(append acc (list (length g) (first g)))))
(define (task n starter)
(for/fold (L (number->list starter)) ((i n))
(writeln (list->string L))
(next L)))
- Output:
(task 10 1)
1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
Elixir
defmodule LookAndSay do
def next(n) do
Enum.chunk_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, &(next/1)
end
def main([start_str|_]) do
{start_val,_} = Integer.parse(start_str)
IO.inspect sequence_from(start_val) |> Enum.take 9
end
def main([]) do
main(["1"])
end
end
LookAndSay.main(System.argv)
- Output:
[1, 11, 21, 1211, 111221, 312211, 13112221, 1113213211, 31131211131221]
Regex version:
defmodule RC do
def look_and_say(n) do
Regex.replace(~r/(.)\1*/, to_string(n), fn x,y -> [to_string(String.length(x)),y] end)
|> String.to_integer
end
end
IO.inspect Enum.reduce(1..9, [1], fn _,acc -> [RC.look_and_say(hd(acc)) | acc] end) |> Enum.reverse
- Output:
[1, 11, 21, 1211, 111221, 312211, 13112221, 1113213211, 31131211131221, 13211311123113112211]
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"]
ERRE
PROGRAM LOOK
PROCEDURE LOOK_AND_SAY(N$->N$)
LOCAL I%,J%,C$,O$
I%=1
REPEAT
C$=MID$(N$,I%,1)
J%=I%+1
WHILE MID$(N$,J%,1)=C$ DO
J%+=1
END WHILE
O$+=MID$(STR$(J%-I%),2)+C$
I%=J%
UNTIL I%>LEN(N$)
N$=O$
END PROCEDURE
BEGIN
NUMBER$="1"
FOR I%=1 TO 10 DO
LOOK_AND_SAY(NUMBER$->NUMBER$)
PRINT(NUMBER$)
END FOR
END PROGRAM
11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221
F#
Library functions somehow missing in F# out of the box (but present in haskell)
let rec brk p lst =
match lst with
| [] -> (lst, lst)
| x::xs ->
if p x
then ([], lst)
else
let (ys, zs) = brk p xs
(x::ys, zs)
let span p lst = brk (not << p) lst
let rec groupBy eq lst =
match lst with
| [] -> []
| x::xs ->
let (ys,zs) = span (eq x) xs
(x::ys)::groupBy eq zs
let group lst : list<list<'a>> when 'a : equality = groupBy (=) lst
Implementation
let lookAndSay =
let describe (xs: char list) =
List.append (List.ofSeq <| (List.length xs).ToString()) [List.head xs]
let next xs = List.collect describe (group xs)
let toStr xs = String (Array.ofList xs)
Seq.map toStr <| Seq.unfold (fun xs -> Some (xs, next xs)) ['1']
let getNthLookAndSay n = Seq.nth n lookAndSay
Seq.take 10 lookAndSay
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
Fennel
(fn look-and-say [t]
(let [lst t
ret []]
(while (> (length lst) 0)
(var (num cnt) (values (table.remove lst 1) 1))
(while (= num (. lst 1))
(set cnt (+ cnt 1))
(when (> (length lst) 0)
(set num (table.remove lst 1))))
(tset ret (+ (length ret) 1) cnt)
(tset ret (+ (length ret) 1) num))
ret))
(var lst [1])
(for [i 1 10]
(print (table.concat lst))
(set lst (look-and-say lst)))
Alternative solution
(fn look-and-say [s]
(var ret [])
(var (num cnt) (values (s:sub 1 1) 1))
(for [i 2 (length s)]
(var cur-num (s:sub i i))
(if (= num cur-num)
(set cnt (+ cnt 1))
(do
(table.insert ret (.. cnt num))
(set cnt 1)
(set num cur-num))))
(table.insert ret (.. cnt num))
(table.concat ret))
(var str "1")
(for [i 1 10]
(print str)
(set str (look-and-say str)))
FOCAL
01.10 A "HOW MANY",M
01.20 S B(0)=1;S B(1)=0
01.30 F Z=1,M;D 4;D 2
01.40 Q
02.10 S X=0;S Y=0
02.15 I (B(X)),2.5
02.17 S CN=0
02.20 S CN=CN+1
02.25 S X=X+1
02.30 I (FABS(B(X)-B(X-1))),2.2
02.35 S C(Y)=CN;S C(Y+1)=B(X-1)
02.40 S Y=Y+2
02.45 G 2.15
02.50 S C(Y)=0
02.55 F X=0,Y;S B(X)=C(X)
03.10 I (A-9)3.2;T "9";R
03.20 I (A-8)3.3;T "8";R
03.30 I (A-7)3.4;T "7";R
03.40 I (A-6)3.5;T "6";R
03.50 I (A-5)3.6;T "5";R
03.60 I (A-4)3.7;T "4";R
03.70 I (A-3)3.8;T "3";R
03.80 I (A-2)3.9;T "2";R
03.90 T "1"
04.10 S X=0
04.20 S A=B(X)
04.30 I (-A)4.4;T !;R
04.40 D 3
04.50 S X=X+1
04.60 G 4.2
- Output:
HOW MANY:12 1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211
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
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
FreeBASIC
Dim As Integer n, j, k, k0, r
Dim As String X(2)
Dim As Integer i = 0 ' índice de cadena de entrada
X(0) = "1"
Input "Indica cuantas repeticiones: ", r
Print Chr(10) & "Secuencia:"
Print X(i)
For n = 1 To r-1
j = 1 - i ' índice de cadena de salida
X(j) = ""
k = 1
While k <= Len(X(i))
k0 = k + 1
While ((k0 <= Len(X(i))) And (Mid(X(i), k, 1) = Mid(X(i), k0, 1)))
k0 += 1
Wend
X(j) += Str(k0 - k) + Mid(X(i), k, 1)
k = k0
Wend
i = j
Print X(j)
Next n
End
- Output:
Indica cuantas repeticiones: 10 Secuencia: 1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211
Frink
LookAndSay = "12211123"
println["Starting Value: " + LookAndSay]
LASStr = { |LaS|
length[LaS@0] + length[LaS@1] + LaS@0
/*
The returned results from the Regex are divided between a distinct matching
character and any following identical characters. For example, a string
of 2222 would be returned from this function as [2,222].
The function adds the length of both elements (1 and 3 in the example
above) and returns that value with the matching character.
i.e. Length of 1st element = 1, Length of 2nd element = 3, value of 1st element = 2
1 + 3 = 4 & value 2. Returned result is "42" i.e. "Four 2s."
*/
}
// Calculate the next 10 Look and Say Sequence Values
for i = 1 to 10
{
LookAndSayReg = LookAndSay =~ %r/(\d)(\1{0,})/g
LookAndSay = join["",mapList[LASStr,LookAndSayReg]]
println["$i - $LookAndSay"]
}
- Output:
Starting Value: 1 1 - 11 2 - 21 3 - 1211 4 - 111221 5 - 312211 6 - 13112221 7 - 1113213211 8 - 31131211131221 9 - 13211311123113112211 10 - 11131221133112132113212221
FutureBasic
include "NSLog.incl"
local fn LookAndSay( testWord as CFStringRef ) as CFStringRef
NSUInteger i, length, times
CFMutableStringRef result = fn MutableStringWithCapacity(0)
unichar repeat = fn StringCharacterAtIndex( testWord, 0 )
times = 1
testWord = fn StringWithFormat( @"%@ ", fn StringSubstringFromIndex( testWord, 1 ) )
length = len(testWord)
for i = 0 to length - 1
unichar actual = fn StringCharacterAtIndex( testWord, i )
if ( actual != repeat )
MutableStringAppendFormat( result, @"%d%c", times, repeat )
times = 1
repeat = actual
else
times++
end if
next
end fn = fn StringWithString( result )
void local fn DoIt
NSUInteger i
CFStringRef numStr = @"1"
for i = 1 to i <= 15
NSLog( @"%@", numStr )
numStr = fn LookAndSay( numStr )
next
end fn
fn DoIt
HandleEvents
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221
Gambas
Code is modified from the [PureBasic] example
Click this link to run this code
Public Sub Main()
Dim i, j, cnt As Integer
Dim txt$, curr$, result$ As String
txt$ = "1211"
i = 1
Print "Sequence: " & txt$ & " = ";
Repeat
j = 1
result$ = ""
Repeat
curr$ = Mid(txt$, j, 1)
cnt = 0
Repeat
Inc cnt
Inc j
Until Mid(txt$, j, 1) <> curr$
result$ &= Str(cnt) & curr$
Until j > Len(txt$)
Print result$
txt$ = result$
Dec i
Until i <= 0
End
Output:
Sequence: 1211 = 111221
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"
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
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
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
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;
}
}
Icon and Unicon
- Output:
11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221
Insitux
(function look-and-say n x
(return-when (empty? n) x)
(let digit (0 n)
[before after] (part-before (!= digit) n))
(recur after (strn x (len before) digit)))
(var result "1")
(loop 10 i
(print (var! result look-and-say)))
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).
Java
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
JavaScript
With RegExp
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);
}
Imperative version
function lookAndSay( s="" ){
var tokens=[]
var i=0, j=1
while( i<s.length ) {
while( j<s.length && s[j]===s[i] ) j++
tokens.push( `${j-i}${s[i]}` )
i=j++
}
return tokens.join("")
}
var phrase="1"
for(var n=0; n<10; n++ )
console.log( phrase = lookAndSay( phrase ) )
- Output:
11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221
jq
def look_and_say:
def head(c; n): if .[n:n+1] == c then head(c; n+1) else n end;
tostring
| if length == 0 then ""
else head(.[0:1]; 1) as $len
| .[0:$len] as $head
| ($len | tostring) + $head[0:1] + (.[$len:] | look_and_say)
end ;
# look and say n times
def look_and_say(n):
if n == 0 then empty
else look_and_say as $lns
| $lns, ($lns|look_and_say(n-1))
end ;
Example
1 | look_and_say(10)
- Output:
11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221
Julia
function lookandsay(s::String)
rst = IOBuffer()
c = 1
for i in 1:length(s)
if i != length(s) && s[i] == s[i+1]
c += 1
else
print(rst, c, s[i])
c = 1
end
end
String(take!(rst))
end
function lookandsayseq(n::Integer)
rst = Vector{String}(undef, n)
rst[1] = "1"
for i in 2:n
rst[i] = lookandsay(rst[i-1])
end
rst
end
println(lookandsayseq(10))
- Output:
String["1", "11", "21", "1211", "111221", "312211", "13112221", "1113213211", "31131211131221", "13211311123113112211"]
K
las: {x{0$,//$(#:'n),'*:'n:(&1,~=':x)_ x:0$'$x}\1}
las 8
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221
Kotlin
// version 1.0.6
fun lookAndSay(s: String): String {
val sb = StringBuilder()
var digit = s[0]
var count = 1
for (i in 1 until s.length) {
if (s[i] == digit)
count++
else {
sb.append("$count$digit")
digit = s[i]
count = 1
}
}
return sb.append("$count$digit").toString()
}
fun main(args: Array<String>) {
var las = "1"
for (i in 1..15) {
println(las)
las = lookAndSay(las)
}
}
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221
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
LiveCode
This function takes a string and returns the next Look-And-Say iteration of it:
function lookAndSay S
put 0 into C
put char 1 of S into lastChar
repeat with i = 2 to length(S)
add 1 to C
if char i of S is lastChar then next repeat
put C & lastChar after R
put 0 into C
put char i of S into lastChar
end repeat
return R & C + 1 & lastChar
end lookAndSay
on demoLookAndSay
put 1 into x
repeat 10
put x & cr after message
put lookAndSay(x) into x
end repeat
put x after message
end demoLookAndSay
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221
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
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
Alternative solution, using Lua Pattern:
function lookandsay(t)
return t:gsub("(1*)(2*)(3*)", function (...)
local ret = {}
for i = 1, select("#", ...) do
local v = select(i, ...)
if #v > 0 then
ret[#ret + 1] = #v
ret[#ret + 1] = v:sub(1,1)
end
end
return table.concat(ret)
end)
end
local t = "1"
for i = 1, 10 do
print(t)
t = lookandsay(t)
end
function lookandsay2(t)
return t:gsub("(1*)(2*)(3*)", function (x, y, z)
return (x == "" and x or (#x .. x:sub(1, 1))) ..
(y == "" and y or (#y .. y:sub(1, 1))) ..
(z == "" and z or (#z .. z:sub(1, 1)))
end)
end
local t = "1"
for i = 1, 10 do
print(t)
t = lookandsay2(t)
end
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211
M4
Using regular expressions:
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
MACRO-11
.TITLE LOKSAY
.MCALL .TTYOUT,.EXIT
LOKSAY::MOV #START,R0
MOV #BUFR1,R1
JSR PC,COPY
MOV #^D14,R5
$1: MOV #BUFR1,R1
JSR PC,PRINT
MOV #NEWLIN,R1
JSR PC,PRINT
JSR PC,STEP
SOB R5,$1
.EXIT
STEP: MOV #BUFR1,R0
MOV #BUFR2,R1
BR 2$
1$: INC R3
CMPB (R0)+,R4
BEQ 1$
ADD #60,R3
MOVB R3,(R1)+
MOVB R4,(R1)+
DEC R0
2$: CLR R3
MOVB (R0)+,R4
BNE 1$
MOV #BUFR2,R0
MOV #BUFR1,R1
COPY: MOVB (R0)+,(R1)+
BNE COPY
RTS PC
PRINT: MOVB (R1)+,R0
.TTYOUT
BNE PRINT
RTS PC
NEWLIN: .BYTE 15,12,0,0
START: .ASCIZ /1/
BUFR1: .BLKB 400
BUFR2: .BLKB 400
.END LOKSAY
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211
Maple
generate_seq := proc(s)
local times, output, i;
times := 1;
output := "";
for i from 2 to StringTools:-Length(s) do
if (s[i] <> s[i-1]) then
output := cat(output, times, s[i-1]);
times := 1; # re-assign
else
times ++;
end if;
end do;
cat(output, times, s[i - 1]);
end proc:
Look_and_Say :=proc(n)
local value, i;
value := "1";
print(value);
for i from 2 to n do
value := generate_seq(value);
print(value);
end do;
end proc:
#Test:
Look_and_Say(10);
- Output:
"1" "11" "21" "1211" "111221" "312211" "13112221" "1113213211" "31131211131221" "13211311123113112211"
Mathematica/Wolfram Language
The function:
LookAndSay[n_Integer?Positive]:= Reverse @@@ Tally /@ Split @ IntegerDigits @ n // Flatten // FromDigits
takes as input an arbitrary positive integer and generates the next member of the ‘Look and Say’ sequence.
The first example returns the next 12 numbers of the sequence starting with 1:
NestList[LookAndSay, 1, 12] // Column
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221
The second example returns the next 12 numbers of the sequence starting with 7:
NestList[LookAndSay, 7, 12] // Column
7 17 1117 3117 132117 1113122117 311311222117 13211321322117 1113122113121113222117 31131122211311123113322117 132113213221133112132123222117 11131221131211132221232112111312111213322117 31131122211311123113321112131221123113111231121123222117
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" */
Implementation treating the sequence as numbers
ciphers(n):=block(makelist(floor(mod(n, 10^(k+1)) / 10^k), k, 0,floor(log(n)/log(10))),reverse(%%));
collect(a) := block(
[n: length(ciphers(a)), b: [ ], x: ciphers(a)[1], m: 1],
for i from 2 thru n do
(if ciphers(a)[i] = x then m: m + 1 else (b: endcons([x, m], b), x: ciphers(a)[i], m: 1)),
b: endcons([x, m], b),
map(reverse,%%),
flatten(%%),
at(sum((part(%%,k))*y^(length(%%)-k),k,1,length(%%)),y=10)
)$
block(i:1,append([i],makelist(i:collect(i),9)),table_form(%%));
/* matrix(
[1],
[11],
[21],
[1211],
[111221],
[312211],
[13112221],
[1113213211],
[31131211131221],
[13211311123113112211]
) */
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
)
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
Miranda
main :: [sys_message]
main = [Stdout (lay (take 15 (iterate looksay "1")))]
looksay :: [char]->[char]
looksay = concat . map f . split
where f xs = show (#xs) ++ [hd xs]
split :: [*]->[[*]]
split = foldr f []
where f x [] = [[x]]
f x (ys:yss) = (x:ys):yss, if x = hd ys
= [x]:ys:yss, otherwise
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221
MiniScript
// Look and Say Sequence
repeats = function(digit, string)
count = 0
for c in string
if c != digit then break
count = count + 1
end for
return str(count)
end function
numbers = "1"
print numbers
for i in range(1,10) // warning, loop size > 15 gets long numbers very quickly
number = ""
position = 0
while position < numbers.len
repeatCount = repeats(numbers[position], numbers[position:])
number = number + repeatCount + numbers[position]
position = position + repeatCount.val
end while
print number
numbers = number
end for
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221
Modula-2
MODULE LookAndSay;
FROM InOut IMPORT WriteString, WriteLn;
FROM Strings IMPORT Assign, Length;
CONST
MaxSize = 128;
Steps = 14;
VAR
buf1, buf2: ARRAY [0..MaxSize-1] OF CHAR;
step: CARDINAL;
PROCEDURE LookSay(in: ARRAY OF CHAR; VAR out: ARRAY OF CHAR);
VAR count, inIdx, outIdx: CARDINAL;
curChar: CHAR;
BEGIN
inIdx := 0;
outIdx := 0;
WHILE in[inIdx] # CHR(0) DO
curChar := in[inIdx];
count := 0;
REPEAT
INC(inIdx);
INC(count);
UNTIL in[inIdx] # curChar;
out[outIdx] := CHR(ORD('0') + count);
out[outIdx+1] := curChar;
outIdx := outIdx + 2;
END;
out[outIdx] := CHR(0);
END LookSay;
BEGIN
Assign("1", buf1);
FOR step := 1 TO Steps DO
WriteString(buf1);
WriteLn();
LookSay(buf1, buf2);
Assign(buf2, buf1);
END;
END LookAndSay.
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 1113122113121113123112111311222112132113213221133122211311221
NewLisp
;;; Compute the following number in the sequence
(define (next-number s)
(let (n 0 c (first s) res "")
(dostring (x s)
(if (= (char x) c) ; the iteration variable is the ASCII code
(++ n)
(begin
(setq res (string res n c))
(setq n 1 c (char x)))))
(setq res (string res n c))
res))
;
;;; Print out the first n+1 numbers, starting from 1
(define (go n)
(let (s "1")
(println s)
(dotimes (x n)
(setq s (next-number s))
(println s))))
;
(go 10)
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221
Nim
iterator lookAndSay(n: int): string =
var current = "1"
yield current
for round in 2..n:
var ch = current[0]
var count = 1
var next = ""
for i in 1..current.high:
if current[i] == ch:
inc count
else:
next.add $count & ch
ch = current[i]
count = 1
current = next & $count & ch
yield current
for s in lookAndSay(12):
echo s
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211
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];
}
}
OCaml
Functional
This function computes a see-and-say sequence from the previous one:
let rec seeAndSay = function
| [], nys -> List.rev nys
| x::xs, [] -> seeAndSay(xs, [x; 1])
| x::xs, y::n::nys when x=y -> seeAndSay(xs, y::1+n::nys)
| x::xs, nys -> seeAndSay(xs, x::1::nys)
It can be used like this:
> let gen n =
let xs = Array.create n [1] in
for i=1 to n-1 do
xs.(i) <- seeAndSay(xs.(i-1), [])
done;
xs;;
val gen : int -> int list array = <fun>
> gen 10;;
- : int list array =
[|[1]; [1; 1]; [2; 1]; [1; 2; 1; 1]; [1; 1; 1; 2; 2; 1]; [3; 1; 2; 2; 1; 1];
[1; 3; 1; 1; 2; 2; 2; 1]; [1; 1; 1; 3; 2; 1; 3; 2; 1; 1];
[3; 1; 1; 3; 1; 2; 1; 1; 1; 3; 1; 2; 2; 1];
[1; 3; 2; 1; 1; 3; 1; 1; 1; 2; 3; 1; 1; 3; 1; 1; 2; 2; 1; 1]|]
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
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'
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 *)
Oforth
import: mapping
: lookAndSay ( n -- )
[ 1 ] #[ dup .cr group map( [#size, #first] ) expand ] times( n ) ;
- Output:
for n = 10
[1] [1, 1] [2, 1] [1, 2, 1, 1] [1, 1, 1, 2, 2, 1] [3, 1, 2, 2, 1, 1] [1, 3, 1, 1, 2, 2, 2, 1] [1, 1, 1, 3, 2, 1, 3, 2, 1, 1] [3, 1, 1, 3, 1, 2, 1, 1, 1, 3, 1, 2, 2, 1] [1, 3, 2, 1, 1, 3, 1, 1, 1, 2, 3, 1, 1, 3, 1, 1, 2, 2, 1, 1]
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}
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))
Pascal
program LookAndSayDemo(input, output);
{$IFDEF FPC}
{$MODE DELPHI}
{$ENDIF}
uses
SysUtils;
function LookAndSay(s: string): string;
var
item: char;
index: integer;
count: integer;
begin
Result := '';
item := s[1];
count := 1;
for index := 2 to length(s) do
if item = s[index] then
inc(count)
else
begin
Result := Result + intTostr(count) + item;
item := s[index];
count := 1;
end;
Result := Result + 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
Even faster imperative Version Improvement: setlength of result,no inttoStr and using pChar But the Code Alignment is very important.
program LookAndSayDemo(input, output);
{$IFDEF FPC}
{$Mode Delphi} // using result
{$optimization ON}
// i3-4330 3.5 Ghz
// {$CodeAlign proc=16,loop=8} //2,6 secs
{$CodeAlign proc=16,loop=1} //1,6 secs so much faster ???
{$ENDIF}
uses
SysUtils;
const
cntChar : array[1..9] of char =
('1','2','3','4','5','6','7','8','9');
function LookAndSay2 (const s: string): string;
//using pChar for result
var
source,
destin : pChar;
len,
idxFrom,
idxTo : integer;
cnt: integer;
item: char;
begin
idxFrom := length(s);
source := @s[1];
//adjust length of result
len := round(length(s)* 1.306+10);
setlength(result,len);
destin := @result[1];
dec(destin);
idxto := 1;
item := source^;
inc(source);
cnt := 1;
for idxFrom := idxFrom downto 2 do
begin
if item <> source^ then
begin
destin[idxTo] := cntChar[cnt];
destin[idxTo+1]:= item;
item := source^;
cnt := 1;
inc(idxto,2);
end
else
inc(cnt);
inc(source);
end;
destin[idxTo] := cntChar[cnt];
destin[idxTo+1]:= item;
setlength(result,idxto+1);
end;
var
number: string;
l1,l2,
i : integer;
begin
number := '1';
writeln(number);
writeln(1:4,length(number):16,1/1:10:6);
For i := 2 to 70 do
begin
l1 := length(number);
number := LookAndSay2(number);
l2 := length(number);
IF i <10 then
writeln(number);
writeln(i:4,length(number):16,l2/l1:10:6);
end;
end.
- Output:
1 1 1 1.000000 11 2 2 2.000000 21 3 2 1.000000 1211 4 4 2.000000 111221 5 6 1.500000 312211 6 6 1.000000 13112221 7 8 1.333333 1113213211 8 10 1.250000 31131211131221 9 14 1.400000 10 20 1.428571 11 26 1.300000 12 34 1.307692 13 46 1.352941 14 62 1.347826 15 78 1.258065 16 102 1.307692 ........ 67 81117366 1.303580 68 105745224 1.303608 69 137842560 1.303535 70 179691598 1.303600 real 0m1.639s user 0m1.593s sys 0m0.043s
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 (local $_ = "1\n"; s/((.)\2*)//s;) {
print $1;
$_ .= ($1 ne "\n" and length($1)).$2
}
Phix
function lookandsay(string s) string res = "" integer p = s[1], c = 1 for i=2 to length(s) do if p=s[i] then c += 1 else res &= sprintf("%d%s",{c,p}) p = s[i] c = 1 end if end for res &= sprintf("%d%s",{c,p}) return res end function string s = "1" ?s for i=1 to 10 do s = lookandsay(s) ?s end for
- Output:
"1" "11" "21" "1211" "111221" "312211" "13112221" "1113213211" "31131211131221" "13211311123113112211" "11131221133112132113212221"
PHP
<?php
function lookAndSay($str) {
return preg_replace_callback('#(.)\1*#', function($matches) {
return strlen($matches[0]).$matches[1];
}, $str);
}
$num = "1";
foreach(range(1,10) as $i) {
echo $num."<br/>";
$num = lookAndSay($num);
}
?>
Picat
go =>
S1 = "1",
foreach(_ in 1..11)
println(S1),
S1 := runs(S1)
end,
println(S1),
nl.
runs(X) = V =>
S = "",
Last = X[1],
C = 1,
foreach(I in 2..X.length)
if X[I] == Last then
C := C + 1
else
S := S ++ C.to_string() ++ [X[I-1]],
C := 1,
Last := X[I]
end
end,
V = S ++ C.to_string() ++ [Last].
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211
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)
PL/M
100H:
BDOS: PROCEDURE (FN, ARG); DECLARE FN BYTE, ARG ADDRESS; GO TO 5; END BDOS;
EXIT: PROCEDURE; CALL BDOS(0,0); END EXIT;
PRINT: PROCEDURE (S); DECLARE S ADDRESS; CALL BDOS(9,S); END PRINT;
COPY$STRING: PROCEDURE (SRC, DEST);
DECLARE (SRC, DEST, I) ADDRESS;
DECLARE (S BASED SRC, D BASED DEST) BYTE;
I = 0;
DO WHILE S(I) <> '$';
D(I) = S(I);
I = I + 1;
END;
D(I) = '$';
END COPY$STRING;
COUNT: PROCEDURE (POS) BYTE;
DECLARE POS ADDRESS, (I, P BASED POS) BYTE;
I = 1;
DO WHILE P(I) = P;
I = I + 1;
END;
RETURN I;
END COUNT;
LOOK$SAY: PROCEDURE (OLD, NEW);
DECLARE (OLD, NEW) ADDRESS;
DECLARE (O BASED OLD, N BASED NEW, C) BYTE;
DO WHILE O <> '$';
C = COUNT(OLD);
N = O;
N(1) = C + '0';
NEW = NEW + 2;
OLD = OLD + C;
END;
N = '$';
END LOOK$SAY;
DECLARE STEPS LITERALLY '15';
DECLARE BUF$SIZE LITERALLY '128';
DECLARE BUFR1 (BUF$SIZE) BYTE INITIAL ('1$');
DECLARE BUFR2 (BUF$SIZE) BYTE;
DECLARE I BYTE;
DO I=1 TO STEPS;
CALL PRINT(.BUFR1);
CALL PRINT(.(13,10,'$'));
CALL LOOK$SAY(.BUFR1, .BUFR2);
CALL COPY$STRING(.BUFR2, .BUFR1);
END;
CALL EXIT;
EOF
- Output:
1 11 12 1121 122111 112213 12221131 1123123111 12213111213113 11221131132111311231 12221231123121133112213111 1123112131122131112112321222113113 1221311221113112221131132112213121112312311231 11221131122213311223123112312112221131112113213111213112213111 122212311223113212223111213112213111211223123113211231211131132111311222113113
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
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
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 ..........................
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);
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
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)
Functional
>>> 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
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)
Q
las:{{raze string[count@'x],'@'[;0]x:where[differ x]_x}\[x;1#"1"]}
las 8
- Output:
,"1" "11" "21" "1211" "111221" "312211" "13112221" "1113213211" "31131211131221"
Quackery
[ stack ] is instances
[ 1 instances put
$ "" swap
behead swap space join
witheach
[ 2dup != iff
[ rot instances share
number$ join
rot join swap
1 instances replace ]
else
[ drop
1 instances tally ] ]
drop instances release ] is lookandsay ( $ --> $ )
$ "1"
15 times
[ dup echo$ cr
lookandsay ]
echo$ cr
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221 132113213221133112132113311211131221121321131211132221123113112221131112311332111213211322211312113211
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)
}
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
Raku
(formerly Perl 6)
In Raku it is natural to avoid explicit loops; rather we use the sequence operator to define a lazy infinite sequence. We'll print the first 15 values here.
.say for ('1', *.subst(/(.)$0*/, { .chars ~ .[0] }, :g) ... *)[^15];
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221
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.
simple version
/*REXX program displays the sequence (and/or lengths) for the look and say series.*/
parse arg N ! . /*obtain optional arguments from the CL*/
if N=='' | N=="," then N= 20 /*Not specified? Then use the default.*/
if !=='' | !=="," then != 1 /* " " " " " " */
do j=1 for abs(N) /*repeat a number of times to show NUMS*/
if j\==1 then != lookNsay(!) /*invoke function to calculate next #. */
if N<0 then say 'length['j"]:" length(!) /*Also, display the sequence's length.*/
else say '['j"]:" ! /*display the number to the terminal. */
end /*j*/
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
lookNsay: procedure; parse arg x,,$ /*obtain the (passed) argument {X}. */
fin = '0'x /*use unique character to end scanning.*/
x= x || fin /*append the FIN character to string.*/
do k=1 by 0 /*now, process the given sequence. */
y= substr(x, k, 1) /*pick off one character to examine. */
if y== fin then return $ /*if we're at the end, then we're done.*/
_= verify(x, y, , k) - k /*see how many characters we have of Y.*/
$= $ || _ || y /*build the "look and say" sequence. */
k= k + _ /*now, point to the next character. */
end /*k*/
- output when using the default input values of: 20 1
[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 using the input values of: 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 using the input value of: -60
(Shown at three-quarter size.)
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
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 program displays the sequence (and/or lengths) for the look and say series.*/
parse arg N ! . /*obtain optional arguments from the CL*/
if N=='' | N=="," then N= 20 /*Not specified? Then use the default.*/
if !=='' | !=="," then != 1 /* " " " " " " */
/* [↑] !: starting char for the seq.*/
do j=1 for abs(N) /*repeat a number of times to show NUMS*/
if j\==1 then != lookNsay(!) /*invoke function to calculate next #. */
if N<0 then say 'length['j"]:" length(!) /*Also, display the sequence's length.*/
else say '['j"]:" ! /*display the number to the terminal. */
end /*j*/
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
lookNsay: procedure; parse arg x,,$ ! /*obtain the (passed) argument {X}. */
chSize= 1000 /*define a sensible chunk size. */
fin = '0'x /*use unique character to end scanning.*/
x= x || fin /*append the FIN character to string.*/
do k=1 by 0 /*now, process the given sequence. */
y= substr(x, k, 1) /*pick off one character to examine. */
if y==fin then return $ /*if we're at the end, then we're done.*/
_= verify(x, y, , k) - k /*see how many characters we have of Y.*/
$= $ || _ || y /*build the "look and say" sequence. */
k= k + _ /*now, point to the next character. */
if length($)<chSize then iterate /*Less than chunkSize? Then keep going*/
!= ! || $ /*append $ to the ! string. */
$= /*now, start $ from scratch. */
chSize= chSize + 100 /*bump the chunkSize (length) counter.*/
end /*k*/
return ! || $ /*return the ! string plus the $ string*/
- output is identical to the 1st REXX version (the simple version).
Refal
$ENTRY Go {
= <Prout <Sequence 10 1>>;
};
Sequence {
0 e.seq = ;
s.N e.seq = <Prout e.seq>
<Sequence <- s.N 1> <LookSay e.seq>>;
}
LookSay {
= ;
e.1,
<First <Group e.1> e.1>: (e.group) e.rest,
<Lenw e.group>: s.num s.item e.discard =
s.num s.item <LookSay e.rest>;
}
Group {
s.1 s.1 e.rest = <+ 1 <Group s.1 e.rest>>;
s.1 e.rest = 1;
};
- Output:
1 1 1 2 1 1 2 1 1 1 1 1 2 2 1 3 1 2 2 1 1 1 3 1 1 2 2 2 1 1 1 1 3 2 1 3 2 1 1 3 1 1 3 1 2 1 1 1 3 1 2 2 1 1 3 2 1 1 3 1 1 1 2 3 1 1 3 1 1 2 2 1 1
Ring
number = "1"
for nr = 1 to 10
number = lookSay(number)
see number + nl
next
func lookSay n
i = 0 j = 0 c="" o=""
i = 1
while i <= len(n)
c = substr(n,i,1)
j = i + 1
while substr(n,j,1) = c
j += 1
end
o += string(j-i) + c
i = j
end
return o
RPL
Code | Comments |
---|---|
≪ DUP 1 DUP SUB → str char ≪ 2 WHILE str OVER DUP SUB char == REPEAT 1 + END DUP 1 - →STR char + str ROT OVER SIZE SUB ≫ ≫ 'CountCut' STO ≪ "" 1 CF SWAP WHILE 1 FC? REPEAT CountCut IF DUP "" == THEN 1 SF END ROT ROT + SWAP END DROP ≫ 'LKSAY' STO |
( "####" -- "n#" "remainder" ) Count occurences of 1st char Build "n#" Extract remaining string ("M(n)" -- "M(n+1)" ) Initialize M(n+1) and flag set flag if at end of "M(n)" build "M(n+1)" Forget "M(n)" |
The following line of code delivers what is required:
≪ {} 1 "1" 12 START SWAP OVER + SWAP LKSAY NEXT DROP ≫
- Output:
1: { "1" "11" "21" "1211" "111221" "312211" "13112221" "1113213211" "31131211131221" "13211311123113112211" "11131221133112132113212221" "3113112221232112111312211312113211" }
Ruby
The simplest one:
class String
def look_and_say
gsub(/(.)\1*/){|s| s.size.to_s + s[0]}
end
end
ss = '1'
12.times {puts ss; ss = ss.look_and_say}
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211
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.
Rust
fn next_sequence(in_seq: &[i8]) -> Vec<i8> {
assert!(!in_seq.is_empty());
let mut result = Vec::new();
let mut current_number = in_seq[0];
let mut current_runlength = 1;
for i in &in_seq[1..] {
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 = vec![1];
for i in 0..10 {
println!("Sequence {}: {:?}", i, seq);
seq = next_sequence(&seq);
}
}
- Output:
Sequence 0: [1] Sequence 1: [1, 1] Sequence 2: [2, 1] Sequence 3: [1, 2, 1, 1] Sequence 4: [1, 1, 1, 2, 2, 1] Sequence 5: [3, 1, 2, 2, 1, 1] Sequence 6: [1, 3, 1, 1, 2, 2, 2, 1] Sequence 7: [1, 1, 1, 3, 2, 1, 3, 2, 1, 1] Sequence 8: [3, 1, 1, 3, 1, 2, 1, 1, 1, 3, 1, 2, 2, 1] Sequence 9: [1, 3, 2, 1, 1, 3, 1, 1, 1, 2, 3, 1, 1, 3, 1, 1, 2, 2, 1, 1]
Sather
class MAIN is
look_and_say!: STR is
current ::= "1";
loop
yield current;
buf ::= #FSTR;
last ::= current[0];
count ::= 0;
loop
ch ::= current.elt!;
if ch /= last then
buf := buf + count + last;
last := ch; count := 1;
else
count := count + 1;
end;
end;
current := (buf + count + last).str;
end;
end;
main is
loop 12.times!;
#OUT+ look_and_say! + "\n";
end;
end;
end;
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211
Scala
Recursive
import scala.annotation.tailrec
object LookAndSay extends App {
loop(10, "1")
@tailrec
private def loop(n: Int, num: String): Unit = {
println(num)
if (n <= 0) () else loop(n - 1, lookandsay(num))
}
private def lookandsay(number: String): String = {
val result = new StringBuilder
@tailrec
def loop(numberString: String, repeat: Char, times: Int): String =
if (numberString.isEmpty) result.toString()
else if (numberString.head != repeat) {
result.append(times).append(repeat)
loop(numberString.tail, numberString.head, 1)
} else loop(numberString.tail, numberString.head, times + 1)
loop(number.tail + " ", number.head, 1)
}
}
- Output:
See it running in your browser by (JavaScript, non JVM) or by Scastie (JVM).
using Iterator
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)
using Stream
object Main extends App {
def lookAndSay(previous: List[BigInt]): Stream[List[BigInt]] = {
def next(num: List[BigInt]): List[BigInt] = num match {
case Nil => Nil
case head :: Nil => 1 :: head :: Nil
case head :: tail =>
val size = (num takeWhile (_ == head)).size
List(BigInt(size), head) ::: next(num.drop(size))
}
val x = next(previous)
x #:: lookAndSay(x)
}
(lookAndSay(1 :: Nil) take 10).foreach(s => println(s.mkString("")))
}
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
SETL
program looksay;
s := "1";
loop for i in [1..10] do
print(s);
s := looksay(s);
end loop;
proc looksay(s);
loop for c in s do;
if cur /= c then
if count /= om then
r +:= count + cur;
end if;
cur := c;
count := 1;
else
count +:= 1;
end if;
end loop;
r +:= count + cur;
return r;
end proc;
end looksay;
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211
Sidef
func lookandsay(str) {
str.gsub(/((.)\2*)/, {|a,b| a.len.to_s + b });
}
var num = "1";
{
say num;
num = lookandsay(num);
} * 10;
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211
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.
]
String compile:
'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).
^('''' join: newColl)'
classified: 'toys'.
result := OrderedCollection new.
r := '1'.
result add: r.
result addAll: ((1 to: 10) collect: [ :i |
r := r lookAndSay.
]).
result.
Output:
an OrderedCollection('1' '11' '21' '1211' '111221' '312211' '13112221' '1113213211' '31131211131221' '13211311123113112211' '11131221133112132113212221')
SNOBOL4
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
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
SQL PL
version 9.7 or higher.
With SQL PL:
SET SERVEROUTPUT ON @
BEGIN
DECLARE NMBR VARCHAR(100) DEFAULT '1';
DECLARE J SMALLINT DEFAULT 1;
CALL DBMS_OUTPUT.PUT_LINE(NMBR);
WHILE (J < 10) DO
BEGIN
DECLARE I SMALLINT;
DECLARE SIZE SMALLINT;
DECLARE ACTUAL CHAR(1);
DECLARE REPEAT CHAR(1);
DECLARE RESULT VARCHAR(100);
DECLARE TIMES SMALLINT;
SET REPEAT = SUBSTR(NMBR, 1, 1);
SET NMBR = SUBSTR(NMBR, 2) || ' ';
SET TIMES = 1;
SET I = 1;
SET SIZE = LENGTH(NMBR);
WHILE (I <= SIZE) DO
SET ACTUAL = SUBSTR(NMBR, I, 1);
IF (ACTUAL <> REPEAT) THEN
SET RESULT = COALESCE(RESULT, '') || TIMES || '' || REPEAT;
SET TIMES = 1;
SET REPEAT = ACTUAL;
ELSE
SET TIMES = TIMES + 1;
END IF;
SET I = I + 1;
END WHILE;
CALL DBMS_OUTPUT.PUT_LINE(RESULT);
SET NMBR = RESULT;
END ;
SET J = J + 1;
END WHILE;
END @
Output:
db2 => BEGIN ... db2 (cont.) => END @ DB20000I The SQL command completed successfully. 1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211
Swift
func lookAndSay(_ seq: [Int]) -> [Int] {
var result = [Int]()
var cur = seq[0]
var curRunLength = 1
for i in seq.dropFirst() {
if cur == i {
curRunLength += 1
} else {
result.append(curRunLength)
result.append(cur)
curRunLength = 1
cur = i
}
}
result.append(curRunLength)
result.append(cur)
return result
}
var seq = [1]
for i in 0..<10 {
print("Seq \(i): \(seq)")
seq = lookAndSay(seq)
}
- Output:
Seq 0: [1] Seq 1: [1, 1] Seq 2: [2, 1] Seq 3: [1, 2, 1, 1] Seq 4: [1, 1, 1, 2, 2, 1] Seq 5: [3, 1, 2, 2, 1, 1] Seq 6: [1, 3, 1, 1, 2, 2, 2, 1] Seq 7: [1, 1, 1, 3, 2, 1, 3, 2, 1, 1] Seq 8: [3, 1, 1, 3, 1, 2, 1, 1, 1, 3, 1, 2, 2, 1] Seq 9: [1, 3, 2, 1, 1, 3, 1, 1, 1, 2, 3, 1, 1, 3, 1, 1, 2, 2, 1, 1]
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:
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
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
Uiua
As noted on the Run-length encoding page, this is just RLE gone bad.
Rle ← /◇⊂≡⍚(⊂⊃(°⋕⧻|⊢))⊜□⊸(+1⊛)
⇌[⍥(⍚Rle.)10□] "1"
- Output:
{"1" "11" "21" "1211" "111221" "312211" "13112221" "1113213211" "31131211131221" "13211311123113112211" "11131221133112132113212221"}
UNIX Shell
lookandsay() {
local num=$1 char seq i
for ((i=0; i<=${#num}; i++)); do
char=${num:i:1}
if [[ $char == ${seq:0:1} ]]; then
seq+=$char
else
[[ -n $seq ]] && printf "%d%s" ${#seq} ${seq:0:1}
seq=$char
fi
done
}
for ((num=1, i=1; i<=10; i++)); do
echo $num
num=$( lookandsay $num )
done
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211
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
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!)
VBScript
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
Invocation
dim m
m = 1
for i = 0 to 13
m = looksay(m)
wscript.echo m
next
- Output:
11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221
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
V (Vlang)
fn lss(s string) string {
mut r := ''
mut c := s[0..1]
mut nc := 1
for i := 1; i < s.len; i++ {
d := s[i..i+1]
if d == c {
nc++
continue
}
r += nc.str() + c
c = d
nc = 1
}
return r + nc.str() + c
}
fn main() {
mut s := "1"
println(s)
for i := 0; i < 8; i++ {
s = lss(s)
println(s)
}
}
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221
Wren
var lookAndSay = Fn.new { |s|
var res = ""
var digit = s[0]
var count = 1
for (i in 1...s.count) {
if (s[i] == digit) {
count = count + 1
} else {
res = res + "%(count)%(digit)"
digit = s[i]
count = 1
}
}
return res + "%(count)%(digit)"
}
var las = "1"
for (i in 1..15) {
System.print(las)
las = lookAndSay.call(las)
}
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221
XPL0
char Seq0(100), Seq1(100);
int Iter, Digit, Count, I0, I1, T;
string 0;
[Seq0(0):= ^1; Seq0(1):= 0;
Text(0, Seq0); CrLf(0);
for Iter:= 2 to 15 do
[I1:= 0; I0:= 0;
repeat Digit:= Seq0(I0);
Count:= ^1;
I0:= I0+1;
while Seq0(I0) = Digit do
[Count:= Count+1;
I0:= I0+1;
];
Seq1(I1):= Count; I1:= I1+1;
Seq1(I1):= Digit; I1:= I1+1;
until Seq0(I0) = 0;
Seq1(I1):= 0;
T:= Seq0; Seq0:= Seq1; Seq1:= T;
Text(0, Seq0); CrLf(0);
];
]
- Output:
1 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221 3113112221232112111312211312113211 1321132132111213122112311311222113111221131221 11131221131211131231121113112221121321132132211331222113112211 311311222113111231131112132112311321322112111312211312111322212311322113212221
Yabasic
dim X$(2)
i = 0 // índice de cadena de entrada
X$(i) = "1"
input "Indica cuantas repeticiones: " r
print "\nSecuencia:"
print X$(i)
for n = 1 to r-1
j = 1 - i // índice de cadena de salida
X$(j) = ""
k = 1
while k <= len(X$(i))
k0 = k + 1
while ((k0 <= len(X$(i))) and (mid$(X$(i), k, 1) = mid$(X$(i), k0, 1)))
k0 = k0 + 1
wend
X$(j) = X$(j) + str$(k0 - k) + mid$(X$(i), k, 1)
k = k0
wend
i = j
print X$(j)
next n
print
- Output:
La salida es similar a la de FreeBASIC, mostrada arriba.
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
zkl
Treating the task as a string manipulation problem.
fcn lookAndSay(seed){ // numeric String --> numeric String
len,c:=[1..seed.len()-1].reduce(fcn([(len,c)]lc,index,s,sb){
if(c!=s[index]) { sb.write(len); sb.write(c); lc.clear(1,s[index]) }
else lc.clear(len+1,c);
},L(1,seed[0]), seed,sb:=Sink(String));
sb.write(len); sb.write(c);
sb.close();
}
- Output:
(0).reduce(10,fcn(seed,_){ lookAndSay(seed).println() },"1"); 11 21 1211 111221 312211 13112221 1113213211 31131211131221 13211311123113112211 11131221133112132113212221
- Programming Tasks
- Text processing
- 11l
- 8080 Assembly
- 8086 Assembly
- ABC
- Action!
- Ada
- ALGOL 68
- ALGOL-M
- APL
- AppleScript
- Arturo
- AutoHotkey
- AWK
- BASIC
- Applesoft BASIC
- Chipmunk Basic
- GW-BASIC
- MSX Basic
- True BASIC
- BASIC256
- BBC BASIC
- BCPL
- BQN
- Bracmat
- C
- C sharp
- C++
- Ceylon
- Clojure
- CLU
- COBOL
- Common Lisp
- Cowgol
- Crystal
- D
- Delphi
- Draco
- E
- EasyLang
- EchoLisp
- Elixir
- Erlang
- ERRE
- F Sharp
- Factor
- Fennel
- FOCAL
- Forth
- Fortran
- FreeBASIC
- Frink
- FutureBasic
- Gambas
- GAP
- Go
- Groovy
- Haskell
- Haxe
- Icon
- Unicon
- Insitux
- J
- Java
- JavaScript
- Jq
- Julia
- K
- Kotlin
- Lasso
- LiveCode
- Logo
- Lua
- M4
- MACRO-11
- Maple
- Mathematica
- Wolfram Language
- Maxima
- MAXScript
- Metafont
- Miranda
- MiniScript
- Modula-2
- NewLisp
- Nim
- Objective-C
- OCaml
- Oforth
- Oz
- PARI/GP
- Pascal
- SysUtils
- Perl
- Phix
- PHP
- Picat
- PicoLisp
- PL/M
- PowerBASIC
- PowerShell
- Prolog
- Pure
- PureBasic
- Python
- Q
- Quackery
- R
- Racket
- Raku
- REXX
- Refal
- Ring
- RPL
- Ruby
- Rust
- Sather
- Scala
- Seed7
- SETL
- Sidef
- Smalltalk
- SNOBOL4
- SQL
- SQLite
- SQL PL
- Swift
- Tcl
- TUSCRIPT
- Uiua
- UNIX Shell
- Ursala
- VBA
- VBScript
- Vedit macro language
- V (Vlang)
- Wren
- XPL0
- Yabasic
- Yorick
- Zkl
- Pages with too many expensive parser function calls