Skip to content

7 Free AIs Wrote the Same Correct Code. Whose Would You Trust?

When every model gets the right answer, correctness stops being the test. So I read all fourteen solutions as a working developer and asked whose code I would actually want on my team.

Eddie Ochieng

Eddie Ochieng

August 21, 2026

7 min read
Reviewing code on a screen
Photo: Jakub Zerdzicki / Pexels

In a companion experiment I gave seven free AI chatbots two invented coding problems, and every one of them scored a perfect ten out of ten, twice. Correctness turned out to be a dead heat. That left a more interesting question hanging. If the code all works, the only thing left to judge is the code itself. So I read all fourteen submissions the way I would read a colleague’s pull request, and they have surprisingly distinct personalities.

How I judged it

This is hands-on. I read every function these seven free models produced across both rounds, looking at the things that separate code you would happily merge from code you would send back, style, robustness, and how much clutter it leaves behind. Same identical prompts, same correct results, very different craft.

Two ways to sort the same thing

The clearest fault line ran right through round two, where the task was to sort characters by frequency and break ties by descending code point. Both directions were descending, so there were two clean ways to write it. Some models sorted a plain tuple with reverse turned on.

The reverse=True approach
sorted(counts, key=lambda ch: (counts[ch], ord(ch)), reverse=True)

Others negated both keys instead.

The negation approach
sorted(counts, key=lambda c: (-counts[c], -ord(c)))

Both are correct here, so on the scoreboard they tie. But they are not equal. The reverse trick only works because both sort keys happen to run the same direction. The moment the spec wanted frequency descending but ties ascending, reverse falls apart and you would have to rewrite it, while the negation version just needs one sign flipped. The models that negated wrote code that survives a change of mind. It is a small thing, and it is exactly the kind of small thing that tells you who is thinking about the next requirement.

Claude and Perplexity: lean and clean

Claude wrote the code I would have been happiest to merge. Compact, no ceremony, the robust negation sort, and not a wasted line.

Claude
def dedup_ranked(s: str) -> str:
    s = s.replace(' ', '')
    if not s:
        return "EMPTY"
    counts = {}
    for c in s:
        counts[c] = counts.get(c, 0) + 1
    ranked = sorted(counts, key=lambda c: (-counts[c], -ord(c)))
    return ''.join(ranked)

Perplexity was cut from the same cloth, and arguably even leaner. It skipped the separate cleaning step entirely and filtered the spaces inline while counting. Minimal, elegant, correct.

DeepSeek: elegant, with one slip

DeepSeek mostly wrote lovely, spare code in the same lean spirit as Claude. But in round one it left a landmine. After the real return statement it added a second, unreachable return that referenced a variable which did not exist.

DeepSeek, round 1
    return '-'.join(filtered[i:i+4] for i in range(0, len(filtered), 4))
    return result   # never runs, and 'result' was never defined

It never executes, so the tests passed. But a linter would flag it, and it is the kind of dead code that makes you wonder what else got left in. To DeepSeek’s credit, round two was spotless. Capable, and mostly elegant, but not perfectly consistent.

ChatGPT: verbose, and it trusts nothing

ChatGPT was the self-reliant one. In round one it refused to use isalnum and hand-wrote the character ranges. In round two it skipped Python’s built-in Counter and hand-rolled its own frequency dictionary. Both choices are perfectly correct, and both are more code than the job needed. If you like an assistant that spells everything out and leans on the language as little as possible, this is your model. If you value brevity, it will feel wordy.

Groq: the over-documenter

Groq wrote correct code and then buried it under paperwork. Its answer opened with a full docstring restating all six rules of the spec, followed by a step comment above nearly every line. Thorough, certainly. But I would side-eye it in a review. When the code is nine lines long, a nine line docstring plus a comment per line is noise, not clarity, and it is the habit of a tool trying to look diligent rather than be clear.

Groq, before any actual code
def dedup_ranked(s: str) -> str:
    """
    Transform s according to the specified rules:
    1. Remove all space characters.
    2. If the result is empty, return "EMPTY".
    3. Count each distinct character (case-sensitive).
    ... (all six rules, restated)
    """

Mistral and Gemini: small quirks

Mistral was fine, with one odd habit. It put its import statement inside the function body rather than at the top of the file. It works, but no seasoned Python developer writes it that way, and it is the sort of thing that quietly signals the model learned from a lot of code snippets rather than a lot of codebases. Gemini sat cleanly in the middle, readable and correct, though one of its comments described a negation the code did not actually use. A tiny drift between what it said and what it did.

How to actually choose now

The practical takeaway. Stop asking which free AI writes correct code, because they all do. Start asking whose code reads like code you would have written. Run a small task you know the answer to, ignore the result, and look only at the style. Pick the one that feels like you.

FAQ

Whose code was the best?+

For my taste, Claude, for consistently lean and elegant solutions with the robust sorting approach. DeepSeek matched it for elegance but slipped once with dead code. Best is partly personal, though, since all seven were correct.

Does verbose code mean a worse model?+

No. ChatGPT and Groq wrote more verbose code and were completely correct. Verbosity is a style choice, and some developers prefer the explicitness. It only becomes a problem when the documentation outweighs the code, as with Groq here.

Why does the sorting approach matter if both work?+

Because one survives a change in requirements and the other does not. Negating the sort keys handles mixed-direction tie-breaks, while the reverse flag only works when everything sorts the same way. It is a sign of code written with the next change in mind.

Should I just use whichever free AI I already have?+

Probably. Since correctness is no longer the differentiator on small tasks, the marginal gains come from matching the tool’s style to yours, not from switching. Try a couple and keep the one whose code you enjoy reading.

This is the companion to the experiment itself, I built a coding gauntlet to trip up 7 free AI chatbots. For the researched comparison of the assistants behind them, see ChatGPT vs Gemini vs Claude.

Eddie Ochieng

Eddie Ochieng

Eddie Ezekiel Ochieng is a software developer and the editor of The Test Card. He has been writing code since 2016 and has spent the last six years building production web applications for clients, work that runs from a non-profit’s platform to a community dictionary and a personal-safety service. He builds mostly in TypeScript, React and Next.js, with Node, Python and PostgreSQL behind them.

He started The Test Card out of mild irritation. Most AI tool coverage is written by people who never ship anything and never have to live with a bad tool choice. He does. The question that interests him is the practical one, which of these tools survive contact with real work, and which are just a subscription you forget to cancel.

He is not an AI researcher and does not pretend to be. What he brings instead is a builder’s scepticism, a habit of actually reading the documentation and the pricing page, and a bias toward simplicity over novelty. Good software, as he puts it, should feel as good as it works.

eddie-ezekiel.com

Leave a Comment

Share your thoughts about this article