18
\$\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\$
  • 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 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 at 15:21
  • 1
    \$\begingroup\$ Nice challenge, made the top HNQ! \$\endgroup\$ – Redwolf Programs Oct 17 at 1:25
  • 2
    \$\begingroup\$ What is a trivial numeric type? \$\endgroup\$ – Zsolt Szilagy Oct 17 at 19:46
  • 2
    \$\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 at 22:58

16 Answers 16

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

| improve this answer | |
\$\endgroup\$
  • 19
    \$\begingroup\$ I can't believe this XD \$\endgroup\$ – RGS Oct 16 at 14:27
  • 1
    \$\begingroup\$ 45 bytes \$\endgroup\$ – att Oct 16 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 at 5:11
  • 14
    \$\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 at 6:43
  • 3
    \$\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 at 8:24
10
\$\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.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\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 at 15:02
  • 1
    \$\begingroup\$ Oh, good catch! Doing the same inline and using $; can get you to 39! Try it online! \$\endgroup\$ – Dom Hastings Oct 16 at 15:21
  • \$\begingroup\$ How about 37 bytes with Try it online! since returning undef as falsy should be ok? \$\endgroup\$ – Kjetil S. Oct 16 at 18:54
  • 5
    \$\begingroup\$ Or 31 bytes with Try it online! Perhaps I missed something. \$\endgroup\$ – Kjetil S. Oct 16 at 19:00
  • \$\begingroup\$ @KjetilS. Nice! \$\endgroup\$ – Abigail Oct 17 at 1:04
7
\$\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.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ Since you are using re.match, you can drop the first ^ \$\endgroup\$ – n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Oct 19 at 7:36
  • \$\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 at 5:39
6
\$\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.

| improve this answer | |
\$\endgroup\$
  • 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 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 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 at 16:27
  • 1
    \$\begingroup\$ 2Ž Ć.¥T+ª saves a byte. \$\endgroup\$ – ovs Oct 16 at 17:18
  • \$\begingroup\$ @ovs Ah, smart! Thanks. :D \$\endgroup\$ – Kevin Cruijssen Oct 16 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.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Brilliant! much better than mine! \$\endgroup\$ – Dominic van Essen Oct 16 at 16:16
  • 1
    \$\begingroup\$ ...so I've used your approach in my Husk answer now. Thanks! \$\endgroup\$ – Dominic van Essen Oct 16 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
| improve this answer | |
\$\endgroup\$
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.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Excellent regex. Well done. \$\endgroup\$ – Eric Duminil Oct 18 at 9:09
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.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ You can use p instead of puts for simple -3 bytes. \$\endgroup\$ – ovs Oct 16 at 16:23
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!

| improve this answer | |
\$\endgroup\$
  • 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 at 5:28
2
\$\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
| improve this answer | |
\$\endgroup\$
2
\$\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?
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ Nice! dȷ2ḟ0 can just become bȷ2. \$\endgroup\$ – Sisyphus Oct 18 at 2:10
  • \$\begingroup\$ @Sisyphus oops, thanks! \$\endgroup\$ – Jonathan Allan Oct 18 at 16:47
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!!!!
| improve this answer | |
\$\endgroup\$
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.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ "134678" is NOT "258" (since you don't need to consider zero), for 39 bytes \$\endgroup\$ – Dominic van Essen Oct 16 at 15:27
  • \$\begingroup\$ and... isn't there some way to use d instead of ""? \$\endgroup\$ – Dominic van Essen Oct 16 at 15:27
  • \$\begingroup\$ 36 bytes using a line function... \$\endgroup\$ – Dominic van Essen Oct 16 at 15:29
  • \$\begingroup\$ @DominicvanEssen ah, completely missed using d. \$\endgroup\$ – Razetime Oct 16 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!

| improve this answer | |
\$\endgroup\$
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?
| improve this answer | |
\$\endgroup\$
  • \$\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 at 5:16
  • \$\begingroup\$ @LegionMammal978 - Thanks x2! \$\endgroup\$ – Dominic van Essen Oct 17 at 9:10
  • \$\begingroup\$ The initial ` is also redundant: can take its arguments in either order if the types match. \$\endgroup\$ – Zgarb Oct 17 at 12:44
  • \$\begingroup\$ @Zgarb - Thanks! \$\endgroup\$ – Dominic van Essen Oct 17 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.

| improve this answer | |
\$\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.