2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -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 are: 1210, 2020, 21200, 3211000, 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>
|
||||
|
|
|
|||
94
Task/Self-describing-numbers/C/self-describing-numbers-5.c
Normal file
94
Task/Self-describing-numbers/C/self-describing-numbers-5.c
Normal 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("");
|
||||
}
|
||||
}
|
||||
38
Task/Self-describing-numbers/C/self-describing-numbers-6.c
Normal file
38
Task/Self-describing-numbers/C/self-describing-numbers-6.c
Normal 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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
Test-SelfDescribing -Number 2020
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
11,2020,21200,321100 | ForEach-Object {
|
||||
[PSCustomObject]@{
|
||||
Number = $_
|
||||
IsSelfDescribing = Test-SelfDescribing -Number $_
|
||||
}
|
||||
} | Format-Table -AutoSize
|
||||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue