Strange numbers: Difference between revisions
m (→idiomatic version: fixed typo.) |
m (→{{header|REXX}}: optimized the program, added support to restrict found numbers to a leading decimal digit for the stretch goal.) |
||
Line 223: | Line 223: | ||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
Some optimization was added to bypass calculating the absolute value of adjacent decimal digit differences, |
|||
===idiomatic version=== |
|||
<br>as well as parsing of a number to determine the differences. |
|||
<lang rexx>/*REXX pgm lists |
<lang rexx>/*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= /* " " " " " " */ |
|||
⚫ | |||
show= LO>0 /*indicator if the list is to be shown.*/ |
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.*/ |
!.= 0; !.2= 1; !.3= 1; !.5= 1; !.7= 1 /*build array of digits that are prime.*/ |
||
Line 233: | Line 237: | ||
do p=1 for 9; _= -p; if !.p then !._= 1 /*extend array for negatives*/ |
do p=1 for 9; _= -p; if !.p then !._= 1 /*extend array for negatives*/ |
||
end /*p*/ |
end /*p*/ |
||
$= /*the list of strange numbers (so far) |
$= /*the list of strange numbers (so far)*/ |
||
#= 0 /* " number " " " " " */ |
#= 0 /* " number " " " " " */ |
||
do j=LO to HI; |
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 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.*/ |
|||
parse var j =(k) y +1 z +1 /*get two adjacent decimal digits: Y Z */ |
|||
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.*/ |
#= # + 1 /*bump the number of "strange" numbers.*/ |
||
if show then $= $ j /*maybe add the number to |
if show then $= $ j /*maybe add the number to the $ list.*/ |
||
end /*j*/ |
end /*j*/ |
||
/*stick a fork in it, we're all done. */ |
/*stick a fork in it, we're all done. */ |
||
say |
say commas(#) ' strange numbers found between ' commas(LO) " and " , |
||
commas(HI) ' (inclusive)' |
|||
⚫ | |||
say |
|||
⚫ | |||
{{out|output|text= when using the default inputs:}} |
{{out|output|text= when using the default inputs:}} |
||
<pre> |
<pre> |
||
Line 255: | Line 263: | ||
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 |
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 |
416 418 420 424 425 427 429 461 463 464 468 469 470 472 474 475 479 492 494 496 497 |
||
</pre> |
|||
{{out|output|text= when using the inputs of: <tt> -1000000000 2000000000 1 </tt>}} |
|||
<pre> |
|||
853,423 strange numbers found between 1,000,000,000 and 2,000,000,000 (inclusive) |
|||
</pre> |
</pre> |
||
Revision as of 05:16, 23 February 2021
n is a strange number if every adjacent decimal digit differs from its neighbour by a prime number.
Where 100 < n < 500
- Stretch goal
Show the number of 10-digit strange numbers that begin with 1
ALGOL W
<lang algolw>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; rest := abs( n ); if rest < 10 then false else begin logical strange; integer d0; 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 if_rest_lt_10__ end isStrange ; % test the isStrange procedure on values 100-499 % begin integer strangeCount; strangeCount := 0; for n := 100 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.</lang>
- 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
Factor
Identifying and filtering
<lang factor>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</lang>
- 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.
<lang factor>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</lang>
- 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 }
Pascal
simple brute force, by adding a prime difference from digit to digit. <lang pascal>program strangenumbers; type
tDeltaIdx = 0..7;
const
dgtCnt = 3; deltaprime : array[tDeltaIdx] of Int32 =(-7,-5,-3,-2,2,3,5,7);
//globals are set to 0 var
Digits : array[0..dgtCnt-1] of Int32; Actdgt,i,j,k,Cnt : Int32;
procedure OutPut; Begin
write(Digits[0],Digits[1],Digits[2],' ');
end;
Begin
For i := 1 to 4 do Begin Digits[0] := i; For k in tDeltaIdx do Begin if (i+deltaprime[k]) in [0..9] then Begin Actdgt := i+deltaprime[k]; Digits[1]:= Actdgt; For j in tDeltaIdx do if (Actdgt+deltaprime[j]) in [0..9] then Begin Digits[2]:= Actdgt+deltaprime[j]; OutPut; inc(cnt); If cnt MOD 20 = 0 then writeln; end; end; end; end; writeln; Writeln('Count : ',cnt);
end. </lang>
- 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 Count : 87
Phix
<lang Phix>function strange(integer left, sequence digits, res={}, part={})
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,part&di)) else sequence nxt = filter(sq_add(di,{-7,-5,-3,-2,2,3,5,7}),"in",{0,9},"[]") res = strange(left-1,nxt,res,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: %v\n",{length(res),shorten(res,"",5)})</lang>
- Output:
87 strange numbers found: {"130","131","135","136","138","...","479","492","494","496","497"}
stretch goal
(Obviously this would be significantly faster if I just counted rather than built the full list.) <lang Phix>res = strange(10,tagset(1)) printf(1,"%,d 10-digit strange numbers beginning with 1: %v (%s)\n",
{length(res),shorten(res,"",2),elapsed(time())})</lang>
- Output:
853,423 10-digit strange numbers beginning with 1: {"1302020202","1302020203","...","1869797975","1869797979"} (4.8s)
Raku
<lang perl6># 20210222 Raku programming solution
sub infix:<′>(\x,\y) { abs(x -y) ∈ [2, 3, 5, 7] ?? True !! False }
for (101..499) { .say if so all .comb.rotor(2 => -1).map: { @_[0] ′ @_[1] } }</lang>
- Output:
./strange.raku | wc 87 87 348
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.
<lang rexx>/*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($)</lang>
- 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
<lang ring> load "stdlib.ring"
row = 0 see "Strange numbers are:"
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 row = row + 1 if (row-1) % 11 = 0 see nl else see " " + str ok ok
next </lang>
- Output:
Strange numbers are: 131 135 136 138 141 142 146 147 149 161 164 168 169 181 183 185 186 202 203 205 241 242 246 247 249 250 252 253 257 258 272 274 275 279 292 294 296 297 302 303 307 313 314 316 318 350 352 353 357 358 363 364 368 369 381 383 385 386 413 414 418 420 424 425 427 429 461 463 464 468 470 472 474 475 479 492 494 496 497
Wren
<lang ecmascript>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.")</lang>
- 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.