33
\$\begingroup\$

Introduction:

A Dutch BSN (BurgerServiceNummer) is valid when it complies to the following rules:

  • It only contains digits.
  • The length should be either 8 or 9 in length.
  • When the digits are indexed as A through I, the result of the following sum: 9xA + 8xB + 7xC + 6xD + 5xE + 4xF + 3xG + 2xH + -1xI (NOTE the -1 instead of 1!) should be divisible by 11, and should not be 0.

Challenge:

Input: A string or char-array representing the BSN.

Output: A truthy or falsey result whether the input is a valid BSN.

Challenge Rules:

  • The input format should be a string or char-array. You are not allowed to use an int-array of digits, or a (possibly octal) number. (You are allowed to convert it to an int-array of digits yourself, though, but not directly as argument.)
  • Despite the restriction on the input above, you can assume all test cases will contain one or more digits ([0-9]+)
  • Regarding the BSN with length 8 instead of 9, the Dutch Wikipedia states the following: "For the eleven-test and for other practical uses, a leading zero is added to make the number of length 9." (source)

General rules:

  • This is , so shortest answer in bytes wins.
    Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
  • Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters, full programs. Your call.
  • Default Loopholes are forbidden.
  • If possible, please add a link with a test for your code.
  • Also, please add an explanation if necessary.

Test cases:

// Truthy test cases:
111222333
123456782
232262536
010464554
10464554
44016773

// Falsey test cases:
000000000
192837465
247594057
88888888
73
3112223342
000000012
\$\endgroup\$
9
  • 5
    \$\begingroup\$ Is it true that if there are 8 digits, one omits A from the formula given? \$\endgroup\$
    – isaacg
    Dec 8, 2016 at 8:29
  • \$\begingroup\$ @isaacg I've added the rule regarding this with a link to the (Dutch) wikipedia page. You are indeed right, it omits A from the formula (or basically adds a leading 0 to make it length 9, resulting in the same result as omitting A). \$\endgroup\$ Dec 8, 2016 at 9:13
  • \$\begingroup\$ Test case for "sum [...] should not be 0.": 000000012 \$\endgroup\$
    – betseg
    Dec 8, 2016 at 11:51
  • \$\begingroup\$ @betseg I've added it to the list \$\endgroup\$ Dec 8, 2016 at 11:58
  • \$\begingroup\$ Hi! I'm doing my solution in python, and am wondering about clarification of truthy and falsey. Python counts the integer 0 as falsey and any other integer as truthy, and my current solution always converts to bools? \$\endgroup\$ Oct 18, 2021 at 13:14

32 Answers 32

12
\$\begingroup\$

JavaScript (ES6) 57

Input as an array of chars. reduceRight saves the day!

s=>!(i=1,t=s.reduceRight((t,v)=>t-v*++i),!t|t%11|(i|1)-9)

Test

F=
s=>!(i=1,t=s.reduceRight((t,v)=>t-v*++i),!t|t%11|(i|1)-9)


;['111222333','123456782','232262536','010464554','10464554','44016773']
.forEach(t=>{
  var r=F([...t]);console.log(t,r)
})

;['000000000','192837465','247594057','88888888','73','3112223342','3112223342']
.forEach(t=>{
  var r=F([...t]);console.log(t,r)
})

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Always nice to see a reduceRight answer! \$\endgroup\$
    – Neil
    Dec 8, 2016 at 11:42
  • \$\begingroup\$ Finally found a way to reach 58 with map(), just to realize that your answer is actually 57 bytes long :-) \$\endgroup\$
    – Arnauld
    Dec 8, 2016 at 15:57
  • \$\begingroup\$ @Arnauld yep I can't believe I counted wrong again, thanks \$\endgroup\$
    – edc65
    Dec 8, 2016 at 17:40
9
\$\begingroup\$

05AB1E, 23 21 bytes

`()DgLR*OD11Ö89¹gåP0Ê

Try it online! or as a Test suite

Explanation

`                        # push input as individual chars onto stack
 (                       # negate top value
  )                      # wrap in list
   DgLR                  # range [len(input) ... 1]
       *O                # multiply with list of digits and sum
         D11Ö            # is evenly divisible by 11
             89¹gå       # len(input) is 8 or 9
                  P      # product of sum/divisible by 11/len in (8,9)
                   0Ê    # not equal to 0
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Probably due to an older version of 05AB1E, but you can save 3 bytes now by changing DgL to ā and to Ā. Try it online. \$\endgroup\$ Aug 31, 2018 at 10:06
  • 1
    \$\begingroup\$ 89 should actually be 89S, since an input with length 89 could potentially give a false-positive. \$\endgroup\$ Nov 7, 2022 at 13:31
8
\$\begingroup\$

R, 86 67 bytes

Edit: Thanks to Jarko Dubbeldam for suggesting the dot product!

l=length(x<-scan(,""));s=as.double(x)%*%c(l:2,-1);!s%%11&s&l>7&l<10

Reads input from stdin and store as an array/vector of characters. Subsequently convert to numeric,multiply with the vector 9...2,-1 and check all conditions.

\$\endgroup\$
4
  • \$\begingroup\$ Does not work for me. You should split x as vector. \$\endgroup\$
    – djhurio
    Dec 8, 2016 at 13:42
  • \$\begingroup\$ @djhurio Enter the values separated by space and they are implicitly stored in a vector of characters. Alternatively enter them one by one by hitting enter in between. \$\endgroup\$
    – Billywob
    Dec 8, 2016 at 15:03
  • 1
    \$\begingroup\$ if(l<9)x=c(0,x);s=sum(as.double(x)*c(9:2,-1)) can be turned into s=sum(as.double(x)*c(l:2,-1)). Also, the sum of the pairwise product of two vectors is the same as their dot-multiplication %*%. \$\endgroup\$
    – JAD
    Dec 9, 2016 at 9:30
  • \$\begingroup\$ @JarkoDubbeldam Nice! The dot product is really clever. \$\endgroup\$
    – Billywob
    Dec 9, 2016 at 9:40
7
\$\begingroup\$

JavaScript (ES6), 61 60 59 58 bytes

Takes an array of chars as input. Returns false / true.

a=>!(a.map(c=>s-=--k?-c*k-c:c,k=a.length&9,s=0)|!s|k|s%11)

Test cases

let f =

a=>!(a.map(c=>s-=--k?-c*k-c:c,k=a.length&9,s=0)|!s|k|s%11)

// truthy
console.log(f([..."111222333"]));
console.log(f([..."123456782"]));
console.log(f([..."232262536"]));
console.log(f([..."010464554"]));
console.log(f([..."10464554"]));
console.log(f([..."44016773"]));

// falsy
console.log(f([..."000000000"]));
console.log(f([..."192837465"]));
console.log(f([..."247594057"]));
console.log(f([..."88888888"]));
console.log(f([..."73"]));
console.log(f([..."3112223342"]));

\$\endgroup\$
6
\$\begingroup\$

C, 112 101 96 98 104 bytes

Thanks to @MartinEnder for saving 5 3 bytes while fixing my code!

j,i,k,l;f(char*s){l=strlen(s);for(i=l,j=k=0;j<l;)k+=(s[j++]-48)*(i>1?i--:-1);return!(k%11)&&k&&(l^8)<2;}

Returns 0 if invalid, 1 if valid. Try it online!

\$\endgroup\$
9
  • \$\begingroup\$ This accepts 61 even though it is not of correct length. \$\endgroup\$ Dec 8, 2016 at 10:53
  • 1
    \$\begingroup\$ This does not work with my personal BSN. \$\endgroup\$
    – roberrrt-s
    Dec 8, 2016 at 11:03
  • \$\begingroup\$ Hopefully fixed. \$\endgroup\$
    – betseg
    Dec 8, 2016 at 11:46
  • \$\begingroup\$ Not fixed. Doesn't work with mine either. \$\endgroup\$ Dec 8, 2016 at 23:32
  • 1
    \$\begingroup\$ @Roberrrt, @DavidPostill; is it OK now or should I just give up? =( \$\endgroup\$
    – betseg
    Dec 9, 2016 at 15:53
5
\$\begingroup\$

R, 95 79 93 bytes

function(x){y=as.double(el(strsplit(x,"")));z=y%*%c((q<-length(y)):2,-1);(z&!z%%11&q>7&q<10)}

Unnamed function that takes a string as argument. At first I overread the requirement of having a string as input instead of a number, but that's good, because it saves some bytes on conversion.

I am not sure how to interpret the array of characters, but if that means that you can use a vector of stringed digits "1" "2" "3" "4" etc as input, it becomes a bit shorter even:

function(x){y=as.double(x);z=y%*%c((q<-length(y)):2,-1);(z&!z%%11&q>7&q<10)}

Splits x into a numeric vector, then appends a 0 if length is 8, then calculates the dotproduct of vector y and c(9,8,7,6,5,4,3,2,-1). Tests if the result is both nonzero and divisible by 11.

Saved 16 bytes thanks to the logic by @Emigna, implicitly appending the 0 in the creation of the vector c(length(x):2,-1).

Forgot to add check for length 8/9, so +14 bytes :(

\$\endgroup\$
4
\$\begingroup\$

Perl, 58 bytes (52 + 6)

@N=(-1,2..9);$r+=$_*shift@N for reverse@F;$_=$r&&/^\d{8,9}$/&&!($r%11)

Run with

perl -F// -lapE

Input passed through STDIN:

Usage

echo 232262536 | perl -F// -lapE '@N=(-1,2..9);$r+=$_*shift@N for reverse@F;$_=$r&&/^\d{8,9}$/&&!($r%11)'

Outputs 1 for as the truthy value, 0 or nothing for falsey values.

\$\endgroup\$
1
  • \$\begingroup\$ You can save some bytes at the beginning: $r+=$_*(-1,2..9)[$i++]for reverse@F. Also, -F -pe (and input supplied without final newline, with echo -n for instance) is enough (unless your Perl is too old, in which case you'll need -a (but on recent Perls, it's implied by -F). Finally, your code was 70 bytes long, not 52 ;) \$\endgroup\$
    – Dada
    Jan 12, 2017 at 21:27
3
\$\begingroup\$

C++14, 107 106 bytes

-1 byte for int instead of auto in for loop.

As unnamed lambda returning via reference parameter. Requires input to be std::string or a container of char, like vector<char>.

[](auto c,int&r){int i=c.size();r=7<i&&i<10?-2*c.back()+96:~1<<9;for(int x:c)r+=(x-48)*i--;r=r%11<1&&r>0;}

Ungolfed and usage:

#include<iostream>
#include<string>

auto f=
[](auto c, int& r){
 int i = c.size();
 //if the size is correct, init r to -2*I so we can add I safely later
 //otherwise such a big negative number, that the final test fails
 r = 7<i && i<10 ? -2*c.back()+96 : ~1<<9;
 for (auto x:c)
  r += (x-48)*i--;
 r = r%11<1 && r>0;
}
;

using namespace std;
using namespace std::literals;

int main(){
 int r;
 f("111222333"s,r); std::cout << r << std::endl;
 f("123456782"s,r); std::cout << r << std::endl;
 f("010464554"s,r); std::cout << r << std::endl;
 f("10464554"s,r); std::cout << r << std::endl;
 f("44016773"s,r); std::cout << r << std::endl;
 std::cout << std::endl;
 f("000000000"s,r); std::cout << r << std::endl;
 f("192837465"s,r); std::cout << r << std::endl;
 f("73"s,r); std::cout << r << std::endl;
 f("88888888"s,r); std::cout << r << std::endl;
 f("3112222342"s,r); std::cout << r << std::endl;
 std::cout << std::endl;
 f("99999999"s,r); std::cout << r << std::endl;
 f("999999999"s,r); std::cout << r << std::endl;
}
\$\endgroup\$
3
\$\begingroup\$

Jelly, 21 bytes

V€U×JN1¦µL:2=4×Sµ11ḍa

TryItOnline! or run all test cases

Truthy return values are non-zero (and are, in fact, the multiple of 11 sum).

How?

V€U×JN1¦µL:2=4×Sµ11ḍa - Main link: string of digits  e.g. "111222333"
V€                    - eval each - effectively cast each to an integer (keeps leading zeros)
  U                   - upend                        e.g. [ 3, 3, 3, 2, 2, 2, 1, 1, 1]
    J                 - range(length)                e.g. [ 1, 2, 3, 4, 5, 6, 7, 8, 9]
   ×                  - multiply                     e.g. [ 3, 6, 9, 8,10,12, 7, 8, 9]
      1¦              - apply to index 1 (first element)
     N                -     negate                   e.g. [-3, 6, 9, 8,10,12, 7, 8, 9]
        µ             - monadic chain separation   e.g. z=[-3, 6, 9, 8,10,12, 7, 8, 9]
         L            - length(z)                    e.g. 9
          :2          - integer divide by 2          e.g. 4
            =4        - equals 4?                    e.g. 1
               S      - sum(z)                       e.g. 66
              ×       - multiply                     e.g. 66
                µ     - monadic chain separation   e.g. z=66
                 11ḍ  - divides(11, z)               e.g. 1
                    a - and z (for z=0 case)         e.g. 66 (truthy)
\$\endgroup\$
2
  • \$\begingroup\$ Unfortunately I can only accept one answer instead of two, since yours has the same 21 byte-count as @Emigna's 05AB1E answer. But since Enigma answered sooner (and his edit for 21 bytes was also sooner) I've accepted his. \$\endgroup\$ Jun 29, 2017 at 11:54
  • \$\begingroup\$ That sounds fair to me! \$\endgroup\$ Jun 29, 2017 at 14:50
3
\$\begingroup\$

Befunge, 72 bytes

>+~>:0`v
^1\-*68_\2/4-!00p*8>1-10p\910gv
@.!+!\%+56:*g00$  _^#!:g01+*-<<

Try it online!

Explanation

>+~>:0`v            Read characters from stdin until EOF, converting each digit into
^1\-*68_              a number on the stack, and keeping a count of the characters read.

      \2/4-!00p     Save !(count/2-4), which is only true for valid lengths (8 and 9).
               *    Multiply the EOF (-1) with the final digit; this is the initial total.

8>1-10p\910gv       Loop over the remaining 8 digits, multiplying each of them by 9-i and
 ^#!:g01+*-<<         add to the total; i goes from 7 down to 0, so 9-i goes from 2 to 9.

               $    Drop the loop counter.
           *g00     Multiply total by the length calculation (invalid lengths become 0).
      %+65:         Make a copy of the total, and calculate modulo 11.
    !\              Boolean not the other copy to check for zero. 
  !+                !(total%11 + !(total)) is only true for non-zero multiples of 11.
@.                  Output the result and exit.
\$\endgroup\$
3
\$\begingroup\$

MATL, 36 bytes

Not the longest MATL program I've ever written, but I like how if/else statements get very lengthy very quickly in golfing languages. I feel that this solution may not be optimal in MATL, but as of yet I can't optimize it any further. I'm thinking of using the double 0 somewhere, and maybe cut down on the t's everywhere.

48-tn8=?0wh]tn9=?P[a2:9]*st11\~Y&}x0

Try it online! Explanation:

48-                                  % Subtract 48 (ASCII '0')
   tn                                % Duplicate. Get length.
     8=?                             % If length equals 8
        0wh                          %     Prepend 0 to the duplicate
           ]                         % End if.
            t                        % Duplicate again.
             n9=?                    % If length equals 9.
                 P                   %     Reverse the duplicate
                  [a2:9]*            %     Element-wise product with [-1 2 ... 9]
                         s           %     Sum
                          t11\       %     Duplicate sum, modulus 11
                              ~Y&    %     Result on stack: modulus==0 AND sum!=0
                                 }   % Else
                                  x0 %     Remove the duplicate. Put 0 on stack.
                                     % Display implicitly.
\$\endgroup\$
3
  • \$\begingroup\$ If you can make do with a column vector: !U instead of 48- \$\endgroup\$
    – Luis Mendo
    Dec 8, 2016 at 15:28
  • \$\begingroup\$ Beat ya :-P \$\endgroup\$
    – Luis Mendo
    Dec 8, 2016 at 15:42
  • \$\begingroup\$ @LuisMendo Too bad. [a2:9]* results in a non-element-wise multiplication, so another ! would be needed which would offset the initial gain. \$\endgroup\$
    – Sanchises
    Dec 8, 2016 at 15:43
3
\$\begingroup\$

PowerShell v2+, 96 bytes

param($n)$i=8-($n.count-eq8);!(($b=($n|%{(-"$_",(($i+1)*+"$_"))[!!$i--]})-join'+'|iex)%11)-and$b

OK, I'll admit, this looks like a complete mess. And it kinda is. But, bear with me and we'll get through it.

We take input $n (as a char-array) and set $i equal to 8 minus a Boolean value for whether there are 8 items in $n. Meaning, if there are 8 items, then $i would be 7.

The next section combines the calculation with our output. Working from the inside, we loop through $n with $n|%{...}. Each iteration, we use a pseudo-ternary to come up with one of two results -- either -"$_" or (($i+1)*+"$_"). The index is based on whether $i is 0 or not (i.e., we've hit the -1xI case from the challenge equation), which gets post-decremented for the next go-round. Those are all gathered up in parens and -joined together with +. For example, with input 111222333 at this point we'd have 9+8+7+12+10+8+9+6+-3. That is piped to iex (short for Invoke-Expression and similar to eval) before being stored into $b. We then take that %11 and perform a Boolean-not !(...) on that (i.e., so if it is divisible by 11, this portion is $true). That's coupled with -and$b to ensure that $b is non-zero. That Boolean result is left on the pipeline and output is implicit.

Examples

PS C:\Tools\Scripts\golfing> 111222333,123456782,232262536,010464554,10464554,44016773|%{"$_ -> "+(.\dutch-burgerservicenummer.ps1 ([char[]]"$_"))}
111222333 -> True
123456782 -> True
232262536 -> True
10464554 -> True
10464554 -> True
44016773 -> True

PS C:\Tools\Scripts\golfing> 000000000,192837465,247594057,88888888,73,3112223342,000000012|%{"$_ -> "+(.\dutch-burgerservicenummer.ps1 ([char[]]"$_"))}
0 -> False
192837465 -> False
247594057 -> False
88888888 -> False
73 -> False
3112223342 -> False
12 -> False
\$\endgroup\$
3
\$\begingroup\$

MATL, 26 bytes

!UGg*R!s0&)s-t11\~Gn8-tg=v

The result is a non-empty column vector, which is truthy iff all its entries are nonzero.

Try it online!

Or verify all test cases with each result on a different line.

Explanation

This tests the three conditions in the following order:

  1. Weighted sum is nonzero;
  2. Weighted sum is dividible by 11;
  3. Length is 8 or 9.

Consider input '8925' for the explanation. ; is the row separator for matrices.

!     % Implicit input. Transpose into a column vecvtor
      % STACK: ['8'; '9'; '2'; '5']
U     % Convert each digit to number
      % STACK: [8; 9; 2; 5]
Gg    % Push a row array of ones as long as the input
      % STACK: [8; 9; 2; 5], [1 1 1 1]
*     % Multiply, element-wise with broadcast
      % STACK: [8 8 8 8; 9 9 9 9; 2 2 2 2; 5 5 5 5]
R     % Upper triangular part
      % STACK: [8 8 8 8; 0 9 9 9; 0 0 2 2; 0 0 0 5]
!     % Transpose
      % STACK: [8 0 0 0;8 9 0 0;8 9 2 0;8 9 2 5]
s     % Sum of each column. This multiplies last element by 1, second-last by 2 etc
      % STACK: [32 27 4 5]
0&)   % Split into last element and remaining elements
      % STACK: 5, [32 27 4]
s     % Sum of array
      % STACK: 5, 63
-     % Subtract
      % STACK: -58. This is the result of condition 1
t11\  % Duplicate. Modulo 11
      % STACK: -58, 8
~     % Logical negation
      % STACK: -58, 0. This gives condition 2
Gn    % Push numnber of entries in the input
      % STACK: -58, 0, 4
8-    % Subtract 8. For valid lengths (8 or 9) this gives 0 or 1
      % STACK: -58, 0, -4
tg    % Duplicate. Convert to logical: set nonzero values to 1
      % STACK: -58, 0, -4, 1
=     % 1 if equal, 0 otherwise. Lenghts 8 or 9 will give 1. This is condition 3
      % STACK: -58, 0, 0
v     % Vertically concatenate the entire stack. This is truthy iff all values 
      % are non-zero. Implicitly display
      % STACK: [-58; 0; 0]
\$\endgroup\$
4
  • \$\begingroup\$ Well done. I figured that an approach without ? would probably be more efficient, but I couldn't figure out how to shorten the length 8 or 9. Your Gn8-tg= is very clever. \$\endgroup\$
    – Sanchises
    Dec 8, 2016 at 15:55
  • 1
    \$\begingroup\$ By the way, wouldn't a column vector input qualify as a char-array representing the BSN, saving you the first !? \$\endgroup\$
    – Sanchises
    Dec 9, 2016 at 14:28
  • \$\begingroup\$ @Sanchises The problem is that then G pushes a column vector and I need to transpose it to do the repetition with g* \$\endgroup\$
    – Luis Mendo
    Dec 9, 2016 at 16:58
  • \$\begingroup\$ Oh right of course. Never mind! \$\endgroup\$
    – Sanchises
    Dec 9, 2016 at 17:30
3
\$\begingroup\$

Haskell, 116 112 102 bytes

f x=div(length x)2==4&&g x>0&&h x
h=((==0).(`mod`11)).g
g=sum.zipWith(*)(-1:[2..]).map(read.(:[])).reverse

g counts the sum used in the eleven-proef of h, while f also checks for the correct length and that the eleven-proef is not 0. Especially the checks of f take a lot of bytes.

EDIT: saved 10 bytes thanks to Lynn and div rounding down.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ How about f x=div(length x)2==4&&g x>0&&h x? \$\endgroup\$
    – Lynn
    Dec 8, 2016 at 17:53
  • \$\begingroup\$ @Lynn: that is a nice one, thanks. \$\endgroup\$
    – Renzeee
    Dec 9, 2016 at 7:50
3
\$\begingroup\$

PHP 139 128 bytes

 $u=-1;$i=$argv[1];while($u<=strlen($i)){$c+=($u*(substr($i,-(abs($u)),1)));$u +=$u<0?3:1;}echo($c>0&&!($c%11)&&$u>8&&$u<11?1:0);

Could not get the CLI to just echo the true of false. Had to make do it this way. Any ideas?

128 bytes: Turned "true" and "false" to 1 and 0.

\$\endgroup\$
3
\$\begingroup\$

Python 3.8 (pre-release), 111 110 104 bytes

-1 byte thanks to @Kevin-cruijssen

-6 bytes by reading the rules (yay)

lambda s:len(s)in(8,9)and not(x:=sum(a:=[*map(lambda n,m:int(n)*m,s[::-1],range(1,10))])-2*a[0])%11and x

Try it online!

There's probably more golfing to do, but this is what I have for now.

\$\endgroup\$
1
  • \$\begingroup\$ You can remove the space at 11and for -1 byte. :) \$\endgroup\$ Oct 18, 2021 at 6:31
2
\$\begingroup\$

Python 2, 102 bytes

def f(i):S=sum(a*b for a,b in zip([-1]+range(2,10),map(int,i)[::-1]));return(7<len(i)<10)*(S%11<1)*S>0
\$\endgroup\$
2
\$\begingroup\$

Python 2, 96 bytes

def g(s):u=7<len(s)<10and sum(x*int(('0'+s)[-x])for x in range(2,10))-int(s[-1]);print(u%11<1)*u

Takes a string as input. The function adds a '0' to the front of the string whether it needs it or not, and uses Python's negative indices to add elements, starting from the end of the string and working back-to-front.

The -1xI is handled separately, using a second call to int(). I couldn't figure out how to avoid this without costing more bytes than I saved.

def g(s):u=7<len(s)<10and sum(x*int(('0'+s)[-x])for x in range(10))-2*int(s[-1]);print(u%11<1)*u would work just as well, since it would add 1 times s[-1] but then subtract it twice, and it would also add 0 times (something) which of course wouldn't affect the sum.

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

Brain-Flak, 345 Bytes

Includes +3 for -a

([]){{}({}[((((()()()){}){}){}){}]<>)<>([])}{}<>([][(()()()()){}]){({}[()]){([]){{}{}([])}}}{}([{}])({}({}){})({}({})({}){})({}(({}){}){})({}(({})({})){}{})({}(({})({}){}){})({}((({}))({}){}){}{})({}((({}){}){}){})(({}(((({})){}){}){}{}{}<(((()()())()){}{})>)){{}({}(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]{}[{}]<(())>){((<{}{}>))}{}(<()>)}{}

Truthy is 1, Falsy has a 0 on the top of the stack.

Try it Online!

I'm pretty sure there is a shorter way to do the multiplication in a loop, but I haven't found it yet.

#reverse and subtract 48 from all numbers (ASCII -> decimal)
([]){{}({}[((((()()()){}){}){}){}]<>)<>([])}{}<> 

([][(()()()()){}])       #height - 8
{({}[()]){               #if not 0 subtract 1
   ([]){{}{}([])}        #if still not 0 pop everything
}}{}                     #this loop pops everything unless there are 8 or 9 digits

([{}])                   # -I
({}({}){})               # H*2
({}({})({}){})           # G*3
({}(({}){}){})           # F*4
({}(({})({})){}{})       # E*5
({}(({})({}){}){})       # D*6
({}((({}))({}){}){}{})   # C*7
({}((({}){}){}){})       # B*8
(({}(((({})){}){}){}{}{} # A*9 pushed twice with:
<(((()()())()){}{})>))   # 11 under it


{{} #if not 0
({}(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]{}   # mod 11
[{}]<(())>){((<{}{}>))}{}                       # logical not
(<()>)                                          # push 0 to exit loop
}{}
                                                # implicit print
\$\endgroup\$
2
\$\begingroup\$

C#, 120 115 bytes

This loops through the char[] it receives as input and returns true or false:

bool b(char[]n){int r=0,k,i=0,l=n.Length;for(;i<l;i++){k=i==l-1?-1:l-i;r+=k*(n[i]-48);}return r>0&r%11<1&l<10&l>7;}

Fiddle: https://dotnetfiddle.net/3Kaxrt

I'm sure I can scrape out a few bytes, especially in the messy return. Any ideas welcome!

Edit: Saved 5 bytes thanks to Kevin. I had no idea I could use & instead of &&!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ +1! r>0&&r%11==0&&l<10&&l>7 can be golfed to r>0&r%11<1&l<10&l>7 (&& to & and r%11==0 to r%11<1). And -'0' can be golfed to -48. \$\endgroup\$ Dec 9, 2016 at 7:56
2
\$\begingroup\$

PHP, 86 85 84 83 82 79 bytes

Note: uses PHP 7.1 for negative string indices.

for($l=log10($a=$argn);~$c=$a[-++$x];)$s+=$x>1?$x*$c:-$c;echo$s%11<1&$l>7&$l<9;

Run like this:

echo 010464554 | php -nR 'for($l=log10($a=$argn);~$c=$a[-++$x];)$s+=$x>1?$x*$c:-$c;echo$s%11<1&$l>7&$l<9;';echo
> 1

Version for PHP < 7.1 (+10 bytes)

echo 010464554 | php -nR 'for($l=log10($a=$argn);~$c=$a[strlen($a)-++$x];)$s+=$x>1?$x*$c:-$c;echo$s%11<1&$l>7&$l<9;';echo

Explanation

for(
  $l=log10(         # Take the log of the input number.
    $a=$argn        # Set input to $a
  );
  ~$c=$a[-++$x];    # Iterate over digits of input (reverse). Negate to
                    # change every char to extended ASCII (all truthy),
                    # without changing empty sting (still falsy, ending
                    # the loop).
)
  $s+=$x>1?         # Add current char to the sum...
     ?$x*$c:-$c;    # multiplied by $x, unless $x is 1; subtract it.
echo
  $s%11<1 &         # Check if sum is divisible by 11, and
  $l>7   &          # log of the input is greater than 7, and
  $l<9;             # log of the input is less than 9. Outputs 0 or 1.

Tweaks

  • Shorter way to distinguish between empty string and "0", saved a byte
  • Since 10000000 is invalid, no need to compare with greater than or equals, greater than suffices, saving a byte
  • Shorter way to subtract least significant digit
  • Negate char instead of XOR, saving a byte
  • Saved 3 bytes by using -R to make $argn available
\$\endgroup\$
2
\$\begingroup\$

Java 8, 115 98 94 bytes

b->{int l=b.length,i=l,r=0;for(;l>7&l<10&i-->0;)r-=(b[i]-48)*(l-i<2?1:i-l);return r>0&r%11<1;}

I'm surprised no one has posted a Java answer yet, so here is one.

-4 bytes thanks to @ceilingcat.

Explanation:

Try it here.

b->{                // Method with character-array as parameter and boolean return-type
  int l=b.length,   //  Length of the array
      i=l,          //  Index-integer, starting at this length
      r=0;          //  The result-sum, starting at 0
  for(;l>7&l<10     //  Start looping if the length is either 8 or 9
       &i-->0;)     //  And continue looping downwards while the index is larger than 0
      r-=           //   Decrease the result-sum by:
         (b[i]-48)  //    The current digit
         *(         //    Multiplied by:
           l-i<2?   //     If `l-i` is 1:
            1       //      Simply multiply by 1
           :        //     Else:
            i-l);   //      Multiply by `i-l`
  return r>0        //  Return if the result-sum is larger than 0,
    &r%11<1;}       //   and if the result-sum is divisible by 11
\$\endgroup\$
0
2
\$\begingroup\$

Ly, 58 bytes

iy9L[r'0r!]ppry9=[pp8[f'0-srlrpsrl`*r,]p'0-N&+[92+%!u;]]u;

Try it online!

I thought this would be shorter... There's probably room for improvement?

First part, input digits, pad with leading 0 if necessary

i              - input all digits (as codepoints)
 y             - push the stack size onto the stack
  9L[    !]p   - if/then block, true if <9 digits
     r'0r      - reverse stack, push 0, reverse again
            p  - pop the stack size entry off the stack

Second part, only process digits if we end up with 9 digits

r              - reverse the stack
 y             - push the stack size info the stack
  9=[pp ... ]  - if/then block, true if stack size is 9

Third part, process the first 8 digits

8[               ,]p - loop 8 times
  f                  - bring digit forward
   '0-               - convert from char to int
      s              - save digit value
       rl            - copy digit to bottom of stack
         rp          - delete from top of stack
           s         - save current loop var
            rl       - copy to bottom of stack
              `      - increment by one
               *     - multiple with current digit
                r    - reverse stack

Fourth part, process last digit, sum results

'0-     - convert digit from char to int
   N    - negate
    &+  - sum all entries on the stack

Fifth part, "is it zero?" and "is divisible by 11?" checks

[       ]   - if/then block, true is sum is non-zero
 92+        - push 11 onto the stack
    %!      - modulo math to get remainder, invert the result
      u;    - print top of stack as int, then exit

Last part, prints "falsey" if some success criteria wasn't met

u;  - print top of stack (which will be 0) and exit

AWK, 88 bytes

$0="0"$0,n=gsub(a," ")-1{b=n-9;c=9}!b||b==1{for(d-=$n;++b<n;e=d%11)d+=$b*c--}1,$0=!e*!!d

Try it online!

And one I had fun golfing, just to abuse the flexibility of AWK.

$0="0"$0                             - append "0" to the input
           gsub(a," ')-1             - re-parse the input, one char per arg
        ,n=           -1             - set "n", decr RC to get number of chars
                        {         }  - code block...
                         b=n-9;      - set "b" to first char to use
                               c=9   - set "c" to initial multiplier val

!b||b==l                                   - true is we got 8 or 9 chars
        {                                } - code block...
         for(                  )           - loop over initial 8 chars
             d-=$n;                        - init: "d" set to neg of last digit
                   ++b<n;                  - test: ends after 8 chars processed
                         e=d%11            - loop-end: "e" is remainder of "%11"
                                d+=$b*c--  - loop-code: multiply and add next digit

1,           - unconditionally run implicit "print $0" code block
  $0=!e*!!d  - "$0" is 1 if accum value is non-zero and divisible by 11
\$\endgroup\$
2
\$\begingroup\$

K (ngn/k), 42 41 bytes

-1 byte from @ngn's improvements

{(4=-2!#x)&t&~11!t:+/(|-1,2+!8)*-9#0,.'x}

Try it online!

Takes the input as a list of characters.

  • .'x convert each digit to its integer (e.g. convert "123" to 1 2 3)
  • -9#0, prepend a 0, then take the last nine values (handles padding 8-digit codes, and avoids errors on input that is not 9 digits long)
  • (|-1,2+!8)* generate 9 8 7 6 5 4 3 2 -1, and multiply the parsed digits by this
  • t:+/ take the sum, storing in variable t
  • t&~11!t check that 11 evenly divides t, and that t is non-zero
  • (4=-2!#x)& also check that the input is 8 or 9 characters long (literally: the length of the input (integer) divided by 2 is equal to 4)
\$\endgroup\$
1
  • 1
    \$\begingroup\$ |/8 9= -> 4=-2! \$\endgroup\$
    – ngn
    Oct 27, 2021 at 19:32
2
\$\begingroup\$

Ruby, 65 bytes

-1 byte thanks to Kevin Cruijssen

->n{a,*b=n.to_i.digits
i=1
b[6]&&(b[..7].sum{_1*i+=1}-a)%11<1||p}

Attempt This Online!

\$\endgroup\$
5
  • \$\begingroup\$ @KevinCruijssen Thanks. I've updated my answer. \$\endgroup\$
    – Jordan
    Nov 7, 2022 at 16:33
  • 1
    \$\begingroup\$ Looking good now, +1 from me. :) Also, I think you can change the ==0 to <1 for -1 byte. :) \$\endgroup\$ Nov 7, 2022 at 18:06
  • \$\begingroup\$ Don't forget about $. for int vars, -1 byte \$\endgroup\$
    – south
    Nov 8, 2022 at 4:13
  • \$\begingroup\$ @south I’m told that’s invalid in function submissions because it’s not reusable. See comments here: codegolf.stackexchange.com/posts/comments/563313?noredirect=1 \$\endgroup\$
    – Jordan
    Nov 8, 2022 at 4:17
  • \$\begingroup\$ @Jordan My understanding might be a little flawed then. Maybe I am making too many assumptions with standard I/O. Will look into it, thanks. \$\endgroup\$
    – south
    Nov 8, 2022 at 4:20
1
\$\begingroup\$

Clojure, 114 bytes

Well this is something, - substracts the rest of the arguments from the first one so that handles the special case of weight -1. This function returns nil for inputs of invalid length, but on if clauses they operate the same as false. (#{8 9}(count v)) returns nil if length of v is not 8 or 9.

(fn[v](if(#{8 9}(count v))(#(and(< % 0)(=(mod % 11)0))(apply -(map *(range 1 10)(reverse(map #(-(int %)48)v)))))))

Test cases:

(pprint (group-by f (map str [123456782 232262536 "010464554" 10464554 44016773 "000000000" 192837465 247594057 88888888 73 3112223342 "000000012"])))
{true  ["123456782" "232262536" "010464554" "10464554" "44016773"],
 false ["000000000" "192837465" "247594057" "88888888" "000000012"],
 nil   ["73" "3112223342"]}
\$\endgroup\$
1
\$\begingroup\$

Perl 5, 63 + 2 (-F) = 65 bytes

$F[-1]*=-1;map$s+=++$i*$_,reverse@F;say/^.{8,9}$/&&$s&&!($s%11)

Try it online!

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

Stax, 23 bytes

╪╦µΘç}<╔▼◘╞i∟~¿≥←║▐√ 4u

Run and debug online!

Explanation

Uses the unpacked version to explain.

i%8A:byr{]ei^*mBN+|+c11%!L|A
i                               Suppress implicit eval
 %8A:b                          Length is 8 or 9 (Element #1 on the final stack)
      yr                        Reverse input
        {     m                 Map each element with
         ]e                         Its numerical value
           i^*                      Multiplied current 1-based loop index
               BN+              Negate the first element
                  |+            Sum (Element #2 on the final stack)
                    c11%!       Sum is multiple of 11 (Element #3 on the final stack)
                         L|A    Collect all the three elements and `and` them.
\$\endgroup\$
1
  • \$\begingroup\$ -1 \$\endgroup\$
    – Razetime
    May 16, 2021 at 8:31
1
\$\begingroup\$

Python 3.8, 96 bytes

lambda i:7<len(i)<10*((S:=sum(a*b for a,b in zip([-1,*range(2,10)],map(int,i[::-1]))))%11<1)*S>0

Try it online!

Similar to @TFeld's Python 2 answer, but uses Python 3.8 assignment expressions and a few other tricks to get it down to 96 bytes.

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

TI-Basic, 60 bytes

max(length(Ans)={8,9})sum(seq(int(10fPart(expr(Ans)/₁₀^(I)))(I-2(I=1)),I,1,9
not(fPart((Ans+not(Ans))/11

Takes input in Ans as a string. Output is stored in Ans and is displayed.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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