tag:blogger.com,1999:blog-21500237.post8447012067148157459..comments2023-04-29T04:08:32.247-04:00Comments on Praise, Curse, and Recurse: From Bits to Cells: Simple Cellular Automata in Haskell, Part TwoPaul R. Pottshttp://www.blogger.com/profile/04401509483200614806noreply@blogger.comBlogger4125tag:blogger.com,1999:blog-21500237.post-43615420050992308922006-12-19T15:49:00.000-05:002006-12-19T15:49:00.000-05:00Nicholas, thanks for the wonderful suggestions! Th...Nicholas, thanks for the wonderful suggestions! That is a lot of new techniques; they will take me a while to digest.<br /><br />I have added an alternate version of universeToTuples that makes my CA generation behave like Mathematica's.<br /><br />I think I am going to take a break from this for at least 48 hours so I can get some sleep! I want to think over just what I'm going to try next.Paul R. Pottshttps://www.blogger.com/profile/04401509483200614806noreply@blogger.comtag:blogger.com,1999:blog-21500237.post-63838712333577048942006-12-19T14:40:00.000-05:002006-12-19T14:40:00.000-05:00Now that your program is getting more sophisticate...Now that your program is getting more sophisticated, it could benefit from rolling your own types. After all, stringifyUniverse shouldn't accept <i>any old</i> list of Bool, it should accept a Universe!<br /><br />> type Cell = Bool<br />> type Universe = [Cell]<br />> type Neighborhood = (Cell, Cell, Cell)<br />> type Rule = Neighborhood -> Cell<br /><br />Give some helpers to abstract away the Boolness of your Cells:<br /><br />> alive = True :: Cell<br />> dead = False :: Cell<br /><br />Then type your functions accordingly:<br /><br />> rule :: Int -> Rule<br />> applyRule :: Rule -> Neighborhood -> Cell<br />> allDead :: Universe<br />> neighborhoodAt :: Universe -> Int -> Neighborhood<br />> universeToNeighborhoods :: Universe -> [Neighborhood]<br />> neighborhoodsToUniverse :: Rule -> [Neighborhood] -> Universe<br />> nextUniverse :: Rule -> Universe -> Universe<br /><br />That way, your program should be more resilient to underlying type changes. You could change Universe to an Array, or Cell to:<br /><br />> data Cell = Dead | Alive deriving (Eq)<br /><br />And the compiler will tell you what you need to change (which should only be the definitions of alive and dead)! Not to mention that the code reads like natural language!<br /><br />The bug in your code is not obvious to me, so I would probably rewrite universeToTuples in terms of this neighborhoodAt:<br /><br />> u `neighborhoodAt` i = (u' !! i, u' !! i + 1, u' !! i + 2)<br />> where u' = [dead] ++ u ++ [dead]<br /><br />One more thing, if you find yourself writing (a -> String) functions a lot, consider making an instance of Show:<br /><br />> instance Show Cell where <br />> show cell = if cell == alive then "#" else " "<br />><br />> instance Show Universe where <br />> show = concat . map show<br /><br />Then printing a Universe at the top level will automatically stringify it.Unknownhttps://www.blogger.com/profile/05423466002788031695noreply@blogger.comtag:blogger.com,1999:blog-21500237.post-80946366327699317312006-12-19T14:34:00.000-05:002006-12-19T14:34:00.000-05:00I experimented with adding in extra False values t...I experimented with adding in extra False values to the left and right, but I was not able to get my code to generate results that look like Wolfram's. Now I know why.<br /><br />It appears that Wolfram's implementation actually wraps at the boundary. According to Wolfram's book A New Kind of Science "we effectively use a cyclic array, in which the left neighbor of the leftmost cell is taken to be rightmost cell, and vice versa."<br /><br />I'll take a shot at implementing that behavior; I'm not sure I would actually call that solution more correct than pretending we have infinite space available, but it does seem to be more canonical.Paul R. Pottshttps://www.blogger.com/profile/04401509483200614806noreply@blogger.comtag:blogger.com,1999:blog-21500237.post-13659822383510712532006-12-19T10:33:00.000-05:002006-12-19T10:33:00.000-05:00Hi Paul,
I guess the bug is the truncation of the...Hi Paul,<br /><br />I guess the bug is the truncation of the list at the boundaries? Rule 29 seems to behave something like<br /><br />r29 (False,True,_) = True<br />r29 (_,_,True) = False<br />r29 (_,False,_) = True<br /><br />so with the extended universe having a [..False,True,True..] at the boundary, it becomes True. Not sure if this makes too much sense, though I get (what seems to be) the proper answer by expanding one step more, and then taking the tail of the list before stringify.<br /><br />Wonderful stuff, though: I've been learning haskell off and on for quite some time now, but never really had this kind of motivation by example through examples :)The Alternate Moebyushttps://www.blogger.com/profile/04163363935773353768noreply@blogger.com