The Independent Consulting Manual - <AUTHOR> http://independentconsultingmanual.com/ <comment><USER2> Heya HNers,

Jumping in here to offer a bit of context to this post!

We — a collection of 13 consultants — wrote the Independent Consulting Manual (ICM) to offer advice, guidance, and direction to consultants who want to grow their business.

The ICM is based on our shared experience growing our consulting practices over the last few years. While it would be impossible to offer a 'Comprehensive Guide To Everything Consulting,' we've done our best to share strategic (ex: building a productized consulting offering, positioning your business, qualifying your prospects and clients, writing better proposals, etc.) and tactical lessons (ex: using cold email outreach, using facebook ads, avoiding late payment, etc.) to help give consultants, like you, a strong direction of the strategies and tactics available — and how to implement them in your business.

Wherever possible, we worked to go 'above and beyond' in the advice we share to make sure that it's actionable, relevant, and specific to an independent consultant who is looking to grow their business.

As Bryce Bladon was kind enough to write in the introduction:

> It would take years of experience and dozens of new and interesting mistakes > to learn as much as I have from Kai and his colleagues over the first few > months of knowing them. That's what this book is: a shortcut for time, > effort, and mistakes.

> If you're someone who considers themselves an independent _anything_, then > you're probably someone who understands accountability. You understand that > this book is not going to catapult you to ridiculous new heights of success > as soon as you finish the last chapter.

> What it is going to do is provide proven and actionable advice. It's going > to make you reflect on how you do business and it's going to make you better > for it.

We wrote the ICM to provide actionable advice specific to independent consultants. But, much like any skill, it takes action on the part of the reader to implement the advice and, slowly, consistently, over time, improve their business to get to that next level.

I know that from when I started my independent consulting practice to when I had my first 6-figure year, it took 5 years of consistent, steady progress. With the ICM, we're offering lessons, advice, and direction to help the reader understand the steps to take to reach that point. Much like a cookbook, we're offering lessons and recipes to follow. The job for the reader is to implement, test, refine, and repeat.

Our Guarantee — We collectively stand behind our product and the quality of the information we're sharing. If you buy the ICM, read it, and find it lacking in any way, not up to your standards, or not meeting your expectations, all you need to do is hit reply to your order email and let me know you want a refund. Then I'll send you an immediate refund. (We list a 14-day money back guarantee on the website and the truth is after 14, 28, or 365+ days, if you said "Hey, you know what, I made this investment and I'm just not happy with it, I'd like a refund," I'll instantly refund you your purchase).

Am I explaining all of that well? I deeply appreciate any questions you have for me / us. I'll be checking this thread throughout the day. You can also always message me on Twitter as @kaisdavis.

Thank you!

— Kai, Editor, Independent Consulting Manual

</comment><comment><USER3> We're allowing straight-up ads on HN now?</comment>


Crashes, injuries spike after Michigan boosts freeway speed limits to 75 MPH - <AUTHOR> https://www.bridgemi.com/michigan-government/crashes-injuries-spike-after-michigan-boosts-freeway-speed-limits-75-mph <comment><USER2> The barrier to entry for getting licensed to operate a vehicle in the United States is way too low. People don't respect what they are doing when operating a motor vehicle.

The deadly issue with driving is that it's just too easy. 99.999% of the time things go just as well as you'd like without much active thinking. People get lulled into a false sense of security and get bored and start distracting themselves with their phone or whatever else.

We really need to redefine a car trip as a way to get you somewhere safely rather than quickly.

<comment> crooked-v > The barrier to entry for getting licensed to operate a vehicle in the United > States is way too low.

That's because we've built the country since the 1950s in such a way that a car is a necessity rather than a luxury.

</comment></comment><comment><USER3> IMO, title has an implication between speed and crashes that is not fair.

The article even says (1) not enough data (2) most crashes leading to the increase aren't in areas where the limits increased.

</comment><comment><USER4> This is a scalding hot take of an article that says nothing of substance, and commits many logical fallacies along the way.

But, most people never read past the headline, so I'm sure this will get passed off as gospel.

<comment><USER5> Yup, from the article: "Police did not identify speed as a primary factor in any of the 14 fatal crashes on 75 mph freeways in 2018, the highest number in five years."

<comment><USER6> Remember that power required to push air out of the way is quadratic with speed. The 10 mph increase here is a 30% increase in kinetic energy in any given crash.

<comment><USER7> You are right that kinetic energy scales quadratically, but it have nothing to do with "pushing air". The kinetic energy formula is the same in a vacuum.

</comment></comment></comment></comment><comment><USER8> I believe there have been studies that indicate traffic accidents on freeways increase as the speed delta between vehicles increases.

My opinion (biased, obviously) is that the people who choose to drive significantly below the speed limit are more of an issue than those who choose to drive above it.

Someone driving over the speed limit is going to be monitoring the traffic ahead of them. Those are the people they are most likely to interact with.

Someone driving exceptionally slowly is much less likely to be monitoring the traffic behind them adequately enough to know when someone is approaching them rapidly from behind.

Further, the amount in excess of the speed limit that the vast majority of people would be willing to drive is a fairly small delta (10, maybe 15mph max). The amount below the speed limit someone may choose to drive is much larger, mostly by definition of it being any value from zero to the speed limit.

A habit I picked up a few years ago thanks to seeing others doing so is to put on my 4-way flasher hazard lights if I'm driving significantly below the speed limit (usually due to snow or super heavy rain). It helps alert people that "hey, this person is going slower than you probably expect them to be, so pay attention"

<comment><USER4> 4-ways are often very under-utilized.

Whenever I get into a car for the first time, one of the first things I do is figure out where the 4-ways are, and try to remember that piece of information so that I can turn them on as a reflex, if needed.

<comment><USER9> Except that's illegal almost everywhere. Maybe it shouldn't be.

[https://drivinglaws.aaa.com/tag/hazard-light- use/](https://drivinglaws.aaa.com/tag/hazard-light-use/)

<comment><USER8> That list looked to me like well over half said either explicitly "permitted" or "prohibited except to indicate a hazard", which I believe the use cases listed qualify under.

</comment></comment></comment></comment><comment><USER10> I wonder how many collective hours have been saved, and what the ratio is between the value of that and the increased accident rate. I'm sure there's a suitably mercenary cost-benefit analysis that would be interesting to see.

My experience, limited though it is, is that in Detroit nobody drives the speed limit or anything close to it. 85 in a 65 zone was standard.

<comment><USER3> In my opinion, weather plays a substantially larger factor than the speed limit. We've had some nasty icy roads the past few winters.

<comment><USER11> I was wondering if there's a correlation with weather for the particular crashes recorded.

</comment></comment></comment><comment><USER12> A major highway in Ontario (402) was increased from 100 to 110 and the police said the current results are that there's no significant changes in crashes.

Now I can't find the article. So take this with a grain of salt.

I doubt Michigan drivers are objectively worse so I imagine it's just a bad finding.

</comment><comment><USER13> 75 on a new car is far different than 75 on my 99 Honda accord. Also, once people get used to winter, they get a little cavalier on these snowy Midwest roads. Did the statistics control for this year's weather?

<comment><USER14> If you look at stats for temperate climates, the chief factor is normally not the winter but the summer. In snowy weather, drivers actually tend to slow down, and even though many go off the road, they are slow crashes with few fatalities. A long, hot summer is deadly though, because it means more miles travelled and hence more accidents. And crashes in the summer tend to be fast, and thus more deadly.

</comment></comment><comment><USER15> I'm really big on the future of self-driving cars and how they'll help with problems like this. Not only will they be inherently safer at any speed, my guess is that drivers won't fret as much to exceed the speed limits.

If you're able to keep your eyes off the road and work on your laptop, read a book, take a snooze, whatever... are you all that worried about whether you're doing 70mph or 80mph?

I think that a lot of the aggression of drivers is due to opportunity cost. They feel like they could be doing something else with their time and that the driving part is a waste.

</comment><comment><USER16> Look at those signs- 65 is the limit for trucks, you have cars pushing 80, and some drivers like the one interviewed in the article driving 70. A higher variance in vehicle speeds makes traffic less safe.

</comment><comment><USER17> Before the change, Michigan had the highest car insurance rates in the US. I am sure this will make them even higher. Having policies that make car insurance expensive is an unforced drain on the statewide economy. Sensible policies would add about $1200/year in disposable income per car in Michigan.

<comment><USER18> Michigan also has auto insurance changes due to take effect in July 2020 that will also wind up affecting their rates, notably the lifting of the heavy Personal Injury Protection coverage:

"Michigan has the highest car insurance coverage requirements in the U.S. — most notably Personal Injury Protection (PIP) insurance with unlimited, lifetime medical coverage for car accident injuries. Michigan's insurance requirements guarantee many health and recovery benefits to injured drivers, including reimbursement for lost wages, in-home nursing care, and specialized medical treatments." [1]

[1] [https://www.thezebra.com/resources/research/michigan-car- ins...](https://www.thezebra.com/resources/research/michigan-car-insurance- crisis)

(I didn't realize their rates were THAT much more than surrounding states... ouch.)

</comment></comment><comment><USER19> I am shocked that the author, much less editor, would allow this to be published. There is nothing but conjecture. I guess websites really will say whatever click-bait title gets them the most traffic.

</comment><comment><USER20> What I think this article gets right, even if accidentally, is that speed is not a great factor in determining traffic crashes or the outcome on human life. While the point of the article seems lost in it's nonsense and meandering story, there are a couple of good points:

1) The one person who says "I go 80 anyway so I like it". People drive whatever speed they want regardless of speed limit. Case in point, the person who said "I still drive 70 because 75 is too fast". There's nothing inherently dangerous about speed until you hit something. Cars hitting each other is much more likely when the speed differential increases.

2) The person who talks about the economy having more of an impact on driving behavior than speed limits. I'd love to see more data on that, but regardless of if it's true, we know that the speed limit doesn't have the biggest impact on driver safety, and we know that thanks to

3) The Autobahn referenced at the very end of the article, and other no-limit freeways that exist even in America. I had an opportunity to drive on some unrestricted sections of the Autobahn this past summer and even with the huge differentials in speed, drivers managed to not crash into each other.

I don't know what the problem is so I don't know what the solution is, but I can make a couple more observations. First, Germany has a law that your car has to be in proper working order and it's taken off the roads if it's not. Having spent a lot of time in Northern Michigan where this article takes place, there is no guarantee that cars on the road are working. As long as the car can move, people will drive it. Doesn't matter how long they've been using the same brakes or tires. So when it comes time to avoid an accident, their car is not capable of stopping or maneuvering in time.

Secondly, drivers training in the US is abysmal. You're expected to learn how to avoid collisions by yourself, and you're expected to learn how to drive in bad weather (wind, snow, rain) by yourself, on public roads, with other drivers around you.

An extra five miles per hour on a limited-access freeway in an amazingly rural area should not impact anything at all, ever. There HAS to be other factors in play besides the speed limit.

</comment><comment><USER21> Any idea how to interpret the first chart?

</comment><comment><USER22> This is total bullshit. Not one citation.

</comment><comment><USER23> this is also called clickbait.

such agencies will die out soon because they spread fake news.

hey bridgemi, I wish you unemployment soon!

</comment><comment><USER24> I suspect one of the biggest impacts was revenue shortfall for the state troopers.

Also, 14 fatal crashes for the year. When numbers are that small, any variation makes for a big change in percentages.</comment>


Static typing will not save us from broken software - <AUTHOR> http://www.drmaciver.com/2016/10/static-typing-will-not-save-us-from-broken-software/ <comment><USER2> I spent 10 hours yesterday refactoring and adding features to a client side enterprise application that is well over 20k lines of TypeScript over tons of files.

Yesterday was a pretty productive day for me. TypeScript easily caught hundreds of little errors as I coded and refactored which I fixed just a quickly. Most of the time when I tested my changes things just worked. I thought to myself every time TypeScript found something, 'wow I just avoiding another runtime error, thanks'

Maybe people don't write or maintain client side software at scale. I don't know. But there's so little cost to having static typing I don't know why you wouldn't want it. I am easily an order of magnitude more productive with it. I code faster, my code works first time around more often, other people can understand my code easier, and my tests don't have to worry about validating types so they can be more logic oriented.

There is zero chance anyone would of been able to be as productive as I was yesterday if that code base was dynamically typed. Not even close.

<comment><USER3> _" …a client side enterprise application that is well over 20k lines of TypeScript over tons of files […] But there's so little cost to having static typing I don't know why you wouldn't want it"_

I don't think the OP would claim TypeScript is a bad idea, as, with its relatively weak type system, it doesn't really suffer from _" if you find a bug it's easy and unintrusive to add a test for it, but may require a substantial amount of work to refactor your code to add types that make the bug impossible"_.

As an example of a strong type system, in Haskell code, the database access layer will may types such as "ISO-8859-1 string of at most ten characters"

If it turns out that you want to store ISO-8859-2, changing that type can and often will cause a cascade of necessary changes, for example because you're calling a ISO-8859-1 to UTf-8 conversion function, and the compiler will not accept that call to now take a ISO-8859-2 string, or because you are concatenating that string with another ISO-8859-1 one. Then, you will have to decide whether to convert locally or whether to also change the type of that second string, etc.

Now, of course, each of those compilation errors becomes a bug if you just use variable-sized byte arrays. Question is how much work you are willing to do to prevent those bugs.

<comment><USER4> > I don't think the OP would claim TypeScript is a bad idea

Confirmed.

TBH there are very few languages that I'd claim were a bad idea. The point I'm making is not "Statically typed languages are a bad idea" it's "If you think statically typed languages are going to make software correctness magically better then you're going to be disappointed".

<comment><USER5> You did actually claim that statically typed languages were _worse_ than dynamically typed ones for correctness:

> My general experience of the correctness software written in fancy > statically typed languages is not overwhelmingly positive compared to that > of software written in dynamic languages. If anything it trends slightly > negative.

<comment><USER4> I might not say that the use of any language is a bad idea, but I'm definitely going to say that basing a language choice on a general and uncertain impression derived from my extremely limited, biased and anecdotal sampling as an end user is a _terrible_ idea :-p

ETA: The point of that anecdotal impression was not "This is definitely true" but "Given that this is my general experience it would be surprising if the actual trade offs experienced in practice were such that static typing was regularly a clear winner", which I feel much happier supporting on an impression than "You should do this".

</comment></comment></comment></comment></comment><comment><USER6> I've started to feel the same way. I feel like a lot of developers would be better off in a dynamically-typed language because it is such common practice to completely subvert the type system and there are such strong resources available for improving testing practices.

My last job was in C#, and it seemed like so many things were stringly typed, entirely nullable, or used something else to weaken the type system.

In addition to this failure to use the type systems, testing is becoming a much more rich environment. I think popular resources on effective testing are much better and numerous than popular resources on effective typing. There are great books and tools around helping developers test their software more thoroughly and efficiently. Comparing these testing resources with typing resources, the closest popular book I can think of for typing is Design Patterns, and I don't think most popular type systems are built with the program correctness as a top priority.

I think rich type systems like haskell's will play more of a role in the future, and I think current users of these systems do experience a benefit. But if you have only ever done dynamically typed programming or used Java/C#, you are probably going to improve your correctness more over the next year by using a property based testing tool like propr (ruby), hypothesis (python), fscheck (.net), scalacheck (jvm), or jsverify (js), spec (clojure).

<comment><USER7> > My last job was in C#, and it seemed like so many things were stringly > typed, entirely nullable, or used something else to weaken the type system.

This sounds like C# as written by people that don't really know or like C#. If you're stuffing everything into strings or a dynamic, you missed the point of the type system in a very serious way.

> In addition to this failure to use the type systems, testing is becoming a > much more rich environment. I think popular resources on effective testing > are much better and numerous than popular resources on effective typing. > There are great books and tools around helping developers test their > software more thoroughly and efficiently. Comparing these testing resources > with typing resources, the closest popular book I can think of for typing is > Design Patterns, and I don't think most popular type systems are built with > the program correctness as a top priority.

There is some overlap between problems that can solved by type systems and test suites, but there are many problems that can only be caught by one or the other.

It also strikes me as strange that people can't be bothered to use the type system provided by the language, but they _can_ be bothered to maintain and add unit tests for their programs. Correctness enforced by types is fused with the code; if you get the types right, you should be all set. There's no additional maintenance beyond making sure that the code compiles.

<comment><USER8> There is a real cost to properly modeling your domain in the type system. You have to conform with the constraints of the type system, there is higher cognitive overhead, it can cost more up-front (which can cause missed deadlines), etc.

Also, there are cases where using strings is more appropriate than using enums. Where passing a blob is preferred over guaranteeing the correctness of the blob's structure. Where "null" really is better than an Option type.

And conversely, there are companies who hire crappy developers or don't give their good developers enough time to learn the idioms and best practices of their tools.

<comment><USER9> "Dynamic Witnesses for Static Type Errors* ("or ill-typed programs usually go wrong)"[0] by Eric Seidel et. al. discusses a prototype for a system that searches for concrete examples of ill-typed inputs that break a program, in order to aid novice programmers with type errors at compile time.

[0][http://eric.seidel.io/pub/nanomaly- icfp16.pdf](http://eric.seidel.io/pub/nanomaly-icfp16.pdf)

<comment><USER10> That is _really_ cool! When will it be in GHC? :D

</comment></comment></comment></comment></comment><comment><USER11> I agree with the article. No silver bullets, just lots of regular bullets, and static typing is just another bullet.

The main advantage for static typing from my experience are what happens when you have projects above 10kloc with multiple maintainers, and maybe the original devs have moved on to other teams. At that stage in a product's lifecycle, static typing reduces friction and covers some cases that are hard to test properly. Greenfield projects don't suffer from this problems for the first year or so.

Refactoring is the major thing that's easier with static typing, IMO.

<comment><USER12> All tooling is much easier with static typing. Code completion, highlighting mistakes as you type... features that are much more powerful in a statically typed world.

I agree though: it's a tool in the tool belt. It also varies dramatically across different languages and supported features which can make a huge difference in the kinds of problems it solves for you. Lately I've been doing a lot more modeling of problems with types when it makes sense... things like measurement units and their operators to ensure you can't accidentally add meters to watts. Or using unique ID types for each model so you can't accidentally create a reference with the wrong ID.

The newer languages and updated standards (e.g. Swift, Rust, C++ with auto) take a lot of the useless repetition of types out of the equation and feel more like type annotations in a dynamic language. In the end I think we'll mostly settle on hybrids. Some will be static by default but support dynamism. Others will be dynamic by default but support static type annotations.

What won't change is that you can't scale transistors below a single atom and we can see that endpoint on the roadmap. Performance improvements will not continue at the current rate. One could argue we're already there given the perf delta between CPU and memory or CPU and storage has gotten orders of magnitude worse.

In a future where abstractions impose a real cost the optimization function may change, especially for established businesses and processes. Hiring a couple of Rust or Swift senior devs to rewrite your Python backend in a statically compiled language, then applying repeated optimizations might be worth the cost when you know it will be 10 years before a new CPU is released and it will be 10-20% faster at best. Or if you imagine future CPUs require exotic materials and 10x as much R&D to hit the same targets they become 10-100x as expensive.

</comment></comment><comment><USER13> > the idea that static typing will solve all our problems, or even one > specific problem: The ubiquity of broken software

Citation needed.

Most proponents of static typing, myself includes, have much more modest claims: that is saves time spent by developers on smaller, more mundane errors. That it makes refactoring easier. That it allows for better IDE support like autocompletion and hover-over documentation.

Even if these advantages are modest compared to fixing "broken software", they're still huge and worth the increasingly minor annoyances of modern static type systems, many times over.

<comment><USER14> You can argue on "most" advocates, but not "certain" advocates. Since you asked for a citation, how about the famous "Not relying on type safety is unethical"?

[https://twitter.com/queertypes/status/513510398570795008](https://twitter.com/queertypes/status/513510398570795008)

</comment></comment><comment><USER15> > Software is broken because its not worth people's while to write non-broken > software

This is the premise of a large part of the article. And it is wrong. At the very least a citation is needed. And even if there is a scientific source, I disagree with it. I'd argue that many people do want to write non-broken software, but they do not know how to efficiently use static type system, or they don't know how effective it is. If all you know is Java or C then of course you're going to doubt if a type system is worth at all.

> As static typing becomes more elaborate the scope of the bugs it can prevent > becomes wider, but it usually comes with an additional cost: Build times.

I disagree. When you are working with Haskell, use ghcid and you'll have near instant recompile times. I made a proof-of-concept of a web frontend in Haskell, and it reloads with sub-second delay. That is comparable to a JavaScript project which uses webpack and babel.

<comment><USER16> You can disagree what you like, but the fact that a lot of software out there has bugs and these bugs don't stop it from being successful clearly supports the point the article makes.

If catching the types of bugs that static typing prevents resulted in reduced costs of software development, you'd see static typing out-compete dynamic typing. It's really that simple.

<comment><USER5> > If catching the types of bugs that static typing prevents resulted in > reduced costs of software development, you'd see static typing out-compete > dynamic typing

Apart from network effects, inertia, lack of education and awareness, and all the other confounding factors.

<comment><USER16> The complete and utter lack of empirical evidence with regards to purported benefits of static typing is the real elephant in the room here I think.

Considering how long both disciplines have been around, you'd think we'd see some clear benefits by now. Yet, here we are swapping anecdotal evidence.

<comment><USER15> The disciplines may have been around for long. But the industry has poured billions into educating people (students in universities) on C, Java, C++, C#. Comparatively little has been invested into educating people how to use and work with good type systems. You're comparing apples and oranges.

You can't ask the general developer population how they feel about static vs dynamic typing. The result will be biased towards dynamic because that's the only thing most developers know.

<comment><USER16> Conversely, a lot of people have have used dynamic typing in languages like JavaScript and Ruby. Their OO nature encourages creation of many types, while pervasive mutability removes any possibility to do local reasoning about the code. The situation is completely different in functional dynamic languages backed by immutable data structures.

</comment></comment></comment></comment></comment></comment><comment><USER17> Both proponents and detractors of static typing seem to miss its major benefit: tooling.

Being able to hit . and get a reliable list of things I can do is worth many millions of dollars to me.

<comment><USER4> > Being able to hit . and get a reliable list of things I can do is worth many > millions of dollars to me.

...and mostly is possible because of the many millions of dollars that were thrown into developing it rather than the type system. Quality of tooling has much more to do with the amount of money invested in it than whether the language is statically typed.

But this isn't a post about static vs dynamic typing as I said right at the top. It's a post about the effect of static typing on software quality.

<comment><USER18> Code completion is a fundamentally harder (if not impossible) problem with dynamically typed languages, as you might need whole-program and control flow analysis to even get the types of local variables. This fact has nothing to do with the money involved, it's probably rather another formulation of the halting problem.

<comment><USER4> > Code completion is a fundamentally harder (if not impossible) problem with > dynamically typed languages

Code completion tools originally came out of Smalltalk. It's relatively doable if you can attach to a running process that has dynamic access to your code.

So that's "not necessary". It's also not sufficient: Most statically typed languages simply don't have this sort of tooling because it's very hard to write, and advanced type systems make it even harder.

<comment><USER19> Most Smalltalks didn't really have great code completion (or code completion at all), and when they did, a lot of it had to do with the verbosity of method signatures removing a lot of ambiguity. Don't get me wrong, Smalltalk has some really cool features, but they did it by having a workflow completely different from static languages, and trying to imitate Smalltalk's environment in a language not designed from the ground up for it (ie, python or perl or whatnot) would be a lot harder. The fact that it's hard to write language tools in general doesn't change the fact that it's way harder to write an IDE for a dynamic language than it is for a static one.

<comment><USER4> > Most Smalltalks didn't really have great code completion (or code completion > at all),

Ditto most statically typed languages.

> The fact that it's hard to write language tools in general doesn't change > the fact that it's way harder to write an IDE for a dynamic language than it > is for a static one.

It doesn't, but the fact that there's nearly as much variation within statically typed languages in terms of how difficult this is to do as there is between statically and dynamically typed languages does. And this only gets worse as we move to the sort of languages that the static-types-for- correctness people advocate for.

<comment><USER19> > It doesn't, but the fact that there's nearly as much variation within > statically typed languages in terms of how difficult this is to do as there > is between statically and dynamically typed languages does.

I really don't buy this. Yes different languages present different degrees of difficulty, but the ceiling is much lower for dynamic languages compared to static ones. In dynamic languages, there are absolutely (very common) situations where types cannot be accurately inferred (or inferred at all). If I write

       def f(x, a): return x[a]

That's practically impossible for an IDE to do anything with.

The reason why not every static language has great tool support is more to do with A) if the compiler was designed with hooks/apis for tools to use (like clang and rust do), and B) if the language has enough popularity for anyone to bother. I'm pretty sure if you take two languages of relatively equal popularity, and compare the dynamic one to the static one, the static one almost always has better IDE/tool support. For instance, lets take Swift vs Ruby (they're next to each other on the Tiobe index). I've yet to see a Ruby IDE that is much of an improvement on a text editor, whereas Swift is pretty young and already has tooling comparable to much more mature languages.

<comment><USER20> > I've yet to see a Ruby IDE that is much of an improvement on a text editor, > whereas Swift is pretty young and already has tooling comparable to much > more mature languages.

I've never worked with Ruby, but I do work with (and mostly enjoy) Swift. The one thing I really don't like about Swift is that the currently available tooling (both AppCode and Xcode) is _extremely_ primitive compared to what I am used to from Common Lisp and Clojure.

<comment><USER19> Anecdotal data point of one guy's opinion, with no elaboration on reasons? Convincing. I'm talking about WHY analyzing dynamic languages is fundamentally undecidable in many cases without run time knowledge. Trying to do anything other than heuristics on some of these things is about as decidable as the halting problem. The only argument I've heard against this is you can have a hybrid environment with a REPL so your dead code is live. Ok, but you can do the same thing with static typing too.

</comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER21> A digression on Java compiler performance:

> Java's compile times are sorta reasonable but are apparently getting worse.

I'm not entirely sure what this is about. Could it have anything to do with JEP 215? [1] There were some slowdowns in `javac` in Java 8, but these should be fixed in Java 9. Note this has more to do with _type inference_ than with Java's type system per se, though this distinction is of little difference to most Java programmers.

In our experience with OpenJDK builds, the main performance issues have been around redundant loading/parsing of library class files and JVM/JIT warmup time. These have mostly been mitigated by JEP 199. [2] With the exception of the issues I mentioned above, it's hard for me to see that static typing has had an impact on the performance of Java compilation.

(Overall I agree with the main thrust of the article, particularly with regard to the "set of complicated trade-offs." Personally I find static typing very helpful, but it won't _solve_ software quality problems.)

[1] [http://openjdk.java.net/jeps/215](http://openjdk.java.net/jeps/215)

[2] [http://openjdk.java.net/jeps/199](http://openjdk.java.net/jeps/199)

<comment><USER4> It might be based on false information - I'm a bit out of touch with Java development. I'll remove it.

<comment><USER21> Thanks for the update. Of course if there are any performance problems, I'm sure the javac team would like to hear about it, as this is something they do pay attention to.

</comment></comment></comment><comment><USER5> > As static typing becomes more elaborate the scope of the bugs it can prevent > becomes wider, but it usually comes with an additional cost: Build times.

This is the meat of the entire argument, and it's false, as you can verify by running ghc with the -fno-code option. Type checking is extremely fast. It's everything else that's slow and that has absolutely nothing to do with static typing.

</comment><comment><USER22> I watched a talk by Erik Meijer [1] recently where he mentioned that an implementation of a tuple such as (C# syntax mine, but illustrates the point)

      class Tuple<T1, T2>
      {
        public Tuple(T1 t1, T2 t2) { }
        public T1 Item1 => default(T1); // null for reference-types
        public T2 Item2 => default(T2); // null for reference-types
      }

is a perfectly type-safe implementation of a tuple that's completely nonsense. I'm curious as to how you might actually encode into the type system that the values that come out of Item1 and Item2 are actually the values you put in.

I would love to see tests at the interface level (or typeclass level for Haskellers) rather than the implementation level, to enforce that all implementations of an interface satisfy laws like this. In Haskell, this would mean that you could enforce things like monadic laws which we all assume to be true anyway.

[1] [https://www.youtube.com/watch?v=JMP6gI5mLHc](https://www.youtube.com/watch?v=JMP6gI5mLHc)

<comment><USER10> If you require a constraint to be able to provide Default values (even if every type in fact implements Default - c.f. Typeable) then for Tuple in particular there is only the correct implementation (modulo bottom or hidden side-effects).

<comment><USER22> True, that's a good point.

Side note: you seem to be replying to all of my comments, are you following me? :P

<comment><USER10> > are you following me?

Checking in occasionally - you've been steadily posting things worth replying to :)

</comment></comment></comment></comment><comment><USER23> OP's argument, boiled down, is the following:

1) Behavior needs to be automatically checked 2) To check behavior, you can either write tests or specify types 3) Tests are more flexible than the type systems of popular languages (e.g. to write end-to-end tests) 4) Testing purely dynamic languages is quicker than compiling statically typed code 5) So prefer tests to type systems because agility

Honestly this is a load of bollocks and I'll explain why:

* When business execs throw out the old UI (old end-to-end tests) and replace it with a new UI (new end-to-end tests) and your new tests are failing because undefined, well, have fun and good luck! * The longer a system lives, the longer the test suite gets. So no, your developers are not going to be running the entire test suite at their desks, even if at the beginning of that project, running that test suite took all of half of a second. This is one of the reasons for continuous integration servers, actually, so that the massive test suite can be parallelized across a bunch of build slaves and run overnight while the programmer is at home or working on a different feature/problem. And then the difference in compile and start-up times is psychologically irrelevant because the programmer will still think "ok, I submitted the build to CI, time to go home/work on something else". * Good type systems, combined with proper IDE support and proper object-oriented design, do optimize for deletion by reducing the number of places in a codebase in which refactoring has an impact. It is incorrect to state that type refactoring should be some kind of massive refactoring affecting every file in the codebase every time you refactor. A refactor should either eliminate a given subtype, thus leaving the other subtypes unaffected, or add a subtype, where no-longer-common code/behavior can be factored into a new intermediate type. When the supertype needs to be changed, well, you still need to test those changes, but at least you only needed to make the change in one place, and not an indeterminate number of copy/pasted places in dynamically typed code which, you know, good luck finding them all.

Static typing is a practical requirement for long-lived, large systems. OP makes way too many assumptions on the basis of small, short-lived projects.

</comment><comment><USER24> Interesting point about the relative value of typing vs. testing, and how too- strict typing can crowd out testing. However, see the discussion under pixie_'s comment about new code vs. refactoring.

Also, this makes me think about incorporating testing directly into the language, which kind of brings us to Design By Contract and formal methods. It seems to me that now would be a good time to resume active research on those things, instead of all these exhortations to use magic type systems and magic immutability and so on.

</comment><comment><USER25> > I'd expect static typing to win out for correctness if: [...] very large.

I would disagree. In very large projects, strong types don't scale very well across repositories / deployable units.

A very large single repository, it may be ok. Except that refactoring types will like break a lot of in-flight pull requests and branches.</comment>


Adobe working on a patch for 'critical' TIFF vulnerability in CS5 software - <AUTHOR> http://www.theverge.com/2012/5/12/3015925/adobe-patch-critical-tiff-vulnerability-cs5-malware <comment><USER2> Context: <http://news.ycombinator.com/item?id=3952263>, Adobe's initial response, mentions upgrading to CS6 as the _only_ remedy. The comments are predictably unhappy about this.

<comment><USER3> Yes, the original wording in Adobe's initial press release was rather convoluted but, once absorbed, fairly clear and unambiguous. I think this Verge article is parroting a false, revisionist history on Adobe's part.

</comment></comment><comment><USER4> Adobe has become a troll of the software industry. Everyone dealt with their Flash crap for years, Apple/HTML5/etc finally killed it, and now all they have left is the CS suite. As soon as a better crop of graphics apps comes around Adobe is finished.

<comment><USER5> > Everyone dealt with their Flash crap for years, Apple/HTML5/etc finally > killed it, and now all they have left is the CS suite.

huh, Flash isn't dead... far from it.

<comment><USER6> It isn't dead. This hatred towards flash has become a mob mentality and it's stupid. No one's charging you to run their software. There have been a lot of amazing cross platform applications made because of flash.

<comment><USER7> "No one's charging you to run their software."

I haven't seen anyone claiming that either. However, you're being forced to install and run it to access certain sites and that's why I'd be more than glad to see it replaced with a more open technology as soon as possible.</comment></comment></comment></comment>


Ask HN: Where to find good CTF / wargame platforms? - <AUTHOR>

These days I am very interested in learning about computer security / cryptography by practice and I  find that CTF / wargames are very practical ways of learning about these subjects.
After a quick google search I did not find that much on HN: site:news.ycombinator.com ctf wargame intitle:"Ask HN"
I am seeking more platforms to train my skills and learn new things.
Here are some I already know of and am working on:
- http://overthewire.org/wargames/vortex/vortex0.html
- http://www.root-me.org/
- Stripe CTF
- Matasano Crypto Challenge
Please post the ones you know about with a symbolic representation of difficulty (* = easy, * * * * * = extremely hard). <comment><USER2> oh and microcorruption.com

</comment><comment><USER2> crackmes.de - RE</comment>


Holy Haskell Project Starter - <AUTHOR> http://yannesposito.com/Scratch/en/blog/Holy-Haskell-Starter/ <comment><USER2> Debian stable has base 4.5 as default, so this wasn't compatible immediately for me. I had to change the .cabal file to use base 4.5.</comment>


How Yahoo allowed hackers to hijack my neighbor's e-mail account - <AUTHOR> http://arstechnica.com/security/2013/01/how-yahoo-allowed-hackers-to-hijack-my-neighbors-e-mail-account/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+arstechnica%2Findex+%28Ars+Technica+-+All+content%29

<comment><USER2> the gist of it seems to be that yahoo ran a vulnerable wordpress site that allowed the attacker to run javascript from the yahoo domain, allowing them to steal login cookies.

That makes me wonder, doesn't yahoo set the http only flag for their session cookies? Is there any reason you may want javascript to access the session cookie?

Suppose it's a good time for everyone to verify that their websites properly set http only on any cookies you don't want to access via javascript.

</comment><comment><USER3> Off the top of my head and as anecdote, I've probably received the most spam and/or malicious emails from friends compromised email accounts where those accounts are Yahoo accounts. Hotmail would probably be second.

I usually go to the effort to call them up as soon as I can to inform them of the compromise. I've started gently describing the problems with these particular hosts; unfortunately, however, most don't go to the effort to make a change. And several have been compromised multiple times.</comment>


U.S. millennials post 'abysmal' scores in tech skills test, lag behind peers - <AUTHOR> http://www.washingtonpost.com/blogs/wonkblog/wp/2015/03/02/u-s-millennials-post-abysmal-scores-in-tech-skills-test-lag-behind-foreign-peers/

<comment><USER2> Top and bottom scoring nations differed by what - 5%? Is that even statistically significant?</comment>


A Better Government, One Tweak at a Time - <AUTHOR> http://www.nytimes.com/2015/09/27/upshot/a-better-government-one-tweak-at-a-time.html <comment><USER2> The way I read this is that the key is the difference between running government at the macro level versus the micro level.

Traditionally, government policies and lawmakers create laws and regulations with broad brushes expecting the people closer to the ground to execute it. This type of centralized authority rarely works.

What they deem A/B testing is executing at the micro level down to almost individual choices. This gets you better and more immediate feedback.

The same thing happens in large companies. When there are so many layers between management and the consumer, it is hard to make the right decisions. But if management is talking directly with the consumer, they get better feedback and better decision making.

<comment><USER3> Technology has disrupted and continues to disrupt many industries, but those focusing around human relationships have been the hardest to automate. As technology gets better, you _will_ see more disruptions to how government goes about its business. The main obstacle to this is that governments don't have natural competitors, and need to be dragged kicking and screaming into the future.

</comment></comment><comment><USER4> This is such an obvious idea you have to wonder why it is even news. Why shouldn't government be constantly iterating and ever so slowly getting better?

What isn't so obvious is that government developers should design from the viewpoint of their users.

[http://www.citylab.com/tech/2014/01/what-really-happens- when...](http://www.citylab.com/tech/2014/01/what-really-happens-when-you- sign-food-stamps/8094/)

</comment><comment><USER5> It's amazing how much of this boils down to "If you make sure people know about things, people know about things!".

I mean it happens over and over in the article "Remember, you can default to double sided", "Did you know about this savings program?", etc.

Still, love the idea, and I hope they keep it up. It sounds like it's had some really positive effects so far and what's the point of the scientific method of testing and evaluation if you never use it?

</comment><comment> irq-1 > eight text messages at a total cost of about $7 a student

lol dumb government wasting money!

> The text intervention was particularly cost effective: the messaging > campaign cost $7 per student, inclusive of the expense of hiring school > counselors to support students who needed additional assistance.

This is from the study[0] linked in the article, and makes it clear that labor is the expense, not sending text messages.

This isn't just an error or a bad story, it's the deliberate removal of defining information. Moreover, I'd argue that it's not only intentional but systemic at the New York Times, and has been for decades.

[0] [http://curry.virginia.edu/uploads/resourceLibrary/9_Castlema...](http://curry.virginia.edu/uploads/resourceLibrary/9_Castleman_SummerTextMessages.pdf)

</comment><comment><USER6> "Certainly eight text messages are a more cost-effective way of promoting college than offering thousands of dollars in grant and scholarship aid."

I do not understand how in the world the person writing this article came to this conclusion unless they just straight up have zero clue how people that did not grow up with a college fund pay for college. Doubly so when paired with "The effect was particularly large for low-income ... students." How do they think that low-income students pay for college?

<comment><USER3> The point is that adding _more_ grants is less effective than making students aware of grants that already exists. For low-income students whose information through local social networks isn't getting the message passed about potential grants, trying to shake the pot around harder isn't going to attract the attention they want.

<comment><USER6> Ah, that makes a lot more sense. I did not think that was very clear in the article, however.

</comment></comment></comment><comment><USER7> Can't be any worse than the way they do it now.

<comment><USER8> I admire your optimism.</comment></comment>


2048 AI - <AUTHOR> http://ov3y.github.io/2048-AI/ <comment><USER2> The AI implements minimax using alpha-beta pruning.

Minimax assumes that the game/computer which the AI is playing against is playing adversarially - i.e. that the computer will insert the new tile that's the worst possible tile for the player/AI to receive.

But that's not actually what the game is doing. Instead, new tiles are inserted randomly. As a result, minimax probably isn't the best approach here.

I think something like monte carlo rollouts would work better. In other words, rather than evaluating a move by "what's the worst that could happen if I make this move", evaluate a move by "what is stochastically likely to happen if I make this move, weighted by how good/bad that outcome is for me." (Losing the game would have a big negative weight, of course).

Given that the current AI isn't actually winning the game, I guess that some sort of monte carlo rollout strategy would do better.

It's still cool to see how minimax does, though, so kudos to the authors - it'd be really interesting to see a comparison of different methods.

<comment><AUTHOR> Heh. If you look in the code you'll see a big commented out chunk where I tried randomly sampling computer moves to get sort of an 'expected value' for the opposition's move. Empirically, it performed worse. I think this is for the same reason that all minimax algos assume optimal play by the opponent: if you assume optimal and they play less than so, it can only work in your favor. However I think there's some truth in the fact that sometimes an unpredicted random computer move can mess things up. Unfortunately exhaustively enumerating all possible computer moves was way too slow (for single-threaded javascript in the browser).

<comment><USER2> Its interesting that your approach performed worse; I wonder if it could be modified to do better? Interesting.

>I think this is for the same reason that all minimax algos assume optimal play by the opponent: if you assume optimal and they play less than so, it can only work in your favor.

That doesn't make sense when talking about a random opponent, though.

Imagine its chess. You are considering moving a pawn into a position where it can be obviously taken with no cost by the other player, but where, if the other player doesn't take the pawn, you'll get a sure checkmate on the next go.

You'd never make that move against an 'intelligent' player (i.e. in a minimax setup). But you'd definitely consider it against an enemy that moves randomly, because the expected value is so high.

This isn't to discount your empirical experience with this game, just to make a more general point.

<comment><USER3> When playing against a random opponent, sometimes it will "accidentally" make the best possible move. In chess, this might be extremely unlikely, as there are so many possible moves: the probability that, of all the pieces on the board, with all of the positions it could have made, that it would stumble upon a move that devastates your position--especially considering that often multiple correct moves must be performed in specific sequence to take advantage of what "should be" a winning position--is vanishingly small.

Further: the potential for gain (trivial mate against a stupid opponent in a handful of moves) is great. If you are thereby playing for "fastest win over time", taking advantage of random's suboptimality seems sane. In 2048, the bottleneck on your score seems best approximated by how long you survive: pulling stunts won't get you to 2048 all that faster as you need to have worked through enough tiles to arrive at that point: I'd imagine the difference would be at best a tiny fraction of the "required" moves.

Meanwhile, the computer has only a few possible moves, increasing the probability of doing something accidentally optimal. As you approach the end, needing over half the board just for unbuilt path up to 1024 and thereby not having as much scratch space, the probability of it hitting a problematic (even if not "devastating", one that suddenly requires you to reorganize things to "clean up the mess") move seems more more of a problem than when playing chess.

In summary: I just don't think comparing this game to chess is leading to useful intuitions.

<comment><USER4> It sounds like you're thinking he suggested just greedily taking the best possible move. But that's not what he suggested; he suggested evaluating the actual distribution of the opponent's moves and making the move with the highest expected value.

<comment><USER5> The question is do you want to have the shortest expected number of turns until you win, or a 100% win rate. Playing safe (min-max) is what ensures the 100% win rate, but you might be making games longer on average.

<comment><USER2> It doesn't have a 100% win rate as it stands.

Mini-max isn't even 'playing safe'.

Consider the following choice of moves, each leading to one of 5 random tile inserts:

Move A, which leads to 5 possible moves with the following game state goodnesses: ['Loss','Win','Win','Win','Win']

Move B, resulting in: ['99%CertainLoss','99%CertainLoss','99%CertainLoss','99%CertainLoss','99%CertainLoss']

Minimax is never going to choose A. Is that really what you want, even if your strategy is 'play it safe'?

<comment><USER5> Fair enough; I only ran it a couple times and it got to 2048 so I assumed it's a guaranteed win.

<comment><USER4> Min-max optimizes your chance of winning under the assumption of a rational adversary. That chance will be lower than "certain victory," especially in un- solved, symmetric games, because a rational adversary will _also_ be playing min-max. The guarantee min-max provides is that it will do even _better_ against a non-rational adversary than it does against a rational adversary; not that it will do _better_ than any other algorithm against non-rational adversaries--which is the way I think it often gets parsed.

Also, we should note that the "value" in "expected value" doesn't have to mean "score." It could be the logarithm of your score, or your chance of winning against a rational adversary, or even the enjoyability of the game to spectators (if you have a precise metric for that).

</comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER6> Yesterday I showed this game to a fellow graph theory buff and we also sat down to think about how to solve this game with AI.

The most straightforward solution is expectiminimax, which I see this solution has implemented quite nicely. In case someone here isn't familiar with minimax, the OP wrote some very elegant and well-commented code that would be a great primer.

The less computationally-intensive approach we came up with was to model the game state as a graph G(V, E), where V is the set of active tiles and E is a set of edges connecting adjacent tiles, weighted by the function c(v1, v2), which returns the absolute value of the difference between two tiles. For each decision, the AI picks the move that minimizes the sum of all edge weights in the new game state.

The reasoning behind this is that the only way to progress in the game is to have tiles of equal values adjacent to each other, for which the weight in G would be 0. Thus, the AI should try to minimize total weight. Eventually there will be large numbers on the boards with large edge weights to adjacent tiles, so the AI would try to keep these tiles next to other large tiles to minimize the difference.

Since the game is stochastic the approach I described may not work in a worst case scenario, but it could also be applied to the existing minimax solution as the weight function for each node in the tree.

<comment><AUTHOR> =)

Check out the eval function, and specifically the function smoothness() in grid.js. It implements the edge weighting you describe!

<comment><USER6> Fantastic! Thanks for pointing that out. My cursory glance over the code in ai.js led me to believe that you were weighting it by score, now I see the full picture.

One more thing - have you looked into storing the game tree? I noticed it is starting the search from the beginning every time. I'd expect you would see a branching factor of around 10, so this would only really make a difference at depths greater than 4.

You started an excellent and inspiring GitHub project - I feel like the AI research into this game has only just begun.

</comment></comment></comment><comment><USER7> Heh, I did something like this for the original Threes games via computer vision and screenshots :)

[http://www.youtube.com/watch?v=Sn2o2hb1bi0](http://www.youtube.com/watch?v=Sn2o2hb1bi0)

Mine is using a minimax variant that replaces the minimum nodes with expectation (given that the choice of next tile is uniformly at random). This is sort of the algorithm used by backgammon solvers. The fun thing is that when expectation factors in, the branching factor is quite wide, _but_ the necessary depth for the algorithm to beat humans is much smaller (with 8-ply on Threes this thing is miles ahead of me, no contest)

</comment><comment><USER8> I've been playing this for awhile now and I think I have found that the best method is to only use 3 directions. This forces your highest number into a corner and only spawns 2's and 4's in the opposite corner. You build up numbers that cascade down to the corner. It almost never gets stuck, but if you do I guess you'd have to push the 4th direction you haven't been using.

<comment><USER9> I got up to 16220 that way-- the thing you have to look out for though is as you build the cascading layers, when you get the row three, not to block yourself in (having all 3 rows full so that the _only_ direction you can go, is the one you are avoiding).

Try to keep your cascading layers down to 2, and keep about 2 steps ahead when you get to the 3rd layer. Many people have suggested keeping your highest number in the corner but I've found that doing so makes it easier to have 2's and 4's "invade" that fortress of high numbers you're building close to the wall. The best position is for the highest number to be 2nd or 3rd in the row closest to the wall cushioned by the second highest numbers on either side so that you can build up the numbers to either side of them, and eventually add them in.

Example:

X___X___X___X

X___X___2___4

8___16__32__16

64__256_512_128

<comment><USER8> Thanks for the suggestion. I can't stop until I beat this eventually.

<comment><USER9> Finally made it-- cascade gif: [https://vine.co/v/Mbb07Wh0UPM/](https://vine.co/v/Mbb07Wh0UPM/)

</comment></comment></comment></comment><comment><USER10> Back in college I implemented a checker AI that used minimax and a neural network that was trained with a genetic algorithm. After 4 days of tournament on a 400mhz box the resulting AI would almost always beat me. It was always fascinating to me that it used a 4 ply minimax with a 50 hidden nodes and 90 inputs to handily kick my ass.

I always wanted to re-implement it in node and for a cooler game. Alas! I have too many side projects.

The source is here: [https://github.com/mkoryak/Evolutionary-Neural-Net- Checker-A...](https://github.com/mkoryak/Evolutionary-Neural-Net-Checker-AI)

and you can play against it here: [http://mkoryak.github.io/checkers/nn_checker_ai_demo.html](http://mkoryak.github.io/checkers/nn_checker_ai_demo.html) (requires java, might also require a 7 year old computer)

</comment><comment><USER11> Hahah, I knew this was coming sooner or later. Thanks! Great job!

EDIT: This AI is a better player than me.

<comment><USER12> I don't know if you've experienced it yourself or have heard other reports of it, but after playing your game for a few hours last night I've been experiencing a 2048-flavored "tetris effect" all day today. My brain keeps on trying to identify "like things" to collapse together; pretty wild.

<comment><USER13> Me too, I have this weird overlay of the game in my vision. It took a lot more of tetris to reach that effect.

<comment><USER14> All the fonts seem smaller, not sure if only one.

<comment><USER15> Assuming you mean all fonts everywhere, I got that too. I thought the next website I looked at went through some kind of redesign until I realized that the next two websites I looked at _also_ looked like that.

</comment></comment></comment></comment></comment><comment><USER16> Here's the routine I've used to win multiple times in a row:

1\. "tumbler" until 128 can move to the upper left corner (up right down left, repeat)

2\. The highest number on the board is always in the upper left. Make the top row descend left to right.

3\. Before combining values on the top row, keep hitting up until one of the lower rows will not combine from a left.

4\. Often, the slot you are filling (eg, top right or one below top right) will have a two. Alternate pressing left and right until a two appears, allowing you to combine

5\. Keep the second row locked as soon as possible with unique values ASCENDING left to right. This way you can use up, left and right without moving the slot you are filling on the far left of the second row.

6\. Never fill the top three rows such that a left or right cannot be used. You will be forced to use a down, messing up the top row.

There are a few other pattern recognition tricks that you'll pick up to aid in filling a slot for higher values. Other misc tips:

* try to keep high number squares close together, and merge up to the top row as soon as possible. Otherwise, they will just close off a slot

* You may get a 2 trapped on the top row blocked by a higher value below it. Unfreeze the second row by combining squares & hope that a two appears in the new opening

* only 2's or 4's will appear. They (always?) appear in the space left behind by the previous movement

</comment><comment><USER17> BUG:

Whenever two sets of tiles combine in a single move, only one of their scores is counted. For example, let's say that a pair of 8s and a pair of 4s are about to be combined into a new 16 tile and a new 8 tile. The game _should_ be giving us 24 points total for this move because we are creating a 16 tile (16 pts) and an 8 tile (8 pts) where 8+16=24.

However, this does not happen. Only one or the other combination will actually be counted, it seems. In a more egregious case, I combined two 512 tiles to form a new 1024 tile and should have gotten those corresponding points. However, there was also a pair of 2s which combined to make a 4-tile. I only received 4 points for the entire move.

The game should be counting the score from all combined tiles!!! This is why my calculated minimum theoretical score of 20480 (assuming only twos are generated) was completely blown out of the water by winning scores of 12k - because in many cases, the score is incorrectly calculated!

If this is fixed.......

The minimum possible score to win the game (I think...) is 18432, although right now, with the bug, scores can be much lower. Here's how I get that. If we assume only 2s can be generated, then the minimum score is 10*2048 = 20480. However, sometimes a 4 is generated rather than a 2. Apparently, this happens 10% of the time. In theory, it is possible for someone to be given only 4s and also have a perfectly efficient game. In this case, the scoring contribution to get all the 4s from the 2s in the first example is eliminated. The total score of any tier is 2048, so we're remove 2048 from 20480, yielding 18432.

The minimum possible score to reach a winning 2048 tile, once this bug is fixed, should be 18432.

<comment><AUTHOR> Ahh good catch. That got messed up during refactoring the original code. Thanks to the person who submitted the fix on github too.

<comment><USER17> Great... yeah, it looks a lot better now! Nice work on the solver. I just tried it and it won the game with 20312 pts. Pretty good one!

</comment></comment></comment><comment><AUTHOR> Source code here [https://github.com/ov3y/2048-AI](https://github.com/ov3y/2048-AI)

</comment><comment><USER18> I'm consistently scoring higher than 2,500, and frequently as high as 3,500 with a tile of 512, by doing this:

1\. Up

2\. Right

3\. Down

4\. Left

5\. Go to 1.

That loop scores better than my trying.

<comment><USER19> I got up to 9,000 with:

left, down, right, down, (repeat)

<comment><USER18> Not bad.

My new simple algo is:

1\. Down until you cannot go down

2\. Left

3\. Down until you cannot go down

4\. Right

5\. Go to 1.

<comment><USER20> Right/Down/right/Down with an Up/Right/Down thrown in when stuck has worked well for me. My first 1024 block came that way.

When I began playing I was moving around the board in an unorganized fashion, but am now finding that moving the larger numbers to one corner (bottom-right for me) is the best method. By having your block consolidation take place in one particular area, the odds that you'll have matching large numbers goes up dramatically.

<comment><USER18> 15,456

Yup, this one works very well.

<comment><USER20> I've tried a few games where I do those exact moves with no human judgement and the score ends up quite a bit lower than when I 'generally' follow those moves and consolidate using my best judgement.

Another interesting test was to always play a clockwise or counter-clockwise pattern. The consolidation happens in the middle of the board. This method seemed to result in higher scores than the right/down/right/down pattern.

</comment></comment></comment></comment></comment></comment><comment><USER17> I'm running some trials here and keeping track of the results with this AI. I'll edit this when I have the data to provide the information.

Something that occurred to me is that "score" and "winning" can have different optimizations. Score is based upon combining blocks, where as winning is based upon reaching the 2048 block. This means the game can be optimzed in two different ways: 1) To maximize score, wherein your goal is to _delay_ reaching 2048 until the last possible moment to allow yourself time to rack up score, and 2) to reach 2048 in the optimal number of moves, which means a lower score.

You're scored on what you combine in a move. So, if you combine two "4" tiles to yield and "8" tile, you'll get 8 points, and so on. To maximize score, the idea would be to basically waste space on the board building up tiles you don't need, while avoiding getting to 2048. In theory, one could build up many 1024 tiles, and maybe even combine several at once to yield multiple 2048 tiles.

To minimize moves in order to reach the fastest would basically be a game of golf. You'd need to reach 2048, but the lowest score in doing so would, by default, mean you've completed the game more efficiently. There's probably some absolute minimum score, but I'm too lazy to figure that out right now...

<comment><USER21> If you have only a single 2048 tile in the end, and arrived to that by only combining the minimum number of required tiles, then your score will be 10*2048. If you think backwards, you'll get 2048 for the last tile, before that you need to get twice 1024 for the previous two, and so on until the level of 4's, which is the first one at which you get scores. This assumes only twos appear on the board.

<comment><USER17> Initially, I had arrived at this conclusion as well, but I've seen solutions (both from other people posting and from running this script) that have gotten to 2048 with 14000 or less. I'm not entirely sure where the discrepancy is coming from, though... Obviously with a certain number of "4"s being generated each turn, the 10x2048 value will be reduced, but not to the degree we see. For example, I have logged a win with a score of 13404 points, and other people in here have screenshots of wins with significantly less than 20480 pts.

Intuitively, I want to say that the optimal score is more like 10x2048/2, but I haven't been able to prove that yet (at least not in between work today :) )

<comment><USER22> It seems there is a bug where only the higher or two cascades trigger at once, will be scored. So some of the points seem to being lost.

</comment></comment></comment></comment><comment><USER23> You can add a simple heuristic to the scoring to increase the win rate by a lot - weighted corners.

Add the logged value of the numbers on the corners to the score and the higher numbers will tend to 'stick' to them. This also serves as a mechanism to guarantee that the new numbers appear away from the large numbers, which tend to block them from combining.

I also turned down the compute time to 20ms and it still runs well.

</comment><comment><USER24> That's awesome. I'm looking at the source code but I can't seem to grasp it. What's a simple explanation of how it works?

<comment><AUTHOR> Sorry, the code is a little unkempt.

The basic idea is minimax search. Googling that will get you started, but basically the algorithm plays out the game and keeps a score of the position after every move. Then it just makes the move that leads to the best score.

The "score" here is basically a count of how many free squares there are (with a little extra to keep things aligned if possible).

One major thing with these search algorithms is that the game tree grows exponentially as you move forward. To combat that, implemented alpha-beta pruning and a heuristic to only search the nastier computer moves rather than all of the possibilities.

<comment><USER24> Awesome, thanks for that! I was going to try when I saw the thread earlier but couldn't figure out how.

</comment></comment></comment><comment><USER25> I haven't read the source code yet, so this might be off right of the bat. But from the general knowledge of minmax I think the end-game code might need some tweaking.

If there is a guaranteed win, the algorithm will find it. However, if there isn't any, how does it pick a path when it thinks it will lose every time? Are all losses equal to each other? Are some better than the others? Could the elgorithm take the path with best chances where the most of the plays end up winning while only a few of them end up losing?

</comment><comment><USER26> Interesting. It seems the solution I and a couple of people more came up with of keeping the top value in a corner isn't being used. It's amazing how it's able to keep the large numbers together throughout the game.

The gameplay is much more interesting but it seems that getting from 1024 to 2048 is much harder this way, probably because the randomness accumulates over time making the depth search unreliable. The more structured solution accumulates much less risk so has some margin to deal with this.

</comment><comment><USER27> I find the translate function, though very simple, rather elegant JS:

      AI.prototype.translate = function(move) {
       return {
          0: 'up',
          1: 'right',
          2: 'down',
          3: 'left'
        }[move];
      }

Ref: [https://github.com/ov3y/2048-AI/blob/master/js/ai.js#L230](https://github.com/ov3y/2048-AI/blob/master/js/ai.js#L230)

</comment><comment><USER28> It won first time, impressive! [http://i.imgur.com/epUtjyB.png](http://i.imgur.com/epUtjyB.png)

<comment><USER29> Yep, same here!

[http://i.imgur.com/4uNBOoj.jpg](http://i.imgur.com/4uNBOoj.jpg)

</comment></comment><comment><USER30> It gets so close! [http://puu.sh/7rrD6.png](http://puu.sh/7rrD6.png)

I find it frustrating to watch it hit (where I have not managed to get to) where you have one block 128, 256, 512, and a 1024. Moving around only makes it harder to join things together.

I am rather convinced this game is more by luck than actual good-play.

<comment><USER31> Does anyone know of a quantitative way to measure the influence of random draws vs. skill on the final score? I would have guessed that strategy would be effective on this game, but that could be wrong.

</comment></comment><comment><USER32> My friend found you can get pretty far in the game (at least a 1024 block) if you just spam RIGHT-DOWN-LEFT-DOWN repeatedl (basically rolling your fingers across the bottom row of arrow keys).

It was a little upsetting when I had actually been putting thought into my play and he was doing better.

</comment><comment><USER33> I watched this run for about 5 minutes and it failed at 1024 with under 5000 points. It looks pretty cool, although it defies all logic when forming the squares (it put the largest number in the middle several times).

</comment><comment><USER34> A new browser performance benchmark has born?

<comment><USER35> It runs based on random numbers, so it's hardly a reliable benchmark.

<comment><USER36> Just use a fixed seed and it's 100% deterministic. Benchmarks use random numbers all the time. (In fact, PRNGs themselves often make OK benchmarks.)

</comment></comment></comment><comment><USER37> I was coincidentally working on the same thing when I saw this yesterday. Pushed the code to [https://github.com/helgefmi/c2048](https://github.com/helgefmi/c2048) if it's of anyones interest.

It's just a wicked fast board implementation with a simple depth first search, as of now. But the idea of "making up" an opponent to make it possible to do alpha beta pruning is a cool idea. I might try to implementet it myself.

I regularly get scores above 50k with AI_DEPTH=5-6 and NUM_TRIES=20-30. My record so far is a score of 220k :-).

</comment><comment><USER38> Is this game always guaranteed to be winnable, or is it like Solitaire?

<comment><USER39> I would go with Solitaire sine mine just lost. Did reach 1024 though.

<comment><USER38> That just means that this particular AI isn't capable of winning all the time. It doesn't tell us weather a theoretical perfect player could always win.

</comment></comment></comment><comment><USER40> It's like watching War Games - [http://www.youtube.com/watch?v=NHWjlCaIrQo](http://www.youtube.com/watch?v=NHWjlCaIrQo)

<comment><USER41> A book with a vaguely similar idea, I recommend over the movie.

Colossus by Dennis Feltham Jones

( don't read the wikipedia entry as it contains spoilers ( whole plot ) )

</comment></comment><comment><USER42> This AI was doing impressively well but still did not quite reach 2048 stopping just before the end.

The way I won myself rather quickly was using bottom right priority and ignoring up key(which was suggested by HN).

That is put highest scoring tiles bottom and sorted to the right if possible.

So it is mostly down, right, with some lefts, but no ups. This way is really easy to get 1024, I think I reached 2048 on the 3rd try with this strategy(score was 20k something).

</comment><comment><USER43> I tried twice and it didn't finish, after getting to 1024 both times... this shows just how difficult is that game!

<comment><USER44> Yeap, same here. [http://i.imgur.com/TIr88B0.png](http://i.imgur.com/TIr88B0.png)

</comment></comment><comment><USER45> Guys. I dont need the AI anymore. I have created my own patterns and methods.

Tada! I got my 2048 tile :) So happy

[https://drive.google.com/file/d/0Bz9_OO8kXRkfY0RWdzZ6cDA4RDQ...](https://drive.google.com/file/d/0Bz9_OO8kXRkfY0RWdzZ6cDA4RDQ/edit?usp=sharing)

</comment><comment><USER46> Nice job on the AI! I can still do much better much quicker by hand using the left-down-right-down-left-... strategy. Obviously an alpha-beta search should be able to do better than that naive strategy, but it needs a little more domain knowledge.

</comment><comment><USER47> What are the rules for new tile placement? Is it deterministic, random, or adversarial?

<comment><AUTHOR> Random location (uniform). 90% chance of a 2, 10% chance of a 4. This actually made it hard to model the computer move in the search.

<comment><USER48> When playing, it seemed like a 50% chance the new tile would be placed in exactly the spot or two that I didn't want it, even if there were 8+ open spaces.

<comment><USER49> That is a sampling bias caused by confirmation bias. Extreme cases such as the one pointed out tend to reinforce the hypothesis because they are more traumatic and, therefore, better remembered then the avalanche of cases where the higher probability positive outcome happens.

</comment></comment></comment></comment><comment><USER50> Lol, even the AI failed :) [https://www.dropbox.com/s/bwdmj5rbgvackls/Screenshot%202014-...](https://www.dropbox.com/s/bwdmj5rbgvackls/Screenshot%202014-03-12%2009.03.33.png)

</comment><comment><USER51> Brilliant game! I got pretty close, but even the AI managged to fail just a few moves before the completion. :( [http://i.imgur.com/F2ldDAS.png](http://i.imgur.com/F2ldDAS.png)

</comment><comment><USER52> I'd be curious to see evolutionary or machine learning algorithms playing this.

<comment><USER53> I was curious too, was thinking about coding it. Anybody know the odds for a 2 or 4 appearing? Is it 50-50 or...?

</comment></comment><comment><USER54> Randomness will not help you guys, look at what a horde of monkeys do on the game when left alone:

[http://popox.github.io/2048/](http://popox.github.io/2048/)

</comment><comment><USER55> I wrote a script last night that does a simple: up, right, down, left. Ran it for a few thousand games last night -- highest it got was over 10k, and consistently got around 2.5-3k.

</comment><comment><USER56> Works like a charm, got to 2048 and over 10k points

Second time around was pretty close [http://i.imgur.com/psdSwjM.png](http://i.imgur.com/psdSwjM.png)

<comment><USER57> It failed when I tried it.

</comment></comment><comment><USER58> Nice one :)

Now, since the board is 16 tiles, and that you need two 2^n can make a 2^(n+1), the max game that can be played is 2^16=65536.

Can a 65536 game can be reallistically won, can it be by OP's AI?

</comment><comment><USER59> I think that the scoring system can be improved. This AI wins with a lot less moves than me, hence it gets lower score for a solution "smarter" than mine.

</comment><comment><USER60> Boom, 13,068 points and 2048! I'm feeling some pride in my AI.

[http://cl.ly/image/3G1a0e1T0Q2O](http://cl.ly/image/3G1a0e1T0Q2O)

<comment><USER61> Mine won as well, on the first try.

[http://cl.ly/image/0H1o1P2Q0A0u/Image%202014-03-12%20at%2012...](http://cl.ly/image/0H1o1P2Q0A0u/Image%202014-03-12%20at%2012.44.31%20AM.png)

I feel bad about my 1024 now, bested by a minmax.

</comment></comment><comment><USER62> I ran it twice and it failed to achieve 2048, are other people having similar issues? Either way, nice attempt it works pretty darn well for 1 night of work.

<comment><USER63> same here

</comment></comment><comment><USER64> Strange game. The only way to win is not to play.

</comment><comment><USER65> What algorithms might do better than this minimax? I've just read all the comments and there are no suggestions...

</comment><comment><USER66> How would I go about making an AI for this game? Mainly getting it to interface with the actual game input and output.

</comment><comment><USER67> I was genuinely surprised when the AI lost.

</comment><comment><USER68> what a fun and easy game. beats a lot of the fps games for me out there. my strategy was just stack the higher numbers together, left down right up and never use right. i ended up with this: [http://imgur.com/KuqAJTM&hrfol9i](http://imgur.com/KuqAJTM&hrfol9i)

</comment><comment><USER69> YAY made it :3 [http://grab.by/v9BA](http://grab.by/v9BA) ^_^

</comment><comment><USER70> Not sure why but every time I ran it on Firefox it failed, but it succeeded solving it on chrome always.

</comment><comment><USER71> I think it's pretty clear the Author of this game is a NSA agent trying to distract us.

</comment><comment><USER72> Oh well, I lost with AI as well. I just let it run and got to a game over with 8476 points.

</comment><comment><USER73> I'm just counting down until someone builds this for the iPhone/Android for $.99

<comment><USER74> I would go crazy trying to play without arrow keys.

<comment><USER73> even this particular game plays surprisingly well on mobile.

</comment></comment></comment><comment><USER75> Seeing the AI work makes me no longer want to play the game. Take to long to get to 2048!

</comment><comment><USER41> How does it decide where the new tile will appear, or it just tries every possibility?

<comment><AUTHOR> Trying every possibility was way too slow (branching factor of ~15 to 20), so it only searches the most "annoying" moves, where annoying is defined by lining up with the highest value tiles and not being adjacent to other 2's (or 4's). The game is random though, so it can and does make moves that haven't been searched.

</comment></comment><comment><USER76> Cool game!! Can't stop playing it. Finally achieved 2048 w/ score 21028 :)

</comment><comment><USER77> Does the AI guarantee winning?

<comment><USER78> I ran 9 browser windows in parallel and 2 of them won the others failed.

</comment></comment><comment><USER79> I always get at least 1024 now. I'm playing somehow like tetris...

</comment><comment><USER79> Anyone implementing other IA technique? What's the link?

</comment><comment><USER77> Please, please, please don't implement rankings...

</comment><comment><USER80> very cool.

now... for a who can make the optimal AI competition... :P

</comment><comment><USER81> I find this game quite addictive, contratulations!

</comment><comment><USER82> Sadly, totally unrelated to the Hong Kong film...

</comment><comment><USER83> Cool But why the autorun can't get a win?

</comment><comment><USER84> While the game is difficult to finish, I'm kind of saddened at how far I can go just by randomly hitting up arrow, left arrow, down arrow, right arrow, etc.

<comment><USER85> When you get up to 128 and 256 it's been easy and it kind of feels like you've come a ways, but remember that you're only 1/16th or 1/8th of the way there.

</comment></comment><comment><USER86> It just won on 1st attempt here. Good job

</comment><comment><USER87> So close to getting 2048. Cool stuff!

</comment><comment><USER88> Cool, spent 15 minutes.

</comment><comment><USER89> Math... the fun killer.

<comment><USER31> Nah, just fun at a higher level.

</comment></comment><comment><USER90> if this is AI why it scores only 512 square as max?

<comment><USER91> Assuming you're not trolling, it's because this AI is using a heuristic approach rather than a guaranteed correct approach.

Heuristics rely on simplified rules which don't accurately model the system on which they're acting 100% of the time. Good heuristics can come close to 100%, however.

 _But why?_ Glad you asked!

A 100% correct solution would be to write an algorithm which enumerates all of the possible moves as a decision tree, and walks the decision tree to find the correct answer.

However, given that there are four possible moves the user can make (up, down, left, right) and an upper bound of 32 possible moves the computer can make (computer places "2" or "4" anywhere in a 4x4 grid), each level of the tree could require up to 128 times the number of computations that it took to compute the previous level of the tree.

For example, calculating the first turn is on the order of 128 calculations. Calculating the second move is on the order of 128^2 calculations. Calculating the third is 128^3, an so on. By order of magnitude, how many moves do you think it takes on average to get to 2048? 10^3? Even if we were being _really_ optimistic, maybe it's 10^2. In that case, you'd have to perform somewhere around 128^100 computations in order to solve the game perfectly every time.

Incidentally, python tells me that'd be

        5260135901548373507240989882880128665550339802823173859498280903068732154297080822113666536277588451226982968856178217713019432250183803863127814770651880849955223671128444598191663757884322717271293251735781376

calculations.

Or for fun, this is 128^1000:

        16216967556622020264666650854783770951911124303637432562359820841515270231627023529870802378794460004651996019099530984538652557892546513204107022110253564658647431585227076599373340842842722420012281878260072931082617043194484266392077784125099996860169436006660011209817579296678781962552377006552947572566780558092938446272186402161088626008160971328747492043520874011018626908423275017246052311293955235059054544214554772509509096507889478094683592939574112569473438619121529684847434440674120417402088754037186942170155022073539838122429925874353753616104159343594557666561701790904172597025336526662682021808493892812699709528570890696375575414344876088248369941993802415197514510125127043829087280919538476302857811854024099958895964192277601255360491156240349994714416090573084242931396211995367937301294479560024833357073899839202991032234659803895306904298017400980173252106913079712420169633972302183530075897845195258485537108858195631737000743805167411189134617501484521767984296782842287373127422122022517597535994839257029877907706355334790244935435386660512591079567291431216297788784818552292819654176600980398997991681404749384215743515802603811510682864067897304838292203460427757655073776567547507027144662263487685709621261074762705203049488907208978593689047063428548531668665657327174660658185609066484950801276175461457216176955575199211750751406777510449672859082255854777144724233490076402632176089211355256124119453870268029904400183858505767193696897593661213568888386800238409325673807775018914703049621509969838539752071549396339237202875920415172949370790977853625108320092839604807237954887069546621688044652112493076290091990717742355039135117441532973747930089955830518884135334798464113680004999403737245600354288112326328218661131064550772899229969469156018580839820741704606832124388152026099584696588161375826382921029547343888832163627122302921229795384868355483535710603407789177417026363656202726955437517780741313455101810009468809407811220573803353711246329589162370895804762245950918253016369092362406714116443316561598280583720783439888562390892028440902553829376

So throwing a few assumptions in there isn't a bad idea...

<comment><USER92> Actually, to make a 2048 you need to make two 1024s. It's unlikely that you'll make two 1024s at the same time. Similarly for the lower tiles. As a sort of upper bound you expect the game to be over in about 1024 moves and it's likely to not be much less than that. I think a more realistic number is somewhere in the 500s

<comment><USER91> I'm not sure I follow, but I think we're saying the same thing.

It's been too long since I've taken any hardcore discrete math for me to reliably reason about the bounds on the number of moves required to win. All I can do is make estimates based on simplifications.

How I arrived at my estimates for the order of magnitude of the minimum number of moves required to win:

At most, you can merge 4 tiles in one move. Assuming you were doing 4 tiles every move, and the game just didn't produce twos, it'd take just 128 moves. Order of magnitude: 10^2.

Assuming exactly one merge per move, and that the game only produces twos, it'd take 1024 moves. Order of magnitude: 10^3.

</comment></comment></comment></comment><comment><USER88> Cool

</comment><comment><USER93> my AI won the game with a score of 20388

pic: [https://cloudup.com/chDTLSElXDN](https://cloudup.com/chDTLSElXDN)

</comment><comment><USER94> memorizing watching it "play" by it's self

i KNEW the AI would have been coming sooner or later [no this fast though], GREAT JOB!</comment>


Show HN: World Cup prediction challenge with friends - <AUTHOR> http://www.scoragora.com/ <comment><AUTHOR> Hi HN community ! I am the cofounder of Scoragora.

Scoragora is intended to be the best webapp for prediction challenges with friends and colleagues for the FIFA world cup. It's free, ad-free, focused on Brasil 2014, mobile friendly, and available in 4 languages. We tried to keep our UX very simple yet provide a lot of interesting features (tchat, email reminders, social logins...).

This app is our first webapp, and first time in nodejs. We are two young engineers freshly graduated in CS from a french engineering school (Ecole Centrale Paris). As we didn't learn a lot about web programing at school, we decided to build something to learn it, to have a lot of fun, and for the joy of building something significant (= that would be use by a lot of people that we do not know).

We are really excited to share it with you, any kind of feedback is welcome =) (and don't hesitate to use our uservoice widget if you spot a bug !). Eventually, we are thinking about making it a business, any clue about an interesting BM is also welcome !

<comment><USER2> Is this definitely going to stay around for the duration of the World Cup? I need something like this for my work tournament and if it gets taken down I won't be popular...

<comment><USER3> Seconded. I think I'm going to make screenshot backups just to make sure.

<comment><AUTHOR> How can I make you more confident ? Emailing it to you for instance ? with a "send me my predictions by email" button ?

<comment><USER2> That would be handy if I could grab a league snapshot or something.

</comment></comment></comment></comment></comment><comment><USER4> Nice webapp! I find the ability to predict scores very interesting. I actually have made my own concept very similar to this but it is an iOS app. Instead of predicting the scores all you have to do is choose a winner. Join a league with your friends and have a custom leaderboard just for your league. Also there is a main league so you can compete against everyone in the app.

Its called "PickUp" and it's Free on the app store. [https://itunes.apple.com/us/app/pickup-league- play/id8837435...](https://itunes.apple.com/us/app/pickup-league- play/id883743542?ls=1&mt=8)

</comment><comment><USER5> This is kind of ironic, though not necessarily in a good way.

When I woke up this morning, I was proud that England's opening match is on the 14th and I still haven't joined a World Cup pool. I normally lose my mind during the World Cup and become a fanatic, but this time around, I was committed to being productive throughout the World Cup. So, no pool for me.

Unfortunately, now I want to start a pool. This is a slippery slope that points towards painting my face, drinking pints, and screaming like a maniac. Excellent work!! :)

</comment><comment><USER6> www.bracqet.com I created this site easy to signup and use. Purpose: Bracqet.com is a University of Technology Sydney, academic project designed to explore the network effects on a product with a high hypothetical viral coefficient. Viral Co-efficient (K) and is a quantitative measure of the average rate of invite sent per user multiplied by the actual signups per invite. Typically actual K > 1 is required to achieve viral growth and the eventual exponential "kick" in the number of user sign-ups. The fundamental premise of bracqet.com was that people would want to fill their brackets (who they are supporting) for the Football WorldCup2014 and publish it on to their Twitter and Facebook accounts, which in turn would induce their friends to do the same. Hence the product design was purely centered around achieving K > 1\. This included premature scaling utilizing an HA Proxy load balancer and multiple web server instances to handle the hypothetical viral growth. To find out more about the results of the actual K achieved and the results of this experiment feel free to contact us at email@example.com. All data is used for academic purposes. Your contribution and feedback to this project is greatly appreciated.

</comment><comment><USER7> Hi edelans, very nice site, congrats! It would be nice if there was a public league so I don't need to join one.

<comment><AUTHOR> Hi rbonvall, thanks ! I will add this tonight, front page.

</comment></comment><comment><USER8> I submitted a two point critique via the Uservoice widget, one was merely a UI issue, another I feel might be worthy of a wider discussion.

I was excited to see this posted, and hoped it would be what I had been looking for. My friends and I had not yet found a suitable World Cup prediction competition site.

I immediately signed up, and was ready to send off some invites, when I found that Scoragora wanted me to predict a score for each of the 48 matches in group play, a fairly tedious exercise. Further, upon completion, it is completely unclear whether the game will be calculating winners and runners-up from the groups automatically, whether there will be an opportunity to pick winners in the knockout rounds—basically everything after group play is a mystery.

Suffice to say this is not what I expected. I can understand some need for score predictions—most likely in the later rounds for tie-breaking purposes (perhaps the best way to handle this is to ask users to predict the cumulative goal differential of the winning side). But score predictions ultimately aren't the core functionality of a game like this. If I predict that Brazil will defeat Mexico 4-0, and my friend predicts that Brazil will win 4-1, I don't really care who was right about the score, we both rightly acknowledged that Mexico is a shambles at the moment (poor Chicharito—he's only 26!) and that Brazil ought to win.

The functionality I expect to see front-and-center is, simply put, predictions about who wins each match through the final. I truly can't tell whether that functionality exists in Scoragora right now, and I don't really care to predict 96 scores for the privilege of finding out. Moreover, I'm the geek in my group of friends, there's at least some chance I might fill out the entire prediction form to satiate my curiosity about how you've constructed this web app, but I'm certain none of my friends will have the patience to do so, so I won't be inviting them, and we'll conduct our competition elsewhere.

UPDATE: I've just tried out Yahoo's game, and theirs is structured almost identically (though a bit prettier), so maybe my expectations are out of line? I don't understand why the game basically resets when the knockout rounds begin. If i predict that Spain and Chile will get out of their group, and a friend predicts Spain and the Netherlands, and another predicts the Netherlands and Chile, there should be some benefit for the one made the correct prediction and some penalty for the two who didn't.

<comment><AUTHOR> Hi Ryan, Thanks for the uservoice tickets (btw, uservoice is really awesome). This is great feedback thanks a lot.

* I'll definitely provide more info on what happens after group play. We say in the rules that "Predictions can be submitted at any time before the official start time of the concerned game", and this is true for all the games, including those in the knockouts. We thought that the knockout rounds would be extremely boring if your predictions are already set with the wrong teams. And you already got penalized for making the bad predictions in the group play. So we took the decision to open the knockout for predictions only when the teams are known, as it seemed to us that it would preserve the fun until very late in the competition.

* regarding the score inputs, actually I think this really depends on people. with my friends we wanted this level of details because it makes it more fun to us. To use your example, if I predict 4-0, you predict 4-1, and the actual score is 4-1, you will earn a few more points than me.

</comment></comment><comment><USER3> Congrats on getting out there & making something!

The biggest request I have is for alternative rule-sets. The pools I typically participate in are a lot less involved - e.g. pick the winner & runner up for a each group and go from there. Going game-by-game with scores is too much for a lot of people.

<comment><AUTHOR> Hi andrewcross, Unfortunately managing alternative rule sets would have very important impacts on our architecture, we reasonnably cannot provide it for the world cup... But I hear the feedback for possible future versions ! Thks.

</comment></comment><comment><USER9> Hey, I can't submit my predictons.

Something wrong?

<comment><AUTHOR> Hi joyinsky, do you happen to be in Brasil ? I realised that a js plugin was crashing in some timezones (tz_manager.js), I have to fix this...

<comment><USER10> I'm in Estonia, and my predictions are not being saved either =( I can see the JS error:

 _TypeError: c is undefined_

 _Uncaught TypeError: Cannot read property 'rule' of undefined... tz_manager.js:9_

<comment><AUTHOR> Yep, thanks, this was finally fixed this morning !

</comment></comment></comment></comment><comment><USER11> Where did you get the match data?

<comment><AUTHOR> from the FIFA official website [http://www.fifa.com/worldcup/matches/index.html](http://www.fifa.com/worldcup/matches/index.html) ? May I ask you why you ask this question (not sure I understood it as you meant it) ?</comment></comment>