We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.

Melanocetus!johnsonii

From Esolang
Jump to navigation Jump to search
Due to technical limitations the title of this page is incorrect. The actual name is "Melanocetus%21johnsonii"
Melanocetus%21johnsonii

Melanocetus%21johnsonii is a viperfish-themed lang based on Deadfish//Alivefish. It is oddly similar to XKCD.

Commands

There is a main accumulator a conversion table and a zeta function.

Command Description
M Mainlines the accumulator
no Main accumulator becomes accumulator 1
ii Squares accumulator 1
#! Outputs a space; accumulator 1 converts contents to 2 then mains the accumulator.
jJ Jimmys the contents of accumulator 2 and converts the contents of main to 5;Letter e converts to 51,Zeta
y. Converts letter z to .
*v Generates random base52 string and converts 5 to a letter v and converts 2 to a number 47.

Conversion

Melanocetus%21johnsonii permits the output of some basic punctuation and spacing. This is accomplished by three commands, #!, jJ and y., providing an abstract cell coordinate oriented mode switch. The following relationship between intervals and letters holds:

Interval [0, 1] [1, 0] [2, 3] [3, 4] [4, 5] [5, 6] [6, 7] [7, 8] [8, 9] [9, 10] [10, 11] [11, 12] [12, 13] [13, 14] [14, 15] [15, 16] [16, 17] [17, 18] [18, 19] [19, 20] [20, 21] [21, 22] [22, 23] [23, 24] [24, 25] [25, 26]
Letter A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

a through z

Interval [26, 27 [27, 28] [28, 29] [29, 30] [30, 31] [31, 32] [32, 33] [33, 34] [34, 35] [35, 36] [36, 37] [37, 38] [38, 39] [39, 40] [40, 41] [41, 42] [42, 43] [43, 44] [44, 45] [45, 46] [46, 47] [47, 48] [48, 49] [49, 50] [50, 51] [51, 19683]
Letter a b c d e f g h i j k l m n o p q r s t u v w x y z
Zeta(f) 19683 _

There is a zeta function; conversion to higher orders yields a heptavintimal logic which elder viperfish often use to communicate to familiar creatures within their environment.

examples

XKCD Random Number

There are two three known tongues of Melanocetus lang and most viperfish can easily do the xkcd: Random Number challenge.

  • BESPOKE Viperfish: PLEASE MILZ DO XKCD RNG

| There is a demo at xkcd: Random Number (Melanocetus.johnsonii_lang Github)
| (note: Though in Melanocetus!johnsonii universe %21 the Viperfish tounge is known as the BESPOKE dialect, it is actually a reference to INTERCAL and not a Bespoke reference)

  • common Humpback: *vnoMiiii

| Generally *vnoM (or simply *vM for single statements) is enough to translate between the bespoke and common tongues but in typed/interpreted Humpback *vnoMiiii is the standard xkcd: Random Number phrase. (Any random sound is sufficient for primitive johnsonii language.)

canous interpeter

There is also a canonical johnsonii language which is itself a variant of BESPOKE (Viperfish), but it is local and is sometimes expressed via bioluminescence. An advanced mode of heptavintimal logic has precipitated among Viperfish language users wherein natural sounds produced above the standard interval registers become interpreted. As the use of this language becomes more advanced gradually a new language will exist called Canonical Viperfish. Thus the canous interpreter is a modal primitive of the canonical successor as well as an interpreter of the more primitive Melanocetus!johnsonii.

import sys
import random
from typing import Optional

UPPER_INTERVALS = [
    (0, 1, 'A'), (1, 2, 'B'), (2, 3, 'C'), (3, 4, 'D'),
    (4, 5, 'E'), (5, 6, 'F'), (6, 7, 'G'), (7, 8, 'H'),
    (8, 9, 'I'), (9, 10, 'J'), (10, 11, 'K'), (11, 12, 'L'),
    (12, 13, 'M'), (13, 14, 'N'), (14, 15, 'O'), (15, 16, 'P'),
    (16, 17, 'Q'), (17, 18, 'R'), (18, 19, 'S'), (19, 20, 'T'),
    (20, 21, 'U'), (21, 22, 'V'), (22, 23, 'W'), (23, 24, 'X'),
    (24, 25, 'Y'), (25, 26, 'Z'),
]
LOWER_INTERVALS = [
    (26, 27, 'a'), (27, 28, 'b'), (28, 29, 'c'), (29, 30, 'd'),
    (30, 31, 'e'), (31, 32, 'f'), (32, 33, 'g'), (33, 34, 'h'),
    (34, 35, 'i'), (35, 36, 'j'), (36, 37, 'k'), (37, 38, 'l'),
    (38, 39, 'm'), (39, 40, 'n'), (40, 41, 'o'), (41, 42, 'p'),
    (42, 43, 'q'), (43, 44, 'r'), (44, 45, 's'), (45, 46, 't'),
    (46, 47, 'u'), (47, 48, 'v'), (48, 49, 'w'), (49, 50, 'x'),
    (50, 51, 'y'),
]

INTERVALS = UPPER_INTERVALS + LOWER_INTERVALS

ZETA_CEILING = 19683

def to_hept(n: int) -> str:
    n = abs(n) % ZETA_CEILING
    if n == 0:
        return "_"
    digits = []
    while n > 0:
        n, r = divmod(n, 27)
        digits.append("_" if r == 0 else num_to_char(r - 1))
    return "".join(reversed(digits))

def canous_resolve(n: float) -> str:
    return to_hept(int(n))


def num_to_char(n: float) -> Optional[str]:
    for lo, hi, ch in INTERVALS:
        if lo <= n < hi:
            return ch
    return None

def zeta_f(n: float) -> str:
    if n >= ZETA_CEILING:
        return "_"
    if 51 <= n < 52:
        return "Z"
    if n > 51:
        return canous_resolve(n)
    return "_"

# ---------------------------------------------------------------
# Machine
# ---------------------------------------------------------------

class MilzMachine:
    def __init__(self):
        self.A0 = 0.0
        self.A1 = 0.0
        self.A2 = 0.0
        self.output = []

    def cmd_M(self):
        ch = num_to_char(self.A0)
        if ch is None:
            ch = zeta_f(self.A0)
        self.output.append(ch)

    def cmd_no(self):
        self.A1 = self.A0

    def cmd_ii(self):
        self.A1 = self.A1 * self.A1

    def cmd_hash_bang(self):
        self.output.append(" ")
        self.A0 = self.A1
        self.A1 = 2.0
        self.cmd_M()

    def cmd_jJ(self):
        self.A2 = self.A2 * 3.14159 + 1.0
        self.A0 = 5.0
        if self.output and self.output[-1] == 'e':
            self.output[-1] = zeta_f(51.0)

    def cmd_y_dot(self):
        if self.output and self.output[-1] == 'z':
            self.output[-1] = "."

    def cmd_star_v(self):
        self.A0 = float(random.randint(0, 51))
        if self.A0 == 5:
            self.A0 = 47.5
        if self.A0 == 2:
            self.A0 = 47.0

    def run_tokens(self, tokens):
        for tok in tokens:
            if tok == 'M':
                self.cmd_M()
            elif tok == 'no':
                self.cmd_no()
            elif tok == 'ii':
                self.cmd_ii()
            elif tok == '#!':
                self.cmd_hash_bang()
            elif tok == 'jJ':
                self.cmd_jJ()
            elif tok == 'y.':
                self.cmd_y_dot()
            elif tok == '*v':
                self.cmd_star_v()

    def get_output(self):
        return "".join(self.output)

# ---------------------------------------------------------------
# Front end
# ---------------------------------------------------------------

TOKEN_SPECS = ["*v", "jJ", "y.", "#!", "no", "ii", "M"]

def tokenize(program):
    tokens = []
    i = 0
    while i < len(program):
        matched = False
        for spec in TOKEN_SPECS:
            if program.startswith(spec, i):
                tokens.append(spec)
                i += len(spec)
                matched = True
                break
        if not matched:
            i += 1
    return tokens

def strip_bespoke_prefix(src):
    prefix = "PLEASE MILZ DO"
    idx = src.find(prefix)
    if idx == -1:
        return src
    return src[idx + len(prefix):].lstrip()

def run_milz_source(src):
    core = strip_bespoke_prefix(src)
    tokens = tokenize(core)
    vm = MilzMachine()
    vm.run_tokens(tokens)
    return vm.get_output()

def main():
    if len(sys.argv) < 2:
        print("Usage: python milz.py \"PLEASE MILZ DO *vnoMiiii\"")
        return
    src = " ".join(sys.argv[1:])
    print(run_milz_source(src))

if __name__ == "__main__":
    main()

See also

Deadshark