5
\$\begingroup\$

Inspired by a restriction on What do you get when you multiply 6 by 9? (42)

By order of the President, we are no longer permitted to use confusing fake numbers (i.e. numbers other than integers from 0 to 99 inclusive), and are instead to use only real numbers, that is, those that are not fake.

Unfortunately, most maths are very unpatriotic at present and thus it is necessary to revolutionalize a new, revised, mathematics for the glory of the State.

Your task is to create a program or function which takes as its input two numbers and provides as its output their product. Your program, obviously, must be consistent with Minitrue's standards for programmatic excellence. Specifically:

  • You may use real numbers in your code; users of fake numbers will be referred to Miniluv
  • If a fake number is provided as input, you are to raise an error to that effect raised only in this case. If your chosen language is incapable of error, you are to write a consistent Truthy or Falsy value to a different output stream than normal, this value being written to that output stream only in this case.
  • Your program must never output any fake numbers; users of fake numbers will by referred to Miniluv
  • Your program must output consistently with pre-Ministry math texts, except where those texts are influenced by thoughtcrime (i.e. where the input or output would be a fake number). In those cases, you are free to define whatever truth you think best furthers the Party's goals, provided your output is consistent with above principles.
  • Your input is guaranteed to be either two real numbers, two fake numbers, or one real and one fake number

This is code golf; the shortest code in bytes wins.

Some test cases:

Input: 0, 3 Output: 0
Input: 2, 5 Output: 10
Input: 9, 11 Output: 99
Input: 10, 10 Output*: 5
Input: -1, 0 Output*: ERROR: THOUGHTCRIME COMMITTED
Input: 2, 2.5 Output*: ERROR: THOUGHTCRIME COMMITTED
Input: 99, 2 Output*: 5
Input: -1, 53 Output*: ERROR: THOUGHTCRIME COMMITTED

Test cases with an 'Output*' indicate that there are multiple valid outputs for that test case.

Please note that while your output in the case of a fake product from real numbers may be an error, it cannot be the same error as for fake input (unless both cases trigger), as explained in rule #2.

\$\endgroup\$
  • \$\begingroup\$ This is my first question here; advice is welcomed \$\endgroup\$ – the dark wanderer Jun 3 '17 at 19:02
  • \$\begingroup\$ Is the input guaranteed to be two numbers, even if they are fake? Will they be of our language's integer type? Can they be negative? \$\endgroup\$ – xnor Jun 3 '17 at 19:17
  • 1
    \$\begingroup\$ @thedarkwanderer people really don't like having to do input validation. If the input is out of scope (letters) we don't want to deal with that. Lemme find the meta post about that real quick. Here it is: invalid inputs meta. The fake numbers are OK because that's part of the challenge, but trying to multiply "Hello" and "World" should not be our business. \$\endgroup\$ – Stephen Jun 3 '17 at 20:11
  • 1
    \$\begingroup\$ In some languages there are literals that would actually be interpreted as fake numbers - e.g. in Jelly ȷ2 is parsed as meaning 100, as is ³ if no command line argments are used (equally, for example, ⁾ab is parsed as 25349) - there is calculation occurring at a deeper level of course (but at the bottom it's all bits, so nothing is using fake numbers...) \$\endgroup\$ – Jonathan Allan Jun 3 '17 at 21:53
  • 1
    \$\begingroup\$ What about covfefe numbers? \$\endgroup\$ – caird coinheringaahing Jun 4 '17 at 20:14

10 Answers 10

2
\$\begingroup\$

Python 2, 41 38 41 39 bytes

lambda a,b:a*b%-~99/(chr(a)<'d'>chr(b))

-2 bytes from xnor.

Uses -~99 to get 100 legally.

Relies on u<v>w is equivalent to u<v and v>w.

If a or b are not integers chr throws a TypeError. If either are less than 0, chr throws a ValueError.

If a or b are greater than or equal to 100 (ord('d')), then the denominator will evaluate to 0, and throws a ZeroDivisionError.

Otherwise, the denominator will evaluate to 1; and returns the modded product.

\$\endgroup\$
  • \$\begingroup\$ I think the first set of parens aren't needed. \$\endgroup\$ – xnor Jun 4 '17 at 20:48
  • \$\begingroup\$ @xnor, thanks! Was thinking about order of operations, but doesn't matter when dividing by 1 or 0. \$\endgroup\$ – Chas Brown Jun 4 '17 at 20:52
2
\$\begingroup\$

Python,  54  52 bytes

lambda a,b:[v for v in(a,b,a*b%-~99)if'd'>chr(v)][2]

An unnamed function raising an error if either of the inputs are fake otherwise returning the product of the inputs modulo 100 (always real and correct if the product itself is real).

Try it online!

How?

First creates a tuple of the inputs and their product modulo 100 using (a,b,a*b%-~99) where ~x computes -1-x and % is the modulo operator.

Then traverses that tuple creating a list of those values which are real numbers.

The test for real-ness is performed by first attempting to cast each value, v, to characters with chr(v) - which will raise a ValueError if v is not a non-negative integer less than 256, then checking the value is less than 100 by a less-than-comparison, <, to the 100th character, 'd'.

If both a and b are real the list will have three entries (the product modulo 100 is alway real), otherwise it will have less. The [...][2] attempts to get the item at the second index (third item), raising an IndexError if it does not exist.

Thus either input being fake results in either a ValueError or IndexError, while both inputs being real always succeeds and returns a real number, and if that product is itself real it is the returned value.

\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 61 57 bytes

g=x=>x<0|x>99|x%1!=0
f=(a,b)=>g(a)|g(b)|g(a*b)?f(a,b):a*b

Similar to the Haskell answer, creates a validation function, called g. g returns false iff x is not a fake number. f checks if the either number or the product is fake. If either number or the product is fake, it calls f again, which will hit a StackOverflow relatively quickly. Otherwise, it returns the product. Same length, with currying:

g=x=>x<0|x>99|x%1!=0
f=a=>b=>g(a)|g(b)|g(a*b)?f(a)(b):a*b

g=x=>x<0|x>99|x%1!=0
f=(a,b)=>g(a)|g(b)|g(a*b)?f(a,b):a*b

//Note that once one console.log crashes, none of the rest will execute
console.log(f(0,3))
console.log(f(2,5))
console.log(f(9,11))
console.log(f(10,10))
console.log(f(-1,0))
console.log(f("Hello"," World"))
console.log(f("Help",""))
console.log(f(2,2.5))

\$\endgroup\$
1
\$\begingroup\$

Python 3 111 101 75 77 59 bytes

EDIT: -10 bytes because of Python's "ternary" operator

EDIT 2: -26 bytes because of lambda and really obfuscating with the ternary operator.

EDIT 3: +2 bytes because range is exclusive. Thanks @ovs for catching that

EDIT 4: -18 bytes thanks to @ovs's suggestion

lambda a,b,s={*range(99+1)}:{a,b}-s and c or max({0,a*b}&s)

Try it online!

Raises a Zero Division Error for fake numbers, returns 0 for a fake product

Works by first checking if a and b are in the range of real numbers. If not, try to access the undefined variable c, resulting in an error. Otherwise, return either 0 or a * b depending on whether a * b is fake or real.

\$\endgroup\$
  • \$\begingroup\$ @thedarkwanderer: "a" is a literal a as the return if the product is a fake number. a the variable is the integers from 0-99. I'll change the variable to b to make it clearer. \$\endgroup\$ – Neil A. Jun 3 '17 at 21:27
  • \$\begingroup\$ @ovs nice catch, I will fix that \$\endgroup\$ – Neil A. Jun 3 '17 at 21:30
  • \$\begingroup\$ @thedarkwanderer: Yes, I could use another variable instead, but then I would need spaces on either side of the name in order for the else and if to work, resulting in the same byte count \$\endgroup\$ – Neil A. Jun 3 '17 at 21:34
1
\$\begingroup\$

Jelly,  (16?) 17  (13?) 15 bytes

⁶Pḟ0r99¤Ȧ$?Dṫ-Ḍ

Monadic link taking a list of numbers, yielding the real answer if the inputs and the result are real, yielding the product modulo 100 if the inputs are real but the product would not be, and raising a TypeError if either of the inputs are fake.

Try it online!

13 byte possible alternative (debatable), works in a similar fashion, but uses:

⁶Pḟȷ2Ḷ¤Ȧ$?%ȷ2
   ȷ2          - literal 100 (interpreted as 10 raised to the power of 2)
     Ḷ         - lowered range -> [0,1,2,...99] (all the *real* numbers)
           ȷ2  - literal 100 (again)
          %    - modulo

How?

⁶Pḟ0r99¤Ȧ$?Dṫ-Ḍ - Main link: list of numbers, [a1, a2]
          ?     - if:
                - ...the if condition:
         $      -   last two links as a monad:
  ḟ             -     filter discard if in:
       ¤        -       nilad followed by link(s) as a nilad:
   0            -         literal zero
     99         -         literal ninety-nine
    r           -         inclusive range -> [0,1,2,...99] - all the *real* numbers
        Ȧ       -     any and all (for our purposes: 0 if empty, 1 otherwise [since zeros were filtered out])
                - ...then:
⁶               -   literal space character
                - ...else:
 P              -   product of [a1, a2]
           D    - convert to a list of it's decimal digits (Type Error 
            ṫ-  - tail from index -1 (keep only the last two (or less) digits)
              Ḍ - convert back to a number
\$\endgroup\$
  • \$\begingroup\$ I would assume the 17 byte solution is allowed, since 100 is represented as a result and not the literal. Likewise for 99+1. \$\endgroup\$ – Neil A. Jun 3 '17 at 22:04
  • \$\begingroup\$ @NeilA. ȷ2 is a literal 100 - this is why it is debatable. \$\endgroup\$ – Jonathan Allan Jun 3 '17 at 22:10
1
\$\begingroup\$

Python 3, 74 69 bytes

-5 bytes thanks to @Adnan

lambda a,b,h=99+1:a*b%h if type(a)==int==type(b)and 0<=a<h>b>=0else c

Try it online!

\$\endgroup\$
  • \$\begingroup\$ @thedarkwanderer fixed it \$\endgroup\$ – ovs Jun 3 '17 at 21:24
  • \$\begingroup\$ Well this technically works :P I think the fact you rely on 10*10 being something other than what 10*10 is according to you is a little silly, but we can go ahead and call it doublespeak \$\endgroup\$ – the dark wanderer Jun 3 '17 at 21:30
  • \$\begingroup\$ I think 0<=b<h>a>=0 instead of h>a>=0and h>b>=0 should work. \$\endgroup\$ – Adnan Jun 3 '17 at 22:09
1
\$\begingroup\$

Perl 6,  57 54  41 bytes

{all(@_ X~~Int,$(0..99))??+([*](@_)~~0..99)&&[*] @_!!die}

Try it

{all(@_ X~~Int,$/=0..99)??+([*](@_)~~$/)&&[*] @_!!die}

Try it

{all(@_ X~~Int,0..99)??[*](@_)%10²!!die}

Try it

Throws an error with the message of Died if given a non-Real number.
(left intentionally vague to confuse the perpetrator, which gives more time to collect them for re-education)

The first two examples return 0 rather than produce a non-Real number.
The third one constrains its result to a Real number using the modulus operator.

Expanded:

{  # bare block lambda with implicit parameter list of 「@_」

    all(           # check if all tests pass
        @_         # the input
      X~~          # cross 「X」 smartmatched 「~~」 with the following
        Int,       # All **Real** numbers are Ints
        0..99      # Range of all **Real** numbers
    )

  ??               # if all inputs are **Real** numbers
      [*](@_)      # reduce using &infix:« * » operator
      %            # modulus
      10²          # 10 to the power of 2
  !!               # die if any input was not a **Real** number
    die
}

Note that 10² is parsed as 10 followed by a postfix operator.

\$\endgroup\$
0
\$\begingroup\$

Haskell, 67 bytes

v a=not$0<=a&&a<=99
a#b|(v a)||(v b)=error""|v$a*b=error""|True=a*b
\$\endgroup\$
  • \$\begingroup\$ Does your program handle floats between 0 and 99? integers from 0 to 99 inclusive \$\endgroup\$ – Stephen Jun 3 '17 at 19:49
0
\$\begingroup\$

Haskell, 35 41 bytes

a#b|all(`elem`[0..99])[a,b]=mod(a*b)$1+99

Try it online!

Example usage: 3#4 returns 12, while fake numbers like 3.5#4, 300#4 and (-3)#4 all yield the error non-exhaustive pattern in function #. Non-fake inputs whose product would be greater than 99 result in the product modulus 100.

Edit: Thanks to Jonathan Allan for pointing out that I initially missed a part of the challenge.

\$\endgroup\$
  • 1
    \$\begingroup\$ You misinterpreted just like I did - if both inputs are real but their product is fake we may not raise the same error as we do in the case of a fake input. So, for example, 10#10 should result in either a real number (even if it is "wrong"- like 5 in OPs examples), or a different error to those that could be raised by the presence of fake input. \$\endgroup\$ – Jonathan Allan Jun 4 '17 at 0:50
  • \$\begingroup\$ @JonathanAllan Thanks! It should be fixed now. \$\endgroup\$ – Laikoni Jun 5 '17 at 19:37
0
\$\begingroup\$

Ruby, 52 bytes

Returns NoMethodError if the input has a fake number.

->a,b{a.chr;b.chr;(r=0..99)===a&&r===b ?a*b%-~99:+p}

Try it online!

\$\endgroup\$

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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