I'm getting in the Christmas spirit, so here's a Python 3 solution to Advent of Code Day 14's puzzle. I love this site, by the way. Looking forward to the 2016 edition!
import re
f = open("input.txt", "r")
fl = f.readlines()
f.close()
names = {}
rawdistances = {}
winner = {}
isresting = {}
##Setting up dicts to store information about each reindeer
for item in fl:
matches = re.search("([A-Za-z]+).*?(\d+).*?(\d+).*?(\d+)", item)
##matches returns a set of groups: the name of the reindeer, its speed,
##the amount of time it can fly before resting, and the time it must rest
name = matches.group(1)
speed = int(matches.group(2))
flytime = int(matches.group(3))
resttime = int(matches.group(4))
names[name] = [speed, flytime, resttime]
##Store the information of the reindeer in a list in a dict
isresting[name] = [False, flytime]
##isresting stores a list with:
##A boolean (False if resting, True if flying)
##The amount of time that will elapse before starting the next segment
rawdistances[name] = 0
winner[name] = 0
for i in range(2503):
##Replace 2503 with 2504 to solve Part Two
##The reason is that second no. 2503 also needs to be counted for Part Two
print(str(i))
for reindeer in names:
if isresting[reindeer][1] == 0 and isresting[reindeer][0] == False:
##Switch to resting at the beginning of the second, it rests for 1 second
isresting[reindeer][0] = True
isresting[reindeer][1] = names[reindeer][2]-1
print(reindeer + ' started resting')
elif isresting[reindeer][0] == False:
##It continues flying
isresting[reindeer][1] -= 1
rawdistances[reindeer] += names[reindeer][0]
print(reindeer + ' flew ' + str(names[reindeer][0]))
print(reindeer + " is at " + str(rawdistances[reindeer]))
elif isresting[reindeer][1] == 0 and isresting[reindeer][0] == True:
##Switch to flying at the beginning of the second, it flies for 1 second
isresting[reindeer][0] = False
isresting[reindeer][1] = names[reindeer][1]-1
rawdistances[reindeer] += names[reindeer][0]
print(reindeer + ' stopped resting')
else:
##It continues resting
isresting[reindeer][1] -= 1
print(reindeer + ' is resting for ' + str(isresting[reindeer][1]) + " more seconds")
##Uncomment the below to find solution to Part Two
##high = 0
##for item in rawdistances.values():
## if high < item:
## high = item
##currname = [k for k, v in rawdistances.items() if v == high]
##for item in currname:
## winner[item] += 1
##Deindent here!
##high = 0
##for item in rawdistances.values():
## if high < winner[list(rawdistances.keys()[[list(rawdistances.values()).index(item)]]:
## high = winner[list(rawdistances.keys())[list(rawdistances.values()).index(item)]]
high = 0
for item in rawdistances.values():
if high < item:
high = item
##Print the reindeer in the lead for Part One, the reindeer with the most points for Part Two
print(high)
Nathan McKinley-Pace, Coder
Friday, November 11, 2016
Wednesday, July 6, 2016
Making an HTML Website with Flask
It's very simple to make a (simple) HTML-based website using Flask to deliver webpages -- that is precisely what I did with my new site mckinleymath.com. Here's a quick guide.
You should have an HTML file before starting, but if you don't, make one using a text editor of your choice and use online resources such as w3schools or HTML Dog to write one. Call this whatever you want - the example uses index.html. If you want a mobile version, make a separate file for that - I called it mobile.html. Then find a web server that can run python files (such as Digital Ocean for $5+ per month, which is what I use). In that server, you can make a file called routes.py like this (vim on DigitalOcean is built in):
from flask import Flask, request, render_template, Blueprint
app = Flask(__name__)
app.config['BASIC_AUTH_FORCE'] = True
@app.route('/')
def site():
return render_template('index.html')##change 'index.html' as necessary
##This is if you have a mobile site
@app.route("/mobile")
def mobile():
return render_template('mobile.html') ##change 'mobile.html' as necessary
if __name__ == "__main__":
app.run(host="0.0.0.0" , port=80)
Use screen to start a new terminal session that persists after you logout. In that session, run python routes.py. Then press Ctrl and A and D simultaneously to exit the session (leaving it running). You can logout at this point using exit.
Then do this on your DNS settings page. Most providers include a "subdomain forward" option, so forward it to your servers IP address. If you have a mobile site, you can subdomain forward that in a similar way -- do m.website.com -> website.com/mobile. Then do this in resource records to enable users being able to use the site without index.html or mobile.html being part of the URL:
Name: www
Type: cname
TTL: 1h
Data: website.com.
That's it. Save your changes and wait a minute or two for the records to update and it should be functional.
You should have an HTML file before starting, but if you don't, make one using a text editor of your choice and use online resources such as w3schools or HTML Dog to write one. Call this whatever you want - the example uses index.html. If you want a mobile version, make a separate file for that - I called it mobile.html. Then find a web server that can run python files (such as Digital Ocean for $5+ per month, which is what I use). In that server, you can make a file called routes.py like this (vim on DigitalOcean is built in):
from flask import Flask, request, render_template, Blueprint
app = Flask(__name__)
app.config['BASIC_AUTH_FORCE'] = True
@app.route('/')
def site():
return render_template('index.html')##change 'index.html' as necessary
##This is if you have a mobile site
@app.route("/mobile")
def mobile():
return render_template('mobile.html') ##change 'mobile.html' as necessary
if __name__ == "__main__":
app.run(host="0.0.0.0" , port=80)
Use screen to start a new terminal session that persists after you logout. In that session, run python routes.py. Then press Ctrl and A and D simultaneously to exit the session (leaving it running). You can logout at this point using exit.
Then do this on your DNS settings page. Most providers include a "subdomain forward" option, so forward it to your servers IP address. If you have a mobile site, you can subdomain forward that in a similar way -- do m.website.com -> website.com/mobile. Then do this in resource records to enable users being able to use the site without index.html or mobile.html being part of the URL:
Name: www
Type: cname
TTL: 1h
Data: website.com.
That's it. Save your changes and wait a minute or two for the records to update and it should be functional.
Monday, October 12, 2015
Project 1, Name Generator
I'm switching to a more readable project list, located here. However, it has different numbering -- it starts at 1 and not 0, so I'm updating some old blog posts over the next few days.
Anyway, the next one is a name generator. I decided to make it such that it could differentiate between female and male names, and include last names too.
So, here it is!
#!/usr/bin/python
from random import *
femaleNames = []
maleNames = []
lastNames = []
allNames = [femaleNames, maleNames, lastNames]
def set_name_lists():
fnames = ["femalenames.txt", "malenames.txt", "lastnames.txt"]
for i in range(len(fnames)):
f = open(fnames[i], "r")
allnamesinfile = f.readlines()
f.close()
shuffle(allnamesinfile)
for x in allnamesinfile:
x = x.replace('\n', "")
allNames[i].append(x[0].upper() + x[1:].lower())
def get_name(b):
if b:
return femaleNames[randint(0, len(femaleNames)-1)] + " " + lastNames[randint(0, len(lastNames)-1)]
else:
return maleNames[randint(0, len(maleNames)-1)] + " " + lastNames[randint(0, len(lastNames)-1)]
def get_a_name():
return get_name(choice([True, False]))
def main():
set_name_lists()
input = " "
while input[0].upper() != "X":
print("F to print a female name. M to print a male name.")
print("Blank or (anything not X) to print a random name. X quits.")
input = raw_input("Please enter your input: ")
if len(input) == 0:
input = " "
if input[0].upper() == "F":
print(get_name(True))
elif input[0].upper() == "M":
print(get_name(False))
elif input[0].upper() == "X":
pass
else:
print(get_a_name())
if __name__ == "__main__":
main()
Anyway, the next one is a name generator. I decided to make it such that it could differentiate between female and male names, and include last names too.
So, here it is!
#!/usr/bin/python
from random import *
femaleNames = []
maleNames = []
lastNames = []
allNames = [femaleNames, maleNames, lastNames]
def set_name_lists():
fnames = ["femalenames.txt", "malenames.txt", "lastnames.txt"]
for i in range(len(fnames)):
f = open(fnames[i], "r")
allnamesinfile = f.readlines()
f.close()
shuffle(allnamesinfile)
for x in allnamesinfile:
x = x.replace('\n', "")
allNames[i].append(x[0].upper() + x[1:].lower())
def get_name(b):
if b:
return femaleNames[randint(0, len(femaleNames)-1)] + " " + lastNames[randint(0, len(lastNames)-1)]
else:
return maleNames[randint(0, len(maleNames)-1)] + " " + lastNames[randint(0, len(lastNames)-1)]
def get_a_name():
return get_name(choice([True, False]))
def main():
set_name_lists()
input = " "
while input[0].upper() != "X":
print("F to print a female name. M to print a male name.")
print("Blank or (anything not X) to print a random name. X quits.")
input = raw_input("Please enter your input: ")
if len(input) == 0:
input = " "
if input[0].upper() == "F":
print(get_name(True))
elif input[0].upper() == "M":
print(get_name(False))
elif input[0].upper() == "X":
pass
else:
print(get_a_name())
if __name__ == "__main__":
main()
The breakdown:
set_name_lists reads three files (the name lists) in and shuffles them so that you don't get the same output upon running the program twice in a row.
get_name takes a truth value (a boolean) in, corresponding to whether you asked for a male name or female name, and returns a last name constructed of a male / female name plus a last name. It does this with randint for extra randomness.
get_a_name returns get_name with a random boolean.
main sets the name lists and loops through, asking you to input M, F, (something else), or X.
Anyway, that was an interesting project -- next up... project 3, temperature converter, which I somehow skipped.
-Nathan
Tuesday, July 28, 2015
Project 6: RPS
Another project that I worked on for the past few hours has been completed. Maybe I'll do the R-P-S-Lizard-Spock (or even the 101-object version!) I thought that using an dictionary as a data structure was appropriate (and slightly creative). Pretty good, if I may say so myself.
rpsdata = {"r":["s"], "p":["r"], "s":["p"]}
def rps(s1, s2):
if s1 in rpsdata:
if s2 not in rpsdata:
print(s2 + " is not valid.")
new = raw_input("Enter a valid input: ")
rps(s1, new)
if s2 in rpsdata[s1]:
print(s1 + " wins!")
return 1
elif s1 in rpsdata[s2]:
print(s2 + " wins!")
return 0
elif s1 == s2:
print("Tie.")
return -1
else:
print(s1 + " is not valid.")
new = raw_input("Enter a valid input: ")
rps(new, s2)
roundnum = 0
p1wins = 0
p2wins = 0
while True:
s1 = raw_input("P1, enter a r, p, or s: ")
s2 = raw_input("P2, enter a r, p, or s: ")
num = rps(s1, s2)
if num == 0:
p2wins += 1
elif num == 1:
p1wins += 1
exit = raw_input("Exit? ")
roundnum += 1
if len(exit) == 0:
continue
elif exit[0].lower() == "e":
print("Thanks for playing.")
print("P1 won %.2f percent of the time." % float(100 * p1wins / roundnum))
print("P2 won %.2f percent of the time." % float(100 * p2wins / roundnum))
break
rpsdata = {"r":["s"], "p":["r"], "s":["p"]}
def rps(s1, s2):
if s1 in rpsdata:
if s2 not in rpsdata:
print(s2 + " is not valid.")
new = raw_input("Enter a valid input: ")
rps(s1, new)
if s2 in rpsdata[s1]:
print(s1 + " wins!")
return 1
elif s1 in rpsdata[s2]:
print(s2 + " wins!")
return 0
elif s1 == s2:
print("Tie.")
return -1
else:
print(s1 + " is not valid.")
new = raw_input("Enter a valid input: ")
rps(new, s2)
roundnum = 0
p1wins = 0
p2wins = 0
while True:
s1 = raw_input("P1, enter a r, p, or s: ")
s2 = raw_input("P2, enter a r, p, or s: ")
num = rps(s1, s2)
if num == 0:
p2wins += 1
elif num == 1:
p1wins += 1
exit = raw_input("Exit? ")
roundnum += 1
if len(exit) == 0:
continue
elif exit[0].lower() == "e":
print("Thanks for playing.")
print("P1 won %.2f percent of the time." % float(100 * p1wins / roundnum))
print("P2 won %.2f percent of the time." % float(100 * p2wins / roundnum))
break
Tuesday, July 7, 2015
Project 5: One-Line Fizzbuzz
It's been a while since I last blogged; I figured I should write something up quickly.
Here's Fizzbuzz from the 100 projects -- in one line. Considering my usual Fizzbuzz solution takes around 8-10 lines, this is more concise. It's quite obtuse, though.
>>> def fizzbuzz(a, b, c): print "\n".join([(("Fizz"*(x%a == 0) + "Buzz"*(x%b == 0)) or str(x)) for x in range(1, c)])
>>> fizzbuzz(3, 2, 10)
1
Buzz
Fizz
Buzz
5
FizzBuzz
7
Buzz
Buzz
Fizz
>>> fizzbuzz(3, 1, 10)
Buzz
Buzz
FizzBuzz
Buzz
Buzz
FizzBuzz
Buzz
Buzz
FizzBuzz
I'm pretty proud of my solution, even if I did take the "\n".join approach from Michael Gilliland's blog entry on Fizzbuzz.
I hope to be publishing more. Thanks for reading.
Here's Fizzbuzz from the 100 projects -- in one line. Considering my usual Fizzbuzz solution takes around 8-10 lines, this is more concise. It's quite obtuse, though.
>>> def fizzbuzz(a, b, c): print "\n".join([(("Fizz"*(x%a == 0) + "Buzz"*(x%b == 0)) or str(x)) for x in range(1, c)])
>>> fizzbuzz(3, 2, 10)
1
Buzz
Fizz
Buzz
5
FizzBuzz
7
Buzz
Buzz
Fizz
>>> fizzbuzz(3, 1, 10)
Buzz
Buzz
FizzBuzz
Buzz
Buzz
FizzBuzz
Buzz
Buzz
FizzBuzz
I'm pretty proud of my solution, even if I did take the "\n".join approach from Michael Gilliland's blog entry on Fizzbuzz.
I hope to be publishing more. Thanks for reading.
Tuesday, June 23, 2015
Caesar Cipher Encryption and Decryption
Here's my blog post to end my hiatus. I decided to make a program that encrypts and decrypts text given in the form of a Caesar cipher. So I did just that in 43 lines of Python (the main portion in 27 lines). On Pastebin like usual.
alphabet = "abcdefghijklmnopqrstuvwxyz"
def encrypt(s, shift):
news = ""
for i in s:
if i.lower() in alphabet:
if i.upper() == i:
c = alphabet[(alphabet.index(i.lower()) + shift) % len(alphabet)]
news = news + c.upper()
else:
c = alphabet[(alphabet.index(i) + shift) % len(alphabet)]
news = news + c
else:
news = news + i
print(news)
def decrypt(s, shift):
news = ""
for i in s:
if i.lower() in alphabet:
if i.upper() == i:
c = alphabet[(alphabet.index(i.lower()) - shift) % len(alphabet)]
news = news + c.upper()
else:
c = alphabet[(alphabet.index(i) - shift) % len(alphabet)]
news = news + c
else:
news = news + i
print(news)
def gettodo():
a = input("What do you want to do? E for encrypt, D for decrypt: ").lower()
if a[0] == "e":
b = input("Enter a plaintext: ")
c = int(input("Enter a shift: "))
encrypt(b, c)
gettodo()
elif a[0] == "d":
b = input("Enter a ciphertext: ")
c = int(input("Enter a shift: "))
decrypt(b, c)
gettodo()
else:
print("Invalid input.")
gettodo()
gettodo()
alphabet = "abcdefghijklmnopqrstuvwxyz"
def encrypt(s, shift):
news = ""
for i in s:
if i.lower() in alphabet:
if i.upper() == i:
c = alphabet[(alphabet.index(i.lower()) + shift) % len(alphabet)]
news = news + c.upper()
else:
c = alphabet[(alphabet.index(i) + shift) % len(alphabet)]
news = news + c
else:
news = news + i
print(news)
def decrypt(s, shift):
news = ""
for i in s:
if i.lower() in alphabet:
if i.upper() == i:
c = alphabet[(alphabet.index(i.lower()) - shift) % len(alphabet)]
news = news + c.upper()
else:
c = alphabet[(alphabet.index(i) - shift) % len(alphabet)]
news = news + c
else:
news = news + i
print(news)
def gettodo():
a = input("What do you want to do? E for encrypt, D for decrypt: ").lower()
if a[0] == "e":
b = input("Enter a plaintext: ")
c = int(input("Enter a shift: "))
encrypt(b, c)
gettodo()
elif a[0] == "d":
b = input("Enter a ciphertext: ")
c = int(input("Enter a shift: "))
decrypt(b, c)
gettodo()
else:
print("Invalid input.")
gettodo()
gettodo()
Wednesday, June 17, 2015
Left-Shifting Zeroes in Java
So I've heard a tricky question that Google apparently likes to ask during interviews:
You have been given an array of integers that may or may not contain zeroes. Your task is to sort the array in-place such that all the zeroes are at the last digits of the array, and all non-zero integers are at the beginning of the array in the order that they were initially given.
For instance,
sort([0, 0, 0]) //the new array is [0, 0, 0]
sort([1, 0, 1, 0, 0, 1, 1, 0, 1, 0]) //the new array is [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
sort([0, 0, 7]) //the new array is [7, 0, 0], i.e. a much less interesting secret agent
sort([8, 6, 7]) //the new array is [8, 6, 7]
sort([5, 3, 0, 9]) //the new array is [5, 3, 9, 0], you got the wrong number
My code to solve it is at the bottom or on Pastebin as per usual.
I thought my method was interesting: I just left-shifted everything over whenever a zero was found, which means that the complexity was O(n^2) if I know my complexity theory (which I very well may not).
The most confusing part for me to code was the notallzeroes part of it. So I had to hard-code in the notallzeroes variable, which tracks the array to see if we can break: if we've reached the end of the non-zero part of the sorted array, we can break automatically. But it also allows us to see if there are any indices we need to go over again so we can redo those. The issue I ran into without that bit is that if multiple zeroes are in a row, every other zero is skipped.
import java.util.*;
public class Main {
static int[] array = new int[20];
public static void sort(int[] a) {
for (int i = 0; i < a.length; i++) {
if (a[i] == 0) {
boolean notallzeroes = false;
for (int j = i; j < a.length - 1; j++ ){
a[j] = a[j+1];
if (a[j] != 0) {
notallzeroes = true;
}
}
a[a.length-1] = 0;
if (notallzeroes) {
i--;
}
else {
break;
}
}
}
}
public static void main(String[] args) {
System.out.println("STARTED!");
for (int j = 0; j < 20; j++) {
Random r = new Random();
for (int i = 0; i < array.length; i++) {
array[i] = r.nextInt(100);
}
for (int i = 0; i < j; i++) {
array[r.nextInt(20)] = 0;
}
System.out.println("BEFORE: " + Arrays.toString(array));
sort(array);
System.out.println("AFTER: " + Arrays.toString(array));
}
}
}
You have been given an array of integers that may or may not contain zeroes. Your task is to sort the array in-place such that all the zeroes are at the last digits of the array, and all non-zero integers are at the beginning of the array in the order that they were initially given.
For instance,
sort([0, 0, 0]) //the new array is [0, 0, 0]
sort([1, 0, 1, 0, 0, 1, 1, 0, 1, 0]) //the new array is [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
sort([0, 0, 7]) //the new array is [7, 0, 0], i.e. a much less interesting secret agent
sort([8, 6, 7]) //the new array is [8, 6, 7]
sort([5, 3, 0, 9]) //the new array is [5, 3, 9, 0], you got the wrong number
My code to solve it is at the bottom or on Pastebin as per usual.
I thought my method was interesting: I just left-shifted everything over whenever a zero was found, which means that the complexity was O(n^2) if I know my complexity theory (which I very well may not).
The most confusing part for me to code was the notallzeroes part of it. So I had to hard-code in the notallzeroes variable, which tracks the array to see if we can break: if we've reached the end of the non-zero part of the sorted array, we can break automatically. But it also allows us to see if there are any indices we need to go over again so we can redo those. The issue I ran into without that bit is that if multiple zeroes are in a row, every other zero is skipped.
import java.util.*;
public class Main {
static int[] array = new int[20];
public static void sort(int[] a) {
for (int i = 0; i < a.length; i++) {
if (a[i] == 0) {
boolean notallzeroes = false;
for (int j = i; j < a.length - 1; j++ ){
a[j] = a[j+1];
if (a[j] != 0) {
notallzeroes = true;
}
}
a[a.length-1] = 0;
if (notallzeroes) {
i--;
}
else {
break;
}
}
}
}
public static void main(String[] args) {
System.out.println("STARTED!");
for (int j = 0; j < 20; j++) {
Random r = new Random();
for (int i = 0; i < array.length; i++) {
array[i] = r.nextInt(100);
}
for (int i = 0; i < j; i++) {
array[r.nextInt(20)] = 0;
}
System.out.println("BEFORE: " + Arrays.toString(array));
sort(array);
System.out.println("AFTER: " + Arrays.toString(array));
}
}
}
Subscribe to:
Comments (Atom)