Skip to content

Instantly share code, notes, and snippets.

@hovsater
Created October 2, 2012 12:09
Show Gist options
  • Select an option

  • Save hovsater/3818527 to your computer and use it in GitHub Desktop.

Select an option

Save hovsater/3818527 to your computer and use it in GitHub Desktop.
Problem Solving Challenge #1

Problem Solving Challenge #1

Problem solving challenges are fun. They make use of one's problem solving skills and stimulate the programmer's need to challenge themselves.

Here we go

These 1151159511610110199114 numbers represent a word.

  • The word may only contain a-zA-Z_
  • The word is of size 8.

In this particular case the secret word was s_ecrets.

Write two functionsthat can encrypt an arbitrary string and return a string of numbers such as the one above. The program should also be able to take a string of numbers and return the original word.

Happy hacking!

@Skalman
Copy link
Copy Markdown

Skalman commented Oct 2, 2012

Alright. Here's an implementation in JavaScript. Not sure which character should be replaced. My program gives the same result.

function solve(input) {
    var i, ch,
        output = "";
    input = input.split("");

    function getchar(number) {
        var char = String.fromCharCode(number);
        if (("A" <= char && char <= "Z") || ("a" <= char && char <= "z") || char === "_") {
            return char;
        }
    }

    for (i = 0; i < input.length; i++) {
        ch = getchar(input[i] + input[i+1]);
        if (ch) {
            output += ch;
            i++;
        } else {
            output += getchar(input[i] + input[i+1] + input[i+2]);
            i += 2;
        }
    }
    return output;
}

console.log(solve("1151159511610110199114")); // gives `ss_teecr`

@hovsater
Copy link
Copy Markdown
Author

hovsater commented Oct 2, 2012

@Skalman, nice. I was not completely clear about the implementation so I've updated the description above. I've added the solution to my example.

@bil-bas
Copy link
Copy Markdown

bil-bas commented Oct 2, 2012

Perhaps a little over-engineered, but I think a complete and robust solution:

module Encoder
  class << self 
    # Create a mapping of encoded string back to characters { "115" => "s" }  
    ASCII_TO_CHAR = {}
    chars = ("A".."Z").to_a + ("a".."z").to_a + ["_"]
    chars.each {|c| ASCII_TO_CHAR[c.bytes.to_a[0].to_s] = c }   

    # Encode a string - non-validating.
    def encode(string)
      riffle(string.each_byte.map {|b| b.to_s }).join
    end

    # Decode string - validating.
    def decode(string)
      pos = 0 # Current position in string.
      decoded = []

      # Code is 2 or 3 character strings. Take 2 characters and
      # see if it is valid, otherwise take another char and check that. 
      until pos >= string.length
        if (s = string[pos, 2]) and ASCII_TO_CHAR.has_key? s
          decoded << ASCII_TO_CHAR[s]
          pos += 2
        elsif (s << string[pos + 2]) and ASCII_TO_CHAR.has_key? s
          decoded << ASCII_TO_CHAR[s]
          pos += 3
        else
          raise "bad encoding at string position #{pos}"
        end
      end

      unriffle(decoded).join
    end

    protected
    # Take first and last element from array until array is empty,
    # to build a new array.
    def riffle(array)    
      # Split into two halves.
      first, second = array.each_slice(array.size / 2).to_a
      # Take from the start and end until empty.
      first.zip(second.reverse).inject([]) do |memo, (a, b)|
        memo.push a, b
      end     
    end

    protected
    # Reverse the effect of #riffle
    def unriffle(array)
      first, second = [], []
      array.each_slice(2).each do |a, b| 
        first << a
        second.unshift b
      end
      first + second
    end
  end
end

# Run with "rspec" rather than "ruby" on the command line to run the specs.
if defined? RSpec
  ENCODED = "1151159511610110199114"
  STRING = "s_ecrets" 

  describe Encoder do
    describe "encode" do
      it "should encode a string" do
        Encoder.encode(STRING).should eq ENCODED
      end    
    end

    describe "decode" do
      it "should decode a string" do
        Encoder.decode(ENCODED).should eq STRING
      end
    end

    describe "riffle" do
      it "should riffle an array" do
        Encoder.send(:riffle, [1, 3, 4, 2]).should eq [1, 2, 3, 4]
      end
    end

    describe "unriffle" do
      it "should unriffle an array" do
        Encoder.send(:unriffle, [1, 2, 3, 4]).should eq [1, 3, 4, 2]
      end
    end
  end
end

@bil-bas
Copy link
Copy Markdown

bil-bas commented Oct 2, 2012

Actually, still bored, so I improved my solution in a separate gist. Might want to delete my previous comment!
https://gist.github.com/3819927

@hovsater
Copy link
Copy Markdown
Author

hovsater commented Oct 2, 2012

@spooner impressive. Great solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment