diff --git a/Python/Player.py b/Python/Player.py new file mode 100644 index 0000000..7b28c74 --- /dev/null +++ b/Python/Player.py @@ -0,0 +1,84 @@ +import math +import random + + +class Player(): + def __init__(self, player): + self.player = player + + def get_move(self, game): + pass + + +class Human(Player): + def __init__(self, player): + super().__init__(player) + + def get_move(self, game): + valid_square = False + val = None + while not valid_square: + square = input(self.player + ' turn. Please introduce a move (1-9): ') + try: + val = int(square) - 1 + if val not in game.remaining_moves(): + raise ValueError + valid_square = True + except ValueError: + print('Invalid square. Try again.') + return val + + +class RandomComputer(Player): + def __init__(self, player): + super().__init__(player) + + def get_move(self, game): + square = random.choice(game.remaining_moves()) + return square + + +class SmartComputer(Player): + def __init__(self, player): + super().__init__(player) + + def get_move(self, game): + if len(game.remaining_moves()) == 9: + square = random.choice(game.remaining_moves()) + else: + square = self.minimax(game, self.player)['position'] + return square + + def minimax(self, state, player): + max_player = self.player + min_player = '0' if player == 'X' else 'X' + + # checking if the previous move is winner + if state.actual_winner == min_player: + return {'position': None, + 'score': 1 * (state.number_null_squares() + 1) if min_player == max_player + else -1 * (state.number_null_squares() + 1)} + elif not state.null_squares(): + return {'position': None, 'score': 0} + + if player == max_player: + best = {'position': None, 'score': -math.inf} + else: + best = {'position': None, 'score': math.inf} + + for possible_move in state.remaining_moves(): + state.make_a_move(possible_move, player) + sim_score = self.minimax(state, min_player) + + # undo move + state.board[possible_move] = ' ' + state.actual_winner = None + sim_score['position'] = possible_move + + if player == max_player: + if sim_score['score'] > best['score']: + best = sim_score + else: + if sim_score['score'] < best['score']: + best = sim_score + return best diff --git a/Python/TicTacToe.py b/Python/TicTacToe.py new file mode 100644 index 0000000..e74c53b --- /dev/null +++ b/Python/TicTacToe.py @@ -0,0 +1,104 @@ +import math +import time +from Player import SmartComputer, RandomComputer, Human + + +class TicTacToe(): + def __init__(self): + self.board = self.create_board() + self.actual_winner = None + + @staticmethod + def create_board(): + return [' ' for _ in range(9)] + + def board_show(self): + for cell in [self.board[i*3:(i+1)*3] for i in range(3)]: + print('| ' + ' | '.join(cell) + ' |') + + @staticmethod + def show_board_numbers(): + number_from_board = [[str(i + 1) for i in range(j*3, (j+1)*3)] for j in range(3)] + for cell in number_from_board: + print('| ' + ' | '.join(cell) + ' |') + + def make_a_move(self, square, player): + if self.board[square] == ' ': + self.board[square] = player + if self.winner_rules(square, player): + self.actual_winner = player + return True + return False + + def winner_rules(self, square, player): + # Checking the row + row_index = math.floor(square / 3) + row = self.board[row_index*3:(row_index+1)*3] + if all([l == player for l in row]): + return True + + # Checking the column + col_index = square % 3 + column = [self.board[col_index+i*3] for i in range(3)] + if all([l == player for l in column]): + return True + + # Checking for diagonal + if square % 2 == 0: + principal_diagonal = [self.board[i] for i in [0, 4, 8]] + if all([l == player for l in principal_diagonal]): + return True + + secondary_diagonal = [self.board[i] for i in [2, 4, 6]] + if all([l == player for l in secondary_diagonal]): + return True + + return False + + def null_squares(self): + return ' ' in self.board + + def number_null_squares(self): + return self.board.count(' ') + + def remaining_moves(self): + return [p for p, i in enumerate(self.board) if i == ' '] + + +def play(game, x_player, o_player, show_game = True): + if show_game: + game.show_board_numbers() + + player = 'X' + while game.null_squares(): + if player == '0': + square = o_player.get_move(game) + else: + square = x_player.get_move(game) + if game.make_a_move(square, player): + if show_game: + print(f'{player} makes a move to square {square}') + game.board_show() + print(' ') + + if game.actual_winner: + if show_game: + print(f'{player} wins!') + return player + player = '0' if player == 'X' else 'X' + + time.sleep(.8) + + if show_game: + print('Tie!') + + +if __name__ == '__main__': + #x_player = RandomComputer('0') + x_player = SmartComputer('0') + o_player = Human('X') + t = TicTacToe() + play(t, o_player, x_player, True) + + + diff --git a/Python/reddit_scraper.py b/Python/reddit_scraper.py new file mode 100644 index 0000000..0b5f9bf --- /dev/null +++ b/Python/reddit_scraper.py @@ -0,0 +1,60 @@ +import requests +import csv +import time +from bs4 import BeautifulSoup + + +class HaikuScraper: + """ + This scraper is designed with the purpose of scraping Haikus (Japanese poems) from Reddit. + """ + def __init__(self, url: str, headers: dict): + self.url = url + self.headers = headers + + def make_request(self): + time.sleep(3) + page = requests.get(self.url, headers=self.headers) + soup = BeautifulSoup(page.text, 'html.parser') + return soup + + def get_next_page(self, soup: BeautifulSoup): + time.sleep(3) + next_button = soup.find('span', class_='next-button') + next_page_link = next_button.find("a").attrs['href'] + return next_page_link + + def get_haikus(self, soup: BeautifulSoup): + haikus = [str(title.text) for title in soup.find_all("a", class_="title may-blank ")] + return haikus + + def write_haikus_to_csv(self, haikus: list): + with open('scraped_haikus_v2.txt', 'a') as f: + writer = csv.writer(f) + for haiku in haikus: + writer.writerow([haiku]) + f.close() + + + +url = "https://old.reddit.com/r/haiku/" +# Headers to mimic a browser visit +headers = {'User-Agent': 'Mozilla/5.0'} + +scraper = HaikuScraper(url, headers) +soup = scraper.make_request() + +haikus = scraper.get_haikus(soup) +scraper.write_haikus_to_csv(haikus) + +counter = 1 + +while (counter <= 2500): + time.sleep(2) + link = scraper.get_next_page(soup) + print(f"Page {counter + 1}. Link {link}.") + scraper = HaikuScraper(link, headers) + soup = scraper.make_request() + haikus = scraper.get_haikus(soup) + scraper.write_haikus_to_csv(haikus) + counter += 1 \ No newline at end of file