<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bartosz Raubo</title>
    <description>The latest articles on DEV Community by Bartosz Raubo (@bmraubo).</description>
    <link>https://dev.to/bmraubo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F547244%2F7a377dbc-00e3-47ff-aad4-8b9ff026c6e8.jpeg</url>
      <title>DEV Community: Bartosz Raubo</title>
      <link>https://dev.to/bmraubo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bmraubo"/>
    <language>en</language>
    <item>
      <title>sudoku solver - Some additions</title>
      <dc:creator>Bartosz Raubo</dc:creator>
      <pubDate>Sun, 08 Aug 2021 19:58:12 +0000</pubDate>
      <link>https://dev.to/bmraubo/sudoku-solver-some-additions-436a</link>
      <guid>https://dev.to/bmraubo/sudoku-solver-some-additions-436a</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/qxcross/sudoku-solver"&gt;Code is here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  August Additions
&lt;/h2&gt;

&lt;p&gt;So, now that the sudoku algo is in place, it would be nice to make it usable. I want to add a couple of things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Making it pretty - give the display of the puzzles some love&lt;/li&gt;
&lt;li&gt;System for inputting sudokus you find online/in RL.&lt;/li&gt;
&lt;li&gt;Ability to store puzzles (and solutions)&lt;/li&gt;
&lt;li&gt;Ability to have a little demo mode&lt;/li&gt;
&lt;li&gt;Diplay how long it took to find the solution.&lt;/li&gt;
&lt;li&gt;and a menu system to tie it all together.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Making it pretty
&lt;/h3&gt;

&lt;p&gt;First thing I touched - just a small function Sudoku.display_board() to print out the information in a visually pleasing manner based on an example I found through Google Image search.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def display_board(puzzle):
        print('\n')
        print('+-------+-------+-------+')
        for y in range(0, len(puzzle)):
            print(f'| {puzzle[y][0]} {puzzle[y][1]} {puzzle[y][2]} ' +
                    f'| {puzzle[y][3]} {puzzle[y][4]} {puzzle[y][5]} ' +
                    f'| {puzzle[y][6]} {puzzle[y][7]} {puzzle[y][8]} |')
            if y in [2, 5, 8]:
                print('+-------+-------+-------+')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The way the func is designed allows for partial boards to be printed - this was kind of accidental but helps with the feedback of information when inputting the board - see below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Puzzle Input
&lt;/h3&gt;

&lt;p&gt;So in an ideal world, I would just want to be able to take a picture of a sudoku, or screenshot, and have that be solved. But that is a little beyond me for now.&lt;/p&gt;

&lt;p&gt;Instead, I used an input function that asks you to type in the puzzle row by row, with 0 representing missing values. It is not the most graceful solution perhaps, but it does allow me to quite easily feed in the input into the solution function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def input_puzzle():
        puzzle = []
        input_msg = 'Input the known values.\nIf value is blank, input 0.\nEg. 530070000\n'
        while len(puzzle) &amp;lt; 9:
            valid = False
            while not valid:
                new_row = input(input_msg)
                puzzle.append(Sudoku.convert_row(new_row))
                valid = Sudoku.validate_row(new_row, puzzle)
                if not valid:
                    puzzle.pop()
                    print('Try Again\n\n')
        return puzzle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Convert_row turns the input into a list.&lt;/p&gt;

&lt;p&gt;The one thing I regret is having to validate each row after it is typed. It is very annoying because most of the time I got the row right, and repeatedly validating got tedious. Then again, when a mistake is made, it mean not only having to start the puzzle again, but also having to complete input of any further rows. Which would be really shit. So its a judgement call between a small amount of constant annoyance or rare catastrophes. Hmmm.&lt;/p&gt;

&lt;p&gt;You can't even press Enter several times... that will just register the row as incomplete. Perhaps it should recognise that if you're just tapping Enter, you've given up on the process. &lt;/p&gt;

&lt;p&gt;[Rest later...]&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>python</category>
      <category>sudoku</category>
    </item>
    <item>
      <title>Solving sudoku - notes from a tutorial</title>
      <dc:creator>Bartosz Raubo</dc:creator>
      <pubDate>Sat, 17 Jul 2021 17:43:25 +0000</pubDate>
      <link>https://dev.to/bmraubo/solving-sudoku-notes-from-a-tutorial-959</link>
      <guid>https://dev.to/bmraubo/solving-sudoku-notes-from-a-tutorial-959</guid>
      <description>&lt;p&gt;I have been working on a little Sudoku solver, mainly in order to familiarise myself with Atom and try to reinforce the testing-first approach.&lt;/p&gt;

&lt;p&gt;Nothing fancy, just an implementation of a tutorial by ComputerPhile. Testing was made easier by the recursive function returns a value instead of logging the console output. The benefit of this is that it can therefore be incorporated into other code.&lt;/p&gt;

&lt;p&gt;At the heart of the software lies a recursive algorithm, that I'm going to talk about to crystallise my thinking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def next_value(puzzle):
    for y in range(0, 9):
        for x in range(0, 9):
            if puzzle[y][x] == 0:
                for n in range(1, 10):
                    if Sudoku.poss(puzzle, x, y, n):
                        puzzle[y][x] = n
                        if Sudoku.next_value(puzzle):
                            return puzzle
                        puzzle[y][x] = 0
                return
    return puzzle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What it does: goes through each list in the array and when it hits a zero, it replaces it with the first possible number (checked using the poss function).&lt;/p&gt;

&lt;p&gt;Then next_value() calls itself, and so the process continues until it encounters a '0' with no possible solution - it then backtracks - returns through the layers of the function until it reaches a point where more than one value is possible, and proceeds as above with the next possible value.&lt;/p&gt;

&lt;p&gt;This is where the code diverges from ComputerPhile's tutorial:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if Sudoku.next_value(puzzle):
    return puzzle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This passes up the answer from the last run of the recursive function to the allow the final return puzzle to provide us with a solution, rather than 'None'.&lt;/p&gt;

&lt;p&gt;The poss function (that checks whether a number is allowed) is simple enough - it checks a input value against the rows and columns according to the rules of Sudoku. The more complicated aspect of these checks are the 3x3 squares. This is dealt with as follows (I take no credit for it - it is taken verbatim from ComputerPhile):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x_sq = (x//3)*3
y_sq = (y//3)*3
for a in range(0, 3):
    for b in range(0, 3):
        if puzzle[y_sq+a][x_sq+b] == n:
            return False
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The // operator is Floor Division. It returns full values, so 3//3 == 1, but 2//3 == 0. This allows squares to be defined - the first three checks will all floor divide to 0, so script can check through all and only the values in the 3x3 square.&lt;/p&gt;

&lt;p&gt;At some point it would be good to incorporate an easy way to input puzzles. There are also some tutorials for building a GUI to show the puzzle being solved (albeit much slower that the runtime of the function) - I hope to look into those.&lt;/p&gt;

&lt;p&gt;The code is available here.&lt;/p&gt;

</description>
      <category>python</category>
      <category>sudoku</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Scan.co.uk sales scraper</title>
      <dc:creator>Bartosz Raubo</dc:creator>
      <pubDate>Sun, 27 Dec 2020 22:44:22 +0000</pubDate>
      <link>https://dev.to/bmraubo/scan-co-uk-sales-scraper-39nl</link>
      <guid>https://dev.to/bmraubo/scan-co-uk-sales-scraper-39nl</guid>
      <description>&lt;p&gt;I was working today on a scraper that grabs the sale items from Scan.co.uk and collects the data in .csv file. Nothing fancy - its sole value is educational. And fittingly, the simple bs4 script threw up two issues that seem worth mentioning.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;HTTP Error 403 - access to the server was not authorised, the html could not be grabbed. How frustrating!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;x.findAll() does not return all result - I was trying to grab 6 'li' containers, but only 4 were ever found by the function. What do?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  HTTP Error 403: Forbidden
&lt;/h2&gt;

&lt;p&gt;This is related to urllib headers - the website does not want to be wrapped in in dealing with requests from countless scrapers, so requests headed urllib are blocked.&lt;/p&gt;

&lt;p&gt;To get around this, you must obscure the fact you are running a scraping bot. The simplest way to do this is by using headers, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;req = Request(my_url, headers={'User-Agent': 'Mozilla/5.0'})
page = urlopen(req)
page_html = page.read()
page.close()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first, did this not work for me &lt;em&gt;(It's &lt;code&gt;User-Agent&lt;/code&gt; not &lt;code&gt;User_Agent&lt;/code&gt;, bwap bwap)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So here's also another, apparently older solution, from user &lt;a href="https://stackoverflow.com/users/678586/zeta"&gt;Zeta&lt;/a&gt; over on &lt;a href="https://stackoverflow.com/questions/16627227/http-error-403-in-python-3-web-scraping"&gt;StackOverflow&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import urllib.request

class AppURLopener(urllib.request.FancyURLopener):
    version = "Mozilla/5.0"

uClient_opener = AppURLopener()
uClient = uClient_opener.open(my_url)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This appears to be a legacy solution, and not preferred. In the end, both solutions worked for me, typos aside.&lt;/p&gt;

&lt;h2&gt;
  
  
  x.findAll() does not return all results
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;product_list = product_categories[x].findAll('li')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code should have returned 6 results, but I could never get it to go above 4.&lt;/p&gt;

&lt;p&gt;Some googling suggested that this was a problem with html_parser. Suggested solution - use html5lib.&lt;/p&gt;

&lt;p&gt;This is what parsing the html with BeautifulSoup looked like before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;page_soup = soup(page_html, 'html_parser')
product_categories = page_soup.findAll('div', {'class':'category'})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The changes to the code are minimal - just replace the html_parser variable with html5lib:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import html5lib

page_soup = soup(page_html, 'html5lib')
product_categories = page_soup.findAll('div', {'class':'category'})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it works! &lt;code&gt;len(product_list)&lt;/code&gt; returns the correct 6 I was looking for.&lt;/p&gt;

&lt;p&gt;Hope someone finds this helpful.&lt;/p&gt;

</description>
      <category>python</category>
      <category>beginners</category>
      <category>beautifulsoup</category>
      <category>scraping</category>
    </item>
  </channel>
</rss>
