Skip to content

Commit

Permalink
add scripts to aid solving problems
Browse files Browse the repository at this point in the history
  • Loading branch information
zsarge committed Nov 2, 2021
1 parent 76ec17f commit 3601b3e
Show file tree
Hide file tree
Showing 4 changed files with 349 additions and 1 deletion.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2021 Zack Sargent
Copyright (c) 2020 Zack Sargent

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# [Advent of Code 2021](https://projecteuler.ne://adventofcode.com/2021)

**Disclaimer:**

Not all of these solutions are particularly good.

## My Advent of Code Solutions
(Click a number to view the associated solution.)
<!---
This table is automatically generated and is best viewed with line wrap off.
I did consider reference style links, and they didn't seem much better.
Just try and view the formatted table, if you can.
-->
| 1 | 2 | 3 | 4 | 5 |
| -- | -- | -- | -- | ------------------------------ |
| 6 | 7 | 8 | 9 | [10](solutions/010/solve10.rb) |
| 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 |


<br>
I have some scripts set up to make working on problems a smoother experience:

- [`addSolution.rb`](addSolution.rb) takes a problem number, creates the associated folder and file, and copies the problem's prompt from the website.
- [`generateReadme.rb`](generateReadme.rb) generates this readme based on the files in the solutions folder.

Some of the scripts were reused from [my Project Euler solutions](https://github.com/zsarge/ProjectEuler).

Code by [Zack Sargent](https://github.com/zsarge).
140 changes: 140 additions & 0 deletions addSolution.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# Run this script to create a new solution
# Run by using 'ruby addSolution.rb {challenge number}'
# or by just 'ruby addSolution.rb'
#
# This assumes you are running a linux like system.

require 'open-uri'
require 'nokogiri'

# Get text from internet -----
def getProblemText(num, language)
url = "https://projecteuler.net/problem=#{num}"
doc = Nokogiri::HTML(URI.open(url))
content = doc.css('div.problem_content')
if language == "hs" || language == "java"
comment = ""
else
comment = "# "
end
return content.text.gsub("\r","").gsub("\n", "\n#{comment}").chomp
end

# Take input ----------------
problemNumber = ""
extension = ""

if ARGV.length == 0
puts "enter the challenge number"
problemNumber = gets.chomp

puts "enter the file extension"
extension = gets.chomp

puts "create solve#{problemNumber}.#{extension}? (y/n)"
input = ""

while input.downcase.count("yn") <= 0
input = gets.chomp
end

return if input.downcase.count("n") >= 1
elsif ARGV.length == 1
puts "Malformed input. Please have both a number and an extension."
puts "For example: "
puts "`ruby addSolution.rb 1 py` will create `./solutions/001/solve1.py`"
exit(1)
else
problemNumber = ARGV[0]
extension = ARGV[1]
end

if extension == ""
extension = rb
end

# Create file ---------------
unless File.directory?("solutions")
puts "no solutions directory found. are you running this from the right directory?"
exit(1)
end
filename = "solve#{problemNumber}.#{extension}"
path = "solutions/#{problemNumber.rjust(3, "0")}"

# do not overwrite existing files
if File.file?("#{path}/#{filename}")
puts "File Exists. Exiting"
exit(1)
end

# pick template based on extension
if extension == "rb"
template = "\
# https://projecteuler.net/problem=#{problemNumber}
# Run with: 'ruby #{filename}'
# using Ruby 2.5.1
# by Zack Sargent
# Prompt:
#{getProblemText(problemNumber, extension)}
puts 'Hello World!'
"
elsif extension == "py"
template = "\
# https://projecteuler.net/problem=#{problemNumber}
# Run with: 'python #{filename}'
# using Python 3.6.9
# by Zack Sargent
\"\"\"
Prompt:
#{getProblemText(problemNumber, extension)}
\"\"\"
def main():
print('Hello World!')
if __name__ == \"__main__\":
main()
"
elsif extension == "hs"
template = "\
-- https://projecteuler.net/problem=#{problemNumber}
-- Run with: 'ghc #{filename} && ./#{filename[0..filename.size-4]}' or 'runhaskell #{filename}'
-- using Haskell with GHC 8.0.2
-- by Zack Sargent
{- Prompt:
#{getProblemText(problemNumber, extension)}
-}
main = putStrLn \"Hello World\"
"
elsif extension == "java"
template = "\
// https://projecteuler.net/problem=#{problemNumber}
// Run with: 'javac #{filename} && java Solve#{problemNumber}'
// using openjdk version 11.0.10 and javac 11.0.10
// by Zack Sargent
/* Prompt:
#{getProblemText(problemNumber, extension)}
*/
class Solve#{problemNumber} {
public static void main(String[] args) {
System.out.println(\"Hello, World!\");
}
}
"
end

Dir.mkdir(path) unless File.directory?(path)

File.write("#{path}/#{filename}", template, mode: "w")

puts "created #{path}/#{filename}"
178 changes: 178 additions & 0 deletions generateReadme.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# This script makes a README.md with links to all my solutions.
# Run it with 'ruby generateReadme.rb'
# This was written using Ruby 2.5.1
# by Zack Sargent

# Start table generation

def makeColumnElement(number, width)
width += 2 # add more spacing
string = number
string.prepend("| ")
return "" if number.nil? || width - number.size <= -1
string << (" " * (width - number.size))
return string
end

def makeRow(array, widths)
row = ""
col = 0
array.each { |ele|
row << makeColumnElement(ele, widths[col] + 1)
col += 1
}
row << "|\n"
return row
end

def makeHeader(widths)
row = ""
widths.each { |width|
row << makeColumnElement("-"*(width), width + 1)
}
row << "|\n"
return row
end

def getWidths(array, cols)
widths = []
1.upto(cols) do |i|
column = []
(i..array.size).step(cols) do |j|
column.append(array[j-1])
end
widths.append(column.max_by(&:length).size)
end
return widths
end

# makeTable takes an array of strings to be formatted as a
# markdown table. The number of elements in the array needs to
# be evenly divisble by the number of columns.
def makeTable(array, cols)
return nil unless array.size%cols == 0
table = []
# width = array.max_by(&:length).size
widths = getWidths(array, cols)

# loop through array by row
(1..array.size).step(cols) do |i|
# section = row, accounting for index changes
section = array[i-1..i+cols-2]
table.append(makeRow(section, widths))
end

table.insert(1, makeHeader(widths))
return table.join
end

# Stop table generation
# Start content generation

def getFilesInDir(dir)
files = Dir.children(dir)
return files
end

def makeLink(files, dirName)
if files.size == 0
return "#{dirName.to_i}"
elsif files.size == 1
return "[#{dirName.to_i}](solutions/#{dirName}/#{files[0]})"
else
return "[#{dirName.to_i}](solutions/#{dirName}/)"
end
end

# takes a name of solution and the solutions,
# and returns either a link to the solution
# or the name if the solution doesn't exist
def getLink(name, solutions, language = nil)
name = name.to_i
if solutions.key?(name)
return solutions[name]
else
return name
end
end

def filterSolutions(solutions, language)
def is_valid?(filename, language)
lower_filename = filename.downcase()
return false if lower_filename.include?(".txt")
return false if lower_filename.include?(".swp")
return false if lower_filename.include?(".hi")
return false if lower_filename.include?(".o")
return false if lower_filename.include?(".class")
# do not keep compiled files
return false unless lower_filename.include?(".")
# keep if no language is specified
return true unless language
extension = filename[filename.size-language.size..filename.size]
return (extension == language)
end

solutions.keep_if { |filename| is_valid?(filename, language) }
return solutions
end


# represent dir as object where
# dir = {
# folder name as integer => content to go in table cell,
# folder name as integer => content to go in table cell,
# }

def makeFilledTable(language = nil)
names = getFilesInDir("solutions")
files = {}
names.each do |name|
solutions = getFilesInDir("solutions/#{name}")
solutions = filterSolutions(solutions, language)
files.store(name.to_i, makeLink(solutions, name))
end

arr = (1..25).to_a
.map { |num| getLink(num, files, language) }
.map(&:to_s)

return makeTable(arr, 5)
end

FULL_TABLE = makeFilledTable()

# Stop content generation
# Start writing to file

content = "\
# [Advent of Code 2021](https://projecteuler.ne://adventofcode.com/2021)
**Disclaimer:**
Not all of these solutions are particularly good.
## My Advent of Code Solutions
(Click a number to view the associated solution.)
<!---
This table is automatically generated and is best viewed with line wrap off.
I did consider reference style links, and they didn't seem much better.
Just try and view the formatted table, if you can.
-->
#{FULL_TABLE}
<br>
I have some scripts set up to make working on problems a smoother experience:
- [`addSolution.rb`](addSolution.rb) takes a problem number, creates the associated folder and file, and copies the problem's prompt from the website.
- [`generateReadme.rb`](generateReadme.rb) generates this readme based on the files in the solutions folder.
Some of the scripts were reused from [my Project Euler solutions](https://github.com/zsarge/ProjectEuler).
Code by [Zack Sargent](https://github.com/zsarge).
"

File.write("README.md", content, mode: "w")

# Stop writing to file

puts "Success"

0 comments on commit 3601b3e

Please sign in to comment.