34
\$\begingroup\$

It's been a while since I last wrote some , so I felt like tackling Project Euler #1.

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.

This is the code/script I wrote to solve this:

HAI 1.2
    VISIBLE "HAI, PROJEK LOLLER ONE!!"

    I HAS A LIMIT ITZ 1000
    I HAS A TOTAL ITZ 0
    I HAS A CHEEZ ITZ 3
    I HAS A BURGER ITZ 5
    I HAS A CHEEZBURGER ITZ PRODUKT OF CHEEZ AN BURGER

    HOW IZ I ADDTOTAL YR VALUE
        I HAS A RESULT ITZ SUM OF VALUE AN TOTAL
        FOUND YR RESULT
    IF U SAY SO


    IM IN YR MIND UPPIN YR NUMBER TIL BOTH SAEM NUMBER AN LIMIT

        I HAS A PICKLE ITZ FAIL

        BOTH SAEM 0 AN MOD OF NUMBER AN CHEEZBURGER
        O RLY?, YA RLY
            PICKLE R WIN
        NO WAI
            BOTH SAEM 0 AN MOD OF NUMBER AN CHEEZ
            O RLY?, YA RLY
                PICKLE R WIN
            NO WAI
                BOTH SAEM 0 AN MOD OF NUMBER AN BURGER
                O RLY?, YA RLY
                    PICKLE R WIN
                OIC
            OIC
        OIC

        BOTH SAEM PICKLE AN WIN
        O RLY?, YA RLY
            TOTAL R I IZ ADDTOTAL YR NUMBER MKAY
        OIC

    IM OUTTA YR MIND

    VISIBLE SMOOSH "TEH ANSWER IZ " AN TOTAL MKAY
    VISIBLE "DOWN WITH PROJEK LOLLER ONE!"

KTHXBYE

This code can be executed on CodingGround, and produces this output:

HAI, PROJEK LOLLER ONE!!

(spoiler)

TEH ANSWER IZ 233168

DOWN WITH PROJEK LOLLER!

Is the -like logic appropriate, or I fell in the "easy" trap? Would there be a way to collapse all the conditions into one and make a shorter script? Or is this algorithm a bad/inefficient one?

\$\endgroup\$
24
+500
\$\begingroup\$

Same Guy, Same Language, same criticism?

Let me start by (again) critzising your variable casing choice of SHOUTCASE
It's so darn hard to tell what's a variable and what's not :(

But your names got better since the last time. Cheez and Burgr aren't the best, but given their content is arbitrarily set and accordingly somewhat meaningless they really stand their ground.

One thing though: your Cheezburgers are not needed.

It's a waste of computation power to check divisors by the biggest one first if you return early. (I recall rolfl having some nice stats on that in one fizz-buzz review I can't find right now). We can completely elimimate that O RLY? YA RLY from your code.

Oh and while we're at cheeseburgers... There's one thing I really dislike on cheeseburgers... Pickles.

The temporary TROOF variable to remove that three YA RLY doing the same thing is completely overkill. Instead of PICKLES R WIN it would be sufficient to add the current Number to the total.

Code until now:

IM IN YR Mind UPPIN YR Number TIL BOTH SAEM Number AN Limit   
    BOTH SAEM 0 AN MOD OF Number AN Cheez
    O RLY?, YA RLY
          Total R I IZ AddToTotal YR Number MKAY
    NO WAI
          BOTH SAEM 0 AN MOD OF Number AN Burger
          O RLY?, YA RLY
                Total R I IZ AddToTotal YR Number MKAY
          OIC
    OIC
IM OUTTA YR Mind

Now what have we got here? this looks like it should be either an ElseIf or just a simple combination of conditions into an Or.

The latter is the easier one, but for reference: There is an else if. It's MEBBE

Final Code:

HAI 1.2
    VISIBLE "HAI, PROJEK LOLLER ONE!!"

    I HAS A Limit ITZ 1000
    I HAS A Total ITZ 0
    I HAS A Cheez ITZ 3
    I HAS A Burger ITZ 5

    HOW IZ I AddToTotal YR Value
        I HAS A Result ITZ SUM OF Value AN Total
        FOUND YR Result
    IF U SAY SO


    BTW Iterates from 0 to 999
    IM IN YR Mind UPPIN YR Number TIL BOTH SAEM Number AN Limit
        EITHER OF BOTH SAEM 0 MOD OF Number AN Cheez AN BOTH SAEM 0 MOD OF Number AN Burger
        O RLY?, YA RLY
             Total R I IZ AddToTotal YR Number MKAY
        OIC
    IM OUTTA YR Mind

    VISIBLE SMOOSH "TEH ANSWER IZ " AN Total MKAY
    VISIBLE "DOWN WITH PROJEK LOLLER ONE!"

KTHXBYE
\$\endgroup\$
  • 5
    \$\begingroup\$ Seriously agreed with this. All of the languages keywords are SHOUTCASE, variables should not be. \$\endgroup\$ – RubberDuck Feb 2 '15 at 16:26
  • 3
    \$\begingroup\$ It's like SQL in that aspect. \$\endgroup\$ – Pimgd Feb 2 '15 at 16:27
  • 5
    \$\begingroup\$ Personally I disagree, as lolcats were typically all in SHOUTCASE. Sure, readability is better with lowercase variables, but that is not the point of lolcode. \$\endgroup\$ – Nick Udell Jun 16 '15 at 12:00
  • 5
    \$\begingroup\$ For production source code, yes. For esoteric programming languages, no. The point is to be experimental, fun, or different with an esoteric language, and that does not necessarily mean it should be readable. Whitespace's readability is essentially zero, after all. \$\endgroup\$ – Nick Udell Jun 16 '15 at 12:44
  • 1
    \$\begingroup\$ This answer is the winner of Best of Code Review 2015 — Lots of Laughs category. Congratulations! \$\endgroup\$ – 200_success Jan 16 '16 at 0:49
14
\$\begingroup\$

IMHO, you picked the wrong algorithm.

Better would be to take the limit...

Integer divide that by \$3\$ ... \$(999\ \mathbf{div}\ 3 = 333)\$.

Then (that number to the power of two plus itself) divided by \$2\$. Then times the value of that what we originally divided it by.

So \$(((333*333) + 333) / 2) * 3\$.

That's \$166833\$.

Next, do the same thing for \$5\$.

\$999\ \mathbf{div}\ 5 = 200, (((199*199) + 199) / 2) * 5 = 99500\$.

Add them together, we have \$266333\$.

But we counted numbers like \$15\$, \$30\$, etc. double!

So do the same thing for \$15\$, and take that off!

\$999/15 = 66, (((66*66) + 66) / 2) * 15) = 33165\$.

\$266333 - 33165 = 233168\$.


The reason this works is because it does this:

First, we take the cap... \$999\$. On the way to \$999\$, we will see \$999\ \mathbf{div}\ 3 = 333\$ numbers that are multiples of 3. And each of them is 3 bigger than the one that comes before it. So what we then do is take the whole series of \$[1, 2, 3...333]\$ and match them opposingly, like so:

1 + 332 = 333
2 + 331 = 333
3 + 330 = 333

And on and on and on.

This is best expressed by \$((x * x) / 2)\$.

Or, rather, it's actually \$(x/2)\$ (the number of pairs) \$* x\$ (the value each pair has).

Then we add \$x\$ manually. This is because \$333\$ doesn't need to be paired.

So then we have the value of the set \$[1, 2, 3...333]\$. But we had \$[3, 6, 9, 12...999]\$. So we do the whole lot * 3.

We do the same thing for 5.

But then we get the problem with \$[15, 30, 45...]\$ we counted those double!

So then we do the same thing for 15, but subtract it from the total of \$(3+5)\$.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.