22
\$\begingroup\$

Context

Consider the following sequence of integers:

$$2, 10, 12, 16, 17, 18, 19, ...$$

Can you guess the next term? Well, it is \$200\$. What about the next? It is \$201\$... In case it hasn't become obvious to you, this is the sequence of positive integers whose name starts with a letter D in Portuguese.

Task

Given a positive integer \$n\$, decide if it belongs in the sequence or not. An algorithm to do so is given next to the Output section.

Input

A positive integer \$n\$, no greater than \$999999999\$.

Output

A truthy/falsey value, representing whether or not the input belongs in the sequence. Truthy if it does, falsey if it doesn't. Truthy/falsey can't be switched for this challenge.

For \$0 < n < 10^9\$, here's how to determine if \$n\$ is part of the sequence. If \$9 < n\$, say \$ab\$ are its two leading digits, so that if \$n = 583\$, \$a = 5\$ and \$b = 8\$. If \$n < 10\$ then \$a = n\$. Let \$k\$ be the number of digits of \$n\$, so that if \$n = 583\$, \$k = 3\$. \$n\$ is in the sequence if any of these hold:

  • \$a = 2\$ and \$k = 1, 3, 4, 6, 7, 9\$;
  • \$ab = 10, 12, 16, 17, 18, 19\$ and \$k = 2, 5, 8\$

Please notice that standard loopholes are forbidden by default, in particular trivialising the challenge by using a language with a trivial numeric type.

(The rules above generalise trivially for \$n\$ arbitrarily big but I capped the input for simplicity)

Test cases

Truthy

2
10
12
16
17
18
19
200
201
223
256
10000
10100
10456
10999
12000
12180
12220
16550
17990
18760
19000
200000
212231
256909
299999
10000000
10999999
12000000
12999999
16000000
16562345
16999999
17000000
17999999
18000000
18999999
19000000
19999999
200000000
200145235
200999999
201000000
245345153
299999999

Falsy

1
3
4
5
6
7
8
9
11
13
14
15
20
100
1000
1200
1600
1738
1854
1953
20000
21352
120000
160000
170000
180000
190000
20000000
100000000
120000000
160000000
170000000
180000000
190000000
999999999

This is so shortest submission in bytes, wins! If you liked this challenge, consider upvoting it! If you dislike this challenge, please give me your feedback. Happy golfing!

\$\endgroup\$
14
  • 2
    \$\begingroup\$ @RGS OK, but it's a bit weird to allow any positive integer as input, and only give the rules for n>9. \$\endgroup\$ – Robin Ryder Oct 16 '20 at 14:25
  • 1
    \$\begingroup\$ Who am I kidding? I am a crowd pleaser. Changed the way the algorithm is written so you can just skim through the challenge without actually having to pay attention! \$\endgroup\$ – RGS Oct 16 '20 at 15:21
  • 2
    \$\begingroup\$ What is a trivial numeric type? \$\endgroup\$ – Zsolt Szilagy Oct 17 '20 at 19:46
  • 3
    \$\begingroup\$ @ZsoltSzilagy for this challenge, I'd define it empirically as a numeric type whose max value is so small, solving this challenge with it would circumventing most of the work \$\endgroup\$ – RGS Oct 17 '20 at 22:58
  • 2
    \$\begingroup\$ @sergiol Hot Network Questions : when navigating the SE sites in a web browser, usually to the right there's a compilation of random (hot) questions from all (?) the sites in the SE network. Many codegolf questions end up there. \$\endgroup\$ – RGS Feb 19 at 15:46

17 Answers 17

34
\$\begingroup\$

Wolfram Language (Mathematica), 42 bytes

Of course there is a built-in for this...
And as @Charlie mentioned we can golf "Portuguese" to "Spanish" and save 3 bytes

#~IntegerName~"Spanish"~StringTake~1=="d"&

Try all test cases

-13 bytes from @att

\$\endgroup\$
6
  • 22
    \$\begingroup\$ I can't believe this XD \$\endgroup\$ – RGS Oct 16 '20 at 14:27
  • 1
    \$\begingroup\$ 45 bytes \$\endgroup\$ – att Oct 16 '20 at 17:12
  • 2
    \$\begingroup\$ How/why is this not "trivialising the challenge by using a language with a trivial numeric type", which is explicitly forbidden in the question? \$\endgroup\$ – Cody Gray Oct 17 '20 at 5:11
  • 16
    \$\begingroup\$ Spanish and Portuguese are so similar that you can change the language for 3 bytes save and the tests will still pass. :-D \$\endgroup\$ – Charlie Oct 17 '20 at 6:43
  • 4
    \$\begingroup\$ @CodyGray: This is a builtin operator that vastly simplifies the problem (to match-first-char), not a numeric type that's trivial. (And it does still output the numbers as decimal digits, not words.) I think the intent of that rule is that you can't use a language only supporting numbers less than 10 or something, or only 1-bit numbers. (But the challenge requires handling any input number up to 10^9, so that would be a redundant point if that's what was meant, so IDK.) \$\endgroup\$ – Peter Cordes Oct 17 '20 at 8:24
11
\$\begingroup\$

perl -plF, 55 41 bytes

Using ideas from @Dom Hastings, and eliminating common expressions:

$x=@F=~/[258]/;$_=/^2/&!$x|/^1[026-9]/&$x

Try it online!

How does it work?

Due to the -F option, the input is split on characters which are put in the array @F. So, if we use @F in scalar context, we have the length of the number.

First, we set $x to true if the number contains 2, 5, or 8 digits (it's given the number is at most 9 digits).

The rest is straightforward. We check whether the number starts with 2, and does not contain 2, 5, or 8 digits, or whether it starts with 10, 12, 16, 17, 18, or 19, and contains 2, 5 or 8 digits.

\$\endgroup\$
5
  • 2
    \$\begingroup\$ Nice approach! Couple of little changes can save you a few here: use !=/[258]/ for the first match, adding -F and using @F in place of y===c and using binary ops instead of boolean too! Try it online! \$\endgroup\$ – Dom Hastings Oct 16 '20 at 15:02
  • 2
    \$\begingroup\$ Oh, good catch! Doing the same inline and using $; can get you to 39! Try it online! \$\endgroup\$ – Dom Hastings Oct 16 '20 at 15:21
  • 1
    \$\begingroup\$ How about 37 bytes with Try it online! since returning undef as falsy should be ok? \$\endgroup\$ – Kjetil S. Oct 16 '20 at 18:54
  • 6
    \$\begingroup\$ Or 31 bytes with Try it online! Perhaps I missed something. \$\endgroup\$ – Kjetil S. Oct 16 '20 at 19:00
  • \$\begingroup\$ @KjetilS. Nice! \$\endgroup\$ – Abigail Oct 17 '20 at 1:04
9
\$\begingroup\$

Python 2, 48 bytes

lambda n:988164-2**200>>n/1000**(len(`n/3`)/3)&1

Try it online!

Python 2, 50 bytes

f=lambda n:f(n/1000)if n>299else 988164>>n&1|n/200

Try it online!

An arithmetic solution. Chomps down n to a three-digit number by repeatedly removing the last 3 digits. Then, checks that the remaining three-digit number is one of [2,10,12,16,17,18,19], or is between 200 and 299.

The [2,10,12,16,17,18,19] is checked against the set bits of a binary number, 988164.

The 200≤n<300 check is simplified by making the ≥300 case never happen. We keep chomping groups of 3 digits if the number is at least 300 (rather than at least 1000), making the 300-999 case go to 0. This leaves us with a 200≤n check that we do simply as n/200.

You might wonder why the if/else isn't shortened to and/or as usual, but the output potentially being truthy or falsey doesn't play nicely here.

53 bytes

import re
re.compile("(2|1[026-9]|2..)(...)*$").match

Try it online!

Porting Neil's Retina solution. Takes input as a string. Thanks to n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ for saving a byte and Sisyphus for saving two.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Since you are using re.match, you can drop the first ^ \$\endgroup\$ – n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Oct 19 '20 at 7:36
  • 1
    \$\begingroup\$ Actually, I think you can even just do re.compile("(2|1[026-9]|2..)(...)*$").match and avoid the lambda entirely. Still much longer than the non-regex solution though. \$\endgroup\$ – Sisyphus Oct 22 '20 at 5:39
7
\$\begingroup\$

05AB1E, 25 21 20 19 18 bytes

2Ž Ć.¥T+ªƵžIgåèÅ?à

-1 byte thanks to @ovs and -1 byte after being inspired by @ovs in the comments

Try it online or verify all test cases.

Explanation:

2                   # Push a 2
 Ž Ć                # Push compressed integer 24111
    .¥              # Push the cumulative sum of its digits with 0 prepended:
                    #  [0,2,6,7,8,9]
      T+            # Add 10 to each: [10,12,16,17,18,19]
        ª           # Append it to the 2: [2,[10,12,16,17,18,19]]
         Ƶž         # Push compressed integer 258
           Ig       # Push the input, and pop and push its length
             å      # Check that this length is in 258 (1 if truthy; 0 if falsey)
              è     # Use that to 0-based index into the list [2,[10,12,16,17,18,19]]
                    # ([10,12,16,17,18,19] if truthy; 2 if falsey)
               Å?   # Check whether the (implicit) input starts with any of these
                    # values (or the 2)
                 à  # And pop and push the maximum of the top item,
                    # which is either already 1 or 0 if it was 2,
                    # or the maximum of the list of truthy/falsey values if not
                    # (after which the result is output implicitly)

See this 05AB1E tip of mine (sections How to compress large integers?) to understand why Ž Ć is 24111 and Ƶž is 258.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ ŽTž4вoηO creates [2,10,12,16,17,18,19] at the same length, but I don't see a way to shorten this further. (•C¬Ï•.¥Ì is the same length as well) \$\endgroup\$ – ovs Oct 16 '20 at 16:18
  • \$\begingroup\$ @ovs Ah nice! I was actually trying how to reduce the rest of the code (like getting rid of that if-statement and save bytes doing so - I've found 5+ alternatives, but all 20 bytes as well), but hadn't thought about shortening the list itself. Thanks! EDIT: Ah, misread. Your approaches are the same byte-count. My bad. Nice regardless! \$\endgroup\$ – Kevin Cruijssen Oct 16 '20 at 16:23
  • \$\begingroup\$ @ovs If you can find a way to create [10,12,16,17,18,19] (so without the 2) shorter than right now I have an alternative approach - order is irrelevant. EDIT: nvm, found something thanks to your second approach: Ž Ć.¥T+ \$\endgroup\$ – Kevin Cruijssen Oct 16 '20 at 16:27
  • 1
    \$\begingroup\$ 2Ž Ć.¥T+ª saves a byte. \$\endgroup\$ – ovs Oct 16 '20 at 17:18
  • \$\begingroup\$ @ovs Ah, smart! Thanks. :D \$\endgroup\$ – Kevin Cruijssen Oct 16 '20 at 17:35
4
\$\begingroup\$

R, 57 56 bytes

substr(n<-scan(),1,2^!nchar(n)%%3<2)%in%c(2,10,12,16:19)

Try it online!

Note that 2^!nchar(n)%%3<2 is equal to 2 when nchar(n)%%3==2, and equal to 1 otherwise.

Extract either the first, or the first 2, digits of n (depending on the value of nchar(n)%%3), and check whether the result is in c(2,10,12,16,17,18,19).

Works for arbitrarily large input.

\$\endgroup\$
2
  • \$\begingroup\$ Brilliant! much better than mine! \$\endgroup\$ – Dominic van Essen Oct 16 '20 at 16:16
  • 1
    \$\begingroup\$ ...so I've used your approach in my Husk answer now. Thanks! \$\endgroup\$ – Dominic van Essen Oct 16 '20 at 16:47
3
\$\begingroup\$

JavaScript (ES6),  51 47  46 bytes

n=>(730>>n.length^n[0])&/^2|^1[^1345]/.test(n)

Try it online!

How?

\$730\$ is the bit-mask of valid lengths when the first digit of \$n\$ is \$2\$:

730 = 1011011010
      ^ ^^ ^^ ^
      9876543210

Once it's been right-shifted by the number of digits, we XOR it with the first digit of \$n\$. Therefore, the least significant bit is left unchanged if the first digit is \$2\$ and inverted if the first digit is \$1\$. For other leading digits, we don't care about the result because the regex will not match anything anyway.

We either keep the least significant bit or discard it according to the result of the following regex:

/^2|^1[^1345]/
 ^2             // either a leading "2"
   |            // or
    ^1          // a leading "1" followed by ...
      [^1345]   // ... anything but 1, 3, 4 or 5
\$\endgroup\$
0
3
\$\begingroup\$

Retina 0.8.2, 24 bytes

^(2|1[026-9]|2..)(...)*$

Try it online! Link includes test cases. Explanation: The rules simplify to: Take the first base 1000 digit, which should be either 2, 10, 12, 16-9, or 200-299.

\$\endgroup\$
1
  • \$\begingroup\$ Excellent regex. Well done. \$\endgroup\$ – Eric Duminil Oct 18 '20 at 9:09
3
\$\begingroup\$

Haskell, 52 bytes

(%)=div
f n|n>299=f$n%1000|r<-2^n=odd$n%200+988164%r

Try it online!

This is a translation of xnor's Python solution. They contributed a byte-save with r<-2^n, too!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Nice solutions! For the second one, it looks like you can bind in a guard to save a byte: Try it online! \$\endgroup\$ – xnor Oct 17 '20 at 5:28
3
\$\begingroup\$

Charcoal, 22 bytes

¬⎇﹪⊕Lθ³⌕θ2⬤026789⌕θ⁺1ι

Try it online! Link is to verbose version of code. Explanation: Works by testing whether the string begins with either 2 or one of 10, 12, 16, 17, 18, or 19, depending on the number of digits in the string; Find() will return 0 if it does, which we then invert to provide the desired truthy answer. (And because we're working in negative logic, we actually use All() to see if any of the strings is found at position 0.)

     θ                  Input as a string
    L                   Length
   ⊕                    Incremented
  ﹪   ³                 Modulo literal `3`
 ⎇                      If nonzero then
       ⌕                Index of
         2              Literal string `2`
        θ               In input
          ⬤             Else map over characters
           026789       Literal string
                 ⌕      Index of
                    1   Literal string `1`
                   ⁺    Concatenated with
                     ι  Current character
                  θ     In input
¬                       (Any) zero
\$\endgroup\$
3
\$\begingroup\$

Jelly,  18  16 bytes

-2 thanks to Sisyphus!

bȷḢbȷ2Ḣe“,-n’DĤ

Try it online! Or see the test-suite.

How?

bȷḢbȷ2Ḣe“,-n’DĤ - Link: n
 ȷ               - 1000
b                - (n) base (1000)
  Ḣ              - head -> x
    ȷ2           - 100
   b             - (x) base (100)
      Ḣ          - head
               ¤ - nilad followed by link(s) as a nilad:
        “,-n’    -   2824111
             D   -   digits
              Ä  -   cumulative sums -> [2,10,12,16,17,18,19]
       e         - exists in?
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Nice! dȷ2ḟ0 can just become bȷ2. \$\endgroup\$ – Sisyphus Oct 18 '20 at 2:10
  • \$\begingroup\$ @Sisyphus oops, thanks! \$\endgroup\$ – Jonathan Allan Oct 18 '20 at 16:47
3
\$\begingroup\$

Zsh, 37 bytes

>$#1$1
: (12|[34679]2|[258]1[^1345])*

Try it online!

Outputs via status code (0 = is in sequence, 1 = is not in sequence).

Explanation:

  • > - create the file
    • $#1 - the length of the input
    • $1 - followed by the input itself
  • (12|[34679]2|[258]1[^1345])* - try to find a file matching this pattern:
    • (||) - one of:
      • 12 (the literal input 2 which is of length 1)
      • [34679]2 - any character from the set 34679, then a 2
      • [258]1[^1345] - any character from the set 258, then a 1, then any character except one from 1345 (shorter than 026789)
    • * - followed by any string
    • this will produce an error if there is no file
  • : - and then do nothing with that file (this is required because otherwise () would be treated as a sub-shell)
\$\endgroup\$
3
\$\begingroup\$

Ruby + i18n + numbers_and_words, 96 93 91 bytes

require'i18n'
require'numbers_and_words'
I18n.with_locale(:pt){p gets.to_i.to_words[0]==?d}

Try it on repl.it!

It's probably longer than a simple pattern matching solution, but I wanted to try it anyway.

-3 bytes from ovs.

-2 bytes from Dingus.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ You can use p instead of puts for simple -3 bytes. \$\endgroup\$ – ovs Oct 16 '20 at 16:23
2
\$\begingroup\$

Scala, 98 79 bytes

n=>{val m=n+"";if(m.size%3>1)Set(0,2,6,7,8,9)(m.take(2).toInt-10)else m(0)==50}

Try it online!

  • Thanks to user for -19!!!!
\$\endgroup\$
0
1
\$\begingroup\$

Husk, 41 33 42 bytes

§|§&ȯ€B19 26441084r↑2o₁L§&o='2←ȯ¬₁Ls
€d258

Try it online!

-8 bytes from Dominic Van Essen.

+9 bytes after corrections.

\$\endgroup\$
4
  • \$\begingroup\$ "134678" is NOT "258" (since you don't need to consider zero), for 39 bytes \$\endgroup\$ – Dominic van Essen Oct 16 '20 at 15:27
  • \$\begingroup\$ and... isn't there some way to use d instead of ""? \$\endgroup\$ – Dominic van Essen Oct 16 '20 at 15:27
  • \$\begingroup\$ 36 bytes using a line function... \$\endgroup\$ – Dominic van Essen Oct 16 '20 at 15:29
  • \$\begingroup\$ @DominicvanEssen ah, completely missed using d. \$\endgroup\$ – Razetime Oct 16 '20 at 15:30
1
\$\begingroup\$

R, 87 82 79 bytes

(or 82 bytes as a function)

`if`(36%%((k=nchar(n<-scan())-1)+5),n%/%10^k==2,n%/%10^(k-1)%in%c(10,12,16:19))

Try it online!

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

Husk, 28 26 25 23 21 20 bytes

or 19 bytes by accepting input as a string

Edit: -2 bytes thanks to LegionMammal978, then -1 more byte thanks to Zgarb

€∫d2824111d↑d¹→=2%3L

Try it online! (header in TIO link loops over integers from 1 to 500, and outputs those beginning with 'D' in Portugese)

Port of Robin Ryder's R answer. Outputs zero (falsy) for numbers not beginning with 'D' in Portugese, or a positive integer (truthy) for numbers beginning with 'D'.

How?

€∫d2824111d`↑d¹→=2%3Ld
€                               # does the argument belong to this list:
 ∫                              # cumulative sum of
  d2824111                      # base-10 digits of 2824111
                                # (2,10,12,16,17,18 and 19)
          d                 # argument is the base-10 number formed from
           `↑d¹             # the first x digits of the input
                                # where x is calculated as:
               →=2%3Ld
               →                # 1 plus
                    Ld          # the number of input digits
                  %3            # mod 3
                =2              # equals 2?
\$\endgroup\$
4
  • \$\begingroup\$ The ` in `↑ is redundant; can take its arguments in the opposite order via take2, and removing the ` doesn't seem to affect the inferencing here. Also, the d in Ld is redundant; L alone can do it via nlen. \$\endgroup\$ – LegionMammal978 Oct 17 '20 at 5:16
  • \$\begingroup\$ @LegionMammal978 - Thanks x2! \$\endgroup\$ – Dominic van Essen Oct 17 '20 at 9:10
  • \$\begingroup\$ The initial ` is also redundant: can take its arguments in either order if the types match. \$\endgroup\$ – Zgarb Oct 17 '20 at 12:44
  • \$\begingroup\$ @Zgarb - Thanks! \$\endgroup\$ – Dominic van Essen Oct 17 '20 at 13:50
1
\$\begingroup\$

Ruby, 48 47 34 bytes

->s{s=~/^(2|1[026-9]|2..)(...)*$/}

Try it online!

Takes input is a string.

Based on Abigail's Perl solution. Based on Neil's impressive regex.

\$\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.