Skip to content

Instantly share code, notes, and snippets.

@ysbaddaden
Created October 21, 2017 12:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ysbaddaden/fccf87d4ca22082c7d645b9f547a9713 to your computer and use it in GitHub Desktop.
Save ysbaddaden/fccf87d4ca22082c7d645b9f547a9713 to your computer and use it in GitHub Desktop.
Search for collisions and display distribution (libsdl2) of hashes for a list of patterns (e.g. words, uuids, numbers, ...) from STDIN
# Requires https://github.com/ysbaddaden/sdl.cr
require "sdl"
# Depends on the Crystal::Hasher implementation.
# Adjust to match the type of `"".hash`
alias HashType = UInt64
word_count = 0
maximum = 0
collisions = 0
print_collisions = ARGV.any?(&.==("--collisions"))
hashes = Hash(HashType, Array(String)).new
while word = STDIN.gets
word_count += 1
hash = word.hash #.to_u64
hashes[hash] ||= [] of String
hashes[hash] << word
end
hashes.each do |hash, words|
next if words.size == 1
puts "COLLISION: #{words.join(' ')}" if print_collisions
maximum = words.size if words.size > maximum
collisions += 1
end
minimum_hash = hashes.keys.min
maximum_hash = hashes.keys.max
puts " WORDS = #{word_count}"
print " COLLISIONS = #{collisions}"
print " (1:#{maximum - 1})" if collisions > 0
puts
puts " SPAN = #{maximum_hash - minimum_hash} (#{minimum_hash}..#{maximum_hash})"
puts "\nPress 's' to take a screenhost, 'q' to quit."
# create GUI
SDL.init(SDL::Init::VIDEO)
at_exit { SDL.quit }
window = SDL::Window.new("Distribution", width = 800, height = 600)
renderer = SDL::Renderer.new(window)
pixels = width * height
ratio = HashType::MAX / pixels.to_f
# clear image
renderer.draw_color = SDL::Color[255, 255, 255, 255]
renderer.clear
# render each hash as a point in image
renderer.draw_color = SDL::Color[255, 0, 0, 255]
hashes.each_with_index do |(hash, words), index|
pixel = hash / ratio
y = (pixel / width).to_i
x = pixel.remainder(width).to_i
renderer.draw_point(x, y)
end
# display distribution
renderer.present
format = window.surface.format
buffer = Bytes.new(width * height * format.bytes_per_pixel)
loop do
case event = SDL::Event.wait
when SDL::Event::Quit
break
when SDL::Event::Keyboard
if event.sym.q?
break
end
if event.sym.s? && event.type.keyup?
# save screenhost
renderer.read_pixels(SDL::Rect[0, 0, width, height], format, buffer)
screenshot = SDL::Surface.from(buffer, width, height, format)
screenshot.save_bmp("screenshot.bmp")
puts "Saved screenshot.bmp"
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment