I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

Special Divisors

From Rosetta Code
Special Divisors is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Task

Numbers n such that reverse(d) divides reverse(n) for all divisors d of n, where n < 200

Factor[edit]

Works with: Factor version 0.99 2021-02-05
USING: grouping kernel math.functions math.parser
math.primes.factors math.ranges prettyprint sequences ;
 
: reverse-number ( n -- reversed ) 10 >base reverse dec> ;
 
: special? ( n -- ? )
[ reverse-number ] [ divisors ] bi
[ reverse-number divisor? ] with all? ;
 
200 [1..b] [ special? ] filter 18 group simple-table.
Output:
1   2   3   4   5   6   7   8   9   11  13  17  19  22  23  26  27  29
31  33  37  39  41  43  44  46  47  53  55  59  61  62  66  67  69  71
73  77  79  82  83  86  88  89  93  97  99  101 103 107 109 113 121 127
131 137 139 143 149 151 157 163 167 169 173 179 181 187 191 193 197 199

Julia[edit]

using Primes
 
function divisors(n)
f = [one(n)]
for (p,e) in factor(n)
f = reduce(vcat, [f*p^j for j in 1:e], init=f)
end
return f[1:end-1]
end
 
function isspecialdivisor(n)::Bool
isprime(n) && return true
nreverse = evalpoly(10, reverse(digits(n)))
for d in divisors(n)
dreverse = evalpoly(10, reverse(digits(d)))
 !(nreverse ÷ dreverse ≈ nreverse / dreverse) && return false
end
return true
end
 
const specials = filter(isspecialdivisor, 1:200)
foreach(p -> print(rpad(p[2], 4), p[1] % 18 == 0 ? "\n" : ""), enumerate(specials))
 
Output:
1   2   3   4   5   6   7   8   9   11  13  17  19  22  23  26  27  29
31  33  37  39  41  43  44  46  47  53  55  59  61  62  66  67  69  71
73  77  79  82  83  86  88  89  93  97  99  101 103 107 109 113 121 127
131 137 139 143 149 151 157 163 167 169 173 179 181 187 191 193 197 199

Perl[edit]

Library: ntheory
use strict;
use warnings;
use feature 'say';
use ntheory 'divisors';
 
my @sd;
for my $n (1..199) {
map { next if $_ != int $_ } map { reverse($n) / reverse $_ } divisors $n;
push @sd, $n;
}
 
say @sd . " matching numbers:\n" .
(sprintf "@{['%4d' x @sd]}", @sd) =~ s/(.{40})/$1\n/gr;
Output:
72 matching numbers:
   1   2   3   4   5   6   7   8   9  11
  13  17  19  22  23  26  27  29  31  33
  37  39  41  43  44  46  47  53  55  59
  61  62  66  67  69  71  73  77  79  82
  83  86  88  89  93  97  99 101 103 107
 109 113 121 127 131 137 139 143 149 151
 157 163 167 169 173 179 181 187 191 193
 197 199

Phix[edit]

function rev(integer n)
    integer r = 0
    while n do
        r = r*10+remainder(n,10)
        n = floor(n/10)
    end while
    return r
end function

function special_divisors(integer n)
    sequence fn = factors(n)
    if length(fn) then
        integer rn = rev(n)
        for i=1 to length(fn) do
            if remainder(rn,rev(fn[i])) then return false end if
        end for
    end if
    return true
end function

sequence res = apply(true,sprintf,{{"%3d"},filter(tagset(200),special_divisors)})
printf(1,"Found %d special divisors:\n%s\n",{length(res),join_by(res,1,18)})
Output:
Found 72 special divisors:
  1     2     3     4     5     6     7     8     9    11    13    17    19    22    23    26    27    29
 31    33    37    39    41    43    44    46    47    53    55    59    61    62    66    67    69    71
 73    77    79    82    83    86    88    89    93    97    99   101   103   107   109   113   121   127
131   137   139   143   149   151   157   163   167   169   173   179   181   187   191   193   197   199

Raku[edit]

use Prime::Factor:ver<0.3.0+>;
 
say "{+$_} matching numbers:\n{.batch(10)».fmt('%3d').join: "\n"}"
given (1..^200).grep: { all .flip «%%« .&divisors».flip };
Output:
72 matching numbers:
  1   2   3   4   5   6   7   8   9  11
 13  17  19  22  23  26  27  29  31  33
 37  39  41  43  44  46  47  53  55  59
 61  62  66  67  69  71  73  77  79  82
 83  86  88  89  93  97  99 101 103 107
109 113 121 127 131 137 139 143 149 151
157 163 167 169 173 179 181 187 191 193
197 199

REXX[edit]

/*REXX program finds special divisors:   numbers  N  such that  reverse(D)  divides     */
/*───────────────────────────────────────────── reverse(N) for all divisors D of N. */
parse arg hi cols . /*obtain optional argument from the CL.*/
if hi=='' | hi=="," then hi= 200 /* " " " " " " */
if cols=='' | cols=="," then cols= 10 /* " " " " " " */
w= 10 /*width of a number in any column. */
@sdns= ' special divisors N that reverse(D) divides reverse(N)' ,
'for all divisors D of N, where N < ' commas(hi)
if cols>0 then say ' index │'center(@sdns, 1 + cols*(w+1) )
if cols>0 then say '───────┼'center("" , 1 + cols*(w+1), '─')
sdns= 0; idx= 1 /*initialize # of nice primes and index*/
$= /*a list of nice primes (so far). */
do j=1 for hi-1; r= reverse(j) /*search for special divisors. */
do k=2 to j%2 /*skip the first divisor (unity) & last*/
if j//k==0 then if r//reverse(k)==0 then nop /*Is OK? keep*/
else iterate j /*Not OK? Skip*/
end /*m*/
sdns= sdns + 1 /*bump the number of sdns numbers. */
if cols==0 then iterate /*Build the list (to be shown later)? */
c= commas(j) /*maybe add commas to the number. */
$= $ right(c, max(w, length(c) ) ) /*add a nice prime ──► list, allow big#*/
if sdns//cols\==0 then iterate /*have we populated a line of output? */
say center(idx, 7)'│' substr($, 2); $= /*display what we have so far (cols). */
idx= idx + cols /*bump the index count for the output*/
end /*j*/
 
if $\=='' then say center(idx, 7)"│" substr($, 2) /*possible display residual output.*/
say
say 'Found ' commas(sdns) @sdns
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: parse arg ?; do jc=length(?)-3 to 1 by -3; ?=insert(',', ?, jc); end; return ?
output   when using the default inputs:
 index │     special divisors  N  that reverse(D) divides reverse(N) for all divisors  D  of  N,  where  N  <  200
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │          1          2          3          4          5          6          7          8          9         11
  11   │         13         17         19         22         23         26         27         29         31         33
  21   │         37         39         41         43         44         46         47         53         55         59
  31   │         61         62         66         67         69         71         73         77         79         82
  41   │         83         86         88         89         93         97         99        101        103        107
  51   │        109        113        121        127        131        137        139        143        149        151
  61   │        157        163        167        169        173        179        181        187        191        193
  71   │        197        199

Found  72  special divisors  N  that reverse(D) divides reverse(N) for all divisors  D  of  N,  where  N  <  200

Ring[edit]

 
load "stdlib.ring"
 
see "working..." + nl
 
row = 0
num = 0
limit1 = 200
 
for n = 1 to limit1
flag = 1
revNum = rever(string(n))
revNum = number(revNum)
for m = 1 to n/2
revDiv = rever(String(m))
revDiv = number(revDiv)
if n%m = 0
if revNum % revDiv = 0
flag = 1
else
flag = 0
exit
ok
ok
next
if flag = 1
num = num + 1
row = row + 1
see "" + n + " "
if row%10 = 0
see nl
ok
ok
next
 
see nl + "Found " + num + " special divisors N that reverse(D) divides reverse(N) for all divisors D of N, where N < 200" + nl
see "done..." + nl
 
func rever(str)
rev = ""
for n = len(str) to 1 step -1
rev = rev + str[n]
next
return rev
 
Output:
working...
1 2 3 4 5 6 7 8 9 11 
13 17 19 22 23 26 27 29 31 33 
37 39 41 43 44 46 47 53 55 59 
61 62 66 67 69 71 73 77 79 82 
83 86 88 89 93 97 99 101 103 107 
109 113 121 127 131 137 139 143 149 151 
157 163 167 169 173 179 181 187 191 193 
197 199 
Found 72 special divisors N that reverse(D) divides reverse(N) for all divisors D of N, where  N  <  200
done...

Wren[edit]

Library: Wren-math
Library: Wren-seq
Library: Wren-fmt
import "/math" for Int
import "/seq" for Lst
import "/fmt" for Fmt
 
var reversed = Fn.new { |n|
var rev = 0
while (n > 0) {
rev = rev * 10 + n % 10
n = (n/10).floor
}
return rev
}
 
var special = []
for (n in 1...200) {
var divs = Int.divisors(n)
var revN = reversed.call(n)
if (divs.all { |d| revN % reversed.call(d) == 0 }) special.add(n)
}
System.print("Special divisors in the range 0..199:")
for (chunk in Lst.chunks(special, 12)) Fmt.print("$3d", chunk)
System.print("\n%(special.count) special divisors found.")
Output:
Special divisors in the range 0..199:
  1   2   3   4   5   6   7   8   9  11  13  17
 19  22  23  26  27  29  31  33  37  39  41  43
 44  46  47  53  55  59  61  62  66  67  69  71
 73  77  79  82  83  86  88  89  93  97  99 101
103 107 109 113 121 127 131 137 139 143 149 151
157 163 167 169 173 179 181 187 191 193 197 199

72 special divisors found.