The wording on question 9 (the regex one) is a little unclear: both b[l].e and ([^b]b[^b]*){3} will match blabber but not babel. Presumably the intended meaning is that the entire string must be matched, but the question does not make this explicit.
The last time I made a world generation algorithm for a voxel engine prototype I got reasonable results through the judicious combination of different types of noise, (specifically simplex, ridged and turbulence noise) and transforming the result using cubic hermite splines for added control, provided you are okay with generally only having one or two main continents (three and four do occur, but are much less common).
This image shows 16 possible world maps (I found it useful to just have them appear next to each other in the world so I could quickly get an overview of the consequences of tweaking parameters): http://imgur.com/dthr7O2
This is the algorithm that generated the world (written in C#). permutation is a random ordering of the numbers 0 to 255, repeated twice. HermitePoints take an x and y coordinate and a slope. Noise functions take an x and y coordinate, a number of octaves, a frequency and a permutation. Turbulence and ridged noise output results in the domain [0, 1], simplex noise in the domain [-1, 1].
private static Chunk GenerateChunk(short chunkX, short chunkZ, int seed, byte[] permutation)
{
var chunk = new Chunk(chunkX, chunkZ);
int worldMapSize = 256;
short maxHeight = (short)Math.Min(worldMapSize >> 2, Chunk.CHUNK_HEIGHT);
float[] worley = new float[2];
HermiteSpline continentCurve = new HermiteSpline(new[]
{
new HermitePoint(0f, 0f, 0f), new HermitePoint(0.07f, 0.03f, 1f), new HermitePoint(0.12f, 0.1f, 0.7f),
new HermitePoint(0.21f, 0.18f, 1f), new HermitePoint(0.24f, 0.2455f, 0f), new HermitePoint(0.26f, 0.26f, 1f), new HermitePoint(1f, 1f, 1f)
});
HermiteSpline continentMask = new HermiteSpline(new[]
{
new HermitePoint(0f, 0f, 0f), new HermitePoint(0.25f, 0f, 0f), new HermitePoint(0.4f, 1f, 0f), new HermitePoint(1f, 1f, 0f)
});
HermiteSpline plateMountainCurve = new HermiteSpline(new[]
{
new HermitePoint(0f, 0f, 0f), new HermitePoint(1f, 1f, 3.5f)
});
for (short x = 0; x < Chunk.CHUNK_SIZE; x++)
{
for (short z = 0; z < Chunk.CHUNK_SIZE; z++)
{
int globalX = (chunkX << Chunk.CHUNK_SIZE_LOG2) + x;
int globalZ = (chunkZ << Chunk.CHUNK_SIZE_LOG2) + z;
//Subdive the world into squares, each of which contains an independent world map
//The edges of each square are lowered so that each map is separated by oceans
float xSeparator = (float)Math.Sin((globalX & (worldMapSize - 1)) * MathHelper.Pi / worldMapSize);
float zSeparator = (float)Math.Sin((globalZ & (worldMapSize - 1)) * MathHelper.Pi / worldMapSize);
float rectSeparator = (float)Math.Min(1, 3 * Math.Min(xSeparator, zSeparator));
float circleSeparator = xSeparator * zSeparator;
float mapSeparator = rectSeparator * 0.375f + circleSeparator * 0.575f + 0.05f;
//Use turbulence noise to get the typical clumped shape of continents and add some simplex and ridged noise for the thinner shapes
float continentNoise1 = Noise.Turbulence(globalX, globalZ, 8, worldMapSize, permutation);
float continentNoise2 = Noise.Simplex(globalX, globalZ, 8, worldMapSize * 0.16f, permutation) * 0.5f + 0.5f;
float continentNoise3 = Noise.Ridged(globalX, globalZ, 8, worldMapSize * 0.5f, permutation);
continentNoise2 *= continentNoise2;
continentNoise3 *= continentNoise3;
float continentHeight = continentNoise1 * 0.5f + continentNoise2 * 0.25f + continentNoise3 * 0.125f;
float baseHeight = continentCurve.Map(continentHeight * mapSeparator);
//Add mountains caused by convergent continental plate boundaries
float continentMult = continentMask.Map(baseHeight);
float plateMountainNoise1 = Noise.Ridged(globalX, globalZ, 8, worldMapSize * 0.4f, permutation);
float plateMountainNoise2 = Noise.Simplex(globalX, globalZ, 8, worldMapSize * 0.2f, permutation) * 0.5f + 0.5f;
float plateMountainNoise = plateMountainNoise1 * 0.66f + plateMountainNoise2 * 0.33f;
float plateMountainHeight = plateMountainCurve.Map(plateMountainNoise) * continentMult;
//Apply the map separation
float finalHeight = baseHeight + plateMountainHeight;
//Convert the height from range [0,1] to range [1,255]
byte height = (byte)(finalHeight * (maxHeight - 1) + 1);
for (short y = 0; y < height; y++)
{
chunk[(short)x, y, z] = (byte)((y + 1) * 255 / (maxHeight + 1));
chunk.SetStack((short)x, z, new short[] { height, (short)(Chunk.CHUNK_HEIGHT - height) });
}
}
}
return chunk;
}
The downside of Simplex noise is that anything greater than 2D is patented: http://en.wikipedia.org/wiki/Simplex_noise There is another project called OpenSimplex that has similar results.
There's no need for XML, nor for all-white video. A 32x32 icon of some color noise, stored as PNG, GIF, or BMP, takes about 2-3 KB. Writing an algorithm to procedurally generate a vaguely interesting video and music can easily be done in less than that. Check out the demoscene for numerous examples. Naturally not all videos can be generated this way, but his statement is still true.
As an alternative to the zipWith method of calculating the Fibonacci series, you can use scanl, resulting in (in my opinion) an even more elegant version:
Joining the other commenter, only 70% of the article reached this recipient's brain.
I would appreciate if you could help me fry it completely by offering a little more than an even shorter one-liner using a function I just read about the first time. Please?
I don't know if this will add much to the article, but let's go over things step by step.
scanl is the same as foldl, save for the fact that it outputs a list of all intermediate values. So where
foldl (+) 0 [1..10]
would output 55,
scanl (+) 0 [1..10]
would output [0,1,3,6,10,15,21,28,36,45,55].
(1 :) means prepend a 1 to the list it is given. The function that is passed as an argument to fix therefore returns a 1 followed by the successive summation values of its argument.
fix just infinitely applies its argument to itself, i.e.
fix f = f (fix f)
In any strict language this would ofcourse just result in an infinite loop, but fortunately Haskell has lazy evaluation. So if we evaluate the list, for example with
take 5 fibs
the following happens:
Haskell wants the first list element. The first element of (1 :) . scanl (+) 1 is 1, so there's no need to evaluate the scanl part yet. Now we need the second element. scanl first returns its accumulator, so that's another 1. For the third list element scanl needs the first element of its argument for the addition, so now we get to the recursive application. As before, the first element of (1 :) . scanl (+) 1 is 1, so the next element is 1 + 1 = 2. This 2 is then added to the next element, which is another 1, resulting in 3. Finally, we add 3 to the third element, giving 5. We now have five elements, which is what we requested, so the result will be [1,1,2,3,5].
I hope this helped a little. If you have any other questions, just let me know.
$40? As long as Joss and the original cast are on board I'll happily pay $100, maybe even $200, even if it's only another half season. Just promise not to start this project before Castle has stopped being good, since I love Nathan in that as well.
Alternatively, for those who want good-looking text but prefer the WYSIWIG approach: just use a half-decent DTP program like InDesign, which will get you everything mentioned in the article except for the per-character transparency.
Another advantage of LaTeX over WYSIWIG alternatives is its simple plaintext representation. If we can still open any documents from our time period in 200 years, we'll be able to open that old LaTeX document of yours, because it's just ASCII (or Unicode in the case of XeLaTeX). And given the portability and simple requirements of the open source, exceptionally well documented TeX code base, it isn't far fetched to imagine someone could even run your documents through the actual LaTeX typesetter, if they really wanted to, 200 years or so from today.
Do you think anyone will still be able to open your documents in Adobe InDesign 200 years from now? This may not matter to everyone, but if it matters for your purposes, LaTeX has a clear advantage here.
EDIT: I'm not affiliated with the author of this article.
While longevity may be important, I think there are other more interesting advantages of plaintext, namely that I can edit in my editor of choice, I can use a host of existing tools, such as sed, grep, etc, to process it, and it plays well with standard source code management systems.
If you ever wrote a paper with another person, you will absolutely hate Word (and other binary formats). It makes working on the paper a pain, since only one person can work on it at the same time.
The ability to split a document in multiple source files and having SVN/git/etc makes it really easy to work on the document at the same time.
InDesign is an absolutely awesome program, my favorite from Adobe next to Lightroom.
Mac OS X’s font palette (while sucky in general and in dire need for a makeover to improve its UI — it’s like vintage 2000 or so) also offers you many of the mentioned features: 1 and 3 are on by default everywhere (type ‘shuffle’ into the Spotlight searchbox, ‘ffl’ will be turned into the appropriate ligature), 2, 4 and 5 are accessible through the palette but I don’t think OS X is clever about line-breaks (at least there are no settings to fine-tune). Don’t know about transparency. It is available to you in every program which uses OS X’s standard method of text input (like Pages or Safari).
OS X's text system does have per character transparency. It's not exposed by TextEdit but it is exposed by Pages's color picker.
You could retrofit smart justification onto the text system, but it would require some non-trivial code (namely an NSTypesetter subclass). It's not easy, but it's possible.
Interestingly, if you multiply 15 years by 365 days and the two hours a day mentioned at some point in the article, you get 10,950 hours, which is remarkably close to Malcolm Gladwell's claim from the book Outliers that it takes 10,000 hours to become a superstar at something.
Umm, that's a bit backwards -- the 10k hours number comes from research by K. Anders Ericsson et al, and the first papers mentioning this are from the early nineties, if not earlier (as for book references, it's discussed in Ericsson's "The Road To Excellence" that predates the Cambridge Handbook by a decade).
I can't comment on Lisp, but I've been working with Haskell for about a year or so now, so I'll cover that instead.
My personal history goes something like QBasic -> Visual Basic -> PHP -> Java -> C# -> Haskell.
Since Haskell is a purely functional language there's no cheating like you could in, say, OCaml. This forces you to learn how to work with immutability, which I have become a big fan of. When working with C# I try to avoid mutability as much as possible (naturally this is quite a bit uglier than in Haskell, but it does avoid some problems). Most of my C# projects now acquire a Haskell.cs file fairly quickly, containing things like a Tuple class, zip, >>=, etc.
In the time I've spent learning it, Haskell has quickly become my favourite language. It's not perfect (my current main wishes are existential types and an extensible record system), but it is considerably less painful than the other languages I know.
As for speeding up the transition, I can't offer anything other than just diving in. At some point it will just click and you will wonder what all the commotion is about (another monad tutorial? why?). Granted, I still don't have the slightest idea about why I would want to use a hylomorphism or what to do with a comonad, but perhaps I will some day. Fortunately you don't need them in everyday Haskell programming :)
You took the words right out of my mouth. I had a bit different language history, but I'm right with you on Haskell. I have always found that it's quickest to just dive in. It's kind of like learning natural languages by immersion...nothing works as fast as dumping yourself in a foreign country where you have no choice but to learn to communicate in their language. Reading some choice books and tutorials can certainly help, but there's really no substitute to writing code.
I've tried it a bit, but I found the syntax rather ugly compared to Haskell. I know, I'm nitpicking and it really shouldn't matter that much, but it put me off the language. Perhaps when they finally release a full-blown implementation of F# for Visual Studio I'll give it another go.
My main reason for still using C# at the moment is the UI integration with WPF and Windows Forms. Ideally there'd be an actively maintained Haskell.NET, but perhaps F# can serve as a compromise when Visual Studio 2010 comes out.
No, I mostly make a new one per project. All the functions are pretty much one-liners anyway, so it's not too much work to make. It's more of a documentation thing; anything in Haskell.cs can be assumed to work exactly the same as its Haskell equivalent.
Not so much obsession as convention. Generally versions 0.x - 1.0 are the alpha and beta releases, with 1.0 being the first "stable" release. Obviously there are hundreds of projects that follow a different schema, but it's used enough that it has stuck. One solution if you want to keep your versioning style would be to annotate them as stable or development, possibly with a short paragraph explaining that version 0.0.3 is in fact bugfree/feature-complete/ready for use in production/etc.