aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2024-09-18 19:59:32 +0100
committerGitHub <noreply@github.com>2024-09-18 19:59:32 +0100
commit85073f31dae3decce780d1fd66cdcb79c82c7f65 (patch)
tree318d3bc02836f4cde215f7f15e9ec875c74a1490
parentbfe139d559d498bcf1ae48cc08520bfc99ee9b85 (diff)
parent51c035e04c5ae5f9f02555206f57eb675a737617 (diff)
downloadperlweeklychallenge-club-85073f31dae3decce780d1fd66cdcb79c82c7f65.tar.gz
perlweeklychallenge-club-85073f31dae3decce780d1fd66cdcb79c82c7f65.tar.bz2
perlweeklychallenge-club-85073f31dae3decce780d1fd66cdcb79c82c7f65.zip
Merge pull request #10860 from pauloscustodio/master
Add Python solutions
-rw-r--r--challenge-060/paulo-custodio/perl/ch-1.pl4
-rw-r--r--challenge-060/paulo-custodio/perl/ch-2.pl2
-rw-r--r--challenge-060/paulo-custodio/python/ch-1.py43
-rw-r--r--challenge-060/paulo-custodio/python/ch-2.py50
-rw-r--r--challenge-061/paulo-custodio/perl/ch-1.pl2
-rw-r--r--challenge-061/paulo-custodio/perl/ch-2.pl4
-rw-r--r--challenge-061/paulo-custodio/python/ch-1.py36
-rw-r--r--challenge-061/paulo-custodio/python/ch-2.py46
-rw-r--r--challenge-062/paulo-custodio/perl/ch-1.pl4
-rw-r--r--challenge-062/paulo-custodio/perl/ch-2.pl10
-rw-r--r--challenge-062/paulo-custodio/python/ch-1.py71
-rw-r--r--challenge-062/paulo-custodio/python/ch-2.py103
-rw-r--r--challenge-063/paulo-custodio/Makefile1
-rw-r--r--challenge-063/paulo-custodio/perl/ch-1.pl4
-rw-r--r--challenge-063/paulo-custodio/perl/ch-2.pl5
-rw-r--r--challenge-063/paulo-custodio/python/ch-1.py45
-rw-r--r--challenge-063/paulo-custodio/python/ch-2.py47
-rw-r--r--challenge-064/paulo-custodio/Makefile2
-rw-r--r--challenge-064/paulo-custodio/perl/ch-1.pl4
-rw-r--r--challenge-064/paulo-custodio/perl/ch-2.pl6
-rw-r--r--challenge-064/paulo-custodio/python/ch-1.py60
-rw-r--r--challenge-064/paulo-custodio/python/ch-2.py52
-rw-r--r--challenge-286/paulo-custodio/perl/ch-1.pl8
-rw-r--r--challenge-286/paulo-custodio/python/ch-1.py44
-rw-r--r--challenge-286/paulo-custodio/python/ch-2.py94
-rw-r--r--challenge-286/paulo-custodio/t/test-1.yaml5
-rw-r--r--challenge-287/paulo-custodio/perl/ch-1.pl42
-rw-r--r--challenge-287/paulo-custodio/python/ch-1.py98
-rw-r--r--challenge-287/paulo-custodio/python/ch-2.py77
29 files changed, 933 insertions, 36 deletions
diff --git a/challenge-060/paulo-custodio/perl/ch-1.pl b/challenge-060/paulo-custodio/perl/ch-1.pl
index 6aac747b1a..aa47f1375b 100644
--- a/challenge-060/paulo-custodio/perl/ch-1.pl
+++ b/challenge-060/paulo-custodio/perl/ch-1.pl
@@ -2,13 +2,13 @@
# Challenge 060
#
-# TASK #1 › Excel Column
+# TASK #1 > Excel Column
# Reviewed by: Ryan Thompson
# Write a script that accepts a number and returns the Excel Column Name it
# represents and vice-versa.
#
# Excel columns start at A and increase lexicographically using the 26 letters
-# of the English alphabet, A..Z. After Z, the columns pick up an extra “digit”,
+# of the English alphabet, A..Z. After Z, the columns pick up an extra "digit",
# going from AA, AB, etc., which could (in theory) continue to an arbitrary
# number of digits. In practice, Excel sheets are limited to 16,384 columns.
#
diff --git a/challenge-060/paulo-custodio/perl/ch-2.pl b/challenge-060/paulo-custodio/perl/ch-2.pl
index 6ec49647e7..ba89e73e05 100644
--- a/challenge-060/paulo-custodio/perl/ch-2.pl
+++ b/challenge-060/paulo-custodio/perl/ch-2.pl
@@ -2,7 +2,7 @@
# Challenge 060
#
-# TASK #2 › Find Numbers
+# TASK #2 > Find Numbers
# Reviewed by: Ryan Thompson
# Write a script that accepts list of positive numbers (@L) and two positive
# numbers $X and $Y.
diff --git a/challenge-060/paulo-custodio/python/ch-1.py b/challenge-060/paulo-custodio/python/ch-1.py
new file mode 100644
index 0000000000..10efd3a1fc
--- /dev/null
+++ b/challenge-060/paulo-custodio/python/ch-1.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+
+# Challenge 060
+#
+# TASK #1 > Excel Column
+# Reviewed by: Ryan Thompson
+# Write a script that accepts a number and returns the Excel Column Name it
+# represents and vice-versa.
+#
+# Excel columns start at A and increase lexicographically using the 26 letters
+# of the English alphabet, A..Z. After Z, the columns pick up an extra "digit",
+# going from AA, AB, etc., which could (in theory) continue to an arbitrary
+# number of digits. In practice, Excel sheets are limited to 16,384 columns.
+#
+# Example
+# Input Number: 28
+# Output: AB
+#
+# Input Column Name: AD
+# Output: 30
+
+import re
+import sys
+
+def col2num(col):
+ num = 0
+ for digit in col:
+ num = 26*num + ord(digit)-ord('A') + 1
+ return num
+
+def num2col(num):
+ col = ""
+ while num > 0:
+ digit = (num-1) % 26
+ num = int((num-1) / 26)
+ col = chr(ord('A')+digit) + col
+ return col
+
+arg = sys.argv[1]
+if re.search(r'^\d+$', arg):
+ print(num2col(int(arg)))
+else:
+ print(col2num(arg))
diff --git a/challenge-060/paulo-custodio/python/ch-2.py b/challenge-060/paulo-custodio/python/ch-2.py
new file mode 100644
index 0000000000..5a159ce266
--- /dev/null
+++ b/challenge-060/paulo-custodio/python/ch-2.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+
+# Challenge 060
+#
+# TASK #2 > Find Numbers
+# Reviewed by: Ryan Thompson
+# Write a script that accepts list of positive numbers (@L) and two positive
+# numbers $X and $Y.
+#
+# The script should print all possible numbers made by concatenating the numbers
+# from @L, whose length is exactly $X but value is less than $Y.
+#
+# Example
+# Input:
+#
+# @L = (0, 1, 2, 5);
+# $X = 2;
+# $Y = 21;
+# Output:
+#
+# 10, 11, 12, 15, 20
+
+import sys
+
+def combine1(combin, prefix, n, digits):
+ if len(prefix) == n:
+ num = int(prefix)
+ if not num in combin:
+ combin.add(num)
+ else:
+ for digit in digits:
+ combine1(combin, prefix+digit, n, digits)
+
+def combine(digits):
+ combin = set()
+ for n in range(1, len(digits)+1):
+ combine1(combin, "", n, digits)
+ nums = sorted(list(combin))
+ return nums
+
+def numbers(X, Y, L):
+ nums = combine(L)
+ nums = list(filter(lambda x:len(str(x))==X and x<Y, nums))
+ return nums
+
+X = int(sys.argv[1])
+Y = int(sys.argv[2])
+L = sys.argv[3:]
+nums = numbers(X, Y, L)
+print(", ".join(map(str, nums)))
diff --git a/challenge-061/paulo-custodio/perl/ch-1.pl b/challenge-061/paulo-custodio/perl/ch-1.pl
index a8a9e2faaf..fcfcd54dd7 100644
--- a/challenge-061/paulo-custodio/perl/ch-1.pl
+++ b/challenge-061/paulo-custodio/perl/ch-1.pl
@@ -2,7 +2,7 @@
# Challenge 061
#
-# TASK #1 › Product SubArray
+# TASK #1 > Product SubArray
# Reviewed by: Ryan Thompson
# Given a list of 4 or more numbers, write a script to find the contiguous
# sublist that has the maximum product. The length of the sublist is irrelevant;
diff --git a/challenge-061/paulo-custodio/perl/ch-2.pl b/challenge-061/paulo-custodio/perl/ch-2.pl
index f7a8e53653..5a2801f33b 100644
--- a/challenge-061/paulo-custodio/perl/ch-2.pl
+++ b/challenge-061/paulo-custodio/perl/ch-2.pl
@@ -2,7 +2,7 @@
# Challenge 061
#
-# TASK #2 › IPv4 Partition
+# TASK #2 > IPv4 Partition
# Reviewed by: Ryan Thompson
# You are given a string containing only digits (0..9). The string should have
# between 4 and 12 digits.
@@ -11,7 +11,7 @@
# partitioning the input string.
#
# For the purpose of this challenge, a valid IPv4 address consists of four
-# “octets” i.e. A, B, C and D, separated by dots (.).
+# "octets" i.e. A, B, C and D, separated by dots (.).
#
# Each octet must be between 0 and 255, and must not have any leading zeroes.
# (e.g., 0 is OK, but 01 is not.)
diff --git a/challenge-061/paulo-custodio/python/ch-1.py b/challenge-061/paulo-custodio/python/ch-1.py
new file mode 100644
index 0000000000..47e232e6aa
--- /dev/null
+++ b/challenge-061/paulo-custodio/python/ch-1.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env perl
+
+# Challenge 061
+#
+# TASK #1 > Product SubArray
+# Reviewed by: Ryan Thompson
+# Given a list of 4 or more numbers, write a script to find the contiguous
+# sublist that has the maximum product. The length of the sublist is irrelevant;
+# your job is to maximize the product.
+#
+# Example
+# Input: [ 2, 5, -1, 3 ]
+#
+# Output: [ 2, 5 ] which gives maximum product 10.
+
+import sys
+
+def product(nums):
+ prod = 1
+ for x in nums:
+ prod *= x
+ return x
+
+
+n = list(map(int, sys.argv[1:]))
+max_sublist = []
+max_prod = int(-1e6)
+
+for i in range(0, len(n)):
+ for j in range(i, len(n)):
+ sublist = n[i:j+1]
+ prod = product(sublist)
+ if prod > max_prod:
+ max_sublist, max_prod = sublist, prod
+
+print(", ".join(list(map(str, max_sublist))))
diff --git a/challenge-061/paulo-custodio/python/ch-2.py b/challenge-061/paulo-custodio/python/ch-2.py
new file mode 100644
index 0000000000..0cbd7cd9c9
--- /dev/null
+++ b/challenge-061/paulo-custodio/python/ch-2.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+
+# Challenge 061
+#
+# TASK #2 > IPv4 Partition
+# Reviewed by: Ryan Thompson
+# You are given a string containing only digits (0..9). The string should have
+# between 4 and 12 digits.
+#
+# Write a script to print every possible valid IPv4 address that can be made by
+# partitioning the input string.
+#
+# For the purpose of this challenge, a valid IPv4 address consists of four
+# "octets" i.e. A, B, C and D, separated by dots (.).
+#
+# Each octet must be between 0 and 255, and must not have any leading zeroes.
+# (e.g., 0 is OK, but 01 is not.)
+#
+# Example
+# Input: 25525511135,
+#
+# Output:
+#
+# 255.255.11.135
+# 255.255.111.35
+
+import re
+import sys
+
+def partition1(prefix, digits):
+ if re.search(r'^(\d+\.){4}$', prefix):
+ if digits == "":
+ prefix = prefix[:-1]
+ print(prefix)
+ else:
+ for l in range(1, 4):
+ if l <= len(digits):
+ part = digits[:l]
+ if int(part) <= 255:
+ partition1(prefix+part+".", digits[l:])
+
+def partition(digits):
+ partition1("", digits)
+
+digits = sys.argv[1]
+partition(digits)
diff --git a/challenge-062/paulo-custodio/perl/ch-1.pl b/challenge-062/paulo-custodio/perl/ch-1.pl
index e6cb2d6ece..538125b0d3 100644
--- a/challenge-062/paulo-custodio/perl/ch-1.pl
+++ b/challenge-062/paulo-custodio/perl/ch-1.pl
@@ -2,7 +2,7 @@
# Challenge 062
#
-# TASK #1 › Sort Email Addresses
+# TASK #1 > Sort Email Addresses
# Submitted by: Neil Bowers
# Reviewed by: Ryan Thompson
#
@@ -11,7 +11,7 @@
# the left of the @ (known as the mailbox).
#
# Note that the domain is case-insensitive, while the mailbox part is case
-# sensitive. (Some email providers choose to ignore case, but that’s another
+# sensitive. (Some email providers choose to ignore case, but that's another
# matter entirely.)
#
# If your script is invoked with arguments, it should treat them as file names
diff --git a/challenge-062/paulo-custodio/perl/ch-2.pl b/challenge-062/paulo-custodio/perl/ch-2.pl
index 2db5a3e870..2e2d9d2e35 100644
--- a/challenge-062/paulo-custodio/perl/ch-2.pl
+++ b/challenge-062/paulo-custodio/perl/ch-2.pl
@@ -2,10 +2,10 @@
# Challenge 062
#
-# TASK #2 › N Queens
+# TASK #2 > N Queens
# Submitted by: Ryan Thompson
#
-# A standard 8×8 chessboard has 64 squares. The Queen is a chesspiece that can
+# A standard 8x8 chessboard has 64 squares. The Queen is a chesspiece that can
# attack in 8 directions, as shown by the green shaded squares below:
#
#
@@ -15,15 +15,15 @@
# overlap). In fact, there are multiple ways to do so, and this is a favourite
# undergraduate assignment in computer science.
#
-# But here at PWC, we’re going to take it into the next dimension!
+# But here at PWC, we're going to take it into the next dimension!
#
# Your job is to write a script to work with a three dimensional chess cube,
-# M×M×M in size, and find a solution that maximizes the number of queens that
+# MxMxM in size, and find a solution that maximizes the number of queens that
# can be placed in that cube without attacking each other. Output one possible
# solution.
#
# Example
-# A trivial 2×2×2 solution might look like this (1 = queen, 0 = empty):
+# A trivial 2x2x2 solution might look like this (1 = queen, 0 = empty):
#
# [
# [[1,0], # Layer 1
diff --git a/challenge-062/paulo-custodio/python/ch-1.py b/challenge-062/paulo-custodio/python/ch-1.py
new file mode 100644
index 0000000000..cc119d7a09
--- /dev/null
+++ b/challenge-062/paulo-custodio/python/ch-1.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python3
+
+# Challenge 062
+#
+# TASK #1 > Sort Email Addresses
+# Submitted by: Neil Bowers
+# Reviewed by: Ryan Thompson
+#
+# Write a script that takes a list of email addresses (one per line) and sorts
+# them first by the domain part of the email address, and then by the part to
+# the left of the @ (known as the mailbox).
+#
+# Note that the domain is case-insensitive, while the mailbox part is case
+# sensitive. (Some email providers choose to ignore case, but that's another
+# matter entirely.)
+#
+# If your script is invoked with arguments, it should treat them as file names
+# and read them in order, otherwise your script should read email addresses from
+# standard input.
+#
+# Bonus
+# Add a -u option which only includes unique email addresses in the output, just
+# like sort -u.
+#
+# Example
+# If given the following list:
+#
+# name@example.org
+# rjt@cpan.org
+# Name@example.org
+# rjt@CPAN.org
+# user@alpha.example.org
+# Your script (without -u) would return:
+#
+# user@alpha.example.org
+# rjt@cpan.org
+# rjt@CPAN.org
+# Name@example.org
+# name@example.org
+# With -u, the script would return:
+#
+# user@alpha.example.org
+# rjt@CPAN.org
+# Name@example.org
+# name@example.org
+
+import sys
+from getopt import getopt
+
+opt_u = False
+opts, args = getopt(sys.argv[1:], 'u')
+for o, a in opts:
+ if o == '-u':
+ opt_u = True
+
+mails = [line.strip() for line in sys.stdin]
+
+sorted_mails = sorted(
+ map(lambda x: [x] + x.split('@'), mails),
+ key=lambda x: (x[2].lower(), x[1])
+)
+
+if opt_u:
+ seen = set()
+ sorted_mails = [
+ [f"{mail[0]}"]
+ for mail in sorted_mails
+ if (key := f"{mail[1]}@{mail[2].lower()}") not in seen and not seen.add(key)
+ ]
+
+print("\n".join([x[0] for x in sorted_mails]))
diff --git a/challenge-062/paulo-custodio/python/ch-2.py b/challenge-062/paulo-custodio/python/ch-2.py
new file mode 100644
index 0000000000..ca8a0f3c6a
--- /dev/null
+++ b/challenge-062/paulo-custodio/python/ch-2.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python3
+
+# Challenge 062
+#
+# TASK #2 > N Queens
+# Submitted by: Ryan Thompson
+#
+# A standard 8x8 chessboard has 64 squares. The Queen is a chesspiece that can
+# attack in 8 directions, as shown by the green shaded squares below:
+#
+#
+#
+# It is possible to place 8 queens on to a single chessboard such that none of
+# the queens can attack each other (i.e., their shaded squares would not
+# overlap). In fact, there are multiple ways to do so, and this is a favourite
+# undergraduate assignment in computer science.
+#
+# But here at PWC, we're going to take it into the next dimension!
+#
+# Your job is to write a script to work with a three dimensional chess cube,
+# MxMxM in size, and find a solution that maximizes the number of queens that
+# can be placed in that cube without attacking each other. Output one possible
+# solution.
+#
+# Example
+# A trivial 2x2x2 solution might look like this (1 = queen, 0 = empty):
+#
+# [
+# [[1,0], # Layer 1
+# [0,0]],
+#
+# [[0,0], # Layer 2
+# [0,0]],
+# ]
+
+from copy import deepcopy
+import re
+
+M = 2
+
+board = [[[0 for _ in range(M)] for _ in range(M)] for _ in range(M)]
+max_board = deepcopy(board)
+max_queens = 0
+
+def set_position(board, l, r, c):
+ if 0 <= l < M and 0 <= r < M and 0 <= c < M:
+ board[l][r][c] = 1
+
+def place_queens(queens, board):
+ global max_queens, max_board
+
+ # check for empty spaces
+ full = True
+ for l in range(M):
+ for r in range(M):
+ for c in range(M):
+ if board[l][r][c] == 0:
+ full = False
+ # empty, place queen
+ copy_board = deepcopy(board)
+ # fill attack positions
+ for i in range(M):
+ set_position(copy_board, i, r, c)
+ set_position(copy_board, l, i, c)
+ set_position(copy_board, l, r, i)
+
+ set_position(copy_board, l, r-i, c-i)
+ set_position(copy_board, l, r-i, c+i)
+ set_position(copy_board, l, r+i, c-i)
+ set_position(copy_board, l, r+i, c+i)
+
+ set_position(copy_board, l-i, r, c-i)
+ set_position(copy_board, l-i, r, c+i)
+ set_position(copy_board, l+i, r, c-i)
+ set_position(copy_board, l+i, r, c+i)
+
+ set_position(copy_board, l-i, r-i, c)
+ set_position(copy_board, l-i, r+i, c)
+ set_position(copy_board, l+i, r-i, c)
+ set_position(copy_board, l+i, r+i, c)
+
+ set_position(copy_board, l-i, r-i, c-i)
+ set_position(copy_board, l-i, r-i, c+i)
+ set_position(copy_board, l-i, r+i, c-i)
+ set_position(copy_board, l-i, r+i, c+i)
+
+ set_position(copy_board, l+i, r-i, c-i)
+ set_position(copy_board, l+i, r-i, c+i)
+ set_position(copy_board, l+i, r+i, c-i)
+ set_position(copy_board, l+i, r+i, c+i)
+ # fill queen position
+ copy_board[l][r][c] = 'Q'
+ # recurse
+ place_queens(queens + 1, copy_board)
+ if full:
+ if queens > max_queens:
+ max_queens = queens
+ max_board = deepcopy(board)
+
+place_queens(0, board)
+out = str(max_board)
+out, _ = re.subn("'", '"', out)
+print(out)
diff --git a/challenge-063/paulo-custodio/Makefile b/challenge-063/paulo-custodio/Makefile
index 0d5753b0fb..3eba7cf291 100644
--- a/challenge-063/paulo-custodio/Makefile
+++ b/challenge-063/paulo-custodio/Makefile
@@ -1,3 +1,4 @@
all:
perl perl/ch-1.pl
+ python3 python/ch-1.py
perl ../../challenge-001/paulo-custodio/test.pl
diff --git a/challenge-063/paulo-custodio/perl/ch-1.pl b/challenge-063/paulo-custodio/perl/ch-1.pl
index d3900d26b7..bf8874c318 100644
--- a/challenge-063/paulo-custodio/perl/ch-1.pl
+++ b/challenge-063/paulo-custodio/perl/ch-1.pl
@@ -2,7 +2,7 @@
# Challenge 063
#
-# TASK #1 › Last Word
+# TASK #1 > Last Word
# Submitted by: Mohammad S Anwar
# Reviewed by: Ryan Thompson
#
@@ -10,7 +10,7 @@
# $regexp found in the given string, or undef if the string does not contain a
# word matching $regexp.
#
-# For this challenge, a “word” is defined as any character sequence consisting
+# For this challenge, a "word" is defined as any character sequence consisting
# of non-whitespace characters (\S) only. That means punctuation and other
# symbols are part of the word.
#
diff --git a/challenge-063/paulo-custodio/perl/ch-2.pl b/challenge-063/paulo-custodio/perl/ch-2.pl
index 70ad2a5098..c477a46a40 100644
--- a/challenge-063/paulo-custodio/perl/ch-2.pl
+++ b/challenge-063/paulo-custodio/perl/ch-2.pl
@@ -2,11 +2,12 @@
# Challenge 063
#
-# TASK #2 › Rotate String
+# TASK #2 > Rotate String
# Submitted by: Mohammad S Anwar
# Reviewed by: Ryan Thompson
#
-# Given a word made up of an arbitrary number of x and y characters, that word can be rotated as follows: For the ith rotation (starting at i = 1),
+# Given a word made up of an arbitrary number of x and y characters, that word
+# can be rotated as follows: For the ith rotation (starting at i = 1),
# i % length(word) characters are moved from the front of the string to the end.
# Thus, for the string xyxx, the initial (i = 1) % 4 = 1 character (x) is moved
# to the end, forming yxxx. On the second rotation, (i = 2) % 4 = 2 characters
diff --git a/challenge-063/paulo-custodio/python/ch-1.py b/challenge-063/paulo-custodio/python/ch-1.py
new file mode 100644
index 0000000000..5fb968ca0d
--- /dev/null
+++ b/challenge-063/paulo-custodio/python/ch-1.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+
+# Challenge 063
+#
+# TASK #1 > Last Word
+# Submitted by: Mohammad S Anwar
+# Reviewed by: Ryan Thompson
+#
+# Define sub last_word($string, $regexp) that returns the last word matching
+# $regexp found in the given string, or undef if the string does not contain a
+# word matching $regexp.
+#
+# For this challenge, a "word" is defined as any character sequence consisting
+# of non-whitespace characters (\S) only. That means punctuation and other
+# symbols are part of the word.
+#
+# The $regexp is a regular expression. Take care that the regexp can only match
+# individual words! See the Examples for one way this can break if you are not
+# careful.
+#
+# Examples
+# last_word(' hello world', qr/[ea]l/); # 'hello'
+# last_word("Don't match too much, Chet!", qr/ch.t/i); # 'Chet!'
+# last_word("spaces in regexp won't match", qr/in re/); # undef
+# last_word( join(' ', 1..1e6), qr/^(3.*?){3}/); # '399933'
+
+import re
+import unittest
+
+def last_word(text, pattern):
+ words = text.split(' ')
+ for word in reversed(words):
+ if re.search(pattern, word, re.IGNORECASE):
+ return word
+ return None
+
+class TestLastWord(unittest.TestCase):
+ def test_last_word(self):
+ self.assertEqual(last_word(' hello world', r'[ea]l'), 'hello')
+ self.assertEqual(last_word("Don't match too much, Chet!", r'ch.t'), 'Chet!')
+ self.assertIsNone(last_word("spaces in regexp won't match", r'in re'))
+ self.assertEqual(last_word(' '.join(str(i) for i in range(1, int(1e6) + 1)), r'^(3.*?){3}'), '399933')
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/challenge-063/paulo-custodio/python/ch-2.py b/challenge-063/paulo-custodio/python/ch-2.py
new file mode 100644
index 0000000000..37f0bab8d2
--- /dev/null
+++ b/challenge-063/paulo-custodio/python/ch-2.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python3
+
+# Challenge 063
+#
+# TASK #2 > Rotate String
+# Submitted by: Mohammad S Anwar
+# Reviewed by: Ryan Thompson
+#
+# Given a word made up of an arbitrary number of x and y characters, that word
+# can be rotated as follows: For the ith rotation (starting at i = 1),
+# i % length(word) characters are moved from the front of the string to the end.
+# Thus, for the string xyxx, the initial (i = 1) % 4 = 1 character (x) is moved
+# to the end, forming yxxx. On the second rotation, (i = 2) % 4 = 2 characters
+# (yx) are moved to the end, forming xxyx, and so on. See below for a complete
+# example.
+#
+# Your task is to write a function that takes a string of xs and ys and returns
+# the minimum non-zero number of rotations required to obtain the original
+# string. You may show the individual rotations if you wish, but that is not
+# required.
+#
+# Example
+# Input: $word = 'xyxx';
+#
+# Rotation 1: you get yxxx by moving x to the end.
+# Rotation 2: you get xxyx by moving yx to the end.
+# Rotation 3: you get xxxy by moving xxy to the end.
+# Rotation 4: you get xxxy by moving nothing as 4 % length(xyxx) == 0.
+# Rotation 5: you get xxyx by moving x to the end.
+# Rotation 6: you get yxxx by moving xx to the end.
+# Rotation 7: you get xyxx by moving yxx to the end which is same as the given word.
+# Output: 7
+
+import sys
+
+def count_rotations(in_str=""):
+ count = 0
+ str_val = in_str
+ while True:
+ count += 1
+ move = count % len(str_val)
+ str_val = str_val[move:] + str_val[:move]
+ if in_str == str_val:
+ break
+ return count
+
+print(count_rotations(sys.argv[1] if len(sys.argv) > 1 else ""))
diff --git a/challenge-064/paulo-custodio/Makefile b/challenge-064/paulo-custodio/Makefile
index ba9a2bf399..9c7316cd76 100644
--- a/challenge-064/paulo-custodio/Makefile
+++ b/challenge-064/paulo-custodio/Makefile
@@ -1,3 +1,5 @@
all:
perl perl/ch-1.pl
perl perl/ch-2.pl
+ python3 python/ch-1.py
+ python3 python/ch-2.py
diff --git a/challenge-064/paulo-custodio/perl/ch-1.pl b/challenge-064/paulo-custodio/perl/ch-1.pl
index 5a1197d4a3..e5acc1ebf1 100644
--- a/challenge-064/paulo-custodio/perl/ch-1.pl
+++ b/challenge-064/paulo-custodio/perl/ch-1.pl
@@ -2,11 +2,11 @@
# Challenge 064
#
-# TASK #1 › Minimum Sum Path
+# TASK #1 > Minimum Sum Path
# Submitted by: Mohammad S Anwar
# Reviewed by: Ryan Thompson
#
-# Given an m × n matrix with non-negative integers, write a script to find a
+# Given an m x n matrix with non-negative integers, write a script to find a
# path from top left to bottom right which minimizes the sum of all numbers
# along its path. You can only move either down or right at any point in time.
#
diff --git a/challenge-064/paulo-custodio/perl/ch-2.pl b/challenge-064/paulo-custodio/perl/ch-2.pl
index e4a4532f3e..5ae8da6e1e 100644
--- a/challenge-064/paulo-custodio/perl/ch-2.pl
+++ b/challenge-064/paulo-custodio/perl/ch-2.pl
@@ -2,7 +2,7 @@
# Challenge 064
#
-# TASK #2 › Word Break
+# TASK #2 > Word Break
# Submitted by: Mohammad S Anwar
#
# You are given a string $S and an array of words @W.
@@ -32,7 +32,7 @@
# 0 as none matching word found.
use Modern::Perl;
-use Math::Combinatorics 'combine';
+use Math::Combinatorics 'permute';
use Test::More;
is word_break("perlweeklychallenge", "weekly", "challenge", "perl"),
@@ -45,7 +45,7 @@ done_testing;
sub word_break {
my($S, @W) = @_;
my $k = scalar(@W);
- for (combine($k, @W)) {
+ for (permute(@W)) {
my @words = @$_;
if (join('', @words) eq $S) {
return "@W";
diff --git a/challenge-064/paulo-custodio/python/ch-1.py b/challenge-064/paulo-custodio/python/ch-1.py
new file mode 100644
index 0000000000..54982caa27
--- /dev/null
+++ b/challenge-064/paulo-custodio/python/ch-1.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python3
+
+# Challenge 064
+#
+# TASK #1 > Minimum Sum Path
+# Submitted by: Mohammad S Anwar
+# Reviewed by: Ryan Thompson
+#
+# Given an m x n matrix with non-negative integers, write a script to find a
+# path from top left to bottom right which minimizes the sum of all numbers
+# along its path. You can only move either down or right at any point in time.
+#
+# Example
+# Input:
+#
+# [ 1 2 3 ]
+# [ 4 5 6 ]
+# [ 7 8 9 ]
+# The minimum sum path looks like this:
+#
+# 1?2?3
+# ?
+# 6
+# ?
+# 9
+# Thus, your script could output: 21 ( 1 ? 2 ? 3 ? 6 ? 9 )
+
+import unittest
+import sys
+
+def min_sum(m):
+ min_sum = [sys.maxsize] # Using a list to simulate a global variable
+
+ def min_sum1(sum, r, c, m):
+ rows = len(m)