Python3 – Sudoku

Codewars

https://www.codewars.com/kata/validate-sudoku-with-size-nxn/python

Given a Sudoku data structure with size NxN, N > 0 and √N == integer, write a method to validate if it has been filled out correctly.

The data structure is a multi-dimensional Array(in Rust: Vec<Vec<u32>>) , ie:

[
  [7,8,4,  1,5,9,  3,2,6],
  [5,3,9,  6,7,2,  8,4,1],
  [6,1,2,  4,3,8,  7,5,9],

  [9,2,8,  7,1,5,  4,6,3],
  [3,5,7,  8,4,6,  1,9,2],
  [4,6,1,  9,2,3,  5,8,7],

  [8,7,6,  3,9,4,  2,1,5],
  [2,4,3,  5,6,1,  9,7,8],
  [1,9,5,  2,8,7,  6,3,4]
]

Rules for validation

  • Data structure dimension: NxN where N > 0 and √N == integer
  • Rows may only contain integers: 1..N (N included)
  • Columns may only contain integers: 1..N (N included)
  • ‘Little squares’ (3x3 in example above) may also only contain integers: 1..N (N included)

Martin’s comment

To be perfectly honest I have never played the sudoku. So firstly I had to learn a how to play it from Sudoku.com, and later solve the problem. My solution is definetely not the shortest nor ideal one but it works. I had saved a lot of work and issues using NumPy library in Python which I would like to learn more deeply.

Below is my solution.

Martin’s solution

import numpy, math

class Sudoku(object):
    def __init__(self, m):
        self.matrix = numpy.matrix(m)
    def is_valid(self):
        self.mysum = sum(x for x in range(1,len(self.matrix)+1))
        self.mylen = int(math.sqrt(len(self.matrix)))
        # iterate over submatrixes
        for x in range(0,self.mylen):
            for y in range(0, self.mylen):
                submatrix = self.matrix[x*self.mylen:x*self.mylen+self.mylen,y*self.mylen:y*self.mylen+self.mylen]
                for i in range(1,self.mylen):
                    if i not in submatrix.A1.tolist():
                        return False
                if numpy.sum(submatrix) != self.mysum:
                    return False
        results = self.numpy_lines(1) + self.numpy_lines(0) # rows + columns parsing
        for result in results:
            if not result:
                return False
        return True

    def line_sudoku(self, line):
        line = line.tolist()[0]
        if sum(line) != self.mysum:
            return False
        for i in range(1, self.mylen):
            if i not in line:
                return False
        return True

    def numpy_lines(self,axis):
        return numpy.apply_along_axis(self.line_sudoku, axis = axis, arr = self.matrix).tolist()

goodSudoku = Sudoku([
  [1,4, 2,3],
  [3,2, 4,1],

  [4,1, 3,2],
  [2,3, 1,4]
])

print(goodSudoku.is_valid())

Tests

# Valid Sudoku
goodSudoku1 = Sudoku([
  [7,8,4, 1,5,9, 3,2,6],
  [5,3,9, 6,7,2, 8,4,1],
  [6,1,2, 4,3,8, 7,5,9],

  [9,2,8, 7,1,5, 4,6,3],
  [3,5,7, 8,4,6, 1,9,2],
  [4,6,1, 9,2,3, 5,8,7],
  
  [8,7,6, 3,9,4, 2,1,5],
  [2,4,3, 5,6,1, 9,7,8],
  [1,9,5, 2,8,7, 6,3,4]
])

goodSudoku2 = Sudoku([
  [1,4, 2,3],
  [3,2, 4,1],

  [4,1, 3,2],
  [2,3, 1,4]
])

# Invalid Sudoku
badSudoku1 = Sudoku([
  [0,2,3, 4,5,6, 7,8,9],
  [1,2,3, 4,5,6, 7,8,9],
  [1,2,3, 4,5,6, 7,8,9],
  
  [1,2,3, 4,5,6, 7,8,9],
  [1,2,3, 4,5,6, 7,8,9],
  [1,2,3, 4,5,6, 7,8,9],
  
  [1,2,3, 4,5,6, 7,8,9],
  [1,2,3, 4,5,6, 7,8,9],
  [1,2,3, 4,5,6, 7,8,9]
])

badSudoku2 = Sudoku([
  [1,2,3,4,5],
  [1,2,3,4],
  [1,2,3,4],  
  [1]
])

Test.it('should be valid')
Test.assert_equals(goodSudoku1.is_valid(), True, 'Testing valid 9x9')
Test.assert_equals(goodSudoku2.is_valid(), True, 'Testing valid 4x4')

Test.it ('should be invalid')
Test.assert_equals(badSudoku1.is_valid(), False, 'Values in wrong order')
Test.assert_equals(badSudoku2.is_valid(), False, '4x5 (invalid dimension)')

Python3 – Next bigger number with the same digits

Codewars

Source: codewars
You have to create a function that takes a positive integer number and returns the next bigger number formed by the same digits:

next_bigger(12)==21
next_bigger(513)==531
next_bigger(2017)==2071

If no bigger number can be composed using those digits, return -1:

next_bigger(9)==-1
next_bigger(111)==-1
next_bigger(531)==-1

Testing cases

Test.assert_equals(next_bigger(12),21)
Test.assert_equals(next_bigger(513),531)
Test.assert_equals(next_bigger(2017),2071)
Test.assert_equals(next_bigger(414),441)
Test.assert_equals(next_bigger(144),414)

Martin’s Comment

Firstly when I saw this exercise first came to my mind python library for permutations which I used before. From that point it is very easy to solve, you just sort all permutations and cycle through sorted numbers and in case you find a first bigger number you return it.

Martin’s Solution

import itertools
def next_bigger(n):
    for num in sorted([int(''.join(map(str,x))) for x in list(set(itertools.permutations([int(x) for x in str(n)])))]):
        if num>n:
            return num
    return -1

Prometheus installation on CentOS 7

wget https://github.com/prometheus/prometheus/releases/download/v1.7.1/prometheus-1.7.1.linux-amd64.tar.gz
  • Install Prometheus
cd /opt
tar -zxvf /root/prometheus-1.7.1.linux-amd64.tar.gz
ln -s prometheus-1.7.1.linux-amd64 prometheus
useradd prometheus
chown prometheus:prometheus /opt/prometheus-1.7.1.linux-amd64/ -R
  • Create Systemd script
  • # /etc/systemd/system/prometheus.service
    [Unit]
    Description=Prometheus Server
    Documentation=https://prometheus.io/docs/introduction/overview/
    After=network-online.target
    
    [Service]
    
    User=prometheus
    Restart=on-failure
    ExecStart=/opt/prometheus/prometheus \
      -config.file=/opt/prometheus/prometheus.yml \
      -storage.local.path=/opt/prometheus/data
    [Install]
    WantedBy=multi-user.target
  • Run prometheus
    ln -s /opt/prometheus/prometheus.yml /etc
    systemctl daemon-reload
    systemctl start prometheus
    systemctl enable prometheus
    
  • Disable firewall
  • systemctl stop firewalld
    systemctl disable firewalld
    
  • Access prometheus on http://prometheus_host:9090/ (Warning: please keep web browser and server time synchronized via ntp or you might be unable to see anything).

 

Python3 – Hex cipher

Intro/Explanation

I am beginning with learning Python3 or I am an actual false beginner. Today I am trying to solve relatively easy task from Codewars. First thing which came to my mind was “This is a typical recursion”

Codewars

Source: Codewars

In order to bamboozle your friends, you decide to encode your communications in hexadecimal, using an ASCII to hexadecimal table. At first, none of them can understand your messages. But quickly enough, one of your cleverer friends uncovers your trick and starts sending messages in hexadecimal himself. To stay one (or shall we say, n) step(s) ahead of your friend, you decide to go one step further : you’ll apply the ASCII to hexadecimal conversion more than once.

Your Task

Implement methods encode and decode of class HexCipher, as described above.

Provided to you is a dictionary, TEXT2HEX, mapping ASCII characters to their corresponding hexadecimal code (which will always be 2 digits). For example, TEXT2HEX['a'] evaluates to '61'.

Happy bamboozlin’!

Note: if you get a timeout, just submit it again. If you repeatedly get a timeout, then your code needs some optimization 🙂

Martin’s solution

import binascii
class HexCipher:
    @classmethod
    def encode(cls, s, n):
        return cls.encode((binascii.hexlify(s.encode('ascii')).decode('ascii')), n-1) if n>0 else s

    # Algorithm to encode the string here

    @classmethod
    def decode(cls, s, n):
        return cls.decode(binascii.unhexlify(s).decode('ascii'), n - 1) if n>0 else s

Test cases

test.describe('Sample tests')
test.assert_equals(HexCipher.encode('Hey guys', 0), 'Hey guys')
test.assert_equals(HexCipher.decode('Hey guys', 0), 'Hey guys')
test.assert_equals(HexCipher.encode('Hey guys', 1), '4865792067757973')
test.assert_equals(HexCipher.decode('4865792067757973', 1), 'Hey guys')
test.assert_equals(HexCipher.encode('Hey guys', 2), '34383635373932303637373537393733')
test.assert_equals(HexCipher.decode('34383635373932303637373537393733', 2), 'Hey guys')
test.assert_equals(HexCipher.decode('34383635373932303637373537393733', 1), '4865792067757973')