Zodiac Discussion Forum

Decoding the locati…
 
Notifications
Clear all

Decoding the location of The Zodiac's bus bomb without Google

66 Posts
2 Users
0 Reactions
981 Views
shaqmeister
(@shaqmeister)
Posts: 635
Honorable Member
Topic starter
 

Posted by: @coder1987

Zodiac didn’t operate in London.  He operated in Vallejo, near Lake Herman Road and Blue Rock Springs.

As I have to believe you would have observed, the point illustrated using the London underground map is quite generalised beyond any specific case or individual and relates solely to the relationships between maps, functioning as maps, and what it is they are mapping.

Being thus fully generalised, it is therefore applicable here, also.


“This isn’t right! It’s not even wrong!”—Wolfgang Pauli (1900–1958)

 
Posted : March 29, 2026 1:19 pm
shaqmeister
(@shaqmeister)
Posts: 635
Honorable Member
Topic starter
 

Posted by: @coder1987

Let me make sure I understand your argument. The Zodiac gave us an origin (Mt. Diablo), a bearing system (clock hours from magnetic north), and a scale (6.4 miles per inch).

The Zodiac has given us an origin (Mt. Diablo), a bearing system (radii at 30° spacing numbered from zero, with reference radius adjusted for magnetic declination), and a map.


“This isn’t right! It’s not even wrong!”—Wolfgang Pauli (1900–1958)

 
Posted : March 29, 2026 3:33 pm
shaqmeister
(@shaqmeister)
Posts: 635
Honorable Member
Topic starter
 

It should be noted that the issues evidenced above—in relation to the poor fit of the features on the ground as identifiable on the Phillips 66 map and the corresponding locations arrived at from applying a coordinate transformation from inches on the map to distances on the ground—is perhaps even more obviously set out for us when we consider how the map boundary itself gets distorted through transformation.

Simple measurement on the map gives the xy coordinates (in inches, with Mount Diablo at the origin) of the four corners as:

  • top-left: –5.6875′′, 2.5000′′;
  • top-right: 1.1563′′, 2.5000′′;
  • bottom-right: 1.1563′′, –5.7500′′;
  • bottom-left: –5.6875′′, –5.7500′′.

Basic trigonometry will permit us to convert these values into clockwise angles from map north (degrees) and measured distances from Mount Diablo (inches), as:

  • top-left: 293.7284°, 6.2127′′;
  • top-right: 24.8215°, 2.7545′′;
  • bottom-right: 168.6297°, 5.8651′′;
  • bottom-left: 224.6869°, 8.0877′′.

Then, subtracting 17° from each of the angles, as the magnetic declination adjustment for the period, and subsequently converting to units of 30° per unit (call these ‘hours’, as per the division of the whole into 12), we finally get, as the Zodiac or ‘Z-coordinates’ of the four corners:

  • top-left: 9.2243h, 6.2127′′;
  • top-right: 0.2607h, 2.7545′′;
  • bottom-right: 5.0562h, 5.8651′′;
  • bottom-left: 6.9229h, 8.0877′′.

These correspond in form to the specification of a ‘radian’ from magnetic north on the map, according to the divisions on the added compass rose, and a distance, in inches, along it.

[cont…]


“This isn’t right! It’s not even wrong!”—Wolfgang Pauli (1900–1958)

 
Posted : April 9, 2026 1:17 am
shaqmeister
(@shaqmeister)
Posts: 635
Honorable Member
Topic starter
 

[…cont.]

Let us next, then, apply a transformation to these coordinates and let this be one that builds from the supposition that the map is accurately plotted in terms of orientation and scale, the given scale being that 6.4 miles on the ground corresponds to 1 inch on the map. That is, let us convert the map coordinates of the four corners into the corresponding bearing from Mount Diablo on the ground, together with the radial distance out from the same point in miles. For this, we get:

  • top-left: 9.2243h, 39.7613ml;
  • top-right: 0.2607h, 17.6288ml;
  • bottom-right: 5.0562h, 37.5366ml;
  • bottom-left: 6.9229h, 51.7613ml.

[cont…]


“This isn’t right! It’s not even wrong!”—Wolfgang Pauli (1900–1958)

 
Posted : April 9, 2026 1:30 am
shaqmeister
(@shaqmeister)
Posts: 635
Honorable Member
Topic starter
 

[…cont.]

Indeed, we can go further and deduce the latitude and longitude for each of these four points that we would now believe we have accurately projected onto the ground. However, to do this, I am not going to re-invent the wheel but will make use of the code written for this purpose by @coder1987, as referenced at the start of his thread elsewhere on this forum. (I can’t, unfortunately, link to the first post on the thread as something appears to be broken with the starting page.) And, from this, we get:

  • top-left: (38.11130845151415, -122.58394165179989)
  • top-right: (38.1131225886571, -121.77825426695198)
  • bottom-right: (37.348840779836024, -121.78031176382503)
  • bottom-left: (37.347155530224306, -122.5770678530985)

If, then, we plot these four locations using a modern mapping, such as Google Maps, we get the following:

[cont…]


This post was modified 2 months ago by shaqmeister

“This isn’t right! It’s not even wrong!”—Wolfgang Pauli (1900–1958)

 
Posted : April 9, 2026 2:16 am
shaqmeister
(@shaqmeister)
Posts: 635
Honorable Member
Topic starter
 

[…cont.]

But then if we consider this projected boundary now in terms of the landmarks that it actually crosses, and superimpose the result back onto the Phillips, we can now clearly see that what we have in reality achieved with our transformation to coordinates on the ground is a completely different boundary mapping altogether.

We get, in fact, something approximating to this:


This post was modified 2 months ago by shaqmeister

“This isn’t right! It’s not even wrong!”—Wolfgang Pauli (1900–1958)

 
Posted : April 9, 2026 3:07 am
shaqmeister
(@shaqmeister)
Posts: 635
Honorable Member
Topic starter
 

From all of this, we can now clearly see the problems that we introduce were we to hold to the idea that the application of a transformation from map coordinates (bearing, range) to geographical coordinates (bearing, range; lat., long.) takes us to some manner of equivalent mapping space on the ground.

These problems are shown to be in this sense twofold. Not only, then, have we seen that such a transformation takes us, in all instances, to a place on the ground that is not the same place we would have identified on the map, but that there are boundary exclusion/constraint issues also.

From the details of this last example we can see that, even were we to start off with the intention of considering all land locations on the map valid bomb sites, the process of transformation to ground coordinates using the given map scale and orientation returns for us a different boundary which, as well as being skewed, already excludes for us areas of potential sites despite our intention for it not to do so.

We can’t get past this. 


This post was modified 2 months ago by shaqmeister

“This isn’t right! It’s not even wrong!”—Wolfgang Pauli (1900–1958)

 
Posted : April 9, 2026 11:58 am
coder1987
(@coder1987)
Posts: 1320
Noble Member
 

Lol


“Sometimes it is the people no one can imagine anything of who do the things no one can imagine.”
Alan Turing
Best regards,
-David Stampher, the solver of Mount Diablo code aka Z32.
Cracked using the Python programming language in December 2025 using modern computational techniques.
Code: https://github.com/dstampher/zodiac-z32-cipher
Paper: https://zenodo.org/records/18645227

 
Posted : April 10, 2026 10:08 am
shaqmeister
(@shaqmeister)
Posts: 635
Honorable Member
Topic starter
 

For some reason that I can’t begin to fathom, I keep getting pings from D Stampher (aka @coder1987) suggesting that without a ‘codebase’ I am not even permitted to have any opinion as to the solution of the Z32 (as, for example, here). Of course, Stampher has had his Copilot produce a codebase for him so, in the sense that he is suggesting through his pings, he certainly has the advantage here.

The problem with Stampher’s code, however, is that is falls squarely into the very error that has been the subject of this thread.

I could only hope one day to silence our coder-friend’s pings, and I was thinking that maybe if I did produce a codebase, that would satisfy him.

Suppose, then, I were to take Stampher’s code exactly as it was provided to him. Then, for the production of an arbitrary codebase of my own, there is no reason for me to change any of his assumptions, his data, or his constraints. We can retain the exact same code for the actual process of deciphering the Z32 without any modification at all and keep his lexicon also, since he is clearly satisfied with both these for use in his own codebase. Likewise, we can retain his odd insistance that, of any of the surviving candidates, we should prefer only that one that is the nearest to one or other of The Zodiac’s known crime scenes. Fair enough.

So, with everything else retained and only the erroneous and unachievable transformation from map to terrestial coordinates corrected, we make the few adjustments needed to derive the codebase linked below.

We run the code.

We get:

==============================================================================
Z32 CIPHER SOLVER
==============================================================================
Run: 2026-04-12T02:27:12.064924

Total candidates: 2,044,224
Passed length (=32): 154,572
Passed homophonic locks: 61
Passed map bounds: 23
Rejection rate: 99.9989%
Survivors: 23

PRIMARY SOLUTION: AT FOUR AND A QUARTER INCH RADIAN EIGHT
4.25 inches at 8 radians
(-4.141073, -0.956042)
Nearest: presidio_heights (0.44 inches)

 


“This isn’t right! It’s not even wrong!”—Wolfgang Pauli (1900–1958)

 
Posted : April 12, 2026 1:58 am
shaqmeister
(@shaqmeister)
Posts: 635
Honorable Member
Topic starter
 
#!/usr/bin/env python3
"""
Z32 Cipher Solver
=================
Selective search over a structured lexicon of English-language phrases
encoding (distance, clock-hour) coordinate pairs. Candidates are filtered
by cipher length, homophonic lock constraints, and Phillips 66 map bounds.
"""

import csv
import json
import argparse
from pathlib import Path
from collections import defaultdict
from datetime import datetime
from math import pi, sin, cos, sqrt, pow
from typing import Dict, Tuple, Any, List

# ---------------------------------------------------------------------------
# Data
# ---------------------------------------------------------------------------

MAG_DEC_1970_DEG_EAST = 17.0

MAP_SCALE_MI_PER_IN = 6.4
MAP_BOUNDS = {
"south": -5.7500,
"north": 2.5000,
"west": -5.6875,
"east": 1.1563,
}

LOCKS_0_INDEXED = [(0, 25), (1, 31), (5, 13)]
CIPHER_LENGTH = 32

POINTS = {
"mt_diablo": {
"map_x": 0.0,
"map_y": 0.0,
"source": "Origin",
"notes": "Anchor point for all bearings/projections."
},

"lake_herman_road": {
"map_x": -1.5938,
"map_y": 2.2813,
"source": "Measurement",
"notes": ""
},
"blue_rock_springs": {
"map_x": -1.8750,
"map_y": 2.6875,
"source": "Measurement",
"notes": ""
},
"lake_berryessa": {
"map_x": .0,
"map_y": .0,
"source": "",
"notes": "Not in range of Phillips 66 map"
},
"presidio_heights": {
"map_x": -4.2500,
"map_y": -0.5313,
"source": "Measurement",
"notes": ""
},
}

# ---------------------------------------------------------------------------
# Runtime constants
# ---------------------------------------------------------------------------

def build_runtime_constants() -> Dict[str, Any]:
return {
"ANCHOR_LAT": float(POINTS["mt_diablo"]["map_x"]),
"ANCHOR_LON": float(POINTS["mt_diablo"]["map_y"]),
"MAG_DECLINATION": float(MAG_DEC_1970_DEG_EAST),
"MAP_BOUNDS": {k: float(v) for k, v in MAP_BOUNDS.items()},
"LOCKS": [tuple(x) for x in LOCKS_0_INDEXED],
"CIPHER_LENGTH": int(CIPHER_LENGTH),
"CRIME_SCENES": {
name: (float(POINTS[name]["map_x"]), float(POINTS[name]["map_y"]))
for name in ("lake_herman_road", "blue_rock_springs",
# "lake_berryessa",
"presidio_heights")
},
}


# ---------------------------------------------------------------------------
# Lexicon
# ---------------------------------------------------------------------------

INTEGERS = {
0: "ZERO", 1: "ONE", 2: "TWO", 3: "THREE", 4: "FOUR",
5: "FIVE", 6: "SIX", 7: "SEVEN", 8: "EIGHT", 9: "NINE",
10: "TEN", 11: "ELEVEN", 12: "TWELVE",
}

FRACTIONS = {
"": 0.0,
"ANDAHALF": 0.5, "ANDONEHALF": 0.5,
"ANDATHIRD": 1/3, "ANDONETHIRD": 1/3, "ANDTWOTHIRDS": 2/3,
"ANDAQUARTER": 0.25, "ANDONEQUARTER": 0.25,
"ANDAFOURTH": 0.25, "ANDONEFOURTH": 0.25,
"ANDTHREEQUARTERS": 0.75, "ANDTHREEFOURTHS": 0.75,
"ANDANEIGHTH": 0.125, "ANDONEEIGHTH": 0.125,
"ANDTHREEEIGHTHS": 0.375,
"ANDFIVEEIGHTHS": 0.625, "ANDSEVENEIGHTHS": 0.875,
"ANDASIXTEENTH": 0.0625, "ANDONESIXTEENTH": 0.0625,
"ANDTHREESIXTEENTHS": 0.1875, "ANDFIVESIXTEENTHS": 0.3125,
"ANDSEVENSIXTEENTHS": 0.4375, "ANDNINESIXTEENTHS": 0.5625,
"ANDELEVENSIXTEENTHS": 0.6875, "ANDTHIRTEENSIXTEENTHS": 0.8125,
"ANDFIFTEENSIXTEENTHS": 0.9375,
}

PREFIXES = ["", "IN", "AT", "TO", "BY", "GO", "ON"]
RAD_UNITS = ["RAD", "RADS", "RADIAN", "RADIANS"]
DIST_UNITS = ["", "INCH", "INCHES"]


# ---------------------------------------------------------------------------
# Geographic helpers
# ---------------------------------------------------------------------------

def gen_xy_coords(angle_twelfths: float, distance_inches,
C: Dict[str, Any]) -> Tuple[float, float]:
true_bearing_deg = (360.0 * angle_twelfths / 12) + C["MAG_DECLINATION"]
true_bearing_rad = 2 * pi * true_bearing_deg / 360.0
x_coord = distance_inches * sin(true_bearing_rad)
y_coord = distance_inches * cos(true_bearing_rad)
return x_coord, y_coord

def in_map_bounds(lat: float, lon: float, C: Dict[str, Any]) -> bool:
b = C["MAP_BOUNDS"]
return b["south"] <= lat <= b["north"] and b["west"] <= lon <= b["east"]

def nearest_crime_scene(x_coord: float, y_coord: float,
C: Dict[str, Any]) -> Tuple[str, float]:
best_name, best_dist = "", float("inf")
for name, (cx_coord, cy_coord) in C["CRIME_SCENES"].items():
d = sqrt(pow((cx_coord - x_coord),2) + pow((cy_coord - y_coord), 2))
if d < best_dist:
best_name, best_dist = name, d
return best_name, best_dist

# ---------------------------------------------------------------------------
# Candidate generation (12 template families x prefix x lexicon)
# ---------------------------------------------------------------------------

def generate_all_phrases():
for dist_int in range(13):
for angle_int in range(1, 13):
for frac_str, frac_val in FRACTIONS.items():
dist_word = INTEGERS[dist_int]
angle_word = INTEGERS[angle_int]
distance = dist_int + frac_val

for rad in RAD_UNITS:
for pre in PREFIXES:
yield (f"{pre}{dist_word}{frac_str}{rad}{angle_word}", distance, angle_int, "A")
yield (f"{pre}{angle_word}{rad}{dist_word}{frac_str}", distance, angle_int, "B")
yield (f"{pre}{dist_word}{frac_str}{angle_word}{rad}", distance, angle_int, "C")
yield (f"{pre}{angle_word}{dist_word}{frac_str}{rad}", distance, angle_int, "D")
yield (f"{pre}{rad}{angle_word}{dist_word}{frac_str}", distance, angle_int, "E")
yield (f"{pre}{rad}{dist_word}{frac_str}{angle_word}", distance, angle_int, "F")

for dunit in DIST_UNITS:
if not dunit:
continue
for pre in PREFIXES:
yield (f"{pre}{dist_word}{frac_str}{dunit}{rad}{angle_word}", distance, angle_int, "G")
yield (f"{pre}{dist_word}{frac_str}{dunit}{angle_word}{rad}", distance, angle_int, "H")
yield (f"{pre}{angle_word}{rad}{dist_word}{frac_str}{dunit}", distance, angle_int, "I")
yield (f"{pre}{angle_word}{dist_word}{frac_str}{dunit}{rad}", distance, angle_int, "J")
yield (f"{pre}{dunit}{dist_word}{frac_str}{rad}{angle_word}", distance, angle_int, "K")
yield (f"{pre}{rad}{angle_word}{dunit}{dist_word}{frac_str}", distance, angle_int, "L")


# ---------------------------------------------------------------------------
# Human-readable tokenizer
# ---------------------------------------------------------------------------

_WORD_TOKENS = [
"THIRTEENSIXTEENTHS", "FIFTEENSIXTEENTHS", "ELEVENSIXTEENTHS",
"SEVENSIXTEENTHS", "NINESIXTEENTHS", "FIVESIXTEENTHS", "THREESIXTEENTHS",
"THREEQUARTERS", "THREEFOURTHS", "THREEEIGHTHS", "SEVENEIGHTHS", "FIVEEIGHTHS",
"TWOTHIRDS", "SIXTEENTH", "RADIANS", "RADIAN", "INCHES",
"TWELVE", "ELEVEN", "QUARTERS", "QUARTER", "FOURTHS", "FOURTH", "EIGHTHS", "EIGHTH",
"SEVEN", "THREE", "EIGHT", "NINE", "FOUR", "FIVE", "ZERO", "THIRDS", "THIRD", "HALF",
"INCH", "RADS", "ONE", "TWO", "SIX", "TEN", "RAD", "AND", "THE", "FROM",
"IN", "AT", "TO", "BY", "GO", "ON", "A",
]


def format_readable(phrase: str) -> str:
result: List[str] = []
remaining = phrase
while remaining:
for w in _WORD_TOKENS:
if remaining.startswith(w):
result.append(w)
remaining = remaining[len(w):]
break
else:
result.append(remaining[0])
remaining = remaining[1:]
return " ".join(result)


# ---------------------------------------------------------------------------
# Solver
# ---------------------------------------------------------------------------

def solve(C: Dict[str, Any], out_dir: Path) -> Dict[str, Any]:
print("=" * 78)
print("Z32 CIPHER SOLVER")
print("=" * 78)
print(f"Run: {datetime.now().isoformat()}\n")

total = 0
passed_length = passed_locks = passed_bounds = 0
survivors: List[Dict[str, Any]] = []
template_survivors: Dict[str, int] = defaultdict(int)

for phrase, distance, clock_hour, template_id in generate_all_phrases():
total += 1

if len(phrase) != C["CIPHER_LENGTH"]:
continue
passed_length += 1

if not all(phrase[i] == phrase[j] for i, j in C["LOCKS"]):
continue
passed_locks += 1

x, y = gen_xy_coords(clock_hour, distance, C)
if not in_map_bounds(y, x, C):
continue

passed_bounds += 1

scene_name, scene_dist = nearest_crime_scene(x, y, C)
template_survivors[template_id] += 1
survivors.append({
"phrase": phrase,
"readable": format_readable(phrase),
"distance_inches": distance,
"clock_hour": clock_hour,
"x_coord": x,
"y_coord": y,
"nearest_scene": scene_name,
"nearest_dist_in": scene_dist,
"template": template_id,
})

survivors.sort(key=lambda x: x["nearest_dist_in"])

rejection_pct = (1 - passed_bounds / total) * 100
print(f"Total candidates: {total:>12,}")
print(f"Passed length (=32): {passed_length:>12,}")
print(f"Passed homophonic locks: {passed_locks:>12,}")
print(f"Passed map bounds: {passed_bounds:>12,}")
print(f"Rejection rate: {rejection_pct:>11.4f}%")
print(f"Survivors: {len(survivors):>12,}")

if survivors:
top = survivors[0]
print(f"\nPRIMARY SOLUTION: {top['readable']}")
print(f" {top['distance_inches']} inches at {top['clock_hour']} radians")
print(f" ({top['x_coord']:.6f}, {top['y_coord']:.6f})")
print(f" Nearest: {top['nearest_scene']} ({top['nearest_dist_in']:.2f} inches)")

out_dir.mkdir(parents=True, exist_ok=True)
output = {
"metadata": {
"solver_version": "2.0",
"timestamp": datetime.now().isoformat(),
"total_candidates": total,
"passed_length": passed_length,
"passed_locks": passed_locks,
"passed_bounds": passed_bounds,
"rejection_rate_pct": rejection_pct,
"num_survivors": len(survivors),
},
"constants": {
"anchor": [C["ANCHOR_LAT"], C["ANCHOR_LON"]],
"mag_declination": C["MAG_DECLINATION"],
"locks": C["LOCKS"],
},
"lexicon_sizes": {
"integers": len(INTEGERS),
"fractions": len(FRACTIONS),
"prefixes": len(PREFIXES),
"rad_units": len(RAD_UNITS),
"dist_units": len(DIST_UNITS),
},
"survivors": survivors,
}

json_path = out_dir / "z32_results.json"
csv_path = out_dir / "z32_results.csv"

with json_path.open("w", encoding="utf-8") as f:
json.dump(output, f, indent=2)

with csv_path.open("w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow([
"Rank", "Plaintext", "Distance_in", "Clock_Hour",
"X_Coord", "Y_Coord", "Nearest_Scene", "Dist_mi", "Template",
])
for i, s in enumerate(survivors, start=1):
writer.writerow([
i, s["readable"], s["distance_inches"], s["clock_hour"],
f"{s['x_coord']:.6f}", f"{s['y_coord']:.6f}",
s["nearest_scene"], f"{s['nearest_dist_in']:.2f}", s["template"],
])

print(f"\nSaved: {json_path}")
print(f"Saved: {csv_path}")
return output


if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Z32 solver")
parser.add_argument("--out", type=Path, default=Path("output"))
args = parser.parse_args()
solve(build_runtime_constants(), args.out)

“This isn’t right! It’s not even wrong!”—Wolfgang Pauli (1900–1958)

 
Posted : April 12, 2026 1:59 am
shaqmeister
(@shaqmeister)
Posts: 635
Honorable Member
Topic starter
 

Our solution, from this codebase, plots on the Phillips 66 like so:


This post was modified 2 months ago by shaqmeister

“This isn’t right! It’s not even wrong!”—Wolfgang Pauli (1900–1958)

 
Posted : April 12, 2026 2:00 am
coder1987
(@coder1987)
Posts: 1320
Noble Member
 

Lol


“Sometimes it is the people no one can imagine anything of who do the things no one can imagine.”
Alan Turing
Best regards,
-David Stampher, the solver of Mount Diablo code aka Z32.
Cracked using the Python programming language in December 2025 using modern computational techniques.
Code: https://github.com/dstampher/zodiac-z32-cipher
Paper: https://zenodo.org/records/18645227

 
Posted : April 12, 2026 2:17 am
coder1987
(@coder1987)
Posts: 1320
Noble Member
 

IN THREE AND THREE EIGHTHS RADIANS TEN is the correct, personally confirmed solution to Z32.

It is safe to ignore shaqs theories and whatnot.  Instead focus on the landmark I found by LHR.  Thank you.


“Sometimes it is the people no one can imagine anything of who do the things no one can imagine.”
Alan Turing
Best regards,
-David Stampher, the solver of Mount Diablo code aka Z32.
Cracked using the Python programming language in December 2025 using modern computational techniques.
Code: https://github.com/dstampher/zodiac-z32-cipher
Paper: https://zenodo.org/records/18645227

 
Posted : April 12, 2026 2:18 am
coder1987
(@coder1987)
Posts: 1320
Noble Member
 

Science calls for the scan rather than the opinions of internet forum users regarding the validity of my personally confirmed solution.

If something is buried there, I win.

And then I am the benevolent codebreaking king, and I will use my powers for good.  The enemy is the Zodiac, not minor forum trolls who argue passionately for the privacy of cows, which is more important than the landmark I found, according to you.  We will see about that.  I think you have placed the wrong bet.


“Sometimes it is the people no one can imagine anything of who do the things no one can imagine.”
Alan Turing
Best regards,
-David Stampher, the solver of Mount Diablo code aka Z32.
Cracked using the Python programming language in December 2025 using modern computational techniques.
Code: https://github.com/dstampher/zodiac-z32-cipher
Paper: https://zenodo.org/records/18645227

 
Posted : April 12, 2026 2:21 am
coder1987
(@coder1987)
Posts: 1320
Noble Member
 

And I think your debunks are not actually debunks, but mental gymnastics by someone that failed to solve Z32 in the past, and is now offended that someone else beat them to it.  Sorry about that, but I accomplished my mission back in December.  I am the finder of the triangle.


“Sometimes it is the people no one can imagine anything of who do the things no one can imagine.”
Alan Turing
Best regards,
-David Stampher, the solver of Mount Diablo code aka Z32.
Cracked using the Python programming language in December 2025 using modern computational techniques.
Code: https://github.com/dstampher/zodiac-z32-cipher
Paper: https://zenodo.org/records/18645227

 
Posted : April 12, 2026 2:22 am
Page 2 / 5
Share: