# Enigmatic Code

Programming Enigma Puzzles

## Enigma 456: Top heat

From New Scientist #1607, 7th April 1988 [link]

“Look at this four-figure temperature,” the furnace foreman said, “it’s HEAT.”

“That’s funny, the temperature of my furnace is HOTS,” said the foreman of the adjacent furnace.

As usual, I’ve replaced digits consistently with letters to confuse you, different letters being used for different digits. One of the above temperatures is on the centigrade scale and the other is on the Fahrenheit scale. In each case if you start with the given temperature and translate it to the other scale you get the same digits you started with, but in a different order.

Funnily enough, the same thing happens for the TOP temperature.

Find THE POST.

[enigma456]

### 6 responses to “Enigma 456: Top heat”

1. Jim Randell 13 July 2018 at 9:02 am

Here’s a solution using the [[ `SubstitutedExpression()` ]] solver from the enigma.py library.

This Python program runs in 97ms.

Run: [ @repl.it ]

```from enigma import nsplit, SubstitutedExpression

# convert from C -> F
def C2F(C):
(x, r) = divmod(C, 5)
return (9 * x + 32 if r == 0 else None)

# convert from F -> C
def F2C(F):
(x, r) = divmod(F - 32, 9)
return (5 * x if r == 0 else None)

# digit content of a number (base 10)
# (we could use set() as the digits are all different)
digits = lambda x: sorted(nsplit(x))

# check a and b have the same digit content
def check(a, b):
return (None if a is None or b is None else digits(a) == digits(b))

# check a temperature given in C or F
C = lambda n: check(n, C2F(n))
F = lambda n: check(n, F2C(n))

# solve the puzzle using the SubstitutedExpression solver
SubstitutedExpression(
[
# TOP works one way or the other
"C({TOP}) or F({TOP})",
# HEAT and HOTS work in opposite directions
"(C({HEAT}) and F({HOTS})) or (F({HEAT}) and C({HOTS}))",
],
env=dict(C=C, F=F),
).go()
```

Solution: THE POST = 546 7235.

And A = 8.

The temperatures are:

HEAT = 4685 °C (= 8465 °F)
HOTS = 4253 °F (= 2345 °C)
TOP = 527 °F (= 275 °C)

The are only two possible pairs of 4-digit temperatures with the same digit content in both scales, and only one possible pair of 3-digit temperatures, so once you’ve worked those out it is easy to arrive at the solution.

2. Hugh Casement 13 July 2018 at 9:44 am

To save trying to remember whether one adds or subtracts 32, and whether before or after multiplying, I always use the fact that -40° is the same in both scales.   So the rule is:
add 40; multiply by 5/9 or 9/5 as appropriate; subtract 40.
Which factor to apply is easy: fewer Celsius degrees are needed to reach boiling point.

I gave up thinking in Fahrenheit over 50 years ago.  It amazes me that anyone still uses it.

3. geoffrounce 13 July 2018 at 10:20 am
```% A Solution in MiniZinc
include "globals.mzn";

var 1..9:H; var 0..9:E; var 0..9:A; var 1..9:T;
var 0..9:O; var 0..9:S; var 1..9:P;

% Main Variables
var 1000..9999: HEAT = 1000*H + 100*E + 10*A + T;
var 1000..9999: HOTS = 1000*H + 100*O + 10*T + S;
var 1000..9999: POST = 1000*P + 100*O + 10*S + T;
var 100..999: THE = 100*T + 10*H + E;
var 100..999: TOP = 100*T + 10*O + P;

constraint all_different([H, E, A, T, O, S, P]);

% Temperature conversion variables
var 1..9:a; var 0..9:b; var 0..9:c; var 0..9:d;
var 1..9:e; var 0..9:f; var 0..9:g; var 0..9:h;
var 1..9:i; var 0..9:j; var 0..9:k;

constraint all_different ([a, b, c, d]) /\ all_different ([e, f, g, h])
/\ all_different ([i, j, k]);

var 1000..9999: abcd = 1000*a + 100*b + 10*c + d;  % HEAT conversion
var 1000..9999: efgh = 1000*e + 100*f + 10*g + h;  % HOTS conversion
var 100..999: ijk = 100*i + 10*j + k;              % TOP conversion

% Sets of temperatures and conversion values
var set of int: s1 = { H, E, A, T };
var set of int: s2 = { a, b, c, d };

var set of int: s3 = { H, O, T, S };
var set of int: s4 = { e, f, g, h };

var set of int: s5 = { T, O, P };
var set of int: s6 = { i, j, k };

% Three temperature conversion constraints (F -> C or C -> F)
constraint (((HEAT - 32) * 5) div 9 == abcd /\ s1 == s2)
\/ ((HEAT * 9) div 5 + 32 = abcd /\ s1 == s2);

constraint (((HOTS - 32) * 5) div 9 == efgh /\ s3 == s4)
\/ ((HOTS * 9) div 5 + 32 = efgh /\ s3 == s4);

constraint (((TOP - 32) * 5) div 9 == ijk /\ s5 == s6)
\/ ((TOP * 9) div 5 + 32 = ijk /\ s5 == s6);

solve satisfy;

output ["HEAT = " ++ show(HEAT) ++ " (" ++ show(abcd) ++ ")" ]
++ [ "\nHOTS = " ++ show(HOTS) ++ " (" ++ show (efgh) ++ ")"]
++ [ "\nTOP = " ++ show(TOP) ++ " (" ++ show(ijk) ++ ")"]
++ [ "\nTHE POST = " ++ show(THE) ++ " " ++ show(POST)];

% HEAT = 4685 (8465)
% HOTS = 4253 (2345)
% TOP = 527 (275)
% THE POST = 546 7235
% ----------
% ==========
% Finished in 81msec
```
• Jim Randell 13 July 2018 at 10:58 am

@geoff: Does this model check that one of HEAT and HOTS is °C and the other is °F?

Given the range of the temperatures I think the following constraint should do it:

```% check HEAT and HOTS are on different temperature scales
constraint (HEAT < abcd) xor (HOTS < efgh);
```
• Jim Randell 13 July 2018 at 2:33 pm

Or you can rearrange the clauses of the constraints in lines 39-43 to give a single constraint that selects only valid values:

```constraint
(((HEAT - 32) * 5) div 9 == abcd /\ s1 == s2) /\ ((HOTS * 9) div 5 + 32 = efgh /\ s3 == s4) \/
(((HOTS - 32) * 5) div 9 == efgh /\ s3 == s4) /\ ((HEAT * 9) div 5 + 32 = abcd /\ s1 == s2);
```
4. geoffrounce 13 July 2018 at 11:39 am

@Jim: The extra constraint you suggest is stated in the Enigma description, but is probably not strictly essential, as the model gets the single correct answer (and your temperature values) without this extra constraint.

This site uses Akismet to reduce spam. Learn how your comment data is processed.