Strange numbers
- Definition
n is a strange number (expressed in base ten) if every adjacent decimal digit differs from its neighbour by a prime number.
- Task
Show all strange numbers for 100 < n < 500
- Stretch goal
Show the number of 10-digit strange numbers that begin with 1
11l
F is_strange(n)
V xs = String(n).map(c -> Int(c))
R all(zip(xs, xs[1..]).map((a, b) -> abs(a - b) C (2, 3, 5, 7)))
V xs = (100..500).filter(n -> is_strange(n))
print("\nStrange numbers in range [100..500]\n")
print(‘(Total: ’String(xs.len)")\n")
L(el) xs
print(el, end' ‘ ’)
I L.index % 10 == 9
print()
- Output:
Strange numbers in range [100..500] (Total: 87) 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
Action!
BYTE Func IsStrangeNumber(INT i)
BYTE ARRAY primes=[0 0 1 1 0 1 0 1 0 0]
BYTE d,diff,prev
prev=255
WHILE i#0
DO
d=i MOD 10
IF prev#255 THEN
IF prev>d THEN
diff=prev-d
ELSE
diff=d-prev
FI
IF primes(diff)=0
THEN RETURN (0)
FI
FI
prev=d
i==/10
OD
RETURN (1)
PROC Main()
INT i,count=[0]
FOR i=101 TO 499
DO
IF IsStrangeNumber(i) THEN
PrintI(i) Put(32)
count==+1
FI
OD
PrintF("%E%EThere are %I strange numbers",count)
RETURN
- Output:
Screenshot from Atari 8-bit computer
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 There are 87 strange numbers
Ada
with Ada.Text_IO; use Ada.Text_IO;
procedure Strange_Numbers is
function Is_Strange (A : Natural) return Boolean is
Last : Natural := A mod 10;
Reminder : Natural := A / 10;
Current : Natural;
begin
while Reminder /= 0 loop
Current := Reminder mod 10;
exit when abs (Current - Last) not in 2 | 3 | 5 | 7;
Last := Current;
Reminder := Reminder / 10;
end loop;
return Reminder = 0;
end Is_Strange;
Count : Natural := 0;
begin
for A in 101 .. 499 loop
if Is_Strange (A) then
Put (A'Image);
Count := Count + 1;
if Count mod 10 = 0 then
New_Line;
end if;
end if;
end loop;
New_Line;
Put_Line ("Strange numbers in range 101 .. 499: " & Count'Image);
New_Line;
Count := 0;
for A in 1_000_000_000 .. 1_999_999_999 loop
if Is_Strange (A) then
Count := Count + 1;
end if;
end loop;
Put_Line ("Strange numbers in range 1_000_000_000 .. 1_999_999_999: " & Count'Image);
end Strange_Numbers;
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 Strange numbers in range 101 .. 499: 87 Strange numbers in range 1_000_000_000 .. 1_999_999_999: 853423
ALGOL 68
BEGIN # show some strange numbers - numbers whose digits differ by a prime #
# returns TRUE if n is strange, FALSE otherwise #
PROC is strange = ( INT n )BOOL:
BEGIN
INT d1 := ABS n MOD 10;
INT v := ABS n OVER 10;
BOOL strange := TRUE;
WHILE strange AND v > 0 DO
INT d2 = v MOD 10;
v OVERAB 10;
INT diff = ABS ( d1 - d2 );
strange := diff = 2 OR diff = 3 OR diff = 5 OR diff = 7;
d1 := d2
OD;
strange
END # is strange # ;
INT s count := 0;
FOR n FROM 101 TO 499 DO
IF is strange( n ) THEN
print( ( whole( n, -4 ) ) );
IF ( s count +:= 1 ) MOD 20 = 0 THEN print( ( newline ) ) FI
FI
OD
END
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
ALGOL W
begin % find "strange numbers" - numbers where digits differ from the next %
% by a prime %
% returns true if n is strange, false otherwise %
logical procedure isStrange( integer value n ) ;
begin
integer rest, d0;
logical strange;
rest := abs( n );
strange := true;
d0 := rest rem 10;
rest := rest div 10;
while strange and rest > 0 do begin
integer d1, diff;
d1 := rest rem 10;
rest := rest div 10;
diff := abs( d1 - d0 );
strange := diff = 2 or diff = 3 or diff = 5 or diff = 7;
d0 := d1
end while_strange_and_rest_gt_0 ;
strange
end isStrange ;
% test the isStrange procedure on values 101-499 %
begin
integer strangeCount;
strangeCount := 0;
for n := 101 until 499 do begin;
if isStrange( n ) then begin
strangeCount := strangeCount + 1;
if strangeCount rem 20 = 1
then write( i_w := 4, s_w := 0, n )
else writeon( i_w := 4, s_w := 0, n )
end if_isStrange_n
end for_n
end
end.
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
APL
(⊢(/⍨)(∧/2 3 5 7∊⍨2+/⍎¨∘⍕)¨) 100+⍳400
- Output:
111 112 114 116 120 121 123 125 141 143 161 202 203 205 207 211 212 214 216 230 232 234 250 252 302 303 305 307 320 321 323 325 341 343 411 412 414 416 430 432 434
AppleScript
--------------------- STRANGE NUMBERS --------------------
-- isStrange :: Int -> Bool
on isStrange(n)
set ds to digits(n)
script sumIsSmallPrime
on |λ|(a, b)
{2, 3, 5, 7} contains abs(a - b)
end |λ|
end script
zipWith(sumIsSmallPrime, ds, rest of ds) ¬
does not contain false
end isStrange
--------------------------- TEST -------------------------
on run
set xs to filter(isStrange, enumFromTo(100, 500))
intercalate("\n\n", ¬
{"Strange numbers found in range [100..500]", ¬
"Full list:", ¬
("(total " & (length of xs) as string) & ")", ¬
unlines(map(unwords, chunksOf(10, map(str, xs))))})
end run
------------------------- GENERIC ------------------------
-- abs :: Num -> Num
on abs(x)
-- Absolute value.
if 0 > x then
-x
else
x
end if
end abs
-- chunksOf :: Int -> [a] -> [[a]]
on chunksOf(k, xs)
script
on go(ys)
set ab to splitAt(k, ys)
set a to item 1 of ab
if {} ≠ a then
{a} & go(item 2 of ab)
else
a
end if
end go
end script
result's go(xs)
end chunksOf
-- digits :: Int -> [Int]
on digits(n)
script go
on |λ|(x)
x as integer
end |λ|
end script
map(go, characters of (n as string))
end digits
-- enumFromTo :: Int -> Int -> [Int]
on enumFromTo(m, n)
if m ≤ n then
set lst to {}
repeat with i from m to n
set end of lst to i
end repeat
lst
else
{}
end if
end enumFromTo
-- intercalate :: String -> [String] -> String
on intercalate(delim, xs)
set {dlm, my text item delimiters} to ¬
{my text item delimiters, delim}
set s to xs as text
set my text item delimiters to dlm
s
end intercalate
-- filter :: (a -> Bool) -> [a] -> [a]
on filter(p, xs)
tell mReturn(p)
set lst to {}
set lng to length of xs
repeat with i from 1 to lng
set v to item i of xs
if |λ|(v, i, xs) then set end of lst to v
end repeat
if {text, string} contains class of xs then
lst as text
else
lst
end if
end tell
end filter
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
-- 2nd class handler function lifted into 1st class script wrapper.
if script is class of f then
f
else
script
property |λ| : f
end script
end if
end mReturn
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
-- The list obtained by applying f
-- to each element of xs.
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min
-- splitAt :: Int -> [a] -> ([a], [a])
on splitAt(n, xs)
if n > 0 and n < length of xs then
if class of xs is text then
{items 1 thru n of xs as text, ¬
items (n + 1) thru -1 of xs as text}
else
{items 1 thru n of xs, items (n + 1) thru -1 of xs}
end if
else
if n < 1 then
{{}, xs}
else
{xs, {}}
end if
end if
end splitAt
-- str :: a -> String
on str(x)
x as string
end str
-- unlines :: [String] -> String
on unlines(xs)
-- A single string formed by the intercalation
-- of a list of strings with the newline character.
set {dlm, my text item delimiters} to ¬
{my text item delimiters, linefeed}
set s to xs as text
set my text item delimiters to dlm
s
end unlines
-- unwords :: [String] -> String
on unwords(xs)
set {dlm, my text item delimiters} to ¬
{my text item delimiters, space}
set s to xs as text
set my text item delimiters to dlm
return s
end unwords
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
on zipWith(f, xs, ys)
set lng to min(length of xs, length of ys)
set lst to {}
if 1 > lng then
return {}
else
tell mReturn(f)
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, item i of ys)
end repeat
return lst
end tell
end if
end zipWith
- Output:
Strange numbers found in range [100..500] Full list: (total 87) 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
Arturo
strange?: function [n][
digs: digits n
loop 1..dec size digs 'd [
if not? contains? [2 3 5 7] abs digs\[d] - digs\[d-1] ->
return false
]
return true
]
strangeNums: select 100..500 => strange?
print "Strange numbers in 100..500:"
loop split.every: 10 strangeNums 'x ->
print map x 's -> pad to :string s 4
- Output:
Strange numbers in 100..500: 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
AWK
# syntax: GAWK -f STRANGE_NUMBERS.AWK
BEGIN {
start = 100
stop = 500
for (i=start; i<=stop; i++) {
flag = 1
for (j=1; j<length(i); j++) {
if (!(is_prime(abs(substr(i,j,1)-substr(i,j+1,1))))) {
flag = 0
break
}
}
if (flag == 1) {
printf("%d%1s",i,++count%10?"":"\n")
}
}
printf("\nStrange numbers %d-%d: %d\n",start,stop,count)
exit(0)
}
function is_prime(x, i) {
if (x <= 1) {
return(0)
}
for (i=2; i<=int(sqrt(x)); i++) {
if (x % i == 0) {
return(0)
}
}
return(1)
}
function abs(x) { if (x >= 0) { return x } else { return -x } }
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 Strange numbers 100-500: 87
BASIC
FreeBASIC
function is_strange( n as ulongint ) as boolean
dim as uinteger d, ld, a
if n<10 then return true 'arbitrary, but makes the recursion easier
d = n mod 10
ld = (n mod 100) \ 10
a = abs(d - ld)
if a = 2 or a = 3 or a = 5 or a = 7 then return is_strange(n\10) else return false
end function
print "Strange numbers between 100 and 500"
for n as uinteger = 101 to 499
if is_strange(n) then print n;" ";
next n
print : print
dim as integer c = 0
for n as ulongint = 1000000000 to 1999999999
if is_strange(n) then c+=1
next n
print using "There are ####### 10-digit strange numbers beginning with 1.";c
- Output:
Strange numbers between 100 and 500 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
There are 853423 10-digit strange numbers beginning with 1.
GW-BASIC
10 REM Strange numbers
20 DEFINT I-K: DEFSTR S
30 FOR I = 100 TO 500
40 S = STR$(I)
50 FOR J = 2 TO LEN(S) - 1
60 K = ABS(VAL(MID$(S, J, 1)) - VAL(MID$(S, J + 1, 1)))
70 IF K <> 2 AND K <> 3 AND K <> 5 AND K <> 7 THEN 100
80 NEXT J
90 PRINT I,
100 NEXT I
110 END
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
BCPL
get "libhdr"
let dgtprime(x) = x=2 | x=3 | x=5 | x=7
let strange(x) =
x<10 -> true,
dgtprime(abs(x rem 10 - (x/10) rem 10)) & strange(x/10)
let start() be
$( let col = 0
for i=100 to 500 do
if strange(i) then
$( writed(i, 4)
col := col + 1
if col rem 10 = 0 then wrch('*N')
$)
wrch('*N')
$)
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
BQN
↑‿10⥊((∧´(|¯1↓«-⊢)∊⟨2,3,5,7⟩˙)○•Fmt)¨⊸/100+↕400
- Output:
The unused positions in the table are filled with 0
s, because that's the behaviour
of ↑‿10⥊
, and writing custom tabulation code would take much more code than the
actual task.
┌─ ╵ 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 0 0 0 ┘
C
#include <stdbool.h>
#include <stdio.h>
bool isPrime(int n) {
if (n < 0) {
n = -n;
}
return n == 2 || n == 3 || n == 5 || n == 7;
}
int main() {
int count = 0;
int i, j;
int d[3];
int dptr;
printf("Strange numbers in the open interval (100, 500) are:\n");
for (i = 101; i < 500; i++) {
dptr = 0;
j = i;
while (j > 0) {
d[dptr++] = j % 10;
j /= 10;
}
if (isPrime(d[0] - d[1]) && isPrime(d[1] - d[2])) {
printf("%d ", i);
count++;
if (count % 10 == 0) {
printf("\n");
}
}
}
if (count % 10 != 0) {
printf("\n");
}
printf("\n%d strange numbers in all.\n", count);
return 0;
}
- Output:
Strange numbers in the open interval (100, 500) are: 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 87 strange numbers in all.
Extended task
#include <stdio.h>
const int next_digit[] = {
0x7532, 0x8643, 0x97540, 0x86510, 0x97621,
0x87320, 0x98431, 0x95420, 0x6531, 0x7642
};
void gen(char *p, int i, const char c)
{
p[i] = c;
if (p[i + 1] == '\0')
puts(p);
else
for (int d = next_digit[p[i++] - '0']; d; d >>= 4)
gen(p, i, '0' + (d&15));
}
int main(void)
{
// show between 100 and 500
char buf[4] = {"Hi!"};
for (char c = '1'; c < '5'; c++)
gen(buf, 0, c);
// count 10 digit ones
unsigned int table[10][10] = {{0}};
for (int j = 0; j < 10; j++) table[0][j] = 1U;
for (int i = 1; i < 10; i++)
for (int j = 0; j < 10; j++)
for (int d = next_digit[j]; d; d >>= 4)
table[i][j] += table[i - 1][d&15];
printf("\n%u 10-digits starting with 1\n", table[9][1]);
return 0;
}
- Output:
% ./a.out | fmt 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 853423 10-digits starting with 1
C++
#include <algorithm>
#include <iostream>
#include <vector>
std::vector<int> digits(int n) {
std::vector<int> result;
while (n > 0) {
auto rem = n % 10;
result.push_back(rem);
n /= 10;
}
std::reverse(result.begin(), result.end());
return result;
}
bool is_strange(int n) {
auto test = [](int a, int b) {
auto v = std::abs(a - b);
return v == 2 || v == 3 || v == 5 || v == 7;
};
auto xs = digits(n);
for (size_t i = 1; i < xs.size(); i++) {
if (!test(xs[i - 1], xs[i])) {
return false;
}
}
return true;
}
int main() {
std::vector<int> xs;
for (int i = 100; i <= 500; i++) {
if (is_strange(i)) {
xs.push_back(i);
}
}
std::cout << "Strange numbers in range [100..500]\n";
std::cout << "(Total: " << xs.size() << ")\n\n";
for (size_t i = 0; i < xs.size(); i++) {
std::cout << xs[i];
if ((i + 1) % 10 == 0) {
std::cout << '\n';
} else {
std::cout << ' ';
}
}
return 0;
}
- Output:
Strange numbers in range [100..500] (Total: 87) 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
CLU
digits = iter (n: int) yields (int)
while n>0 do
yield(n // 10)
n := n / 10
end
end digits
strange = proc (n: int) returns (bool)
last: int := -1
for d: int in digits(n) do
if last ~= -1 then
diff: int := int$abs(last-d)
if diff~=2 cand diff~=3 cand diff~=5 cand diff~=7 then
return(false)
end
end
last := d
end
return(true)
end strange
start_up = proc ()
po: stream := stream$primary_output()
col: int := 0
for n: int in int$from_to(100, 500) do
if ~strange(n) then continue end
stream$putright(po, int$unparse(n), 3)
col := col + 1
if col = 10 then
stream$putc(po, '\n')
col := 0
else
stream$putc(po, ' ')
end
end
end start_up
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
COBOL
IDENTIFICATION DIVISION.
PROGRAM-ID. STRANGE-NUMBERS.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 COMPUTATION.
02 NUM PIC 999.
02 DIGITS REDEFINES NUM PIC 9 OCCURS 3 TIMES.
02 DIGIT-PRIME PIC 9.
88 PRIME VALUES 2 3 5 7.
02 CUR-DIGIT PIC 9.
01 OUTPUT-FORMAT.
02 N-OUT PIC ZZ9.
PROCEDURE DIVISION.
BEGIN.
PERFORM STRANGE-TEST
VARYING NUM FROM 100 BY 1
UNTIL NUM IS GREATER THAN 500.
STOP RUN.
STRANGE-TEST SECTION.
BEGIN.
SET CUR-DIGIT TO 1.
STEP.
IF DIGITS(CUR-DIGIT) IS LESS THAN DIGITS(CUR-DIGIT + 1)
SUBTRACT DIGITS(CUR-DIGIT + 1) FROM DIGITS(CUR-DIGIT)
GIVING DIGIT-PRIME
ELSE
SUBTRACT DIGITS(CUR-DIGIT) FROM DIGITS(CUR-DIGIT + 1)
GIVING DIGIT-PRIME.
IF PRIME NEXT SENTENCE ELSE GO TO DONE.
ADD 1 TO CUR-DIGIT.
IF CUR-DIGIT IS LESS THAN 3 GO TO STEP.
MOVE NUM TO N-OUT.
DISPLAY N-OUT.
DONE. EXIT.
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
Cowgol
include "cowgol.coh";
sub abs(n: int8): (r: uint8) is
if n<0 then n := -n; end if;
r := n as uint8;
end sub;
sub strange(n: uint16): (s: uint8) is
s := 1;
while n >= 10 loop
var da: int8 := (n % 10) as int8;
n := n / 10;
var db: int8 := (n % 10) as int8;
var diff := abs(da-db);
if diff!=2 and diff!=3 and diff!=5 and diff!=7 then
s := 0;
return;
end if;
end loop;
end sub;
var n: uint16 := 100;
var col: uint8 := 0;
while n <= 500 loop
if strange(n) != 0 then
print_i16(n);
print_char(' ');
col := col + 1;
if col == 10 then
print_nl();
col := 0;
end if;
end if;
n := n + 1;
end loop;
print_nl();
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
Delphi
{This code is normally in a separate library, but it is included here for clarity}
procedure GetDigits(N: integer; var IA: TIntegerDynArray);
{Get an array of the integers in a number}
{Numbers returned from least to most significant}
var T,I,DC: integer;
begin
DC:=Trunc(Log10(N))+1;
SetLength(IA,DC);
for I:=0 to DC-1 do
begin
T:=N mod 10;
N:=N div 10;
IA[I]:=T;
end;
end;
function IsStrangeNumber(N: integer): boolean;
{Test if the difference between digits is prime}
var Digits: TIntegerDynArray;
var I: integer;
begin
Result:=False;
{Get digits}
GetDigits(N,Digits);
{test if the difference between digits is prime}
for I:=0 to High(Digits)-1 do
if not IsPrime(abs(Digits[I+1]-Digits[I])) then exit;
Result:=True
end;
procedure ShowStrangeNumbers(Memo: TMemo);
var I,Cnt: integer;
var S: string;
begin
S:='';
Cnt:=0;
for I:=100 to 500-1 do
if IsStrangeNumber(I) then
begin
Inc(Cnt);
S:=S+Format('%5d',[I]);
if (Cnt mod 10)=0 then S:=S+CRLF;
end;
Memo.Lines.Add('Count = '+IntToStr(Cnt));
Memo.Lines.Add(S);
end;
- Output:
Count = 87 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 Elapsed Time: 2.428 ms.
Draco
proc nonrec strange(word n) bool:
bool is_strange;
short da, db, diff;
is_strange := true;
while is_strange and n >= 10 do
da := n % 10;
n := n / 10;
db := n % 10;
diff := |(da-db);
is_strange := is_strange and
(diff=2 or diff=3 or diff=5 or diff=7)
od;
is_strange
corp
proc nonrec main() void:
word n, col;
col := 0;
for n from 100 upto 500 do
if strange(n) then
write(n:3, ' ');
col := col + 1;
if col = 10 then
writeln();
col := 0
fi
fi
od
corp
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
EasyLang
func strange n .
dig = n mod 10
n = n div 10
while n > 0
digp = dig
dig = n mod 10
n = n div 10
d = abs (dig - digp)
if d <> 2 and d <> 3 and d <> 5 and d <> 7
return 0
.
.
return 1
.
for i = 100 to 499
if strange i = 1
write i & " "
.
.
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
F#
// Strange numbers. Nigel Galloway: February 25th., 2021
let N=Array.init 10(fun n->[2;3;5;7]|>List.collect(fun g->[n+g;n-g])|>List.filter((<) -1)|>List.filter((>)10))
[1..4]|>List.collect(fun g->N.[g]|>List.map(fun n->g*10+n%10))|>List.collect(fun n->N.[n%10]|>List.map(fun g->n*10+g%10))|>List.iter(printf "%d "); printfn ""
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 180 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 380 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
Factor
Identifying and filtering
USING: grouping io kernel math.ranges math.statistics
math.text.utils math.vectors prettyprint sequences ;
: strange? ( n -- ? )
1 digit-groups differences vabs
[ { 2 3 5 7 } member? ] all? ;
"Strange numbers in (100, 500):" print nl
100 500 (a,b) [ strange? ] filter dup
10 group [ [ pprint bl ] each nl ] each nl
length pprint " strange numbers found." print
- Output:
Strange numbers in (100, 500): 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 87 strange numbers found.
Generating
Since we know the next possible digits based on the current last digit, we can construct strange numbers with a backtracking algorithm.
USING: backtrack compiler.tree.propagation.call-effect
formatting io kernel sequences sequences.generalizations
tools.memory.private tools.time ;
: d ( digit -- digit next-digit )
dup {
{ 2 3 5 7 } ! from 0 we can get to these digits
{ 3 4 6 8 } ! from 1 we can get to these
{ 0 4 5 7 9 } ! etc...
{ 0 1 5 6 8 }
{ 1 2 6 7 9 }
{ 0 2 3 7 8 }
{ 1 3 4 8 9 }
{ 0 2 4 5 9 }
{ 1 3 5 6 }
{ 2 4 6 7 }
} nth amb-lazy ;
[ [ 1 d d d d d d d d d 10 narray ] bag-of ] time
dup length commas write
" 10-digit strange numbers beginning with 1:" print
[ first2 ] [ last2 ] bi "%u\n%u\n...\n%u\n%u\n" printf
- Output:
Running time: 1.904245898 seconds 853,423 10-digit strange numbers beginning with 1: { 1 3 0 2 0 2 0 2 0 2 } { 1 3 0 2 0 2 0 2 0 3 } ... { 1 8 6 9 7 9 7 9 7 5 } { 1 8 6 9 7 9 7 9 7 9 }
Forth
\ tests whether n is prime for 0 <= n < 10
: prime? ( n -- ? )
1 swap lshift 0xac and 0<> ;
: strange? ( n -- ? )
dup 10 < if drop false exit then
10 /mod swap >r
begin
dup 0 >
while
10 /mod swap
dup r> - abs
prime? invert if 2drop false exit then
>r
repeat
drop rdrop true ;
: main
0
500 101 do
i strange? if
i .
1+
dup 10 mod 0= if cr then else
then
loop
cr
drop ;
main
bye
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
Go
Basic task
package main
import "fmt"
func isPrime(n int) bool {
if n < 0 {
n = -n
}
return n == 2 || n == 3 || n == 5 || n == 7
}
func main() {
count := 0
var d []int
fmt.Println("Strange numbers in the open interval (100, 500) are:\n")
for i := 101; i < 500; i++ {
d = d[:0]
j := i
for j > 0 {
d = append(d, j%10)
j /= 10
}
if isPrime(d[0]-d[1]) && isPrime(d[1]-d[2]) {
fmt.Printf("%d ", i)
count++
if count%10 == 0 {
fmt.Println()
}
}
}
if count%10 != 0 {
fmt.Println()
}
fmt.Printf("\n%d strange numbers in all.\n", count)
}
- Output:
Strange numbers in the open interval (100, 500) are: 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 87 strange numbers in all.
Stretch goal
package main
import "fmt"
func main() {
diffs := []int{-7, -5, -3, -2, 2, 3, 5, 7}
possibles := make([][]int, 10)
for i := 0; i < 10; i++ {
possibles[i] = []int{}
for _, d := range diffs {
sum := i + d
if sum >= 0 && sum < 10 {
possibles[i] = append(possibles[i], sum)
}
}
}
places := 10
start := 1
strangeOnes := []int{start}
for i := 2; i <= places; i++ {
var newOnes []int
for _, n := range strangeOnes {
for _, nextN := range possibles[n%10] {
newOnes = append(newOnes, n*10+nextN)
}
}
strangeOnes = newOnes
}
fmt.Println("Found", len(strangeOnes), places, "\b-digit strange numbers beginning with", start)
}
- Output:
Found 853423 10-digit strange numbers beginning with 1.
Haskell
import Data.List (intercalate)
import Data.List.Split (chunksOf)
--------------------- STRANGE NUMBERS --------------------
isStrange :: Int -> Bool
isStrange n =
all
(\(a, b) -> abs (a - b) `elem` [2, 3, 5, 7])
$ (zip <*> tail) (digits n)
digits :: Int -> [Int]
digits = fmap (read . return) . show
--------------------------- TEST -------------------------
main =
let xs = filter isStrange [100 .. 500]
in (putStrLn . intercalate "\n\n")
[ "Strange numbers found in range [100..500]",
"(total " <> (show . length) xs <> ")",
"Full list:",
unlines
(unwords <$> chunksOf 10 (show <$> xs))
]
- Output:
Strange numbers found in range [100..500] (total 87) Full list: 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
J
isStrange=: ([: */ 2 3 5 7 e.&:|~ 2 -/\ 10 #.inv ])"0
strangePair=: (1 p: ::0:"0 i.10),. 0 1}.isStrange (+ 10&*)"0/~ i.10
To test if a number is strange, we check if the absolute value of the differences of adjacent pairs of digits are 2, 3, 5 or 7.
To count the number of ten digit strange numbers which begin with 1, we first build a table which associates each digit with the digits which have a prime difference from it. Then we take a list of lists where there's only one list which has the single element 1, for each list we find the digits which have a prime difference from the last digit in that list and append those digits each to copies of that list. Since each iteration here adds a single digit, nine iterations give us lists representing 10 digit numbers. We count those lists and that gives us the number needed for the stretch goal.
Task examples:
(#~ 100&<:) I. isStrange i.500
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 ...
#{{ ;<@{{x,"1 0 I. ({:x){y }}&strangePair"1 y}}^:9 ,:1
853423
Java
import java.util.LinkedList;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class StrangeNumbers {
private static List<Integer> digits(int n) {
var result = new LinkedList<Integer>();
while (n > 0) {
var rem = n % 10;
result.addFirst(rem);
n /= 10;
}
return result;
}
private static boolean isStrange(int n) {
BiPredicate<Integer, Integer> test = (a, b) -> {
var abs = Math.abs(a - b);
return abs == 2 || abs == 3 || abs == 5 || abs == 7;
};
var xs = digits(n);
for (int i = 1; i < xs.size(); i++) {
if (test.negate().test(xs.get(i - 1), xs.get(i))) {
return false;
}
}
return true;
}
public static void main(String[] args) {
var xs = IntStream.rangeClosed(100, 500)
.filter(StrangeNumbers::isStrange)
.boxed()
.collect(Collectors.toList());
System.out.println("Strange numbers in range [100..500]");
System.out.printf("(Total: %d)\n\n", xs.size());
for (int i = 0; i < xs.size(); i++) {
Integer x = xs.get(i);
System.out.print(x);
if ((i + 1) % 10 == 0) {
System.out.println();
} else {
System.out.print(' ');
}
}
}
}
- Output:
Strange numbers in range [100..500] (Total: 87) 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
jq
Works with gojq, the Go implementation of jq
Filter method
def is_strange:
def digits: tostring | explode | map([.] | implode | tonumber);
digits
| . as $d
| [2, 3, 5, 7] as $primes
| all( range(1; length);
($d[.] - $d[. - 1]) | length | IN( $primes[]));
# Pretty-printing
def nwise($n):
def n: if length <= $n then . else .[0:$n] , (.[$n:] | n) end;
n;
def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;
def task($start; $stop; filter):
"Finding numbers matching $f for open interval \($start), \($stop):\n",
( [range($start; $stop) | select(filter) ]
| nwise(10) | map(lpad(3)) | join(" ") );
task(100; 500; is_strange)
- Output:
Finding numbers matching $f for open interval 100, 500: 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
Generator method
`lpad` and and `nwise` are as above and so their definitions are not repeated.
# input: width
# $start: maximum first digit allowed e.g. 9 for unrestricted
# output: the specified stream of strange numbers
def generate($start):
# The next permissible digit
def nxt: . as $i | range(0;10) | select($i - . | length | IN(2, 3, 5, 7));
# input: width
# $first: first digit
# output: an array of $n digits
def gen($first):
. as $n
| if $n == 0 then []
elif $n == 1 then [$first]
else ($n - 1) | gen($first) | . + ((.[-1]|nxt) | [.])
end;
gen( range(1; $start+1) );
[3 | generate(4) | map(tostring) | join("") | tonumber]
| nwise(10) | map(lpad(3)) | join(" ")
- Output:
As above, except for the header.
Stretch goal
Using generate/1 as already defined:
def count(s): reduce s as $x (null; .+1);
count(10 | generate(1))
- Output:
853423
Julia
Filter method
isstrange(n::Integer) = (d = digits(n); all(i -> abs(d[i] - d[i + 1]) ∈ [2, 3, 5, 7], 1:length(d)-1))
function filter_open_interval(start, stop, f, doprint=true, rowlength=92)
colsize = length(string(stop)) + 1
columns, ncount = rowlength ÷ colsize, 0
println("Finding numbers matching $f for open interval ($start, $stop):\n")
for n in start+1:stop-1
if f(n)
ncount += 1
doprint && print(rpad(n, colsize), ncount % columns == 0 ? "\n" : "")
end
end
println("\n\nThe total found was $ncount\n\n")
end
filter_open_interval(100, 500, isstrange)
- Output:
Finding numbers matching isstrange for open interval (100, 500): 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 The total found was 87
Generator method
HT: Factor for the table.
function countstrange(places, fixedstart=1)
possibles = [
[2, 3, 5, 7],
[3, 4, 6, 8],
[0, 4, 5, 7, 9],
[0, 1, 5, 6, 8],
[1, 2, 6, 7, 9],
[0, 2, 3, 7, 8],
[1, 3, 4, 8, 9],
[0, 2, 4, 5, 9],
[1, 3, 5, 6],
[2, 4, 6, 7],
]
strangeones = [fixedstart]
for _ in 2:places
newones = Int[]
for n in strangeones, nextn in possibles[n % 10 + 1]
push!(newones, n * 10 + nextn)
end
strangeones = newones
end
println("Found ", length(strangeones), " $places-digit strange numbers with the most significant digit $fixedstart.\n")
end
countstrange(10)
@time countstrange(10)
- Output:
Found 853423 10-digit strange numbers with the most significant digit 1. Found 853423 10-digit strange numbers with the most significant digit 1. 0.014545 seconds (139 allocations: 13.298 MiB, 29.39% gc time)
Kotlin
import kotlin.math.abs
fun digits(n: Int): List<Int> {
var nn = n
val result = mutableListOf<Int>()
while (nn > 0) {
val rem = nn % 10
result.add(0, rem)
nn /= 10
}
return result
}
fun isStrange(n: Int): Boolean {
val test = { a: Int, b: Int ->
val abs = abs(a - b)
abs == 2 || abs == 3 || abs == 5 || abs == 7
}
val xs = digits(n)
for (i in 1 until xs.size) {
if (!test(xs[i - 1], xs[i])) {
return false
}
}
return true
}
fun main() {
val xs = (100 until 500)
.filter(::isStrange)
.toList()
println("Strange numbers in range [100..500]")
println("(Total: ${xs.size})")
println()
for (i in xs.indices) {
val x = xs[i]
print(x)
if ((i + 1) % 10 == 0) {
println()
} else {
print(' ')
}
}
println()
}
- Output:
Strange numbers in range [100..500] (Total: 87) 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
MAD
NORMAL MODE IS INTEGER
INTERNAL FUNCTION(D)
ENTRY TO PRMDGT.
DD = D
WHENEVER DD.LE.0, DD=-D
FUNCTION RETURN
0 DD.E.2 .OR. DD.E.3 .OR. DD.E.5 .OR. DD.E.7
END OF FUNCTION
INTERNAL FUNCTION(A,B)
ENTRY TO REM.
FUNCTION RETURN A-A/B*B
END OF FUNCTION
INTERNAL FUNCTION(X)
ENTRY TO STRNGE.
XX = X
LOOP WHENEVER XX.G.9
D0 = REM.(XX,10)
XX = XX/10
D1 = REM.(XX,10)
WHENEVER PRMDGT.(D0-D1), TRANSFER TO LOOP
FUNCTION RETURN 0B
END OF CONDITIONAL
FUNCTION RETURN 1B
END OF FUNCTION
PRINT COMMENT $ STRANGE NUMBERS $
THROUGH TEST, FOR I=100, 1, I.GE.500
TEST WHENEVER STRNGE.(I), PRINT FORMAT F, I
VECTOR VALUES F = $I4*$
END OF PROGRAM
- Output:
STRANGE NUMBERS 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
Mathematica /Wolfram Language
Select[Range[101, 499],
AllTrue[Partition[IntegerDigits[#], 2, 1], Differences /* First /* PrimeQ] &
]
- Output:
{130,131,135,136,138,141,142,146,147,149,161,163,164,168,169,181,183,185,186,202,203,205,207,241,242,246,247,249,250,252,253,257,258,270,272,274,275,279,292,294,296,297,302,303,305,307,313,314,316,318,350,352,353,357,358,361,363,364,368,369,381,383,385,386,413,414,416,418,420,424,425,427,429,461,463,464,468,469,470,472,474,475,479,492,494,496,497}
Modula-2
MODULE StrangeNumbers;
FROM InOut IMPORT WriteCard, WriteLn;
VAR n, col: CARDINAL;
PROCEDURE strange(n: CARDINAL): BOOLEAN;
VAR dl, dr, diff: INTEGER;
BEGIN
WHILE n >= 10 DO
dl := n MOD 10;
n := n DIV 10;
dr := n MOD 10;
diff := ABS(dl-dr);
IF (diff#2) AND (diff#3) AND (diff#5) AND (diff#7) THEN
RETURN FALSE
END
END;
RETURN TRUE
END strange;
BEGIN
col := 0;
FOR n := 100 TO 500 DO
IF strange(n) THEN
WriteCard(n, 4);
col := col + 1;
IF col = 10 THEN
WriteLn;
col := 0
END
END
END;
WriteLn
END StrangeNumbers.
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
Nim
Our program finds the strange numbers with a given number of digits. Filtering is done afterwards. It consumes a lot of memory but is able to find the result in less than a second on our small laptop.
import algorithm, sequtils
const PrimeDigits = [2, 3, 5, 7]
type
Digit = 0..9
DigitSeq = seq[Digit]
func toInt(s: DigitSeq): int =
## Convert a sequence of digits to an int.
for d in s:
result = 10 * result + d
proc findStrangeNumbers(ndigits: Positive): seq[int] =
## Return the list of strange numbers with "ndigits" digits.
var list: seq[DigitSeq] = toSeq(1..9).mapIt(@[Digit it]) # Starting digits.
for _ in 2..ndigits:
var newList: seq[DigitSeq] # List with one more digit.
for dseq in list:
let last = dseq[^1]
for p in PrimeDigits:
if last - p >= 0:
newList.add dseq & (last - p)
if last + p <= 9:
newList.add dseq & (last + p)
list = move(newList) # "newList" becomes the current list.
result = list.map(toInt)
var result = sorted(findStrangeNumbers(3).filterIt(it < 500))
echo "Found ", result.len, " strange numbers between 101 and 499."
for i, n in result:
stdout.write n, if (i + 1) mod 15 == 0: '\n' else: ' '
echo()
result = findStrangeNumbers(10).filterIt(it div 1_000_000_000 == 1)
echo "\nFound ", result.len, " strange numbers with 10 digits and starting with 1."
- Output:
Found 87 strange numbers between 101 and 499. 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 Found 853423 strange numbers with 10 digits and starting with 1.
Pascal
modified recursive version like Julia/Factor using the digits that can follow.
Not dynamically memorizing of all numbers saves much time 200ms -> 4ms.
Count is about 4.6 to the power of Digitscount -> first digit 1 followed by 9 digit -> 4.6^9 = 922190
program strangenumbers;
const
dgtMaxCnt = 10;
deltaDgtCnt: array[0..9] of Int32 =(4,4,5,5,5,5,5,5,4,4); // (4*4+6*5)/10 => 4.6
// digits that can follow
DPrmNxtDgt : array[0..9,0..4] of Int32 =((2,3,5,7,0), //0 +2,+3,+5,+7
(3,4,6,8,0), //1 +2,+3,+5,+7
(0,4,5,7,9), //2 -2,+2,+3,+5,+7
(0,1,5,6,8), //3 -3,-2,+2,+3,+5
(1,2,6,7,9), //4 -3,-2,+2,+3,+5
(0,2,3,7,8), //5 -5,-3,-2,+2,+3
(1,3,4,8,9), //6 -5,-3,-2,+2,+3
(0,2,4,5,9), //7 -7,-5,-3,-2,+2
(1,3,5,6,0), //8 -7,-5,-3,-2
(2,4,6,7,0)); //9 -7,-5,-3,-2
type
tDigits = array[0..dgtMaxCnt-1] of Int32;
//globals are set to 0
var
Digits : tDigits;
i,Cnt,dgtCnt : Int32;
procedure OutPut(const Digits:tDigits);
var
i : Int32;
Begin
For i := 0 to dgtcnt-1 do
write(Digits[i]);
write(' ');
end;
procedure NextDigit(var Digits:TDigits;DgtIdx:Int32);
var
idx,dgt :Int32;
Begin
dgt := Digits[DgtIdx];
inc(DgtIdx);
IF DgtIdx < dgtCnt-1 then
Begin
For idx := 0 to deltaDgtCnt[dgt]-1 do
Begin
Digits[DgtIdx]:= DPrmNxtDgt[dgt,idx];
NextDigit(Digits,DgtIdx);
end;
end
else
Begin
For idx := 0 to deltaDgtCnt[dgt]-1 do
Begin
Digits[DgtIdx]:= DPrmNxtDgt[dgt,idx];
inc(cnt);
IF dgtCnt<5 then
Begin
OutPut(Digits);
If cnt mod 16 = 0 then
Writeln;
end;
end;
end;
end;
Begin
cnt := 0;
dgtCnt := 3;
Writeln('Count of digits : ', dgtCnt,' in 100..499');
For i := 1 to 4 do
Begin
Digits[0] := i;
NextDigit(Digits,0);
end;
Writeln;
Writeln('Count : ',cnt);
Writeln;
cnt := 0;
dgtCnt := 10;
Writeln('Count of digits : ', dgtCnt);
For i := 1 to 1 do
Begin
Digits[0] := i;
NextDigit(Digits,0);
end;
Writeln;
Writeln('Count : ',cnt);
end.
- Output:
Count of digits : 3 in 100..499 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 Count : 87 Count of digits : 10 Count : 853423
Perl
use strict;
use warnings;
use feature 'say';
use Quantum::Superpositions;
sub is_strange {
my @digits = split '', $_;
my @deltas = map { abs $digits[$_-1] - $digits[$_] } 1..$#digits;
all(@deltas) == any(2, 3, 5, 7);
}
my($low, $high) = (100, 500);
my $cnt = my @strange = grep { is_strange($_) } $low+1 .. $high-1;
say "Between $low and $high there are $cnt strange numbers:\n" .
(sprintf "@{['%5d' x $cnt]}", @strange[0..$cnt-1]) =~ s/(.{80})/$1\n/gr;
- Output:
Between 100 and 500 there are 87 strange numbers: 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
Phix
constant diff = {-7,-5,-3,-2,2,3,5,7}, poss = apply(true,sq_add,{tagset(9,0),{diff}}), nxts = apply(true,filter,{poss,{"in"},{{0,9}},{"[]"}}) -- nxts is {{2,3,5,7},{3,4,6,8}..., as per the factor and other entries function strange(integer left, sequence digits, part={}) sequence res = {} for i=1 to length(digits) do integer di = digits[i] if left=1 then string fmt = join(repeat("%d",length(part)+1),"") res = append(res,sprintf(fmt,deep_copy(part)&di)) else res &= strange(left-1,nxts[di+1],deep_copy(part)&di) end if end for return res end function sequence res = strange(3,tagset(4)) -- (3 digit numbers beginning 1..4) printf(1,"%d strange numbers found: %s\n",{length(res),join(shorten(res,"",5),",")})
- Output:
87 strange numbers found: 130,131,135,136,138,...,479,492,494,496,497
stretch goal
Dunno when to quit, me. As there does not appear to be much interest in which 1-digits are strange, I've shown three ways to set ones (output of 0, 10, or 4).
constant diff = {-7,-5,-3,-2,2,3,5,7}, poss = apply(true,sq_add,{tagset(9,0),{diff}}), nxts = apply(true,filter,{poss,{"in"},{{0,9}},{"[]"}}), -- nxts is {{2,3,5,7},{3,4,6,8}..., as per the factor and other entries -- ones = columnize({columnize({repeat(0,10),tagset(9,0)}),repeat(0,10)}), -- ones = columnize({columnize({repeat(0,10),tagset(9,0)}),repeat(1,10)}), ones = columnize({columnize({repeat(0,10),tagset(9,0)}),apply(tagset(9,0),is_prime)}), twos = columnize({columnize({repeat(1,10),tagset(9,0)}),apply(nxts,length)}), dict = new_dict(ones&twos) function count_strange(integer left, sequence digits, atom res=0) for i=1 to length(digits) do integer di = digits[i] if getd_index({left-1,di},dict)!=NULL then res += getd({left-1,di},dict) else atom prev = res res = count_strange(left-1,nxts[di+1],res) setd({left-1,di},res-prev,dict) end if end for return res end function atom t0 = time() atom count = count_strange(10,tagset(1)) printf(1,"There are %,d %d-digit strange numbers beginning with 1\n\n",{count,10}) for n=1 to iff(machine_bits()=32?23:28) do printf(1,"Total %d-digit strange numbers: %,d\n",{n,count_strange(n,tagset(9,n>1))}) end for printf(1,"(%s)\n",elapsed(time()-t0))
- Output:
There are 853,423 10-digit strange numbers beginning with 1 Total 1-digit strange numbers: 4 Total 2-digit strange numbers: 42 Total 3-digit strange numbers: 194 Total 4-digit strange numbers: 901 Total 5-digit strange numbers: 4,178 Total 6-digit strange numbers: 19,395 Total 7-digit strange numbers: 90,011 Total 8-digit strange numbers: 417,837 Total 9-digit strange numbers: 1,939,540 Total 10-digit strange numbers: 9,003,578 Total 11-digit strange numbers: 41,795,409 Total 12-digit strange numbers: 194,020,644 Total 13-digit strange numbers: 900,672,711 Total 14-digit strange numbers: 4,181,070,893 Total 15-digit strange numbers: 19,409,220,279 Total 16-digit strange numbers: 90,100,876,862 Total 17-digit strange numbers: 418,263,512,702 Total 18-digit strange numbers: 1,941,650,412,637 Total 19-digit strange numbers: 9,013,471,997,782 Total 20-digit strange numbers: 41,842,075,002,263 Total 21-digit strange numbers: 194,238,054,320,527 Total 22-digit strange numbers: 901,686,217,399,477 Total 23-digit strange numbers: 4,185,781,417,010,380 Total 24-digit strange numbers: 19,431,112,295,670,526 Total 25-digit strange numbers: 90,202,542,361,448,337 Total 26-digit strange numbers: 418,735,609,894,371,624 Total 27-digit strange numbers: 1,943,842,229,729,877,443 Total 28-digit strange numbers: 9,023,647,681,353,485,161 (0.0s)
PL/0
PL/0 can only output 1 value per line, so the output has been manually adjusted to show multiple values per line to save space.
var n, v, d1, d2, diff, strange;
begin
n := 100;
while n < 499 do begin
n := n + 1;
d1 := n - ( ( n / 10 ) * 10 );
v := n / 10;
strange := 1;
while strange * v > 0 do begin
d2 := v - ( ( v / 10 ) * 10 );
v := v / 10;
strange := 0;
diff := d1 - d2;
if diff < 0 then diff := - diff;
d1 := d2;
if diff = 2 then strange := 1;
if diff = 3 then strange := 1;
if diff = 5 then strange := 1;
if diff = 7 then strange := 1;
end;
if strange = 1 then ! n
end
end.
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
PL/I
strangeNumbers: procedure options(main);
strange: procedure(nn) returns(bit);
declare (n, nn) fixed;
n = nn;
do while(n >= 10);
declare (dl, dr, diff) fixed;
dl = mod(n, 10);
n = n/10;
dr = mod(n, 10);
diff = abs(dl-dr);
if diff^=2 & diff^=3 & diff^=5 & diff^=7 then
return('0'b);
end;
return('1'b);
end strange;
declare (n, col) fixed;
col = 0;
do n=100 to 500;
if strange(n) then do;
put edit(n) (F(4));
col = col + 1;
if col = 10 then do;
col = 0;
put skip;
end;
end;
end;
end strangeNumbers;
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
PL/M
100H:
BDOS: PROCEDURE (F,A); DECLARE F BYTE, A ADDRESS; GO TO 5; END BDOS;
EXIT: PROCEDURE; GO TO 0; END EXIT;
PRINT: PROCEDURE (S); DECLARE S ADDRESS; CALL BDOS(9,S); END PRINT;
PR$NUM: PROCEDURE (N);
DECLARE S (7) BYTE INITIAL ('..... $');
DECLARE N ADDRESS, I BYTE;
I = 5;
DIGIT: S(I := I-1) = '0' + N MOD 10;
IF (N := N/10) > 0 THEN GO TO DIGIT;
CALL PRINT(.S(I));
END PR$NUM;
ABS$DIFF: PROCEDURE (A, B) BYTE;
DECLARE (A, B) BYTE;
IF A > B
THEN RETURN A - B;
ELSE RETURN B - A;
END ABS$DIFF;
STRANGE: PROCEDURE (N) BYTE;
DECLARE N ADDRESS, (D1, D2, DIFF) BYTE;
DO WHILE N>=10;
D1 = N MOD 10;
N = N / 10;
D2 = N MOD 10;
DIFF = ABS$DIFF(D1, D2);
IF DIFF<>2 AND DIFF<>3 AND DIFF<>5 AND DIFF<>7 THEN
RETURN 0;
END;
RETURN -1;
END STRANGE;
DECLARE N ADDRESS, COL BYTE INITIAL (0);
DO N = 100 TO 500;
IF STRANGE(N) THEN DO;
CALL PR$NUM(N);
IF (COL := COL+1) = 10 THEN DO;
CALL PRINT(.(13,10,'$'));
COL = 0;
END;
END;
END;
CALL EXIT;
EOF
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
Python
'''Strange Numbers'''
# isStrange :: Int -> Bool
def isStrange(n):
'''True if all consecutive decimal digit
pairs in n have a prime difference.
'''
def test(a, b):
return abs(a - b) in [2, 3, 5, 7]
xs = digits(n)
return all(map(test, xs, xs[1:]))
# ------------------- TEST AND DISPLAY -------------------
# main :: IO ()
def main():
'''List and count of Strange numbers'''
xs = [
n for n in range(100, 1 + 500)
if isStrange(n)
]
print('\nStrange numbers in range [100..500]\n')
print('(Total: ' + str(len(xs)) + ')\n')
print(
'\n'.join(
' '.join(
str(x) for x in row
) for row in chunksOf(10)(xs)
)
)
# ----------------------- GENERIC ------------------------
# chunksOf :: Int -> [a] -> [[a]]
def chunksOf(n):
'''A series of lists of length n, subdividing the
contents of xs. Where the length of xs is not evenly
divible, the final list will be shorter than n.
'''
def go(xs):
return (
xs[i:n + i] for i in range(0, len(xs), n)
) if 0 < n else None
return go
# digits :: Int -> [Int]
def digits(n):
'''Component digits of a decimal number.'''
return [int(c) for c in str(n)]
# MAIN ---
if __name__ == '__main__':
main()
- Output:
Strange numbers in range [100..500] (Total: 87) 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
Quackery
[ ' [ 2 3 5 7 11 13 17 ]
find 7 < ] is prime ( n --> b )
[ 10 /mod
swap 10 /mod
tuck - abs prime not iff
[ 2drop false ] done
- abs prime ] is strange ( n --> b )
[] 399 times
[ i^ 101 +
dup strange iff
join else drop ]
dup size echo
say " strange numbers:"
cr cr
witheach
[ echo
i^ 10 mod 9 = iff cr else sp ]
- Output:
87 strange numbers: 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
Raku
sub infix:<′>(\x,\y) { abs(x - y) ∈ (2, 3, 5, 7) }
my ($low,$high) = 100, 500;
my @strange.push: $_ if so all .comb.rotor(2 => -1).map: { .[0] ′ .[1] } for $low ^..^ $high;
say "Between $low and $high there are {+@strange} strange numbers:\n";
print @strange.batch(20)».fmt("%4d").join: "\n";
- Output:
Between 100 and 500 there are 87 strange numbers: 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
REXX
Some optimization was added to bypass calculating the absolute value of adjacent decimal digit differences,
as well as parsing of a number to determine the differences.
/*REXX pgm lists strange integers (within a range) whose decimal digs differ by a prime.*/
numeric digits 20 /*allow processing of larger numbers. */
parse arg LO HI bd . /*obtain optional arguments from the CL*/
if LO=='' | LO=="," then LO= 101 /*Not specified? Then use the default.*/
if HI=='' | HI=="," then HI= 499 /* " " " " " " */
if bd=='' | bd=="," then bd= /* " " " " " " */
begDig= bd\=='' /*look for numbers that start with:" BD*/
show= LO>0 /*indicator if the list is to be shown.*/
!.= 0; !.2= 1; !.3= 1; !.5= 1; !.7= 1 /*build array of digits that are prime.*/
LO = abs(LO) /*use the absolute value for the search*/
do p=1 for 9; _= -p; if !.p then !._= 1 /*extend array for negatives*/
end /*p*/
$= /*the list of strange numbers (so far)*/
#= 0 /* " number " " " " " */
do j=LO to HI; L= length(j) /*find for strange numbers in the range*/
if L==1 then iterate /*Number too short? Then skip it. */
if bd\=='' then if left(j, 1)\==bd then iterate /*Need leading dig? Maybe skip.*/
do k=1 for L-1 /*examine the difference in the digits.*/
parse var j =(k) y +1 z +1 /*get two adjacent decimal digits: Y Z */
dif= y - z /*difference between any adjacent digs.*/
if \!.dif then iterate j /*Difference not prime? Then skip it. */
end /*k*/
#= # + 1 /*bump the number of "strange" numbers.*/
if show then $= $ j /*maybe add the number to the $ list.*/
end /*j*/
/*stick a fork in it, we're all done. */
say commas(#) ' strange numbers found between ' commas(LO) " and " ,
commas(HI) ' (inclusive)'
say
if show then say strip($)
exit 0
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: parse arg _; do jc=length(_)-3 to 1 by -3; _=insert(',', _, jc); end; return _
- output when using the default inputs:
87 strange numbers found between 101 and 499 (inclusive) 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
- output when using the inputs of: -1000000000 2000000000 1
853,423 strange numbers found between 1,000,000,000 and 2,000,000,000 (inclusive)
Ring
load "stdlib.ring"
row = 0
see "Strange numbers are:" + nl
for n = 100 to 500
flag = 1
str = string(n)
for m = 1 to len(str)-1
num1 = number(str[m])
num2 = number(str[m+1])
pr = fabs(num1-num2)
if not isprime(pr)
flag = 0
exit
ok
next
if flag = 1
see str + " "
row = row + 1
if row % 10 = 0
see nl
ok
ok
next
- Output:
Strange numbers are: 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
RPL
RPL code | Comment |
---|---|
≪ IF DUP 10 < THEN DROP 0 ELSE →STR → n ≪ 1 SF { 0 1 4 6 8 9 } 1 n SIZE 1 - FOR j n j DUP SUB NUM n j 1 + DUP SUB NUM - ABS IF OVER SWAP POS THEN 1 CF n SIZE 'j' STO END NEXT DROP 1 FS? ≫ END ≫ 'STRG?' STO |
STRG? n -- boolean ) return false if n < 10 store locally n as a string initialize return flag and list of non-prime numbers scan n get |n[j]-n[j+1]| if not prime then clear flag and exit loop return flag value |
- Input:
≪ {} 101 499 FOR j IF j STRG? THEN j + END NEXT ≫ EVAL
- Output:
1: { 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 }
Ruby
def digits(n)
result = []
while n > 0
rem = n % 10
result.unshift(rem)
n = n / 10
end
return result
end
def isStrange(n)
def test(a, b)
abs = (a - b).abs
return abs == 2 || abs == 3 || abs == 5 || abs == 7
end
xs = digits(n)
for i in 1 .. xs.length - 1
if !test(xs[i - 1], xs[i]) then
return false
end
end
return true
end
xs = []
for i in 100 .. 500
if isStrange(i) then
xs << i
end
end
print "Strange numbers in range [100 .. 500]\n"
print "(Total: %d)\n\n" % [xs.length]
xs.each_slice(10) do |s|
print s, "\n"
end
- Output:
Strange numbers in range [100 .. 500] (Total: 87) [130, 131, 135, 136, 138, 141, 142, 146, 147, 149] [161, 163, 164, 168, 169, 181, 183, 185, 186, 202] [203, 205, 207, 241, 242, 246, 247, 249, 250, 252] [253, 257, 258, 270, 272, 274, 275, 279, 292, 294] [296, 297, 302, 303, 305, 307, 313, 314, 316, 318] [350, 352, 353, 357, 358, 361, 363, 364, 368, 369] [381, 383, 385, 386, 413, 414, 416, 418, 420, 424] [425, 427, 429, 461, 463, 464, 468, 469, 470, 472] [474, 475, 479, 492, 494, 496, 497]
Sidef
func generate_from_prefix(limit, p, base) {
var seq = [p]
for d in (base-1 -> primes) {
for k in ([1, -1]) {
var r = p[0]+(k*d)
next if (r < 0)
next if (r >= base)
var t = [r, p...]
if (t.digits2num(base) <= limit) {
seq << __FUNC__(limit, t, base)...
}
}
}
return seq
}
func strange_numbers(limit, base = 10, digits = @(^base)) {
digits.map {|p| generate_from_prefix(limit, [p], base)... }\
.map {|t| t.digits2num(base) }\
.sort.uniq
}
strange_numbers(500).grep { _ > 100 }.slices(10).each{
.join(' ').say
}
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
V (Vlang)
Basic task
fn is_prime(nn int) bool {
mut n := nn
if n < 0 {
n = -n
}
return n == 2 || n == 3 || n == 5 || n == 7
}
fn main() {
mut count := 0
mut d := []int{}
println("Strange numbers in the open interval (100, 500) are:\n")
for i in 101..500{
d = d[..0]
mut j := i
for j > 0 {
d << j%10
j /= 10
}
if is_prime(d[0]-d[1]) && is_prime(d[1]-d[2]) {
print("$i ")
count++
if count%10 == 0 {
println('')
}
}
}
if count%10 != 0 {
println('')
}
println("\n$count strange numbers in all.")
}
- Output:
Strange numbers in the open interval (100, 500) are: 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 87 strange numbers in all.
VTL-2
100 K=0
110 N=100
120 #=N>499*9999
130 N=N+1
140 V=N/10
150 D=%
160 S=1
170 #=S*V=0*280
180 V=V/10
190 E=%
200 S=0
210 F=E<D*(D-E)+((E>D)*(E-D))
220 D=E
230 S=F=2+S
240 S=F=3+S
250 S=F=5+S
260 S=F=7+S
270 #=170
280 #=S=0*350
290 ?=N
300 $=32
310 K=K+1
320 #=K<10*350
330 ?=""
340 K=0
350 #=120
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497
Wren
Basic task
var primes = [2, 3, 5, 7]
var count = 0
var d = []
System.print("Strange numbers in the open interval (100, 500) are:\n")
for (i in 101..499) {
d.clear()
var j = i
while (j > 0) {
d.add(j % 10)
j = (j/10).floor
}
if (primes.contains((d[0] - d[1]).abs) && primes.contains((d[1] - d[2]).abs)) {
System.write("%(i) ")
count = count + 1
if (count % 10 == 0) System.print()
}
}
if (count % 10 != 0) System.print()
System.print("\n%(count) strange numbers in all.")
- Output:
Strange numbers in the open interval (100, 500) are: 130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 87 strange numbers in all.
Stretch goal
... though I've generated the 'possibles' table rather than hard-code it. Runtime about 0.085 seconds which is quick for Wren.
var diffs = [-7, -5, -3, -2, 2, 3, 5, 7]
var possibles = List.filled(10, null)
for (i in 0..9) {
possibles[i] = []
for (d in diffs) {
var sum = i + d
if (sum >= 0 && sum < 10) possibles[i].add(sum)
}
}
var places = 10
var start = 1
var strangeOnes = [start]
for (i in 2..places) {
var newOnes = []
for (n in strangeOnes) {
for (nextN in possibles[n%10]) newOnes.add(n*10 + nextN)
}
strangeOnes = newOnes
}
System.print("Found %(strangeOnes.count) %(places)-digit strange numbers beginning with %(start).")
- Output:
Found 853423 10-digit strange numbers beginning with 1
XPL0
Takes 49 seconds on Raspberry Pi 4.
func Strange(N);
int N, A, B, D;
[N:= N/10;
A:= rem(0);
loop [N:= N/10;
B:= rem(0);
D:= abs(A-B);
if D#2 & D#3 & D#5 & D#7 then return false;
if N = 0 then return true;
A:= B;
];
];
int Cnt, N;
[Cnt:= 0;
for N:= 100 to 500-1 do
if Strange(N) then
[Cnt:= Cnt+1;
IntOut(0, N);
if rem(Cnt/20) = 0 then CrLf(0) else ChOut(0, ^ );
];
CrLf(0);
Cnt:= 0;
for N:= 1_000_000_000 to 1_999_999_999 do
if Strange(N) then
Cnt:= Cnt+1;
IntOut(0, Cnt);
]
- Output:
130 131 135 136 138 141 142 146 147 149 161 163 164 168 169 181 183 185 186 202 203 205 207 241 242 246 247 249 250 252 253 257 258 270 272 274 275 279 292 294 296 297 302 303 305 307 313 314 316 318 350 352 353 357 358 361 363 364 368 369 381 383 385 386 413 414 416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 853423
- Draft Programming Tasks
- Prime Numbers
- 11l
- Action!
- Ada
- ALGOL 68
- ALGOL W
- APL
- AppleScript
- Arturo
- AWK
- BASIC
- FreeBASIC
- GW-BASIC
- BCPL
- BQN
- C
- C++
- CLU
- COBOL
- Cowgol
- Delphi
- SysUtils,StdCtrls
- Draco
- EasyLang
- F Sharp
- Factor
- Forth
- Go
- Haskell
- J
- Java
- Jq
- Julia
- Kotlin
- MAD
- Mathematica
- Wolfram Language
- Modula-2
- Nim
- Pascal
- Perl
- Phix
- PL/0
- PL/I
- PL/M
- Python
- Quackery
- Raku
- REXX
- Ring
- RPL
- Ruby
- Sidef
- V (Vlang)
- VTL-2
- Wren
- XPL0