Numbers divisible by their individual digits, but not by the product of their digits.: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Haskell}}: Added a variant obtaining digit lists numerically.)
Line 510: Line 510:
and another approach might be to obtain (unordered) digit lists numerically, rather by string conversion.
and another approach might be to obtain (unordered) digit lists numerically, rather by string conversion.


<lang haskell>import Data.List (unfoldr)
<lang haskell>import Data.Bool (bool)
import Data.List (unfoldr)
import Data.List.Split (chunksOf)
import Data.List.Split (chunksOf)
import Data.Tuple (swap)
import Data.Tuple (swap)
Line 529: Line 530:


digits :: Int -> [Int]
digits :: Int -> [Int]
digits = unfoldr go
digits =
unfoldr $
where
(bool Nothing . Just . swap . flip quotRem 10) <*> (0 <)
go x
| 0 < x = Just $ swap $ quotRem x 10
| otherwise = Nothing


--------------------------- TEST -------------------------
--------------------------- TEST -------------------------

Revision as of 22:34, 10 April 2021

Numbers divisible by their individual digits, but not by the product of their digits. 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

Find and show positive decimal integers divisible by their individual digits,   but not divisible by the product of their digits,
where   n   <   1000

8086 Assembly

<lang asm> cpu 8086 org 100h section .text mov si,1 ; Current number number: mov bp,1 ; BP holds product mov di,si ; DI holds number digit: mov ax,di ; Get digit xor dx,dx mov cx,10 div cx mov di,ax ; Store remaining digits in DI test dx,dx ; Is the digit zero? jz next ; Then this number is not valid mov cx,dx ; Is the number divisible by the digit? xor dx,dx mov ax,si div cx test dx,dx jnz next ; If not, this number is not valid mov ax,bp ; Otherwise, multiply digit into product mul cx mov bp,ax test di,di ; More digits? jnz digit ; If so, do next digit mov ax,si ; Is the number divisible by the product? xor dx,dx div bp test dx,dx jz next ; If so, this number is not valid mov ax,si ; Otherwise, print the number call prnum next: inc si ; Next number cmp si,1000 ; Are we there yet? jne number ; If not, do the next number ret ; But if so, stop ;;; Print number in AX prnum: mov bx,dbuf ; Start of buffer mov cx,10 ; Divisor .dgt: xor dx,dx ; Divide by 10 div cx add dl,'0' ; Make ASCII digit dec bx mov [bx],dl ; Store digit test ax,ax ; Any more digits remaining? jnz .dgt ; If so, next digits mov dx,bx ; Print string using MS-DOS mov ah,9 int 21h ret section .data db '*****' dbuf: db 13,10,'$'</lang>

Output:
22
33
44
48
55
66
77
88
99
122
124
126
155
162
168
184
222
244
248
264
288
324
333
336
366
396
412
424
444
448
488
515
555
636
648
666
728
777
784
824
848
864
888
936
999

Ada

<lang Ada>with Ada.Text_Io; with Ada.Integer_Text_Io;

procedure Numbers_Divisible is

  function Is_Divisible (N : Natural) return Boolean is
     function To_Decimal (C : Character) return Natural
     is ( Character'Pos (C) - Character'Pos ('0'));
     Image : constant String := N'Image;
     Digit : Natural;
     Prod  : Natural := 1;
  begin
     for A in Image'First + 1 .. Image'Last loop
        Digit := To_Decimal (Image (A));
        if Digit = 0 then
           return False;
        end if;
        if N mod Digit /= 0 then
           return False;
        end if;
        Prod := Prod * Digit;
     end loop;
     return N mod Prod /= 0;
  end Is_Divisible;
  Count : Natural := 0;

begin

  for N in 1 .. 999 loop
     if Is_Divisible (N) then
        Count := Count + 1;
        Ada.Integer_Text_Io.Put (N, Width => 5);
        if Count mod 15 = 0 then
           Ada.Text_Io.New_Line;
        end if;
     end if;
  end loop;

end Numbers_Divisible;</lang>

Output:
   22   33   44   48   55   66   77   88   99  122  124  126  155  162  168
  184  222  244  248  264  288  324  333  336  366  396  412  424  444  448
  488  515  555  636  648  666  728  777  784  824  848  864  888  936  999

ALGOL W

<lang algolw>begin % find numbers divisible by their digits but not the product of their digits %

   % returns true if n is divisible by its digits but not the product of its      %
   %         digits, false otherwise                                              %
   logical procedure divisibleByDigitsButNotDigitProduct ( integer value n ) ;
   begin
       integer v, p;
       logical matches;
       v       := n;
       p       := 1;
       matches := v not = 0;
       while matches and v > 0 do begin
           integer d;
           d       := v rem 10;
           v       := v div 10;
           if d = 0 then matches := false else matches := n rem d = 0;
           p       := p * d
       end while_matches_and_v_gt_0 ;
       if matches then begin
           if p = 0 then matches := false else matches := n rem p not = 0
       end if_matche ;
       matches
   end divisibleByDigitsButNotDigitProduct ;
   integer count;
   % show the members of the seuence up to 1000 %
   write( "Numbers below 1000 that are divisible by their digits but not the product of their digits:" );
   write();
   count := 0;
   for i := 0 until 999 do begin
       if divisibleByDigitsButNotDigitProduct( i ) then begin
           writeon( i_w := 3, s_w := 0, " ", i );
           count := count + 1;
           if count rem 15 = 0 then write()
       end if_divisibleByDigitsButNotDigitProduct__i
   end for_i

end.</lang>

Output:
Numbers below 1000 that are divisible by their digits but not the product of their digits:
  22  33  44  48  55  66  77  88  99 122 124 126 155 162 168
 184 222 244 248 264 288 324 333 336 366 396 412 424 444 448
 488 515 555 636 648 666 728 777 784 824 848 864 888 936 999

APL

Works with: Dyalog APL

<lang APL>(⊢(/⍨)((⍎¨∘⍕)((∧/0=|)∧0≠(×/⊣)|⊢)⊢)¨)⍳999</lang>

Output:
22 33 44 48 55 66 77 88 99 122 124 126 155 162 168 184 222 244 248 264 288 324 333 336 366 396 412 424 444 448 488 515 555
      636 648 666 728 777 784 824 848 864 888 936 999

BASIC

<lang basic>10 DEFINT A-Z 20 FOR I=1 TO 999 30 N=I: P=1 40 D=N MOD 10 50 IF D=0 THEN 110 60 P=P*D 70 IF I MOD D THEN 110 80 N=N\10 90 IF N THEN 40 100 IF I MOD P <> 0 THEN PRINT I, 110 NEXT I</lang>

Output:
 22            33            44            48            55
 66            77            88            99            122
 124           126           155           162           168
 184           222           244           248           264
 288           324           333           336           366
 396           412           424           444           448
 488           515           555           636           648
 666           728           777           784           824
 848           864           888           936           999

C

<lang c>#include <stdio.h>

int divisible(int n) {

   int p = 1;
   int c, d;
   
   for (c=n; c; c /= 10) {
       d = c % 10;
       if (!d || n % d) return 0;
       p *= d;
   }
   
   return n % p;

}

int main() {

   int n, c=0;
   
   for (n=1; n<1000; n++) {
       if (divisible(n)) {
           printf("%5d", n);
           if (!(++c % 10)) printf("\n");
       }
   }
   printf("\n");
   
   return 0;

}</lang>

Output:
   22   33   44   48   55   66   77   88   99  122
  124  126  155  162  168  184  222  244  248  264
  288  324  333  336  366  396  412  424  444  448
  488  515  555  636  648  666  728  777  784  824
  848  864  888  936  999

Cowgol

<lang cowgol>include "cowgol.coh";

sub divisible(n: uint16): (r: uint8) is

   var product: uint16 := 1;
   var c := n;
   r := 1;
   
   while c != 0 loop
       var digit := c % 10;
       if digit == 0 or n % digit != 0 then
           r := 0;
           return;
       end if;
       product := product * digit;
       c := c / 10;
   end loop;
   
   if n % product == 0 then
       r := 0;
   end if;

end sub;

var n: uint16 := 1; var c: uint8 := 1; while n < 1000 loop

   if divisible(n) != 0 then
       print_i16(n);
       c := c + 1;
       if c % 10 == 1 then
           print_nl();
       else
           print_char('\t');
       end if;
   end if;
   n := n + 1;

end loop; print_nl();</lang>

Output:
22      33      44      48      55      66      77      88      99      122
124     126     155     162     168     184     222     244     248     264
288     324     333     336     366     396     412     424     444     448
488     515     555     636     648     666     728     777     784     824
848     864     888     936     999

F#

<lang fsharp> // Nigel Galloway. April 9th., 2021 let rec fN i g e l=match g%10,g/10 with (0,_)->false |(n,_) when i%n>0->false |(n,0)->i%(l*n)>0 |(n,g)->fN i g (e+n) (l*n) seq{1..999}|>Seq.filter(fun n->fN n n 0 1)|>Seq.iter(printf "%d "); printfn "" </lang>

Output:
22 33 44 48 55 66 77 88 99 122 124 126 155 162 168 184 222 244 248 264 288 324 333 336 366 396 412 424 444 448 488 515 555 636 648 666 728 777 784 824 848 864 888 936 999

Factor

Works with: Factor version 0.99 2021-02-05

<lang factor>USING: combinators.short-circuit grouping kernel math math.functions math.ranges math.text.utils prettyprint sequences ;

needle? ( n -- ? )
   dup 1 digit-groups dup product
   {
       [ 2nip zero? not ]
       [ nip divisor? not ]
       [ drop [ divisor? ] with all? ]
   } 3&& ;

1000 [1..b] [ needle? ] filter 9 group simple-table.</lang>

Output:
22  33  44  48  55  66  77  88  99
122 124 126 155 162 168 184 222 244
248 264 288 324 333 336 366 396 412
424 444 448 488 515 555 636 648 666
728 777 784 824 848 864 888 936 999

FOCAL

<lang FOCAL>01.10 F I=1,999;D 2 01.20 Q

02.10 S N=I 02.15 S P=1 02.20 S Z=FITR(N/10) 02.25 S D=N-Z*10 02.30 S N=Z 02.35 S P=P*D 02.40 I (-D)2.45,2.65 02.45 S Z=I/D 02.60 I (FITR(Z)-Z)2.65,2.7 02.65 R 02.70 I (-N)2.2 02.75 S Z=I/P 02.80 I (FITR(Z)-Z)2.85,2.65 02.85 T %4,I,!</lang>

Output:
=   22
=   33
=   44
=   48
=   55
=   66
=   77
=   88
=   99
=  122
=  124
=  126
=  155
=  162
=  168
=  184
=  222
=  244
=  248
=  264
=  288
=  324
=  333
=  336
=  366
=  396
=  412
=  424
=  444
=  448
=  488
=  515
=  555
=  636
=  648
=  666
=  728
=  777
=  784
=  824
=  848
=  864
=  888
=  936
=  999

Forth

Works with: Gforth

<lang forth>: divisible? { n -- ? }

 1 { p }
 n
 begin
   dup 0 >
 while
   10 /mod swap
   dup 0= if
     2drop false exit
   then
   dup n swap mod 0<> if
     2drop false exit
   then
   p * to p
 repeat
 drop n p mod 0<> ;
main
 0 { count }
 1000 1 do
   i divisible? if
     i 4 .r
     count 1+ to count
     count 10 mod 0= if cr else space then
   then
 loop cr ;

main bye</lang>

Output:
  22   33   44   48   55   66   77   88   99  122
 124  126  155  162  168  184  222  244  248  264
 288  324  333  336  366  396  412  424  444  448
 488  515  555  636  648  666  728  777  784  824
 848  864  888  936  999 

FreeBASIC

This function does a bit more than the task asks for, just to make things interesting. <lang freebasic>function divdignp( n as const integer ) as ubyte

   'returns 1 if the number is divisible by its digits
   '        2 if it is NOT divisible by the product of its digits
   '        3 if both are true
   '        0 if neither are true
   dim as integer m = n, p = 1, r = 1, d
   while m>0
       d = m mod 10
       m \= 10
       p *= d
       if d<>0 andalso n mod d <> 0 then r = 0
   wend
   if p<>0 andalso n mod p <> 0 then r += 2
   return r

end function

for i as uinteger = 1 to 999

   if divdignp(i) = 3 then print i;" ";

next i : print</lang>

Output:
22 33 44 48 55 66 77 88 99 122 124 126 155 162 168 184 222 244 248 264 288 324 333 336 366 396 412 424 444 448 488 515 555 636 648 666 728 777 784 824 848 864 888 936 999

Haskell

<lang haskell>import Data.List.Split (chunksOf) import Text.Printf

divisible :: Int -> Bool divisible = divdgt <*> dgt

 where
   dgt = map (read . pure) . show
   divdgt x d =
     notElem 0 d
       && 0 /= x `mod` product d
       && all ((0 ==) . mod x) d

numbers :: [Int] numbers = filter divisible [1 ..]

main :: IO () main = putStr $ unlines $ map (concatMap $ printf "%5d") split

 where
   n = takeWhile (< 1000) numbers
   split = chunksOf 10 n</lang>
Output:
   22   33   44   48   55   66   77   88   99  122
  124  126  155  162  168  184  222  244  248  264
  288  324  333  336  366  396  412  424  444  448
  488  515  555  636  648  666  728  777  784  824
  848  864  888  936  999

and another approach might be to obtain (unordered) digit lists numerically, rather by string conversion.

<lang haskell>import Data.Bool (bool) import Data.List (unfoldr) import Data.List.Split (chunksOf) import Data.Tuple (swap)

-- DIVISIBLE BY ALL DIGITS, BUT NOT BY PRODUCT OF ALL DIGITS

p :: Int -> Bool p n =

 ( ( (&&)
       . all
         ( (&&) . (0 /=)
             <*> (0 ==) . rem n
         )
   )
     <*> (0 /=) . rem n . product
 )
   $ digits n

digits :: Int -> [Int] digits =

 unfoldr $
   (bool Nothing . Just . swap . flip quotRem 10) <*> (0 <)

TEST -------------------------

main :: IO () main =

 let xs = [1 .. 1000] >>= (\n -> [show n | p n])
     w = length $ last xs
  in (putStrLn . unlines) $
       unwords
         <$> chunksOf
           10
           (fmap (justifyRight w ' ') xs)

justifyRight :: Int -> Char -> String -> String justifyRight n c = (drop . length) <*> (replicate n c <>)</lang>

Output:
 22  33  44  48  55  66  77  88  99 122
124 126 155 162 168 184 222 244 248 264
288 324 333 336 366 396 412 424 444 448
488 515 555 636 648 666 728 777 784 824
848 864 888 936 999

J

<lang J>([ #~ ((10 #.^:_1]) ((0:~:*/@[|]) *. *./@(0:=|)) ])"0) >:i.999</lang>

Output:
22 33 44 48 55 66 77 88 99 122 124 126 155 162 168 184 222 244 248 264 288 324 333 336 366 396 412 424 444 448 488 515 555 636 648 666 728 777 784 824 848 864 888 936 999

Julia

<lang julia>isonlydigdivisible(n) = (d = digits(n); !(0 in d) && all(x -> n % x == 0, d) && n % prod(d) != 0)

foreach(p -> print(rpad(p[2], 5), p[1] % 15 == 0 ? "\n" : ""), enumerate(filter(isonlydigdivisible, 1:1000)))

</lang>

Output:
22   33   44   48   55   66   77   88   99   122  124  126  155  162  168  
184  222  244  248  264  288  324  333  336  366  396  412  424  444  448
488  515  555  636  648  666  728  777  784  824  848  864  888  936  999

MAD

<lang MAD> NORMAL MODE IS INTEGER

           PRINT COMMENT $ $
           
           INTERNAL FUNCTION(N)
           ENTRY TO DVDGT.
           P=1            
           C=N

DGT WHENEVER C.NE.0

               Z = C/10
               D = C-Z*10
               WHENEVER D.E.0 .OR. N/D*D.NE.N, FUNCTION RETURN 0B
               P = P*D
               C = Z
               TRANSFER TO DGT
           END OF CONDITIONAL
           FUNCTION RETURN N/P*P.NE.N
           END OF FUNCTION
           
           THROUGH TEST, FOR I=1, 1, I.E.1000

TEST WHENEVER DVDGT.(I), PRINT FORMAT FMT, I

           VECTOR VALUES FMT = $I4*$
           END OF PROGRAM </lang>
Output:
  22
  33
  44
  48
  55
  66
  77
  88
  99
 122
 124
 126
 155
 162
 168
 184
 222
 244
 248
 264
 288
 324
 333
 336
 366
 396
 412
 424
 444
 448
 488
 515
 555
 636
 648
 666
 728
 777
 784
 824
 848
 864
 888
 936
 999

Phix

function didbntp(integer n)
    integer w = n, p = 1
    while w do
        integer d = remainder(w,10)
        if d=0 or remainder(n,d) then return false end if
        p *= d
        w = floor(w/10)
    end while
    return remainder(n,p)!=0
end function
sequence res = apply(filter(tagset(1000),didbntp),sprint)
printf(1,"found %d didbntp thingies less than one thousand: %s\n",{length(res),join(shorten(res,"",5),",")})
Output:
found 45 didbntp thingies less than one thousand: 22,33,44,48,55,...,848,864,888,936,999

Raku

<lang perl6>say "{+$_} matching numbers:\n{.batch(10)».fmt('%3d').join: "\n"}" given

  (^1000).grep: -> $n { $n.contains(0) ?? False !! all |($n.comb).map($n %% *), $n % [*] $n.comb };</lang>
Output:
45 matching numbers:
 22  33  44  48  55  66  77  88  99 122
124 126 155 162 168 184 222 244 248 264
288 324 333 336 366 396 412 424 444 448
488 515 555 636 648 666 728 777 784 824
848 864 888 936 999

REXX

<lang rexx>/*REXX pgm finds numbers divisible by its individual digits, but not by product of digs.*/ parse arg hi cols . /*obtain optional argument from the CL.*/ if hi== | hi=="," then hi= 1000 /*Not specified? Then use the default.*/ if cols== | cols=="," then cols= 10 /* " " " " " " */ w= 10 /*width of a number in any column. */

                   @ndnp= ' base ten integers  < '   commas(hi)   " that are divisible" ,
                          'by its digits, but not by the product of its digits'

if cols>0 then say ' index │'center(@ndnp, 1 + cols*(w+1) ) if cols>0 then say '───────┼'center("" , 1 + cols*(w+1), '─') finds= 0; idx= 1 /*initialize # of found numbers & index*/ $= /*a list of integers found (so far). */

    do j=1  for hi-1;    L= length(j);    != 1  /*search for integers within the range.*/
    if pos(0, j)>0  then iterate                /*Does J have a zero?  Yes, then skip. */
           do k=1  for L;    x= substr(j, k, 1) /*extract a single decimal digit from J*/
           if j//x\==0   then iterate j         /*J ÷ by this digit?  No, then skip it.*/
           != ! * x                             /*compute the running product of digits*/
           end   /*k*/
    if j//!==0           then iterate           /*J ÷ by its digit product?  Yes, skip.*/
    finds= finds + 1                            /*bump the number of  found  integers. */
    if cols==0           then iterate           /*Build the list  (to be shown later)? */
    $= $ right( commas(j), w)                   /*add the number found to the  $  list.*/
    if finds//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.*/ if cols>0 then say '───────┴'center("" , 1 + cols*(w+1), '─') say say 'Found ' commas(finds) @ndnp 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 ?</lang>

output   when using the default inputs:
 index │      base ten integers  <  1,000  that are divisible by its digits, but not by the product of its digits
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │         22         33         44         48         55         66         77         88         99        122
  11   │        124        126        155        162        168        184        222        244        248        264
  21   │        288        324        333        336        366        396        412        424        444        448
  31   │        488        515        555        636        648        666        728        777        784        824
  41   │        848        864        888        936        999
───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────

Found  45  base ten integers  <  1,000  that are divisible by its digits, but not by the product of its digits

Ring

<lang ring> load "stdlib.ring"

decimals(0) see "working..." + nl see "Numbers divisible by their individual digits, but not by the product of their digits are:" + nl

row = 0 limit = 1000

for n = 1 to limit

   flag = 1
   pro = 1
   strn = string(n)
   for m = 1 to len(strn)
       temp = strn[m]
       if temp != 0
          pro = pro * number(temp)
       ok
       if n%temp = 0
          flag = 1
       else
          flag = 0
          exit
       ok
    next
    bool = ((n%pro) != 0)
    if flag = 1 and bool
       row = row + 1
       see "" + n + " "
       if row%10 = 0
          see nl
       ok
    ok

next

see nl + "Found " + row + " numbers" + nl see "done..." + nl </lang>

Output:
working...
Numbers divisible by their individual digits, but not by the product of their digits are:
22 33 44 48 55 66 77 88 99 122 
124 126 155 162 168 184 222 244 248 264 
288 324 333 336 366 396 412 424 444 448 
488 515 555 636 648 666 728 777 784 824 
848 864 888 936 999 
Found 45 numbers
done...

Snobol

<lang snobol> define('divis(n)i,d,p')  :(divis_end) divis p = 1

       i = n

digit d = remdr(i,10)

       p = ne(d,0) eq(remdr(n,d),0) p * d  :f(freturn)
       i = gt(i,9) i / 10                  :s(digit)
       ne(remdr(n,p))                      :s(return)f(freturn)

divis_end

       n = 1

loop output = divis(n) n

       n = lt(n,1000) n + 1                :s(loop)

end</lang>

Output:
22
33
44
48
55
66
77
88
99
122
124
126
155
162
168
184
222
244
248
264
288
324
333
336
366
396
412
424
444
448
488
515
555
636
648
666
728
777
784
824
848
864
888
936
999

Wren

Library: Wren-math
Library: Wren-seq
Library: Wren-fmt

<lang ecmascript>import "/math" for Int, Nums import "/seq" for Lst import "/fmt" for Fmt

var res = [] for (n in 1..999) {

   var digits = Int.digits(n)
   if (digits.all { |d| n % d == 0 }) {
       var prod = Nums.prod(digits)
       if (prod > 0 && n % prod != 0) res.add(n)
   }

} System.print("Numbers < 1000 divisible by their digits, but not by the product thereof:") for (chunk in Lst.chunks(res, 9)) Fmt.print("$4d", chunk) System.print("\n%(res.count) such numbers found")</lang>

Output:
Numbers < 1000 divisible by their digits, but not by the product thereof:
  22   33   44   48   55   66   77   88   99
 122  124  126  155  162  168  184  222  244
 248  264  288  324  333  336  366  396  412
 424  444  448  488  515  555  636  648  666
 728  777  784  824  848  864  888  936  999

45 such numbers found