O'Halloran numbers: Difference between revisions
conjecture |
m →{{header|jq}}: for jaq |
||
Line 69: | Line 69: | ||
# Emit a stream of possible cuboid areas less than or equal to the specified limit, |
# Emit a stream of possible cuboid areas less than or equal to the specified limit, |
||
# $maxarea, which should be an even integer. |
# $maxarea, which should be an even integer. |
||
def cuboid_areas( |
def cuboid_areas(maxarea): |
||
maxarea as $maxarea |
maxarea as $maxarea |
||
# min area per face is 1 so if total area is $maxarea, the max dimension is ($maxarea-4)/2 |
# min area per face is 1 so if total area is $maxarea, the max dimension is ($maxarea-4)/2 |
Revision as of 06:03, 5 November 2022
For this task, the term "cuboid" means a 3-dimensional object with six rectangular faces, where all angles are right angles, where opposite faces are equal, and where each dimension is a positive integer unit length.
The surface area of a cuboid so-defined is two times the length times the width, plus two times the length times the height, plus two times the width times the height. For example, a cuboid with l = 2, w = 1 h = 1 has a surface area of 10:
2 × ( 2 × 1 + 1 × 1 + 1 × 2 ) = 10
The minimum surface area a cuboid may have is 6 - namely one for which the l, w, and h measurements are all 1:
2 × ( l × w + w × h + h × l ) 2 × ( 1 × 1 + 1 × 1 + 1 × 1 ) = 6
Notice that the total surface area of a cuboid is always an integer and is always even, but the converse is not true. For example, there is no cuboid with a surface area of 8. It is conjectured, however, that for every even integer greater than 924, there is a corresponding cuboid with that area.
- Task
- Find and display the sixteen even integer values larger than 6 (the minimum cuboid area) and less than 1000
that can not be the surface area of a cuboid.
- See also
ALGOL 68
BEGIN # find O'Halloran numbers - numbers that cannot be the surface area of #
# a cuboid with integer dimensions #
INT count := 0;
INT max area = 1 000;
INT half max area = max area OVER 2;
FOR n FROM 8 BY 2 TO max area DO
BOOL ohalloran := TRUE;
FOR l TO half max area WHILE ohalloran DO
FOR b TO half max area WHILE INT lb = l * b;
lb < n AND ohalloran
DO
FOR h TO half max area WHILE INT bh = b * h, lh = l * h;
INT sum = 2 * ( lb + bh + lh );
sum <= n
AND ( ohalloran := sum /= n )
DO SKIP OD
OD
OD;
IF ohalloran THEN
print( ( " ", whole( n, 0 ) ) );
count +:= 1
FI
OD
END
- Output:
8 12 20 36 44 60 84 116 140 156 204 260 380 420 660 924
J
require'stats'
2*(3}.i.501)-.+/1 */\.(|:3 comb 42)-i:1
8 12 20 36 44 60 84 116 140 156 204 260 380 420 660 924
Here, we use combinations with repetitions to generate the various relevant cuboid side lengths. Then we multiply all three pairs of these side length combinations and sum the pairs. Then we remove these sums from the sequence 3..500, and finally we multiply the remaining 16 values by 2.
jq
Also works with jaq and with gojq, the Go implementation of jq
# Emit a stream of possible cuboid areas less than or equal to the specified limit,
# $maxarea, which should be an even integer.
def cuboid_areas(maxarea):
maxarea as $maxarea
# min area per face is 1 so if total area is $maxarea, the max dimension is ($maxarea-4)/2
| ($maxarea/2) as $halfmax
| ($halfmax - 2) as $max
| foreach range(1; 1+$max) as $i (null;
label $loopj
# By symmetry, we can assume i < j < k
| foreach range($i; 1+$max) as $j (.;
($i*$j) as $ij
| if $ij + 2 > $halfmax then break $loopj else . end
| label $loopk
| foreach range($j; 1+$max) as $k (.;
($ij + $i*$k + $j*$k) as $total
| if $total > $halfmax then break $loopk
else 2 * $total
end) ) );
1000 as $n
| "Even integers greater than 6 but less than \($n) that cannot be cuboid surface areas:",
[range(6;$n;2)] - [cuboid_areas($n-2)]
Even integers greater than 6 but less than 1000 that cannot be cuboid surface areas: [8,12,20,36,44,60,84,116,140,156,204,260,380,420,660,924]
Julia
""" Rosetta code task: rosettacode.org/wiki/O%27Halloran_numbers """
const max_area, half_max = 1000, 500
const areas = trues(max_area)
areas[1:2:max_area] .= false
for i in 1:max_area
for j in 1:half_max
i * j > half_max && break
for k in 1:half_max
area = 2 * (i * j + i * k + j * k)
area > max_area && break
areas[area] = false
end
end
end
println("Even surface areas < $max_area NOT achievable by any regular integer-valued cuboid:\n",
[n for n in eachindex(areas) if areas[n]])
- Output:
Even surface areas < 1000 NOT achievable by any regular integer-valued cuboid: [2, 4, 8, 12, 20, 36, 44, 60, 84, 116, 140, 156, 204, 260, 380, 420, 660, 924]
Perl
use v5.36;
my @A;
my $threshold = 10_000; # redonkulous overkill
for my $x (1..$threshold) {
X: for my $y (1..$x) {
last X if $x*$y > $threshold;
Y: for my $z (1..$y) {
last Y if (my $area = 2 * ($x*$y + $y*$z + $z*$x)) > $threshold;
$A[$area] = "$x,$y,$z";
}
}
say 'Even integer surface areas NOT achievable by any regular, integer dimensioned cuboid';
for (0..$#A) {
print "$_ " if $_ < $threshold and $_ > 6 and 0 == $_ % 2 and not $A[$_];
}
- Output:
Even integer surface areas NOT achievable by any regular, integer dimensioned cuboid: 8 12 20 36 44 60 84 116 140 156 204 260 380 420 660 924
Phix
Since we are going to check {1,1,2}, there is no point checking {1,2,1} or {2,1,1} etc.
with javascript_semantics constant max_area = 1000, half_max = max_area/2 sequence areas = repeat(0,5)&tagset(max_area,6) for x=1 to max_area do if odd(x) then areas[x] = 0 end if for y=x to floor(half_max/x) do for z=y to half_max do atom area = 2 * (x * y + x * z + y * z) if area > max_area then exit end if areas[area] = 0 end for end for end for printf(1,"Even surface areas < %d NOT achievable by any regular integer-valued cuboid:\n%s\n", {max_area,join(filter(areas,"!=",0),fmt:="%d")})
- Output:
You can also set max_area to 1,000,000 and get no more results.
Even surface areas < 1000 NOT achievable by any regular integer-valued cuboid: 8 12 20 36 44 60 84 116 140 156 204 260 380 420 660 924
PROMAL
;;; find O'Halloran numbers - numbers that cannot be the surface area of
;;; a cuboid with integer dimensions
PROGRAM OHalloran
INCLUDE LIBRARY
CON WORD maxArea = 1000
WORD count
WORD halfMaxArea
WORD n
WORD l
WORD b
WORD h
WORD lb
WORD lh
WORD bh
WORD sum
BYTE isOHalloran
BEGIN
count = 0
halfMaxArea = maxArea / 2
n = 8
WHILE n <= maxArea
isOHalloran = 1
l = 1
REPEAT
b = 1
lb = l
REPEAT
h = 1
REPEAT
bh = b * h
lh = l * h
sum = 2 * ( lb + ( h * ( b + l ) ) )
IF sum = n
isOHalloran = 0
h = h + 1
UNTIL h > halfMaxArea OR sum > n OR NOT isOHalloran
b = b + 1
lb = l * b
UNTIL b > halfMaxArea OR lb >= n OR NOT isOHalloran
l = l + 1
UNTIL l > halfMaxArea OR NOT isOHalloran
IF isOHalloran
OUTPUT " #W", n
count = count + 1
n = n + 2
END
- Output:
8 12 20 36 44 60 84 116 140 156 204 260 380 420 660 924
Raku
my @Area;
my $threshold = 1000; # a little overboard to make sure we get them all
for 1..$threshold -> $x {
for 1..$x -> $y {
last if $x × $y > $threshold;
for 1..$y -> $z {
push @Area[my $area = ($x × $y + $y × $z + $z × $x) × 2], "$x,$y,$z";
last if $area > $threshold;
}
}
}
say "Even integer surface areas NOT achievable by any regular, integer dimensioned cuboid:\n" ~
@Area[^$threshold].kv.grep( { $^key > 6 and $key %% 2 and !$^value } )»[0];
- Output:
Even integer surface areas NOT achievable by any regular, integer dimensioned cuboid: 8 12 20 36 44 60 84 116 140 156 204 260 380 420 660 924
Wren
import "./seq" for Lst
var found = []
for (l in 1..497) {
for (w in 1..l) {
var lw = l * w
if (lw >= 498) break
for (h in 1..w) {
var sa = (lw + w*h + h*l) * 2
if (sa < 1000) found.add(sa) else break
}
}
}
var allEven = (6..998).where { |i| i%2 == 0 }.toList
System.print("All known O'Halloran numbers:")
System.print(Lst.except(allEven,found))
- Output:
All known O'Halloran numbers: [8, 12, 20, 36, 44, 60, 84, 116, 140, 156, 204, 260, 380, 420, 660, 924]
XPL0
int L, W, H, HA, I;
char T(1000/2); \table of half areas
[for I:= 0 to 1000/2-1 do
T(I):= true; \assume all are O'Halloran numbers
for L:= 1 to 250 do
for W:= 1 to 250/L do
for H:= 1 to 250/L do
[HA:= L*W + L*H + W*H;
if HA < 500 then \not an O'Halloran number
T(HA):= false;
];
for I:= 6/2 to 1000/2-1 do
if T(I) then
[IntOut(0, I*2); ChOut(0, ^ )];
]
- Output:
8 12 20 36 44 60 84 116 140 156 204 260 380 420 660 924