# Practical numbers

Practical numbers 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.

A Practical number P has some selection of its proper divisors, (other than itself), that can be selected to sum to every integer less than itself.

Compute all the proper divisors/factors of an input number X, then, using all selections from the factors compute all possible sums of factors and see if all numbers from 1 to X-1 can be created from it.

Write a function that given X returns a boolean value of whether X is a Practical number, (using the above method).

• Show how many Practical numbers there are in the range 1..333, inclusive.
• Show that the Practical numbers in the above range start and end in:
1, 2, 4, 6, 8, 12, 16, 18, 20, 24 ... 288, 294, 300, 304, 306, 308, 312, 320, 324, 330
Stretch Goal
• Show if 666 is a Practical number

## 11l

Translation of: Nim
```F properDivisors(n)
V result = [1]
L(i) 2 .. Int(sqrt(n))
I n % i == 0
V j = n I/ i
result.append(i)
I i != j
result.append(j)
R result

F allSums(n)
V divs = properDivisors(n)
V currSet = Set[Int]()
V result = Set[Int]()
L(d) divs
currSet = copy(result)
L(sum) currSet
R result

F isPractical(n)
R Set(Array(1 .< n)) <= allSums(n)

V count = 0
L(n) 1..333
I isPractical(n)
count++
print(‘#3’.format(n), end' I count % 11 == 0 {"\n"} E ‘ ’)
print(‘Found ’count‘ practical numbers between 1 and 333.’)
print()
print(‘666 is ’(I isPractical(666) {‘’} E ‘not ’)‘a practical number.’)```
Output:
```  1   2   4   6   8  12  16  18  20  24  28
30  32  36  40  42  48  54  56  60  64  66
72  78  80  84  88  90  96 100 104 108 112
120 126 128 132 140 144 150 156 160 162 168
176 180 192 196 198 200 204 208 210 216 220
224 228 234 240 252 256 260 264 270 272 276
280 288 294 300 304 306 308 312 320 324 330
Found 77 practical numbers between 1 and 333.

666 is a practical number.
```

## ALGOL 68

```BEGIN # find some practical numbers - positive integers n where subsets of   #
# their proper divisors can be summed to every positive integer < n    #

# returns TRUE if n is practical, FALSE otherwise                        #
PROC is practical = ( INT n )BOOL:
IF   n < 1 THEN FALSE
ELIF n = 1 THEN TRUE
ELIF ODD n THEN FALSE
ELSE
# get a list of the proper divisors of n                        #
[ 1 : 30 ]INT pd;      # should be more than enough for n < 667 #
INT pd pos := LWB pd - 1;

# returns TRUE if a subset of pd can be summed to n, FALSE otherwise     #
PROC can sum to = ( INT x )BOOL:
BEGIN
BOOL  found sum := FALSE;
INT   max v      = ( 2 ^ pd pos ) - 1;
INT sum := 0;
INT v   := i;
INT bit := 0;
WHILE v > 0 DO
bit +:= 1;
IF ODD v THEN sum +:= pd[ bit ] FI;
v OVERAB 2
OD;
found sum := sum = x
OD;
found sum
END # can sum to # ;

pd[ pd pos +:= 1 ] := 1;
FOR i FROM 2 TO ENTIER sqrt( n ) DO
IF n MOD i = 0 THEN
pd[ pd pos +:= 1 ] := i;
INT j = n OVER i;
IF i /= j THEN pd[ pd pos +:= 1 ] := j FI
FI
OD;
# check that subsets of the divisors can be summed to every     #
# integer less than n                                           #
BOOL practical := TRUE;
FOR i TO n - 1 WHILE practical := can sum to( i ) DO SKIP OD;
practical
FI # is practical # ;

[ 1 : 333 ]BOOL practical;
FOR i FROM LWB practical TO UPB practical DO practical[ i ] := is practical( i ) OD;
INT p count := 0;
FOR i FROM LWB practical TO UPB practical DO IF practical[ i ] THEN p count +:= 1 FI OD;
print( ( "Found ", whole( p count, 0 ), " practical numbers up to ", whole( UPB practical, 0 ), newline ) );
INT count := 0;
FOR i FROM LWB practical TO UPB practical WHILE count < 10 DO
IF practical[ i ] THEN
count +:= 1;
print( ( " ", whole( i, 0 ) ) )
FI
OD;
print( ( " ..." ) );
count := 0;
FOR i FROM LWB practical TO UPB practical DO
IF practical[ i ] THEN
count +:= 1;
IF count > p count - 10 THEN print( ( " ", whole( i, 0 ) ) ) FI
FI
OD;
print( ( newline ) );
print( ( "666 is ", IF NOT is practical( 666 ) THEN "not " ELSE "" FI, "a practical number", newline ) )

END```
Output:
``` 1 2 4 6 8 12 16 18 20 24 ... 288 294 300 304 306 308 312 320 324 330
666 is a practical number
```

## APL

Works with: Dyalog APL
```pract ← ∧/⍳∊(+⌿⊢×[1](2/⍨≢)⊤(⍳2*≢))∘(⍸0=⍳|⊢)
```
Output:
```      ⍸pract¨⍳333  ⍝ Which numbers from 1 to 333 are practical?
1 2 4 6 8 12 16 18 20 24 28 30 32 36 40 42 48 54 56 60 64 66 72 78 80 84 88 90 96 100 104 108 112 120 126 128 132 140 144
150 156 160 162 168 176 180 192 196 198 200 204 208 210 216 220 224 228 234 240 252 256 260 264 270 272 276 280 288
294 300 304 306 308 312 320 324 330
pract 666    ⍝ Is 666 practical?
1
```

## Arturo

```allSums: function [n][
result: []
current: []
loop factors n 'd [
current: new result
loop current 's ->
'result ++ s+d
'result ++ d
unique 'result
]
return result
]

practical?: function [n]->
or? -> n=1 -> subset? @1..dec n allSums n

practicals: select 1..333 => practical?

print ["Found" size practicals "practical numbers between 1 and 333:"]
loop split.every: 10 practicals 'x ->
print map x 's -> pad to :string s 4

print ""
p666: practical? 666
print ["666" p666 ? -> "is" -> "is not" "a practical number"]
```
Output:
```Found 77 practical numbers between 1 and 333:
1    2    4    6    8   12   16   18   20   24
28   30   32   36   40   42   48   54   56   60
64   66   72   78   80   84   88   90   96  100
104  108  112  120  126  128  132  140  144  150
156  160  162  168  176  180  192  196  198  200
204  208  210  216  220  224  228  234  240  252
256  260  264  270  272  276  280  288  294  300
304  306  308  312  320  324  330

666 is a practical number```

## C#

```using System.Collections.Generic; using System.Linq; using static System.Console;

class Program {

static bool soas(int n, IEnumerable<int> f) {
if (n <= 0) return false; if (f.Contains(n)) return true;
switch(n.CompareTo(f.Sum())) { case 1: return false; case 0: return true;
case -1: var rf = f.Reverse().ToList(); var d = n - rf[0]; rf.RemoveAt(0);
return soas(d, rf) || soas(n, rf); } return true; }

static bool ip(int n) { var f = Enumerable.Range(1, n >> 1).Where(d => n % d == 0).ToList();
return Enumerable.Range(1, n - 1).ToList().TrueForAll(i => soas(i, f));  }

static void Main() {
int c = 0, m = 333; for (int i = 1; i <= m; i += i == 1 ? 1 : 2)
if (ip(i) || i == 1) Write("{0,3} {1}", i, ++c % 10 == 0 ? "\n" : "");
Write("\nFound {0} practical numbers between 1 and {1} inclusive.\n", c, m);
do Write("\n{0,5} is a{1}practical number.",
m = m < 500 ? m << 1 : m * 10 + 6, ip(m) ? " " : "n im"); while (m < 1e4); } }
```
Output:
```  1   2   4   6   8  12  16  18  20  24
28  30  32  36  40  42  48  54  56  60
64  66  72  78  80  84  88  90  96 100
104 108 112 120 126 128 132 140 144 150
156 160 162 168 176 180 192 196 198 200
204 208 210 216 220 224 228 234 240 252
256 260 264 270 272 276 280 288 294 300
304 306 308 312 320 324 330
Found 77 practical numbers between 1 and 333 inclusive.

666 is a practical number.
6666 is a practical number.
66666 is an impractical number.```

## C++

Translation of: Phix
```#include <algorithm>
#include <iostream>
#include <numeric>
#include <sstream>
#include <vector>

// Returns true if any subset of [begin, end) sums to n.
template <typename iterator>
bool sum_of_any_subset(int n, iterator begin, iterator end) {
if (begin == end)
return false;
if (std::find(begin, end, n) != end)
return true;
int total = std::accumulate(begin, end, 0);
if (n == total)
return true;
if (n > total)
return false;
--end;
int d = n - *end;
return (d > 0 && sum_of_any_subset(d, begin, end)) ||
sum_of_any_subset(n, begin, end);
}

// Returns the proper divisors of n.
std::vector<int> factors(int n) {
std::vector<int> f{1};
for (int i = 2; i * i <= n; ++i) {
if (n % i == 0) {
f.push_back(i);
if (i * i != n)
f.push_back(n / i);
}
}
std::sort(f.begin(), f.end());
return f;
}

bool is_practical(int n) {
std::vector<int> f = factors(n);
for (int i = 1; i < n; ++i) {
if (!sum_of_any_subset(i, f.begin(), f.end()))
return false;
}
return true;
}

std::string shorten(const std::vector<int>& v, size_t n) {
std::ostringstream out;
size_t size = v.size(), i = 0;
if (n > 0 && size > 0)
out << v[i++];
for (; i < n && i < size; ++i)
out << ", " << v[i];
if (size > i + n) {
out << ", ...";
i = size - n;
}
for (; i < size; ++i)
out << ", " << v[i];
return out.str();
}

int main() {
std::vector<int> practical;
for (int n = 1; n <= 333; ++n) {
if (is_practical(n))
practical.push_back(n);
}
std::cout << "Found " << practical.size() << " practical numbers:\n"
<< shorten(practical, 10) << '\n';
for (int n : {666, 6666, 66666, 672, 720, 222222})
std::cout << n << " is " << (is_practical(n) ? "" : "not ")
<< "a practical number.\n";
return 0;
}
```
Output:
```Found 77 practical numbers:
1, 2, 4, 6, 8, 12, 16, 18, 20, 24, ..., 288, 294, 300, 304, 306, 308, 312, 320, 324, 330
666 is a practical number.
6666 is a practical number.
66666 is not a practical number.
672 is a practical number.
720 is a practical number.
222222 is a practical number.
```

See Pascal.

## FreeBASIC

```sub make_divisors( n as uinteger, div() as uinteger )
'produces a list of an integer's proper divisors
for i as uinteger = n/2 to 1 step -1
if n mod i = 0 then
redim preserve div(1 to 1 + ubound(div))
div(ubound(div)) = i
end if
next i
end sub

function sum_divisors( n as uinteger, div() as uinteger ) as uinteger
'takes a list of divisors and an integer which, when interpreted
'as binary, selects which terms to sum
dim as uinteger sum = 0, term = 1
while n
if n mod 2 = 1 then sum += div(term)
term += 1
n\=2
wend
return sum
end function

function is_practical( n as uinteger ) as boolean
'determines if an integer is practical
if n = 1 then return true
if n mod 2 = 1 then return false    'there can be no odd practicals other than 1
if n < 5 then return true           '2 and 4 are practical, but small enough to be handled specially
dim as uinteger hits(1 to n-1), nt, i, sd
redim as uinteger div(0 to 0)
make_divisors( n, div() )
nt = ubound(div)
for i = 1 to 2^nt-1
sd = sum_divisors(i, div())
if sd<n then hits(sd)+=1
next i
for i = 1 to n-1
if hits(i) = 0 then return false
next i
return true
end function

print 1;" ";  'treat 1 as a special case

for n as uinteger = 2 to 666
if is_practical(n) then print n;" ";
next n:print```

All practical numbers up to and including the stretch goal of DCLXVI.

Output:
```
1 2 4 6 8 12 16 18 20 24 28 30 32 36 40 42 48 54 56 60 64 66 72 78 80 84 88 90 96 100 104 108 112 120 126 128 132 140 144 150 156 160 162 168 176 180 192 196 198 200 204 208 210 216 220 224 228 234 240 252 256 260 264 270 272 276 280 288 294 300 304 306 308 312 320 324 330 336 340 342 348 352 360 364 368 378 380 384 390 392 396 400 408 414 416 420 432 440 448 450 456 460 462 464 468 476 480 486 496 500 504 510 512 520 522 528 532 540 544 546 552 558 560 570 576 580 588 594 600 608 612 616 620 624 630 640 644 648 660 666```

## Go

Translation of: Wren
Library: Go-rcu
```package main

import (
"fmt"
"rcu"
)

func powerset(set []int) [][]int {
if len(set) == 0 {
return [][]int{{}}
}
tail := set[1:]
p1 := powerset(tail)
var p2 [][]int
for _, s := range powerset(tail) {
h = append(h, s...)
p2 = append(p2, h)
}
return append(p1, p2...)
}

func isPractical(n int) bool {
if n == 1 {
return true
}
divs := rcu.ProperDivisors(n)
subsets := powerset(divs)
found := make([]bool, n) // all false by default
count := 0
for _, subset := range subsets {
sum := rcu.SumInts(subset)
if sum > 0 && sum < n && !found[sum] {
found[sum] = true
count++
if count == n-1 {
return true
}
}
}
return false
}

func main() {
fmt.Println("In the range 1..333, there are:")
var practical []int
for i := 1; i <= 333; i++ {
if isPractical(i) {
practical = append(practical, i)
}
}
fmt.Println(" ", len(practical), "practical numbers")
fmt.Println("  The first ten are", practical[0:10])
fmt.Println("  The final ten are", practical[len(practical)-10:])
fmt.Println("\n666 is practical:", isPractical(666))
}
```
Output:
```In the range 1..333, there are:
77 practical numbers
The first ten are [1 2 4 6 8 12 16 18 20 24]
The final ten are [288 294 300 304 306 308 312 320 324 330]

666 is practical: true
```

## J

Borrowed from the Proper divisors#J page:

```factors=: [: /:~@, */&>@{@((^ i.@>:)&.>/)@q:~&__
properDivisors=: factors -. ]
```

Borrowed from the Power set#J page:

```ps=:  #~ 2 #:@i.@^ #
```

Implementation:

```isPrac=: ('' -:&# i. -. 0,+/"1@(ps ::empty)@properDivisors)"0
```

```   +/ isPrac 1+i.333    NB. count practical numbers
77
(#~ isPrac) 1+i.333  NB. list them
1 2 4 6 8 12 16 18 20 24 28 30 32 36 40 42 48 54 56 60 64 66 72 78 80 84 88 90 96 100 104 108 112 120 126 128 132 140 144 150 156 160 162 168 176 180 192 196 198 200 204 208 210 216 220 224 228 234 240 252 256 260 264 270 272 276 280 288 294 300 304 306 30...
isPrac 666           NB. test
1
```

## Java

Translation of: Phix
```import java.util.*;

public class PracticalNumbers {
public static void main(String[] args) {
final int from = 1;
final int to = 333;
List<Integer> practical = new ArrayList<>();
for (int i = from; i <= to; ++i) {
if (isPractical(i))
}
System.out.printf("Found %d practical numbers between %d and %d:\n%s\n",
practical.size(), from, to, shorten(practical, 10));

printPractical(666);
printPractical(6666);
printPractical(66666);
printPractical(672);
printPractical(720);
printPractical(222222);
}

private static void printPractical(int n) {
if (isPractical(n))
System.out.printf("%d is a practical number.\n", n);
else
System.out.printf("%d is not a practical number.\n", n);
}

private static boolean isPractical(int n) {
int[] divisors = properDivisors(n);
for (int i = 1; i < n; ++i) {
if (!sumOfAnySubset(i, divisors, divisors.length))
return false;
}
return true;
}

private static boolean sumOfAnySubset(int n, int[] f, int len) {
if (len == 0)
return false;
int total = 0;
for (int i = 0; i < len; ++i) {
if (n == f[i])
return true;
total += f[i];
}
if (n == total)
return true;
if (n > total)
return false;
--len;
int d = n - f[len];
return (d > 0 && sumOfAnySubset(d, f, len)) || sumOfAnySubset(n, f, len);
}

private static int[] properDivisors(int n) {
List<Integer> divisors = new ArrayList<>();
for (int i = 2;; ++i) {
int i2 = i * i;
if (i2 > n)
break;
if (n % i == 0) {
if (i2 != n)
}
}
int[] result = new int[divisors.size()];
for (int i = 0; i < result.length; ++i)
result[i] = divisors.get(i);
Arrays.sort(result);
return result;
}

private static String shorten(List<Integer> list, int n) {
StringBuilder str = new StringBuilder();
int len = list.size(), i = 0;
if (n > 0 && len > 0)
str.append(list.get(i++));
for (; i < n && i < len; ++i) {
str.append(", ");
str.append(list.get(i));
}
if (len > i + n) {
if (n > 0)
str.append(", ...");
i = len - n;
}
for (; i < len; ++i) {
str.append(", ");
str.append(list.get(i));
}
return str.toString();
}
}
```
Output:
```Found 77 practical numbers between 1 and 333:
1, 2, 4, 6, 8, 12, 16, 18, 20, 24, ..., 288, 294, 300, 304, 306, 308, 312, 320, 324, 330
666 is a practical number.
6666 is a practical number.
66666 is not a practical number.
672 is a practical number.
720 is a practical number.
222222 is a practical number.
```

## jq

Works with: jq

Works with gojq, the Go implementation of jq

This implementation does not create an in-memory representation of the powerset; this saves some time and of course potentially a great deal of memory.

The version of `proper_divisors` at Proper_divisors#jq may be used and therefore its definition is not repeated here.

```# A reminder to include the definition of `proper_divisors`
# include "proper_divisors" { search: "." };

# Input: an array, each of whose elements is treated as distinct.
# Output: a stream of arrays.
# If the items in the input array are distinct, then the items in the
# stream represent the items in the powerset of the input array.  If
# the items in the input array are sorted, then the items in each of
# the output arrays will also be sorted.  The lengths of the output
# arrays are non-decreasing.
def powersetStream:
if length == 0 then []
else .[0] as \$first
| (.[1:] | powersetStream)
| ., ([\$first] + . )
end;

def isPractical:
. as \$n
| if . == 1 then true
elif . % 2 == 1 then false
else [proper_divisors] as \$divs
| first(
foreach (\$divs|powersetStream) as \$subset (
{found: [],
count:  0 };
| if \$sum > 0 and \$sum < \$n and (.found[\$sum] | not)
then .found[\$sum] = true
| .count += 1
| if (.count == \$n - 1) then .emit = true
else .
end
else .
end;
select(.emit).emit) )
// false
end;

# Input: the upper bound of range(1,_) to consider (e.g. infinite)
# Output: a stream of the practical numbers, in order
def practical:
range(1;.)
| select(isPractical);

(\$n + 1 | [practical]) as \$p
| ("In the range 1 .. \(\$n) inclusive, there are \(\$p|length) practical numbers.",
"The first ten are:", \$p[0:10],
"The last ten are:", \$p[-10:] );

(666,6666,66666
| "\nIs \(.) practical? \(if isPractical then "Yes." else "No." end)" )```
Output:
```In the range 1 .. 333 inclusive, there are 77 practical numbers.
The first ten are:
[1,2,4,6,8,12,16,18,20,24]
The last ten are:
[288,294,300,304,306,308,312,320,324,330]

Is 666 practical? Yes.

Is 6666 practical? Yes.

Is 66666 practical? No.
```

## Julia

Translation of: Python
```using Primes

""" proper divisors of n """
function proper_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
pop!(f)
return f
end

""" return true if any subset of f sums to n. """
function sumofanysubset(n, f)
n in f && return true
total = sum(f)
n == total && return true
n > total && return false
rf = reverse(f)
d = n - popfirst!(rf)
return (d in rf) || (d > 0 && sumofanysubset(d, rf)) || sumofanysubset(n, rf)
end

function ispractical(n)
n == 1 && return true
isodd(n) && return false
f = proper_divisors(n)
return all(i -> sumofanysubset(i, f), 1:n-1)
end

const prac333 = filter(ispractical, 1:333)
println("There are ", length(prac333), " practical numbers between 1 to 333 inclusive.")
println("Start and end: ", filter(x -> x < 25, prac333), " ... ", filter(x -> x > 287, prac333), "\n")
for n in [666, 6666, 66666, 222222]
println("\$n is ", ispractical(n) ? "" : "not ", "a practical number.")
end
```
Output:
```There are 77 practical numbers between 1 to 333 inclusive.
Start and end: [1, 2, 4, 6, 8, 12, 16, 18, 20, 24] ... [288, 294, 300, 304, 306, 308, 312, 320, 324, 330]

666 is a practical number.
6666 is a practical number.
66666 is not a practical number.
222222 is a practical number.
```

## Nim

```import intsets, math, sequtils, strutils

func properDivisors(n: int): seq[int] =
result = @[1]
for i in 2..sqrt(n.toFloat).int:
if n mod i == 0:
let j = n div i
if i != j: result.add j

func allSums(n: Positive): IntSet =
let divs = n.properDivisors()
var currSet: IntSet
for d in divs:
currSet.assign(result)  # Make a copy of the set.
for sum in currSet:
result.incl sum + d   # Add a new sum to the set.
result.incl d           # Add the single value.

func isPractical(n: Positive): bool =
toSeq(1..<n).toIntSet <= allSums(n)

var count = 0
for n in 1..333:
if n.isPractical:
inc count
stdout.write (\$n).align(3), if count mod 11 == 0: '\n' else: ' '
echo "Found ", count, " practical numbers between 1 and 333."
echo()
echo "666 is ", if 666.isPractical: "" else: "not ", "a practical number."
```
Output:
```  1   2   4   6   8  12  16  18  20  24  28
30  32  36  40  42  48  54  56  60  64  66
72  78  80  84  88  90  96 100 104 108 112
120 126 128 132 140 144 150 156 160 162 168
176 180 192 196 198 200 204 208 210 216 220
224 228 234 240 252 256 260 264 270 272 276
280 288 294 300 304 306 308 312 320 324 330
Found 77 practical numbers between 1 and 333.

666 is a practical number.```

## Pascal

simple brute force.Marking sum of divs by shifting the former sum by the the next divisor.
SumAllSetsForPractical tries to break as soon as possible.Should try to check versus https://en.wikipedia.org/wiki/Practical_number#Characterization_of_practical_numbers

```...σ denotes the sum of the divisors of x. For example, 2 × 3^2 × 29 × 823 = 429606 is practical,
because the inequality above holds for each of its prime factors:
3 ≤ σ(2) + 1 = 4, 29 ≤ σ(2 × 3^2) + 1 = 40, and 823 ≤ σ(2 × 3^2 × 29) + 1 = 1171. ```
```program practicalnumbers;
{\$IFDEF FPC}
{\$MODE DELPHI}{\$OPTIMIZATION ON,ALL}
{\$ELSE}
{\$APPTYPE CONSOLE}

{\$ENDIF}

uses
sysutils
{\$IFNDEF FPC}
,Windows
{\$ENDIF}
;

const
LOW_DIVS = 0;
HIGH_DIVS = 2048 - 1;

type
tdivs = record
DivsVal: array[LOW_DIVS..HIGH_DIVS] of Uint32;
DivsMaxIdx, DivsNum, DivsSumProp: NativeUInt;
end;

var
Divs: tDivs;
HasSum: array of byte;

procedure GetDivisors(var Divs: tdivs; n: Uint32);
//calc all divisors,keep sorted
var
i, quot, ug, og: UInt32;
sum: UInt64;
begin
with Divs do
begin
DivsNum := n;
sum := 0;
ug := 0;
og := HIGH_DIVS;
i := 1;

while i * i < n do
begin
quot := n div i;
if n - quot * i = 0 then
begin
DivsVal[og] := quot;
Divs.DivsVal[ug] := i;
inc(sum, quot + i);
dec(og);
inc(ug);
end;
inc(i);
end;
if i * i = n then
begin
DivsVal[og] := i;
inc(sum, i);
dec(og);
end;
//move higher divisors down
while og < high_DIVS do
begin
inc(og);
DivsVal[ug] := DivsVal[og];
inc(ug);
end;
DivsMaxIdx := ug - 2;
DivsSumProp := sum - n;
end; //with
end;

function SumAllSetsForPractical(Limit: Uint32): boolean;
//mark sum and than shift by next divisor == add
//for practical numbers every sum must be marked
var
hs0, hs1: pByte;
idx, j, loLimit, maxlimit, delta: NativeUint;
begin
Limit := trunc(Limit * (Limit / Divs.DivsSumProp));
loLimit := 0;
maxlimit := 0;
hs0 := @HasSum[0];
hs0[0] := 1; //empty set
for idx := 0 to Divs.DivsMaxIdx do
begin
delta := Divs.DivsVal[idx];
hs1 := @hs0[delta];
for j := maxlimit downto 0 do
hs1[j] := hs1[j] or hs0[j];
maxlimit := maxlimit + delta;
while hs0[loLimit] <> 0 do
inc(loLimit);
//IF there is a 0 < delta, it will never be set
//IF there are more than the Limit set,
//it will be copied by the following Delta's
if (loLimit < delta) or (loLimit > Limit) then
Break;
end;
result := (loLimit > Limit);
end;

function isPractical(n: Uint32): boolean;
var
i: NativeInt;
sum: NativeUInt;
begin
if n = 1 then
EXIT(True);
if ODD(n) then
EXIT(false);
if (n > 2) and not ((n mod 4 = 0) or (n mod 6 = 0)) then
EXIT(false);

GetDivisors(Divs, n);
i := n - 1;
sum := Divs.DivsSumProp;
if sum < i then
result := false
else
begin
if length(HasSum) > sum + 1 + 1 then
FillChar(HasSum[0], sum + 1, #0)
else
begin
setlength(HasSum, 0);
setlength(HasSum, sum + 8 + 1);
end;
result := SumAllSetsForPractical(i);
end;
end;

procedure OutIsPractical(n: nativeInt);
begin
if isPractical(n) then
writeln(n, ' is practical')
else
writeln(n, ' is not practical');
end;

const
ColCnt = 10;
MAX = 333;

var
T0: Int64;
n, col, count: NativeInt;

begin
col := ColCnt;
count := 0;
for n := 1 to MAX do
if isPractical(n) then
begin
write(n: 5);
inc(count);
dec(col);
if col = 0 then
begin
writeln;
col := ColCnt;
end;
end;
writeln;
writeln('There are ', count, ' pratical numbers from 1 to ', MAX);
writeln;

T0 := GetTickCount64;
OutIsPractical(666);
OutIsPractical(6666);
OutIsPractical(66666);
OutIsPractical(954432);
OutIsPractical(720);
OutIsPractical(5384);
OutIsPractical(1441440);
writeln(Divs.DivsNum, ' has ', Divs.DivsMaxIdx + 1, ' proper divisors');
writeln((GetTickCount64 - T0) / 1000: 10: 3, ' s');
T0 := GetTickCount64;
OutIsPractical(99998640);
writeln(Divs.DivsNum, ' has ', Divs.DivsMaxIdx + 1, ' proper divisors ');
writeln((GetTickCount64 - T0) / 1000: 10: 3, ' s');
T0 := GetTickCount64;
OutIsPractical(99998640);
writeln(Divs.DivsNum, ' has ', Divs.DivsMaxIdx + 1, ' proper divisors ');
writeln((GetTickCount64 - T0) / 1000: 10: 3, ' s');
setlength(HasSum, 0);
end.
```
Output:
``` TIO.RUN.

1    2    4    6    8   12   16   18   20   24
28   30   32   36   40   42   48   54   56   60
64   66   72   78   80   84   88   90   96  100
104  108  112  120  126  128  132  140  144  150
156  160  162  168  176  180  192  196  198  200
204  208  210  216  220  224  228  234  240  252
256  260  264  270  272  276  280  288  294  300
304  306  308  312  320  324  330
There are 77 pratical numbers from 1 to 333

666 is practical
6666 is practical
66666 is not practical
954432 is not practical
720 is practical
5384 is not practical
1441440 is practical
1441440 has 287 proper divisors
0.017 s
99998640 is not practical
99998640 has 119 proper divisors
0.200 s // with reserving memory
99998640 is not practical
99998640 has 119 proper divisors
0.081 s // already reserved memory

Real time: 0.506 s CPU share: 87.94 %```

### alternative

Now without generating sum of allset.

```program practicalnumbers2;

{\$IFDEF FPC}
{\$MODE DELPHI}{\$OPTIMIZATION ON,ALL}
{\$ELSE}
{\$APPTYPE CONSOLE}
{\$ENDIF}
uses
SysUtils;

type
tdivs = record
DivsVal: array[0..1024 - 1] of Uint32;
end;

var
Divs: tDivs;

function CheckIsPractical(var Divs: tdivs; n: Uint32): boolean;
//calc all divisors,calc sum of divisors
var
sum: UInt64;
i :NativeInt;
quot,ug,sq,de: UInt32;

begin
with Divs do
begin
sum := 1;
ug := Low(tdivs.DivsVal);
i  := 2;
sq := 4;
de := 5;
while sq < n do
begin
quot := n div i;
if n - quot * i = 0 then
begin
if sum + 1 < i then
EXIT(false);
Inc(sum, i);
DivsVal[ug] := quot;
Inc(ug);
end;
Inc(i);
sq += de;
de := de+2;
end;
if sq = n then
begin
if sum + 1 < i then
EXIT(false);
DivsVal[ug] := i;
Inc(sum, i);
Inc(ug);
end;
//check higher
while ug > 0 do
begin
Dec(ug);
i := DivsVal[ug];
if sum + 1 < i then
EXIT(false);
Inc(sum, i);
if sum >= n - 1 then
break;
end;
end;//with
result := true;
end;

function isPractical(n: Uint32): boolean;
begin
if n in [1,2] then
EXIT(True);
if ODD(n) then
EXIT(False);
Result := CheckIsPractical(Divs, n);
end;

procedure OutIsPractical(n: nativeInt);
begin
if isPractical(n) then
writeln(n, ' is practical')
else
writeln(n, ' is not practical');
end;

const
ColCnt = 10;
MAX = 333;
var
T0 : int64;
n, col, Count: NativeInt;
begin
col := ColCnt;
Count := 0;
for n := 1 to MAX do
if isPractical(n) then
begin
Write(n: 5);
Inc(Count);
Dec(col);
if col = 0 then
begin
writeln;
col := ColCnt;
end;
end;
writeln;
writeln('There are ', Count, ' pratical numbers from 1 to ', MAX);
writeln;

OutIsPractical(666);
OutIsPractical(6666);
OutIsPractical(66666);
OutIsPractical(954432);
OutIsPractical(720);
OutIsPractical(5184);
OutIsPractical(1441440);
OutIsPractical(99998640);

T0 := GetTickCOunt64;
count := 0;
For n := 1 to 1000*1000 do
inc(count,Ord(isPractical(n)));
writeln('Count of practical numbers til 1,000,000 ',count,(GetTickCount64-t0)/1000:8:4,' s');
{\$IFDEF WINDOWS}
{\$ENDIF}
end.
```
Output:
``` TIO.RUN
1    2    4    6    8   12   16   18   20   24
28   30   32   36   40   42   48   54   56   60
64   66   72   78   80   84   88   90   96  100
104  108  112  120  126  128  132  140  144  150
156  160  162  168  176  180  192  196  198  200
204  208  210  216  220  224  228  234  240  252
256  260  264  270  272  276  280  288  294  300
304  306  308  312  320  324  330
There are 77 pratical numbers from 1 to 333

666 is practical
6666 is practical
66666 is not practical
954432 is not practical
720 is practical
5184 is practical
1441440 is practical
99998640 is not practical
Count of practical numbers til 1,000,000 97385  2.1380 s

Real time: 2.277 s CPU share: 99.55 %```

## Perl

Library: ntheory
```use strict;
use warnings;
use feature 'say';
use enum <False True>;
use ntheory <divisors vecextract>;
use List::AllUtils <sum uniq firstidx>;

sub proper_divisors {
return 1 if 0 == (my \$n = shift);
my @d = divisors(\$n);
pop @d;
@d
}

sub powerset_sums { uniq map { sum vecextract(\@_,\$_) } 1..2**@_-1 }

sub is_practical {
my(\$n) = @_;
return True  if \$n == 1;
return False if 0 != \$n % 2;
(\$n-2 == firstidx { \$_ == \$n-1 } powerset_sums(proper_divisors(\$n)) ) ? True : False;
}

my @pn;
is_practical(\$_) and push @pn, \$_ for 1..333;
say @pn . " matching numbers:\n" . (sprintf "@{['%4d' x @pn]}", @pn) =~ s/(.{40})/\$1\n/gr;
say '';
printf "%6d is practical? %s\n", \$_, is_practical(\$_) ? 'True' : 'False' for 666, 6666, 66666;
```
Output:
```77 matching numbers:
1   2   4   6   8  12  16  18  20  24
28  30  32  36  40  42  48  54  56  60
64  66  72  78  80  84  88  90  96 100
104 108 112 120 126 128 132 140 144 150
156 160 162 168 176 180 192 196 198 200
204 208 210 216 220 224 228 234 240 252
256 260 264 270 272 276 280 288 294 300
304 306 308 312 320 324 330

666 is practical? True
6666 is practical? True
66666 is practical? False```

## Phix

Translation of: Python – (the composition of functions version)
```function sum_of_any_subset(integer n, sequence f)
-- return true if any subset of f sums to n.
if find(n,f) then return true end if
integer total = sum(f)
if n=total then return true
elsif n>total then return false end if
integer d = n-f[\$]
f = f[1..\$-1]
return find(d,f)
or (d>0 and sum_of_any_subset(d, f))
or sum_of_any_subset(n, f)
end function

function is_practical(integer n)
sequence f = factors(n,-1)
for i=1 to n-1 do
if not sum_of_any_subset(i,f) then return false end if
end for
return true
end function

sequence res = apply(true,sprintf,{{"%3d"},filter(tagset(333),is_practical)})
printf(1,"Found %d practical numbers:\n%s\n\n",{length(res),join(shorten(res,"",10),", ")})

procedure stretch(integer n)
printf(1,"is_practical(%d):%t\n",{n,is_practical(n)})
end procedure
papply({666,6666,66666,672,720},stretch)
```
Output:
```Found 77 practical numbers:
1,   2,   4,   6,   8,  12,  16,  18,  20,  24, ..., 288, 294, 300, 304, 306, 308, 312, 320, 324, 330

is_practical(666):true
is_practical(6666):true
is_practical(66666):false
is_practical(672):true
is_practical(720):true
```

## Python

### Python: Straight forward implementation

```from itertools import chain, cycle, accumulate, combinations
from typing import List, Tuple

# %% Factors

def factors5(n: int) -> List[int]:
"""Factors of n, (but not n)."""
def prime_powers(n):
# c goes through 2, 3, 5, then the infinite (6n+1, 6n+5) series
for c in accumulate(chain([2, 1, 2], cycle([2,4]))):
if c*c > n: break
if n%c: continue
d,p = (), c
while not n%c:
n,p,d = n//c, p*c, d + (p,)
yield(d)
if n > 1: yield((n,))

r = [1]
for e in prime_powers(n):
r += [a*b for a in r for b in e]
return r[:-1]

# %% Powerset

def powerset(s: List[int]) -> List[Tuple[int, ...]]:
"""powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3) ."""
return chain.from_iterable(combinations(s, r) for r in range(1, len(s)+1))

# %% Practical number

def is_practical(x: int) -> bool:
"""
Is x a practical number.

I.e. Can some selection of the proper divisors of x, (other than x), sum
to i for all i in the range 1..x-1 inclusive.
"""
if x == 1:
return True
if x %2:
return False  # No Odd number more than 1
f = factors5(x)
ps = powerset(f)
found = {y for y in {sum(i) for i in ps}
if 1 <= y < x}
return len(found) == x - 1

if __name__ == '__main__':
n = 333
p = [x for x in range(1, n + 1) if is_practical(x)]
print(f"There are {len(p)} Practical numbers from 1 to {n}:")
print(' ', str(p[:10])[1:-1], '...', str(p[-10:])[1:-1])
x = 666
print(f"\nSTRETCH GOAL: {x} is {'not ' if not is_practical(x) else ''}Practical.")
```
Output:
```There are 77 Practical numbers from 1 to 333:
1, 2, 4, 6, 8, 12, 16, 18, 20, 24 ... 288, 294, 300, 304, 306, 308, 312, 320, 324, 330

STRETCH GOAL: 666 is Practical.```

#### Python: Faster version

This version has an optimisation that proves much faster when testing a range of numbers for Practicality.

A number with a large number of factors, f has `2**len(f)` sets in its powerset. 672 for example has 23 factors and so 8_388_608 sets in its powerset.
Just taking the sets as they are generated and stopping when we first know that 672 is Practical needs just the first 28_826 or 0.34% of the sets. 720, another Practical number needs just 0.01% of its half a billion sets to prove it is Practical.

The inner loop is sensitive to the order of factors passed to the powerset generator and experimentation shows that reverse sorting the factors saves the most computation.
An extra check on the sum of all factors has a minor positive effect too.

```def is_practical5(x: int) -> bool:
"""Practical number test with factor reverse sort and short-circuiting."""

if x == 1:
return True
if x % 2:
return False  # No Odd number more than 1
mult_4_or_6 = (x % 4 == 0) or (x % 6 == 0)
if x > 2 and not mult_4_or_6:
return False  # If > 2 then must be a divisor of 4 or 6

f = sorted(factors5(x), reverse=True)
if sum(f) < x - 1:
return False # Never get x-1
ps = powerset(f)

found = set()
for nps in ps:
if len(found) < x - 1:
y = sum(nps)
if 1 <= y < x:
else:
break   # Short-circuiting the loop.

return len(found) == x - 1

if __name__ == '__main__':
n = 333
print("\n" + is_practical5.__doc__)
p = [x for x in range(1, n + 1) if is_practical5(x)]
print(f"There are {len(p)} Practical numbers from 1 to {n}:")
print(' ', str(p[:10])[1:-1], '...', str(p[-10:])[1:-1])
x = 666
print(f"\nSTRETCH GOAL: {x} is {'not ' if not is_practical(x) else ''}Practical.")
x = 5184
print(f"\nEXTRA GOAL: {x} is {'not ' if not is_practical(x) else ''}Practical.")
```
Output:

Using the definition of factors5 from the simple case above then the following results are obtained.

```Practical number test with factor reverse sort and short-circuiting.
There are 77 Practical numbers from 1 to 333:
1, 2, 4, 6, 8, 12, 16, 18, 20, 24 ... 288, 294, 300, 304, 306, 308, 312, 320, 324, 330

STRETCH GOAL: 666 is Practical.

EXTRA GOAL: 5184 is Practical.```

5184, which is practical, has 34 factors!

A little further investigation shows that you need to get to 3850, for the first example of a number with 23 or more factors that is not Practical.

Around 1/8'th of the integers up to the 10_000'th Practical number have more than 22 factors but are not practical numbers themselves. (Some of these have 31 factors whilst being divisible by four or six so would need the long loop to complete)!

### Composition of pure functions

```'''Practical numbers'''

from itertools import accumulate, chain, groupby, product
from math import floor, sqrt
from operator import mul
from functools import reduce
from typing import Callable, List

def isPractical(n: int) -> bool:
'''True if n is a Practical number
(a member of OEIS A005153)
'''
ds = properDivisors(n)
return all(map(
sumOfAnySubset(ds),
range(1, n)
))

def sumOfAnySubset(xs: List[int]) -> Callable[[int], bool]:
'''True if any subset of xs sums to n.
'''
def go(n):
if n in xs:
return True
else:
total = sum(xs)
if n == total:
return True
elif n < total:
h, *t = reversed(xs)
d = n - h
return d in t or (
d > 0 and sumOfAnySubset(t)(d)
) or sumOfAnySubset(t)(n)
else:
return False
return go

# ------------------------- TEST -------------------------
def main() -> None:
'''Practical numbers in the range [1..333],
and the OEIS A005153 membership of 666.
'''

xs = [x for x in range(1, 334) if isPractical(x)]
print(
f'{len(xs)} OEIS A005153 numbers in [1..333]\n\n' + (
spacedTable(
chunksOf(10)([
str(x) for x in xs
])
)
)
)
print("\n")
for n in [666]:
print(
f'{n} is practical :: {isPractical(n)}'
)

# ----------------------- GENERIC ------------------------

def chunksOf(n: int) -> Callable[[List[str]], List[List[str]]]:
'''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

def primeFactors(n: int) -> List[int]:
'''A list of the prime factors of n.
'''
def f(qr):
r = qr[1]
return step(r), 1 + r

def step(x):
return 1 + (x << 2) - ((x >> 1) << 1)

def go(x):
root = floor(sqrt(x))

def p(qr):
q = qr[0]
return root < q or 0 == (x % q)

q = until(p)(f)(
(2 if 0 == x % 2 else 3, 1)
)[0]
return [x] if q > root else [q] + go(x // q)

return go(n)

def properDivisors(n: int) -> List[int]:
'''The ordered divisors of n, excluding n itself.
'''
def go(a, x):
return [a * b for a, b in product(
a,
accumulate(chain([1], x), mul)
)]
return sorted(
reduce(go, [
list(g) for _, g in groupby(primeFactors(n))
], [1])
)[:-1] if 1 < n else []

def listTranspose(xss: List[List[str]]) -> List[List[str]]:
'''Transposed matrix'''
def go(xss):
if xss:
h, *t = xss
return (
[[h[0]] + [xs[0] for xs in t if xs]] + (
go([h[1:]] + [xs[1:] for xs in t])
)
) if h and isinstance(h, list) else go(t)
else:
return []
return go(xss)

def until(p: Callable[[int], bool]) -> Callable[[int], bool]:
'''The result of repeatedly applying f until p holds.
The initial seed value is x.
'''
def go(f):
def g(x):
v = x
while not p(v):
v = f(v)
return v
return g
return go

# ---------------------- FORMATTING ----------------------

def spacedTable(rows: List[List[str]]) -> str:
'''Tabulation with right-aligned cells'''
columnWidths = [
len(str(row[-1])) for row in listTranspose(rows)
]

def aligned(s, w):
return s.rjust(w, ' ')

return '\n'.join(
' '.join(
map(aligned, row, columnWidths)
) for row in rows
)

# MAIN ---
if __name__ == '__main__':
main()
```
Output:
```77 OEIS A005153 numbers in [1..333]

1   2   4   6   8  12  16  18  20  24
28  30  32  36  40  42  48  54  56  60
64  66  72  78  80  84  88  90  96 100
104 108 112 120 126 128 132 140 144 150
156 160 162 168 176 180 192 196 198 200
204 208 210 216 220 224 228 234 240 252
256 260 264 270 272 276 280 288 294 300
304 306 308 312 320 324 330

666 is practical :: True```

## Raku

```use Prime::Factor:ver<0.3.0+>;

sub is-practical (\$n) {
return True  if \$n == 1;
return False if \$n % 2;
my @proper = \$n.&proper-divisors :sort;
return True if all( @proper.rotor(2 => -1).map: { .[0] / .[1] >= .5 } );
my @proper-sums = @proper.combinations».sum.unique.sort;
+@proper-sums < \$n-1 ?? False !! @proper-sums[^\$n] eqv (^\$n).list ?? True !! False
}

say "{+\$_} matching numbers:\n{.batch(10)».fmt('%3d').join: "\n"}\n"
given [ (1..333).hyper(:32batch).grep: { is-practical(\$_) } ];

printf "%5s is practical? %s\n", \$_, .&is-practical for 666, 6666, 66666, 672, 720;
```
Output:
```77 matching numbers:
1   2   4   6   8  12  16  18  20  24
28  30  32  36  40  42  48  54  56  60
64  66  72  78  80  84  88  90  96 100
104 108 112 120 126 128 132 140 144 150
156 160 162 168 176 180 192 196 198 200
204 208 210 216 220 224 228 234 240 252
256 260 264 270 272 276 280 288 294 300
304 306 308 312 320 324 330

666 is practical? True
6666 is practical? True
66666 is practical? False
672 is practical? True
720 is practical? True```

## RPL

Works with: HP version 49/50

#### Brute & slow force

```« 1 SF REVLIST
1 « IF 1 FS? THEN NOT IF DUP THEN 1 CF END END » DOLIST
REVLIST
» 'INCLIST' STO                                         @ ( { bit..bit } → { bit..bit+1 } )

« CASE
DUP LN 2 LN / FP NOT THEN SIGN END                 @ powers of two are practical
DUP 2 MOD THEN NOT END                             @ odd numbers are not practical
DUP DIVIS 1 OVER SIZE 1 - SUB { } → n divs sums
« 2 CF 1
0 divs SIZE NDUPN →LIST INCLIST
DO INCLIST
DUP divs * ∑LIST
CASE
DUP n ≥ THEN DROP END
sums OVER POS THEN DROP END
'sums' STO+ SWAP 1 + SWAP
END
IF OVER n == THEN 2 SF END
UNTIL DUP 0 POS NOT 2 FS? OR END
DROP2 2 FC?
»
END
» 'PRACTICAL?' STO                                      @ ( n → boolean )
```

#### Using Srinivasan-Stewart-Sierpinsky characterization

From the Wikipedia article. It's very fast and needs only to store the prime decomposition of the tested number.

```« CASE
DUP LN 2 LN / FP NOT THEN SIGN END                 @ powers of two are practical
DUP 2 MOD THEN NOT END                             @ odd numbers are not practical
2 SF FACTORS
2 OVER DUP SIZE GET ^
OVER SIZE 2 - 2 FOR j
OVER j 1 - GET
DUP2 SWAP DIVIS ∑LIST 1 +
IF > THEN 2 CF 2. 'j' STO END                   @ 2. is needed to exit the loop
PICK3 j GET ^ *
-2 STEP
DROP2 2 FS?
END
» 'PRACTICAL?' STO                                      @ ( n → boolean )

« { }
1 333 FOR j
IF j PRACTICAL? THEN j + END
NEXT
666 PRACTICAL?
66666 PRACTICAL?
```
Output:
```4: { 1 2 4 6 8 12 16 18 20 24 28 30 32 36 40 42 48 54 56 60 64 66 72 78 80 84 88 90 96 100 104 108 112 120 126 128 132 140 144 150 156 160 162 168 176 180 192 196 198 200 204 208 210 216 220 224 228 234 240 252 256 260 264 270 272 276 280 288 294 300 304 306 308 312 320 324 330 }
3: 77
2: 1
1: 0
```

Non-practicality of 66666 is established in 0.57 seconds on an HP-50 handheld calculator; testing 222222 or 9876543210 needs 1.5 seconds. Because of the algorithm's efficiency, even antique calculators from the 1970s could implement it, with an acceptable execution time.

## Rust

Translation of: Phix
```fn sum_of_any_subset(n: isize, f: &[isize]) -> bool {
let len = f.len();
if len == 0 {
return false;
}
if f.contains(&n) {
return true;
}
let mut total = 0;
for i in 0..len {
total += f[i];
}
if n == total {
return true;
}
if n > total {
return false;
}
let d = n - f[len - 1];
let g = &f[0..len - 1];
(d > 0 && sum_of_any_subset(d, g)) || sum_of_any_subset(n, g)
}

fn proper_divisors(n: isize) -> Vec<isize> {
let mut f = vec![1];
let mut i = 2;
loop {
let i2 = i * i;
if i2 > n {
break;
}
if n % i == 0 {
f.push(i);
if i2 != n {
f.push(n / i);
}
}
i += 1;
}
f.sort();
f
}

fn is_practical(n: isize) -> bool {
let f = proper_divisors(n);
for i in 1..n {
if !sum_of_any_subset(i, &f) {
return false;
}
}
true
}

fn shorten(v: &[isize], n: usize) -> String {
let mut str = String::new();
let len = v.len();
let mut i = 0;
if n > 0 && len > 0 {
str.push_str(&v[i].to_string());
i += 1;
}
while i < n && i < len {
str.push_str(", ");
str.push_str(&v[i].to_string());
i += 1;
}
if len > i + n {
if n > 0 {
str.push_str(", ...");
}
i = len - n;
}
while i < len {
str.push_str(", ");
str.push_str(&v[i].to_string());
i += 1;
}
str
}

fn main() {
let from = 1;
let to = 333;
let mut practical = Vec::new();
for n in from..=to {
if is_practical(n) {
practical.push(n);
}
}
println!(
"Found {} practical numbers between {} and {}:\n{}",
practical.len(),
from,
to,
shorten(&practical, 10)
);
for n in &[666, 6666, 66666, 672, 720, 222222] {
if is_practical(*n) {
println!("{} is a practical number.", n);
} else {
println!("{} is not practical number.", n);
}
}
}
```
Output:
```Found 77 practical numbers between 1 and 333:
1, 2, 4, 6, 8, 12, 16, 18, 20, 24, ..., 288, 294, 300, 304, 306, 308, 312, 320, 324, 330
666 is a practical number.
6666 is a practical number.
66666 is not practical number.
672 is a practical number.
720 is a practical number.
222222 is a practical number.
```

## Sidef

Built-in:

```say is_practical(2**128 + 1)   #=> false
say is_practical(2**128 + 4)   #=> true
```

Slow implementation (as the task requires):

```func is_practical(n) {

var set = Set()

n.divisors.grep { _ < n }.subsets {|*a|
set << a.sum
}

1..n-1 -> all { set.has(_) }
}

var from = 1
var upto = 333

var list = (from..upto).grep { is_practical(_) }

say "There are #{list.len} practical numbers in the range #{from}..#{upto}."
say "#{list.first(10).join(', ')} ... #{list.last(10).join(', ')}\n"

for n in ([666, 6666, 66666]) {
say "#{'%5s' % n } is practical? #{is_practical(n)}"
}
```

Efficient algorithm:

```func is_practical(n) {

n.is_odd && return (n == 1)
n.is_pos || return false

var p = 1
var f = n.factor_exp

f.each_cons(2, {|a,b|
b.head > (1 + p) && return false
})

return true
}
```
Output:
```There are 77 practical numbers in the range 1..333.
1, 2, 4, 6, 8, 12, 16, 18, 20, 24 ... 288, 294, 300, 304, 306, 308, 312, 320, 324, 330

666 is practical? true
6666 is practical? true
66666 is practical? false
```

## Visual Basic .NET

Translation of: C#
```Imports System.Collections.Generic, System.Linq, System.Console

Module Module1
Function soas(ByVal n As Integer, ByVal f As IEnumerable(Of Integer)) As Boolean
If n <= 0 Then Return False Else If f.Contains(n) Then Return True
Select Case n.CompareTo(f.Sum())
Case 1 : Return False : Case 0 : Return True
Case -1 : Dim rf As List(Of Integer) = f.Reverse().ToList() : Dim D as Integer = n - rf(0)
rf.RemoveAt(0) : Return soas(d, rf) OrElse soas(n, rf)
End Select : Return true
End Function

Function ip(ByVal n As Integer) As Boolean
Dim f As IEnumerable(Of Integer) = Enumerable.Range(1, n >> 1).Where(Function(d) n Mod d = 0).ToList()
Return Enumerable.Range(1, n - 1).ToList().TrueForAll(Function(i) soas(i, f))
End Function

Sub Main()
Dim c As Integer = 0, m As Integer = 333, i As Integer = 1 : While i <= m
If ip(i) OrElse i = 1 Then c += 1 : Write("{0,3} {1}", i, If(c Mod 10 = 0, vbLf, ""))
i += If(i = 1, 1, 2) : End While
Write(vbLf & "Found {0} practical numbers between 1 and {1} inclusive." & vbLf, c, m)
Do : m = If(m < 500, m << 1, m * 10 + 6)
Write(vbLf & "{0,5} is a{1}practical number.", m, If(ip(m), " ", "n im")) : Loop While m < 1e4
End Sub
End Module
```
Output:

Same as C#

## Wren

Library: Wren-math
```import "./math" for Int, Nums

var powerset // recursive
powerset = Fn.new { |set|
if (set.count == 0) return [[]]
var tail = set[1..-1]
return powerset.call(tail) + powerset.call(tail).map { |s| [head] + s }
}

var isPractical = Fn.new { |n|
if (n == 1) return true
var divs = Int.properDivisors(n)
var subsets = powerset.call(divs)
var found = List.filled(n, false)
var count = 0
for (subset in subsets) {
var sum = Nums.sum(subset)
if (sum > 0 && sum < n && !found[sum]) {
found[sum] = true
count = count + 1
if (count == n - 1) return true
}
}
return false
}

System.print("In the range 1..333, there are:")
var practical = []
for (i in 1..333) {
if (isPractical.call(i)) {
}
}
System.print("  %(practical.count) practical numbers")
System.print("  The first ten are %(practical[0..9])")
System.print("  The final ten are %(practical[-10..-1])")
System.print("\n666 is practical: %(isPractical.call(666))")
```
Output:
```In the range 1..333, there are:
77 practical numbers
The first ten are [1, 2, 4, 6, 8, 12, 16, 18, 20, 24]
The final ten are [288, 294, 300, 304, 306, 308, 312, 320, 324, 330]

666 is practical: true
```

## XPL0

```int  Divs(32), NumDivs;

proc    GetDivs(N);     \Fill array Divs with proper divisors of N
int     N, I, Div, Quot;
[Divs(0):= 1;  I:= 1;  Div:= 2;
loop    [Quot:= N/Div;
if Div > Quot then quit;
if rem(0) = 0 then
[Divs(I):= Div;  I:= I+1;
if Div # Quot then
[Divs(I):= Quot;  I:= I+1];
if I > 30 then
[Text(0, "beyond the limit of 30 divisors.^m^j");  exit];
];
Div:= Div+1;
];
NumDivs:= I;
];

func PowerSet(N);       \Return 'true' if some combination of Divs sums to N
int  N, I, J, Sum;
[for I:= 0 to 1<<NumDivs - 1 do         \(beware of 1<<31 - 1 infinite loop)
[Sum:= 0;
for J:= 0 to NumDivs-1 do
[if I & 1<<J then       \for all set bits...
[Sum:= Sum + Divs(J);
if Sum = N then return true;
];
];
];
return false;
];

func Practical(X);      \Return 'true' if X is a practical number
int  X, N;
[GetDivs(X);
for N:= 1 to X-1 do
if PowerSet(N) = false then return false;
return true;
];

int  N, I;
[for N:= 1 to 333 do
if Practical(N) then
[IntOut(0, N);  ChOut(0, ^ )];
CrLf(0);
N:= [666, 6666, 66666, 672, 720, 222222];
for I:= 0 to 6-1 do
[IntOut(0, N(I));  Text(0, " is ");
if not Practical(N(I)) then Text(0, "not ");
Text(0, "a practical number.^m^j");
];
]```
Output:
```1 2 4 6 8 12 16 18 20 24 28 30 32 36 40 42 48 54 56 60 64 66 72 78 80 84 88 90 96 100 104 108 112 120 126 128 132 140 144 150 156 160 162 168 176 180 192 196 198 200 204 208 210 216 220 224 228 234 240 252 256 260 264 270 272 276 280 288 294 300 304 306 308 312 320 324 330
666 is a practical number.
6666 is a practical number.
66666 is not a practical number.
672 is a practical number.
720 is a practical number.
222222 is beyond the limit of 30 divisors.
```