Skip to content

Instantly share code, notes, and snippets.

@YoukaiCat
Last active January 27, 2018 21:55
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 YoukaiCat/0e376e7c4744c57cc27fb3d411ac1d7e to your computer and use it in GitHub Desktop.
Save YoukaiCat/0e376e7c4744c57cc27fb3d411ac1d7e to your computer and use it in GitHub Desktop.
Random Sequence Analysis
class Analyzer
attr_reader :name
def initialize name, numbers, bits_count = 16
@name = name
@numbers = numbers
@bits_count = bits_count
end
# Случайность распределения
# Сколько в отрезок входит чисел.
# Например, массив из 13473467 чисел, значениями от 1 до 100
# Делим на 10 интервалов, получается по 10 возможных чисел в интервале
# Найти сколько чисел принадлежит этим интервалам
def randomness_of_distribution
min = @numbers.min
max = @numbers.max
intervals_num = 10
step = (max - min) / intervals_num
# Нижние границы, границы интервалов без хвоста списка
# Например, [1, 11, 21, 31, 41] -> [1, 11, 21, 31]
lower = (min..max).step(step).to_a[0..-2] #init
# Верхние границы, границы интервалов без головы списка
# Например, [1, 11, 21, 31, 41] -> [11, 21, 31, 41]
upper = (min..max).step(step).to_a[1..-1] #tail
# Массив границ для каждого интервала
# Например, [[1, 11], [11, 21], [21, 31], [31, 41]]
bounds = lower.zip upper
# Количество значений для каждого интервала
counts = bounds.map do |lower_bound, upper_bound|
# Фильтрация значений, входящих в интервал и подсчёт их количества
@numbers.count { |number| number.between? lower_bound, upper_bound - 1 }
end
{ results: counts, x: x_randomness_of_distribution(counts, @numbers.size, intervals_num) }
end
# Магическая формула Хиквадрата
def x_randomness_of_distribution m, n, intervals_num
m.map do |mi|
p = 1.0 / intervals_num
pn = p * n
dividend = (mi - pn) ** 2
dividend / pn
end.reduce(&:+)
end
# Случайность разрядов
# Количество чисел, имеющих единицу в n бите (разряде)
# Числа по битам
def randomness_of_bits
ones_at_bits = Array.new @bits_count, 0
# Трансформация всех чисел в массивы битов см. #to_bit_array
numbers = @numbers.map { |number| to_bit_array number }
numbers.each do |number|
# Для каждого значения бита и индекса бита каждого числа
number.each_with_index do |bit, index|
# Увеличить счётчик единиц бита
ones_at_bits[index] += 1 if bit == 1
end
end
{ results: ones_at_bits, x: x_randomness_of_bits(ones_at_bits, @numbers.size) }
end
def x_randomness_of_bits m, n
m.map do |mi|
p = 1.0 / 2.0
pn = p * n
dividend = (mi - pn) ** 2
dividend / pn
end.reduce(&:+)
end
# Случайность числа
# Количество чисел, содержащих n битов (разрядов) со значением 1
# Числа по количеству
def randomness_of_number
# Может быть ноль битов с единицами, поэтому 17 элементов (16 возможных битов + 1)
counts = Array.new @bits_count + 1, 0
# Трансформация всех чисел в массивы битов см. #to_bit_array
numbers = @numbers.map { |number| to_bit_array number }
# Количество битов с единицами для каждого числа
n_ones = numbers.map do |number|
# Отфильтровать биты с единицами, посчитать количество
number.count { |bit| bit == 1 }
end
# Увеличить счётчик для такого-то количества
n_ones.each { |n| counts[n] += 1 }
{ results: counts, x: x_randomness_of_number(counts, @numbers.size, @bits_count) }
end
def x_randomness_of_number m, n, bits_count
pis = Array.new m.size
pis.each_index do |i|
if i == 0
pis[i] = 2.0 ** (- bits_count)
else
pis[i] = (bits_count - i + 1.0) * pis[i - 1] / i
end
end
m.zip(pis).map do |tuple|
mi, pi = tuple
pn = pi * n
dividend = (mi - pn) ** 2
dividend / pn
end.reduce(&:+)
end
# Трансформация числа в двоичное строковое представление
# 5 => "0000000101"
def to_binary_string number
"%0#{@bits_count}b" % number
end
# Трансформация числа в массив битов
# 5 => [0,0,0,0,0,0,0,1,0,1]
def to_bit_array number
to_binary_string(number).split('').map(&:to_i)
end
def unique_persentage
count = @numbers.uniq.size
{ results: count, x: "#{count * 100 / @numbers.size}%" }
end
end
data = {}
data[:lcg] = File.readlines "/home/natsuo/Development/Current/Cypher/Second/Data/Task1_example/Метод вычетов"
data[:msp430] = File.readlines "/home/natsuo/Development/Current/Cypher/Second/Data/Task1_example/msp430"
data[:random_sharp] = File.readlines "/home/natsuo/Development/Current/Cypher/Second/Data/Task1_example/Random_c#"
data[:rngcrypto] = File.readlines "/home/natsuo/Development/Current/Cypher/Second/Data/Task1_example/RNGCrypto"
data[:_0] = File.readlines "/home/natsuo/Development/Current/Cypher/Second/Data/Task1/0"
data[:_1] = File.readlines "/home/natsuo/Development/Current/Cypher/Second/Data/Task1/1"
data[:_2] = File.readlines "/home/natsuo/Development/Current/Cypher/Second/Data/Task1/2"
data[:_3] = File.readlines "/home/natsuo/Development/Current/Cypher/Second/Data/Task1/3"
analyzers = data.map { |name, strings| strings.map!(&:to_i); Analyzer.new(name, strings) }
# Просто метод, который печатает результаты,
# вызвая у анализатора заданный метод
def analyzer_print analyzer, method
print '%-15.15s' % "#{analyzer.name}:"
result = analyzer.method(method).call
print result[:results]
puts " = #{result[:x]}"
end
puts 'Случайность распределения:'
analyzers.each { |a| analyzer_print a, :randomness_of_distribution }
puts
puts 'Случайность разрядов:'
analyzers.each { |a| analyzer_print a, :randomness_of_bits }
puts
puts 'Случайность числа:'
analyzers.each { |a| analyzer_print a, :randomness_of_number }
puts
puts 'Процент уникальных чисел:'
analyzers.each { |a| analyzer_print a, :unique_persentage }
@YoukaiCat
Copy link
Author

Случайность распределения:
lcg:           [4941, 5067, 4928, 5033, 4962, 5044, 4953, 5062, 4973, 5034] = 5.1122000000000005
msp430:        [4357, 2813, 3073, 2893, 1402, 0, 0, 1462, 2808, 3822] = 8706.531163434902
random_sharp:  [5098, 5016, 4873, 4983, 4965, 5049, 4988, 5053, 5021, 4948] = 7.2004
rngcrypto:     [5020, 5009, 4963, 4960, 4937, 4998, 5006, 5012, 5094, 4996] = 3.291
_0:            [4965, 5025, 4980, 4997, 4992, 5027, 4981, 5035, 4987, 5006] = 0.9686
_1:            [9287, 6367, 6294, 6215, 3187, 0, 0, 3142, 6271, 8270] = 18489.0386
_2:            [4976, 5056, 4970, 5073, 4957, 4968, 5011, 5048, 4853, 5084] = 8.7808
_3:            [5043, 4887, 4902, 5026, 4949, 5130, 5002, 4999, 5019, 5040] = 9.273

Случайность разрядов:
lcg:           [25068, 24981, 25011, 25002, 25014, 24999, 25002, 25009, 24998, 25000, 25000, 24997, 25000, 25000, 25000, 25000] = 0.21620000000000003
msp430:        [0, 8566, 14538, 14538, 2870, 10236, 9996, 11437, 0, 8636, 14468, 14468, 2844, 10106, 10097, 11525] = 41441.86625692521
random_sharp:  [25062, 24832, 24970, 24937, 24965, 25015, 24975, 25002, 25034, 24950, 25001, 24938, 24739, 25051, 24992, 24895] = 5.13312
rngcrypto:     [25111, 24924, 24863, 25161, 24932, 25226, 24987, 24919, 24721, 25176, 24799, 25095, 24993, 25057, 24876, 25216] = 13.951600000000001
_0:            [25038, 25038, 24996, 25012, 24988, 25011, 24994, 25002, 25001, 24999, 25001, 25002, 25000, 25000, 25000, 25000] = 0.13440000000000002
_1:            [0, 18650, 31350, 31350, 6370, 21781, 21746, 24878, 0, 18574, 31426, 31426, 6276, 21947, 21629, 25022] = 89366.53196000001
_2:            [24968, 24967, 25137, 24968, 24920, 24978, 25060, 24983, 25100, 24786, 25002, 25094, 24980, 25011, 24938, 25037] = 4.12196
_3:            [25192, 24972, 24923, 25002, 24939, 25102, 25173, 25083, 25031, 24796, 24925, 24890, 24974, 25079, 25092, 25027] = 6.837440000000001

Случайность числа:
lcg:           [0, 13, 93, 423, 1375, 3379, 6063, 8682, 9894, 8689, 6114, 3382, 1355, 437, 86, 14, 1] = 5.45030189010989
msp430:        [0, 0, 0, 0, 1483, 5069, 7249, 5755, 2728, 755, 65, 0, 0, 0, 0, 0, 0] = 25618.384454080853
random_sharp:  [0, 13, 89, 460, 1424, 3298, 6207, 8783, 9846, 8608, 5919, 3422, 1416, 411, 90, 13, 1] = 17.944157602397606
rngcrypto:     [1, 10, 93, 446, 1425, 3219, 6242, 8757, 9628, 8770, 6113, 3363, 1370, 438, 110, 15, 0] = 18.943601607281607
_0:            [1, 11, 91, 413, 1397, 3352, 6057, 8745, 9879, 8661, 6126, 3359, 1371, 432, 89, 15, 1] = 3.516766199134199
_1:            [0, 0, 0, 0, 3135, 10983, 15702, 12623, 5823, 1527, 207, 0, 0, 0, 0, 0, 0] = 55613.16816124676
_2:            [0, 13, 95, 450, 1328, 3253, 6125, 8864, 9968, 8561, 6131, 3308, 1361, 439, 91, 11, 2] = 17.561087715839715
_3:            [0, 15, 105, 438, 1392, 3374, 5917, 8703, 9939, 8752, 6085, 3375, 1370, 408, 105, 21, 1] = 21.98685367965368

Процент уникальных чисел:
lcg:           50000 = 100%
msp430:        256 = 1%
random_sharp:  34949 = 69%
rngcrypto:     35033 = 70%
_0:            50000 = 100%
_1:            256 = 0%
_2:            34927 = 69%
_3:            34912 = 69%

0 - LCG
1 - MSP430
2 - ? (Random C#)
3 - ? (RNGCrypto)

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