2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -2,15 +2,18 @@ There are several so-called "self-describing" or "[[wp:Self-descriptive number|s
An integer is said to be "self-describing" if it has the property that, when digit positions are labeled 0 to N-1, the digit in each position is equal to the number of times that that digit appears in the number.
For example, 2020 is a four-digit self describing number:
For example,   '''2020'''   is a four-digit self describing number:
* position 0 has value 2 and there are two 0s in the number;
* position 1 has value 0 and there are no 1s in the number;
* position 2 has value 2 and there are two 2s;
* position 3 has value 0 and there are zero 3s.
*   position   0   has value   2   and there are two 0s in the number;
*   position   1   has value   0   and there are no 1s in the number;
*   position   2   has value   2   and there are two 2s;
*   position   3   has value   0   and there are zero 3s.
<br>
Self-describing numbers < 100.000.000&nbsp; are: &nbsp; &nbsp; 1210, &nbsp; 2020, &nbsp; 21200, &nbsp; 3211000, &nbsp; 42101000.
Self-describing numbers < 100.000.000: 1210, 2020, 21200, 3211000, 42101000.
;Task Description
# Write a function/routine/method/... that will check whether a given positive integer is self-describing.
# As an optional stretch goal - generate and display the set of self-describing numbers.
<br><br>

View file

@ -0,0 +1,94 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BASE_MIN 2
#define BASE_MAX 94
void selfdesc(unsigned long);
const char *ref = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
char *digs;
unsigned long *nums, *inds, inds_sum, inds_val, base;
int main(int argc, char *argv[]) {
int used[BASE_MAX];
unsigned long digs_n, i;
if (argc != 2) {
fprintf(stderr, "Usage is %s <digits>\n", argv[0]);
return EXIT_FAILURE;
}
digs = argv[1];
digs_n = strlen(digs);
if (digs_n < BASE_MIN || digs_n > BASE_MAX) {
fprintf(stderr, "Invalid number of digits\n");
return EXIT_FAILURE;
}
for (i = 0; i < BASE_MAX; i++) {
used[i] = 0;
}
for (i = 0; i < digs_n && strchr(ref, digs[i]) && !used[digs[i]-*ref]; i++) {
used[digs[i]-*ref] = 1;
}
if (i < digs_n) {
fprintf(stderr, "Invalid digits\n");
return EXIT_FAILURE;
}
nums = calloc(digs_n, sizeof(unsigned long));
if (!nums) {
fprintf(stderr, "Could not allocate memory for nums\n");
return EXIT_FAILURE;
}
inds = malloc(sizeof(unsigned long)*digs_n);
if (!inds) {
fprintf(stderr, "Could not allocate memory for inds\n");
free(nums);
return EXIT_FAILURE;
}
inds_sum = 0;
inds_val = 0;
for (base = BASE_MIN; base <= digs_n; base++) {
selfdesc(base);
}
free(inds);
free(nums);
return EXIT_SUCCESS;
}
void selfdesc(unsigned long i) {
unsigned long diff_sum, upper_min, j, lower, upper, k;
if (i) {
diff_sum = base-inds_sum;
upper_min = inds_sum ? diff_sum:base-1;
j = i-1;
if (j) {
lower = 0;
upper = (base-inds_val)/j;
}
else {
lower = diff_sum;
upper = diff_sum;
}
if (upper < upper_min) {
upper_min = upper;
}
for (inds[j] = lower; inds[j] <= upper_min; inds[j]++) {
nums[inds[j]]++;
inds_sum += inds[j];
inds_val += inds[j]*j;
for (k = base-1; k > j && nums[k] <= inds[k] && inds[k]-nums[k] <= i; k--);
if (k == j) {
selfdesc(i-1);
}
inds_val -= inds[j]*j;
inds_sum -= inds[j];
nums[inds[j]]--;
}
}
else {
for (j = 0; j < base; j++) {
putchar(digs[inds[j]]);
}
puts("");
}
}

View file

@ -0,0 +1,38 @@
$ time ./selfdesc.exe 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
1210
2020
21200
3211000
42101000
521001000
6210001000
72100001000
821000001000
9210000001000
A2100000001000
B21000000001000
C210000000001000
D2100000000001000
E21000000000001000
F210000000000001000
G2100000000000001000
H21000000000000001000
I210000000000000001000
J2100000000000000001000
K21000000000000000001000
L210000000000000000001000
M2100000000000000000001000
N21000000000000000000001000
O210000000000000000000001000
P2100000000000000000000001000
Q21000000000000000000000001000
R210000000000000000000000001000
S2100000000000000000000000001000
T21000000000000000000000000001000
U210000000000000000000000000001000
V2100000000000000000000000000001000
W21000000000000000000000000000001000
real 0m0.094s
user 0m0.046s
sys 0m0.030s

View file

@ -0,0 +1,11 @@
defmodule Self_describing do
def number(n) do
digits = Integer.digits(n)
Enum.map(0..length(digits)-1, fn s ->
length(Enum.filter(digits, fn c -> c==s end))
end) == digits
end
end
m = 3300000
Enum.filter(0..m, fn n -> Self_describing.number(n) end)

View file

@ -0,0 +1,12 @@
function Test-SelfDescribing ([int]$Number)
{
[int[]]$digits = $Number.ToString().ToCharArray() | ForEach-Object {[Char]::GetNumericValue($_)}
[int]$sum = 0
for ($i = 0; $i -lt $digits.Count; $i++)
{
$sum += $i * $digits[$i]
}
$sum -eq $digits.Count
}

View file

@ -0,0 +1 @@
Test-SelfDescribing -Number 2020

View file

@ -0,0 +1,6 @@
11,2020,21200,321100 | ForEach-Object {
[PSCustomObject]@{
Number = $_
IsSelfDescribing = Test-SelfDescribing -Number $_
}
} | Format-Table -AutoSize

View file

@ -1,39 +1,26 @@
/*REXX program checks if a number (base 10) is self-describing, */
/* self-descriptive, */
/* autobiographical, or */
/* a curious number. */
/* */
/* Also see: http://oeis.org/A046043 */
/* and: http://oeis.org/A138480 */
/*REXX program determines if a number (in base 10) is a self─describing, */
/*────────────────────────────────────────────────────── self─descriptive, */
/*────────────────────────────────────────────────────── autobiographical, or a */
/*────────────────────────────────────────────────────── curious number. */
parse arg x y . /*obtain optional arguments from the CL*/
if x=='' | x=="," then exit /*Not specified? Then get out of Dodge*/
if y=='' | y=="," then y=x /* " " Then use the X value.*/
w=length(y) /*use Y's width for aligned output. */
numeric digits max(9, w) /*ensure we can handle larger numbers. */
if x==y then do /*handle the case of a single number. */
noYes=test_SDN(y) /*is it or ain't it? */
say y word("is isn't", noYes+1) 'a self-describing number.'
exit
end
parse arg x y . /*get args from the command line.*/
if x=='' then exit /*if no X, then get out of Dodge.*/
if y=='' then y=x /*if no Y, then use the X value. */
y=min(y,999999999)
w=length(y) /*use Y's width for pretty output*/
/*══════════════════════════════════════test for a single number. */
if x==y then do /*handle the case of a single #. */
noYes=test_sdn(y) /*is it or ain't it? */
say y word("is isn't",noYes+1) 'a self-describing number.'
exit
end
/*══════════════════════════════════════test for a range of numbers. */
do n=x to y
if test_sdn(n) then iterate /*if ¬ self-describing, try again*/
say right(n,w) 'is a self-describing number.' /*is it? */
do n=x to y
if test_SDN(n) then iterate /*if not self─describing, try again. */
say right(n,w) 'is a self-describing number.' /*is it? */
end /*n*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────TEST_SDN subroutine─────────────────*/
test_sdn: procedure; parse arg ?; L=length(?)
do j=L to 1 by -1 /*backwards is slightly faster. */
if substr(?,j,1)\==L-length(space(translate(?,,j-1),0)) then return 1
end /*j*/
return 0 /*faster if inverted truth table.*/
/* ┌──────────────────────────────────────────────────────────────────┐
The method used above is to TRANSLATE the digit being queried to
blanks, then use the SPACE bif function to remove all blanks,
and then compare the new number's length to the original length.
The difference in length is the number of digits translated.
This method works if there're no imbedded/leading/trailing blanks
(or other whitespace like tabs) in the number.
*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
test_SDN: procedure; parse arg ?; L=length(?) /*obtain the argument and its length.*/
do j=L to 1 by -1 /*parsing backwards is slightly faster.*/
if substr(?,j,1)\==L-length(space(translate(?,,j-1),0)) then return 1
end /*j*/
return 0 /*faster if used inverted truth table. */

View file

@ -1,21 +1,19 @@
/*REXX program checks if a number (base 10) is self-describing */
parse arg x y . /*get args from the command line.*/
if x=='' then exit /*if no X, then get out of Dodge.*/
if y=='' then y=x /*if no Y, then use the X value. */
y=min(y,999999999)
w=length(y) /*use Y's width for pretty output*/
/*══════════════════════════════════════test for a single number. */
if x==y then do /*handle the case of a single #. */
noYes=test_sdn(y) /*is it or ain't it? */
say y word("is isn't",noYes+1) 'a self-describing number.'
exit
end
/*══════════════════════════════════════test for a range of numbers. */
do n=x to y
if test_sdn(n) then iterate /*if ¬ self-describing, try again*/
say right(n,w) 'is a self-describing number.' /*is it? */
/*REXX program determines if a number (in base 10) is a self-describing number.*/
parse arg x y . /*obtain optional arguments from the CL*/
if x=='' | x=="," then exit /*Not specified? Then get out of Dodge*/
if y=='' | y=="," then y=x /*Not specified? Then use the X value.*/
w=length(y) /*use Y's width for aligned output. */
numeric digits max(9, w) /*handle the possibility of larger #'s.*/
$= '1210 2020 21200 3211000 42101000 521001000 6210001000' /*the list of numbers.*/
/*test for a single integer. */
if x==y then do /*handle the case of a single number. */
say word("isn't is", wordpos(x, $) + 1) 'a self-describing number.'
exit
end
/* [↓] test for a range of integers.*/
do n=x to y; parse var n '' -1 _ /*obtain the last decimal digit of N. */
if _\==0 then iterate
if wordpos(n, $)==0 then iterate
say right(n,w) 'is a self-describing number.'
end /*n*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────TEST_SDN subroutine─────────────────*/
test_sdn: procedure; parse arg ?; if right(?,1)\==0 then return 1
return wordpos(?,'1210 2020 21200 3211000 42101000 521001000 6210001000')==0
/*stick a fork in it, we're all done. */

View file

@ -1,23 +1,17 @@
/*REXX program checks if a number (base 10) is self-describing */
parse arg x y . /*get args from the command line.*/
if x=='' then exit /*if no X, then get out of Dodge.*/
if y=='' then y=x /*if no Y, then use the X value. */
y=min(y,999999999)
w=length(y) /*use Y's width for pretty output*/
$='1210 2020 21200 3211000 42101000 521001000 6210001000' /*the list.*/
/*══════════════════════════════════════test for a single number. */
if x==y then do /*handle the case of a single #. */
noYes=test_sdn(y) /*is it or ain't it? */
say y word("is isn't",noYes+1) 'a self-describing number.'
exit
end
/*══════════════════════════════════════test for a range of numbers. */
do n=1 for words($) /*look for nums that are in range*/
_=word($,n)
if _<x | _>y then iterate /*if ¬ self-describing, try again*/
say right(_,w) 'is a self-describing number.' /*display it.*/
end /*n*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────TEST_SDN subroutine─────────────────*/
test_sdn: procedure expose $; parse arg ?
if right(?,1)\==0 then return 1; return wordpos(?,$)==0
/*REXX program determines if a number (in base 10) is a self-describing number.*/
parse arg x y . /*obtain optional arguments from the CL*/
if x=='' | x=="," then exit /*Not specified? Then get out of Dodge*/
if y=='' | y=="," then y=x /*Not specified? Then use the X value.*/
w=length(y) /*use Y's width for aligned output. */
numeric digits max(9, w) /*handle the possibility of larger #'s.*/
$= '1210 2020 21200 3211000 42101000 521001000 6210001000' /*the list of numbers.*/
/*test for a single integer. */
if x==y then do /*handle the case of a single number. */
say word("isn't is", wordpos(x, $) + 1) 'a self-describing number.'
exit
end
/* [↓] test for a range of integers.*/
do n=1 for words($); _=word($, n) /*look for integers that are in range. */
if _<x | _>y then iterate /*if not self-describing, try again. */
say right(_, w) 'is a self-describing number.'
end /*n*/ /*stick a fork in it, we're all done. */

View file

@ -1,14 +1,6 @@
def is_self_describing?(n)
digits = n.to_s.chars.collect {|digit| digit.to_i}
len = digits.length
count = Array.new(len, 0)
digits.each do |digit|
return false if digit >= len
count[digit] = count[digit] + 1
end
digits.eql?(count)
digits = n.to_s.chars.map(&:to_i)
digits.each_with_index.all?{|digit, idx| digits.count(idx) == digit}
end
3_300_000.times {|n| puts n if is_self_describing?(n)}