
Security News
Follow-up and Clarification on Recent Malicious Ruby Gems Campaign
A clarification on our recent research investigating 60 malicious Ruby gems.
This is basically a coding exercise.
The goal of this gem is to solve puzzles à-la NY Times Digits game. You may actually know this game under a different name. In France this looks like the calculation part of an almost 50 year old TV show named 'Les chiffres et les lettres'...
The goal is to use numbers from the draw combined by any basic operation (+ - / *) to reach that goal. You cannot have negative numbers as result of "-" operation, and can only divide number resulting into an integer.
This gem implements a brute-force approach to solve the problem but is ready to host alternate strategies.
Basically this strategy won't work beyond 7 numbers in the draw (it is limited in the command line to 6 numbers but not within
the code), as for a 7 numbers draw it already takes few minutes on my machine. Although this strategy does not
stop at the first encountered solution but browses the whole tree of possibilities (that could be easily done).
To go beyond, you would probably have to go for a more mathematical approach...
You need to have the Ruby language working on your machine.
Install this Ruby gem:
$ gem install digits_solver
Once this gem installed, it provides an executable named find_nydigits_solutions
(you may potentially have to log-out/in if it is not available in your shell).
ex:
$ find_nydigits_solutions 437 3 5 7 13 20 25
Trying to find 437
A best solution has been found (total of 67 found).
Solved in 4 operations:
=> 5 * 7 = 35
=> 35 - 13 = 22
=> 22 * 20 = 440
=> 440 - 3 = 437
This program will only display the "best" solution found (ie the one implying the least number of operations), but code does not (you see here above that 67 solutions were found).
You have basically access to the same functions but with more flexibility.
# The interface looks a lot like the command line, here as opposed to the command line
# you are not limited to 6 numbers in the draw, but be aware that 7 takes already few minutes
# and I never tried beyond...
r = DigitsSolver.solve_for 437, 3, 5, 7, 13, 20, 25
# The object returned is a DigitsSolver::SolutionSet
# You can query it
r.size
# => 67
# You can query the "best" solution found. It returns a DigitsSolver::Solution object.
r.best_solution
# => #<DigitsSolver::Solution:0x000055b96f5f97a8
# Solution: '(5 * 7 - 13) * 20 - 3 = 437',
# @problem_statement=#<DigitsSolver::ProblemStatement:0x000055b96fe71020 @draw=[3, 5, 7, 13, 20, 25], @max_operations_number=5, @target_number=437>,
# @operands=[5, 7, 13, 20, 3],
# @operations_to_apply=[:multiply, :minus, :multiply, :minus]>
# Or you can query the "best" solutions, then it would return an array of DigitsSolver::Solution
#
r.best_solutions 3
# => [#<DigitsSolver::Solution:0x000055b96f5f97a8
# Solution: '(5 * 7 - 13) * 20 - 3 = 437',
# @problem_statement=#<DigitsSolver::ProblemStatement:0x000055b96fe71020 @draw=[3, 5, 7, 13, 20, 25], @max_operations_number=5, @target_number=437>,
# @operands=[5, 7, 13, 20, 3],
# @operations_to_apply=[:multiply, :minus, :multiply, :minus]>,
# #<DigitsSolver::Solution:0x000055b96f663ef0
# Solution: '(7 * 5 - 13) * 20 - 3 = 437',
# @problem_statement=#<DigitsSolver::ProblemStatement:0x000055b96fe71020 @draw=[3, 5, 7, 13, 20, 25], @max_operations_number=5, @target_number=437>,
# @operands=[7, 5, 13, 20, 3],
# @operations_to_apply=[:multiply, :minus, :multiply, :minus]>,
# #<DigitsSolver::Solution:0x000055b96f6b2528
# Solution: '((20 - 3) * 25 + 5) + 7 = 437',
# @problem_statement=#<DigitsSolver::ProblemStatement:0x000055b96fe71020 @draw=[3, 5, 7, 13, 20, 25], @max_operations_number=5, @target_number=437>,
# @operands=[20, 3, 25, 5, 7],
# @operations_to_apply=[:minus, :multiply, :plus, :plus]>]
# DigitsSolver::Solution objects can be printed
puts r.best_solution
# Solved in 4 operations:
# => 5 * 7 = 35
# => 35 - 13 = 22
# => 22 * 20 = 440
# => 440 - 3 = 437
# => nil
# or debugged
pp r.best_solution
# #<DigitsSolver::Solution:0x000055b96f5f97a8
# Solution: '(5 * 7 - 13) * 20 - 3 = 437',
# @problem_statement=#<DigitsSolver::ProblemStatement:0x000055b96fe71020
# @draw=[3, 5, 7, 13, 20, 25],
# @max_operations_number=5,
# @target_number=437>,
# @operands=[5, 7, 13, 20, 3],
# @operations_to_apply=[:multiply, :minus, :multiply, :minus]>
# And of course it has other methods, you could use. Ex:
r.sorted_solutions.map(&:to_evaluable_code).take 10
# => ["(5 * 7 - 13) * 20 - 3",
# "(7 * 5 - 13) * 20 - 3",
# "((20 - 3) * 25 + 5) + 7",
# "((20 - 3) * 25 + 7) + 5",
# "((20 - 5) + 3) * 25 - 13",
# "((20 - 7) + 5) * 25 - 13",
# "((3 * 5 + 20) * 13 + 7) - 25",
# "((3 * 5 + 20) * 13 - 25) + 7",
# "((3 * 7 * 20 + 5) - 13) + 25",
# "((3 * 7 * 20 + 5) + 25) - 13"]
FAQs
Unknown package
We found that digits_solver demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
A clarification on our recent research investigating 60 malicious Ruby gems.
Security News
ESLint now supports parallel linting with a new --concurrency flag, delivering major speed gains and closing a 10-year-old feature request.
Research
/Security News
A malicious Go module posing as an SSH brute forcer exfiltrates stolen credentials to a Telegram bot controlled by a Russian-speaking threat actor.