Showing posts with label Recursion. Show all posts
Showing posts with label Recursion. Show all posts

Tuesday, March 24, 2015

Week 2: Putting together a basic M3 Enigma Machine in Prolog


Using what little built in features GNU Prolog has, by the beginning of this week I was able to compile all that I need to begin work on the actual encryption process. Here's a small list of some of the predicates I implemented. I'm not sitting in front of my programming pc at the moment so these may not all be 100% accurate.

  • len(List,Length), returns the length of the list.
  • indexFromChar(List,Char,Index), returns the index of a char in a list.
  • CharFromIndex(List,Char,Index), returns the Char of a index in a list.
  • turn(List,NList), "turns" a list (Tail+Head).
  • turnN(List,Times,NList), turns the list as many times as you'd like.
  • sswap(List,Char1,Char2,NList), replaces the first instance of Char1 with Char2.
  • dswap(List,Char1,Char2,NList), replaces both first instances of Char1 and Char2.
  • plugboard(Alphabet, Lol, Plugboard), generates a plugboard from pairs in Lol.
  • transition(List1,List2,I,O), finds the index of I in List2, returns the Char as O. 
I'm sure most Prolog vets would scoff at my work, but I particularly proud of dswap and sswap, which both saw use in the plugboard function. I've seen in a Tower of Hanoi demonstration by my mate Kyle Godbey that Prolog has a (relatively) small stack (because it does like a million things!), so my concentration became to reduce as many calls to the accumulative dswap as possible. I accomplished this by considering the fact that I'll working with lists that contain one of each character-- rearrangements of the alphabet. I made the predicate follow suite by having it "abandon ship" so to speak once it's swapped two chars to reduce calls to the same function. Even more fun is that dswap knows to call an sswap with the proper parameters in order to complete the remaining swap.

With all of these helpful predicates I've been carving my way through actually constructing the Enigma machine. I'm trying to keep versatility in mind as I code, but at the same time I'm expected to have this done at the end of three weeks, so I'm trying to follow the model of the M3 Enigma Machine, which is common in many simulations. What I've been doing in order to build my first basic model is constantly referring to these two sites: A great visualization and an in-depth look into how the pieces and parts work. A lot of the diagrams were lifted Dartmouth's awesome and detailed simulator, but this page is helpful with taking you through baby steps. Funny enough, this guide to yet another emulator has been helpful in explaining the hefty German vocabulary for the parts as well as how actual messages should look.  

As far as my current implementation, I'm as far as returning from the reflector plate. The goal is to get all the way home this week, and then next week to incorporate lists, and then incorporate the multi-rotor stepping (the whole Royal Flags Wave Kings Above business). 

Useful Tips From My First Week Of Prolog:


  1. Understanding how Prolog works is paradigm. Unlike other procedural languages, Prolog is seeking to set things equal, or unify them. This a much more intelligent behavior that characterizes it as a “fifth-generation language”. The philosophy of the fifth-generation languages is to attempt to “describe” the problem to Prolog as opposed to just writing it out. Take that with a grain of salt though. It will make sense as you develop more and more advanced programs.
  2. Prolog is pretty bare bones in that you have to write a lot of basic features yourself, and you also have limited tools at your disposal for debugging. One of the tools you need to take advantage of is the trace function. This allows you incite to the complex control flow of Prolog’s stack. However, do not get too caught up in what it’s trying to do, but instead focus on what is being called, and watch diligently for failures.
  3. When making accumulator-style predicates, try to include an extra argument, as it will make writing a base case a lot easier. Here’s a simple example of an accumulator-style length predicate, len, that calls on a predicate accLen to accomplish the task:

    accLen([_|T],A,L)  :-
    Anew  is  A+1,  
    accLen(T,Anew,L).
    accLen([],A,A).    
    len(List,Length)  :-  accLen(List,0,Length).
  4. If you have a problem where prolog seems to want to “redo” one of your predicates to find another unification, you can use the symbol ! to denote no redos. This will be most helpful in your base case.
  5. Prolog has a sort of “not” operator, but it can be hard to find in the documentation or in a google search (unless you sold out to SWI-prolog). By using \+ we signify that the predicate is true if it fails.

    For example,
    \+ member(x, List).

    Is only true if x is not in the list.