國三下(2010 年 1 月到 4 月)Grade 9, second term (January to April 2010)
演化:把 ff 改成 fun 的字串生物Evolution: string-command creatures that turn ff into fun
演化的網頁版,照 2010 年 4 月 16 日的原始碼改寫。打開時每秒走 60 步,可以調快。Evolution running in the browser, rewritten from the source of 16 April 2010. It opens at 60 steps a second and can be sped up.
What runs above is the program itself, rewritten line by line in JavaScript in 2026 from Form1.vb, ClsEater.vb and ClsFood.vb. Each tick of the timer is one step: first every piece of food moves, then each creature in turn looks for food, eats, tries ff, copies itself and mates. VB's rounding to even when a fraction is stored in an Integer, a Collection that can grow and shrink while it is being looped over, and the bounds of the random numbers all follow VB's rules, because how the creatures move and when they die depends on them.
A few things that look like mistakes are kept as well. Food runs from creatures, but the line meant to find the nearest one compares the food with itself, so every piece of food runs from the last creature in the collection. One time in six a mating produces an extra offspring placed at the sum of its parents' coordinates, often off screen. Food that crosses the right or bottom edge is moved to the far left and, one line later, back to the far right, so it waits just outside the bottom-right of the window and creatures chase it out there; the "outside the window" count in the status line is that food.
This code was run six times for three million steps each. Five runs evolved words: yoy 5 times, cat 10, fly 4, fun 7, much the same set as in ff--result.txt; frank, facebook and majer never appeared. The first success came at step 327,044 at the earliest and step 1,290,427 at the latest, and one run had none in three million steps. At 60 steps a second that is a wait of one and a half to six hours; at 3,840 steps a second, about one and a half to six minutes.
Where it differs from the original: the window size and timer interval are set in Form1.Designer.vb, which this rewrite did not use, so the view defaults to 960 × 600 at 60 steps a second and scales down on a phone. Every 500 steps the original saved every creature's gene into the SaveText folder; the web version saves nothing and lists the Diary and ff--result lines under the view instead. Reading the code, the original would stop with an Integer overflow error once there are more than about 63 creatures; the web version carries on and says so below the view.
On screen a crowd of small squares and circles chases food. Each creature carries a list of commands, its gene looking like ADD s,ADH f. The program does the same thing for every newborn: it feeds the string "ff" through the creature's commands in order, and if the result is on the goodword list it writes "ff-->fun" (or the word it got) to ff--result.txt, followed by the creature's gene. The goodword list has 15 entries (frog appears twice): fun, cell, hello, nice, fly, frog, yeah, yoy, flash, frank, facebook, majer, favorite, cat.
The April ClsEater runs six commands: ADD appends a character, ADH puts one at the front, LFT reverses the string, LRD and RRD keep the left or right n characters, and DEL deletes the n-th character. Three more, ERA (erase a stretch), SUB (take a stretch) and SPA (insert an underscore), come from a text-editing exercise of November 2009 that sits in the folder of exercise program B, and the food objects' genes grow them when they mutate.
A creature that eats food picks one of ADD, ADH, LRD, RRD, LFT and DEL at random and appends it to its own list; superior food teaches two. When a creature reproduces, each command has a one in two chance of being copied to the offspring, The exception is a creature that has succeeded: it and its next 9 generations of descendants copy the whole list.
Public Function WordTran(ByVal Texta, ByVal Command) As String
Try
CommandText = Split(Command)(0)
Select Case CommandText
Case "ADD"
Texta += Split(Command)(1)
Case "ADH"
Texta = Split(Command)(1) + Texta
Case "LFT"
Texta = LeftToRight(Texta)
Case "LRD"
Texta = Microsoft.VisualBasic.Left(Texta, CInt(Split(Command)(1)))
Case "RRD"
Texta = Microsoft.VisualBasic.Right(Texta, CInt(Split(Command)(1)))
Case "DEL"
Texta = Microsoft.VisualBasic.Left(Texta, CInt(Split(Command)(1)) - 1) & Microsoft.VisualBasic.Mid(Texta, CInt(Split(Command)(1)) + 1)
Case Else
If BigCommands.Item(CommandText) IsNot Nothing Then
For Each Commanda As String In BigCommands.Item(CommandText)
WordTran(Texta, Commanda)
Next
End If
End Select
Return Texta
Catch ex As Exception
Return Texta
End Try
Return Texta
End Function
ClsEater.vb 的 WordTran:每個指令對字串做什麼。指令數字超出範圍時 VB 丟出錯誤,Catch 把字串原樣傳回。WordTran in ClsEater.vb: what each command does to the string. When a number is out of range VB throws an error and the Catch returns the string unchanged.
objEater.Live += 25
Select Case ran.Next(0, 6)
Case 0
objEater.Commands.Add("ADD " & Chr(97 + ran.Next(0, 26)))
Case 1
objEater.Commands.Add("ADH " & Chr(97 + ran.Next(0, 26)))
Case 2
objEater.Commands.Add("LRD " & ran.Next(0, 14))
Case 3
objEater.Commands.Add("RRD " & ran.Next(0, 14))
Case 4
objEater.Commands.Add("LFT")
Case 5
objEater.Commands.Add("DEL " & ran.Next(0, 14))
End Select
Form1.vb:生物吃到普通食物,隨機學一條指令。Form1.vb: a creature that eats ordinary food learns one random command.
If objEater.TryWord = False Then
testword = objEater.result("ff")
Print("Try " + testword)
objEater.ResultText = testword
If goodword.Contains(testword) Then
BestObjEater = objEater
'(這裡省略 10 行被註解掉的舊寫法)
Label4.Text = "成功!!!!!!~" + oktime.ToString
oktime += 1
My.Computer.FileSystem.WriteAllText("C:\Users\Majer\Desktop\演化\演化\ff--result.txt", "ff-->" + testword + vbNewLine, True)
My.Computer.FileSystem.WriteAllText("C:\Users\Majer\Desktop\演化\演化\ff--result.txt", "|" + BestObjEater.DNA + "|" + vbNewLine, True)
objEater.TruelyNum = 10
End If
objEater.TryWord = True
Form1.vb:對新生的生物試 "ff",成功就寫進 ff--result.txt。Form1.vb: try "ff" on a newborn and write a success to ff--result.txt.
SaveText 資料夾有 37 個實驗資料夾,其中 36 個有 Diary.txt,逐行記下每個新生物試出的字(Try fffs)和族群的增減(Copy OK Live 2、Died OK Live 5)。起始生物的基因是 ADD s,ADH f,所以這 36 份 Diary 開頭第一個 Try 都是 fffs。
ff--result.txt holds 32 success records: fun 13, yoy 12, fly 4, cat 2, frog 1. The shortest, a fly, takes 16 commands and the longest, a yoy, 4,574. The short one uses LRD 0 to empty the string and then rebuilds it with ADD and ADH. cell, hello, nice, yeah, flash, frank, facebook, majer and favorite have no success record in this file.
The SaveText folder holds 37 experiment folders, 36 of them with a Diary.txt that logs, line by line, the word each newborn produced (Try fffs) and the population going up and down (Copy OK Live 2, Died OK Live 5). The starting creature's gene is ADD s,ADH f, so the first Try in each of those 36 Diaries is fffs.
ff-->fly
|Speed 36;
Shape AA;
Live 3522;
CopyTime 31;
Width 24;
Hash 18288157;
R 90;
G 61;
B 34;
WordsTrans-
ADD l,ADH t,ADH n,LFT,LRD 13,DEL 13,RRD 7,LRD 2,LRD 5,ADH t,
LFT,LRD 0,LRD 0,ADD l,ADD y,ADH f|
ff--result.txt 第 47、48 行:一筆 fly 的紀錄(為了排版,基因在逗號處換行)。Lines 47 and 48 of ff--result.txt: one record for fly (the gene is wrapped at commas for layout).
Time-->0
Try fffs
Copy OK Live 2
Try fffs
Copy OK Live 3
Try fffs
Copy OK Live 4
Try fffs
Tor OK Live 5
Try ssffff
Try fffs
Died OK Live 5
Copy OK Live 6
Try ffs
Try fffs
Tor OK Live 8
Try dfffss
Try fffs
Tor OK Live 10
Try
Died OK Live 9
Try dfffss
Died OK Live 9
Died OK Live 8
Copy OK Live 9
Try cfff
SaveText/No_0/Diary.txt 開頭 26 行。The first 26 lines of SaveText/No_0/Diary.txt.
Below is the replayer. Pick a record from ff--result.txt and watch "ff" turn into the target word one command at a time, in Chinese or English. I re-implemented the commands as ClsEater.vb writes them and ran the recorded successes through it: 30 of them give the recorded word. Two more records, at the end of the menu, do not reach their target when their gene is run as recorded; the note under the replayer says why.
指令串重播器。預設是 fly 那筆,16 步。The command-string replayer, opened on the fly record, 16 steps.
The fun on line 1 uses SUB, which the April ClsEater does not know, so I ran it the way exercise program B writes it and got fun. The exercise's pb.in holds 7 commands, and the 7 lines produced by the same code match pb.out line for line.
Lines 27 (fly) and 29 (fun) do not reproduce. What is logged is the gene a creature was born with, and in its first frame a creature may already have eaten food and learned new commands before it is checked; those commands are not written back. Line 29 is the starting creature, whose gene is only ADD s,ADH f and gives fffs. This is a guess with no direct evidence.