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.

User:Aadenboy/Miscellanium 2's cipher

From Esolang
Jump to navigation Jump to search

The cipher used by Miscellanium 2 is based on two strings, where you require both strings and the deciphered string as it is currently known to decipher it. The format used is [ID]#[SUBID]; the names "ID" and "SUBID" are not relevant—all that is necessary is that ID defines the structure of the string and SUBID determines what is in it.

To encrypt with the cipher:

  • Initialize two empty strings ID and SUBID.
  • For each character in the string...
    • If this is the first occurrence of this character...
      • Append the character to SUBID.
      • Insert the index of the character in SUBID to ID. This will also be the first instance of that number in ID.
    • Otherwise...
      • Take the substring of characters between the current character and the previous instance of it.
      • Count how many unique characters there are in the substring.
      • Add the count to ID. This will never exceed the current length of SUBID.
hi im misc
1231421256#hi msc

To decrypt with the cipher:

  • Initialize an empty result string.
  • For each index in ID...
    • If this is the first occurrence of this index...
      • Add the character in SUBID with the same index to the result string.
    • Otherwise...
      • Pick the nth unique character starting from the end of the string, where n is the current index plus one.
      • Add the character at that final position to the result string.

For indexes greater than 9, they should be wrapped in parentheses, i.e 10 becomes (10).

Encryption implementations

Countable

/*
0 - 255 = Unique lookup (global)
256 - 511 = Unique lookup (local)
512 = Input/ID string end
513 = Input string length
514 = Current character
515 = SUBID string end
516 = SUBID string length
517 = Unique lookup index

The first table is for counting unique occurences everywhere.
The second table is for counting unique occurences between
two characters; the unique lookup key allows reuse of this
table by checking if each entry is equal to this value.
*/

512+525 // Input/ID string end
513+0   // Input string length
514+524 // Current character
515+525 // SUBID string end
516+0   // SUBID string length
517+524 // Unique lookup index

1*1< // Get input
  2*∞<
    a512@
    *aa512<
      512+1
      513+1
      515+1 // Just to save effort, we'll move the SUBID end alongside it
      517+1 // Also this one
      2&
    >
    1&
  >
>
// We can reuse pointer 512 as it now points to the start of ID
515+a513 // ID will be the same length as the original string (ignoring digit length)
517+a513 517+a513 // SUBID will be either the same length as or shorter than the original string

0*a513< // Cipher the string
  514+1
  *aaa514< // Check if character has been seen before
    0*1<
      *∞<
        aa514+1 // We can reuse the table entry as a second counter from its last instance
        ∞*1<
          aaa514*1< // Check if we are at the current character
            a514&
            ∞& // We are not, continue
          >
          0& // We are, stop checking
        >
        517+1
        a517+256 a517+aaaa514 // Access the second lookup table
        ∞*1<
          a514*1< // Check if the value is equal to the lookup key (current index in string)
            0*1< aaa517& >
            // Not equal
            a512+1 // Increment the digit in ID by one
            a514*1< // Set the value to equal the key
              *∞<
                aa517+1
                aaa517&
              >
            >
            ∞&
          >
          // Equal
        >
      >
    >
    512+1 // Next character
    0&
  >
  // Unique character
  a515+aa514 515+1 // Append to SUBID
  516+1 // Update length
  a512+a516 512+1 // Length of SUBID corresponds to the same digit used for ID
  aa514+a514 // The entry in the table will be the index of the character for easier use later
>

518+a517
519+a517
520+a517
521+a517
522+a517
523+a517
524+a517

∞*a513< // Print ID
  514+1 // Move to next character in ID
  *1<
    0*1< 1*1< 2*1< 3*1< 4*1< 5*1< 6*1< 7*1< 8*1< 9*1< // Check if single digit
      aa514&
      // More than one digit
      %40 // Left parenthesis
      517+1 // Length
      a517*1< *∞< a518& 518+1 > > 518+1 // Previous current value
      a518+aa514 // Value to print
      a517*1< *∞< a519& 519+1 > > 519+2 // Previous reversed value

      a517*1< *∞< a520& 520+1 > > 520+aa518 520+aa518 520+1 // Current value
      a517*1< *∞< a521& 521+1 > > 521+aa518 521+aa518 521+2 // Reversed value
      a517*1< *∞< a522& 522+1 > > 522+aa518 522+aa518 522+4 // Equal flag
      a517*1< *∞< a523& 523+1 > > 523+aa518 523+aa518 523+3 // Previous mod
      a517*1< *∞< a524& 524+1 > > 524+aa518 524+aa518 524+4 // Pointer

      // This is the same reverse-digit-then-print algorithm used by the A+B program.
      0*1<
        *∞<
          1*1<
            *aa518<
              *aa518<
                522+2
              >
              1&
            >
            0&
          >
          a517+1
          a522+1
          a523+9
          10*1<
            *∞<
              *10<
                *aa524<
                  10&
                >
                524+1
                9*1<
                  0*1< 1*1< 2*1< 3*1< 4*1< 5*1< 6*1< 7*1< 8*1<
                    aa523&
                  > > > > > > > > >
                  a524+aa523 a524+1
                >
                524+1
                523+2
              >
              a520+1
            >
          >
          524+1
          9*1<
            0*1< 1*1< 2*1< 3*1< 4*1< 5*1< 6*1< 7*1< 8*1<
              aa523&
            > > > > > > > > >
            a524+aa523 a524+1
          >
          *10<
            a521+aa519
          >
          a521+aa524
        
          522+5
          523+5
          524+4
          a520*1<
            *∞<
              a519&
              519+1
            >
          >
          520+aa518 520+aa518 520+5
          521+aa518 521+aa518 521+5
          a519*1<
            *∞<
              a518&
              518+1
            >
          >
          519+1
        >
      >

      a518+aa519
      *aa517<
        *aa518<
          522+2
        >
        a522+1
        a523+9
        10*1<
          *∞<
            *10<
              *aa524<
                10&
              >
              524+1
              9*1<
                0*1< 1*1< 2*1< 3*1< 4*1< 5*1< 6*1< 7*1< 8*1<
                  aa523&
                > > > > > > > > >
                a524+aa523 a524+1
              >
              524+1
              523+2
            >
            a520+1
          >
        >
        524+1
        9*1<
          0*1< 1*1< 2*1< 3*1< 4*1< 5*1< 6*1< 7*1< 8*1<
            aa523&
          > > > > > > > > >
          a524+aa523 a524+1
        >
        a524+48
        %aa524
      
        522+5
        523+5
        524+4
        a520*1<
          *∞<
            a519&
            519+1
          >
        >
        520+aa518 520+aa518 520+5
        521+aa518 521+aa518 521+5
        a519*1<
          *∞<
            a518&
            518+1
          >
        >
        519+1
      >
      %41 // Right parenthesis
      a523*1< *∞< a517& 517+1 > > // Move to new register
      ∞&
    > > > > > > > > > >
    // Single digit, simply transform and output
    a514+48
    %aa514
  >
>
%35 // Hashtag
*a516< // Print SUBID
  514+1 %aa514
>

Lua

o=io.read()u={}s=""print(o:gsub("()(.)",load'i,c=...if u[c]then z={}l=#({o:sub(0,i):match"(.)(.-)%1$"})[2]:gsub(".",load"c=...z[c]=(z[c]or 0)+1 return c:sub(z[c])")return l>9 and"("..l..")"or l end u[c]=#u s=s..c return #s>9 and"("..#s..")"or#s').."#"..s)

Decryption implementations

Lua

I,i=io.read():match"(.-)#(.+)"s=""n=1 p=1 repeat V=I:sub(p):match"^%b()"v=(V and V:sub(2,-2)or I:sub(p,p))+1 p=p+(V and#V or 1)if v>n then s=s..(" "..i):sub(v,v)n=n+1 else u=""z={}s:reverse():gsub(".",load'c=...z[c]=(z[c]or 0)+1 u=u..c:sub(z[c])')s=s..u:sub(v,v)end until#I<p print(s)