aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2024-09-30 21:59:28 +0100
committerGitHub <noreply@github.com>2024-09-30 21:59:28 +0100
commite4cdda8a1053c2bcd7d33bbad494158355fd0b3c (patch)
treecc3c55c356d6a6c0a3ddf40e5e1853b341787b94
parentfb4ae25cbf52df4ae59b5b7dfbd32004b67be604 (diff)
parent13ac4b279c2937fc35bb2094095fa9203a7f5e30 (diff)
downloadperlweeklychallenge-club-e4cdda8a1053c2bcd7d33bbad494158355fd0b3c.tar.gz
perlweeklychallenge-club-e4cdda8a1053c2bcd7d33bbad494158355fd0b3c.tar.bz2
perlweeklychallenge-club-e4cdda8a1053c2bcd7d33bbad494158355fd0b3c.zip
Merge pull request #10934 from pauloscustodio/master
Add Python solutions
-rw-r--r--challenge-165/paulo-custodio/ch-2.svg2
-rw-r--r--challenge-165/paulo-custodio/perl/ch-1.pl10
-rw-r--r--challenge-165/paulo-custodio/perl/ch-2.pl4
-rw-r--r--challenge-165/paulo-custodio/python/ch-1.py71
-rw-r--r--challenge-165/paulo-custodio/python/ch-2.py75
-rw-r--r--challenge-166/paulo-custodio/perl/ch-1.pl10
-rw-r--r--challenge-166/paulo-custodio/perl/ch-2.pl2
-rw-r--r--challenge-166/paulo-custodio/python/ch-1.py45
-rw-r--r--challenge-166/paulo-custodio/python/ch-2.py83
-rw-r--r--challenge-166/paulo-custodio/t/dir_a/Old_Fonts/.keep0
10 files changed, 289 insertions, 13 deletions
diff --git a/challenge-165/paulo-custodio/ch-2.svg b/challenge-165/paulo-custodio/ch-2.svg
index 32091d0113..4e115403f6 100644
--- a/challenge-165/paulo-custodio/ch-2.svg
+++ b/challenge-165/paulo-custodio/ch-2.svg
@@ -49,5 +49,5 @@
<circle cx="189" cy="154" r="1" stroke="black" />
<circle cx="361" cy="82" r="1" stroke="black" />
<circle cx="363" cy="89" r="1" stroke="black" />
-<line x1="0" y1="200.132272535582" x2="500" y2="50.1540224049662" stroke="black" />
+<line x1="0" y1="200" x2="500" y2="50" stroke="black" />
</svg>
diff --git a/challenge-165/paulo-custodio/perl/ch-1.pl b/challenge-165/paulo-custodio/perl/ch-1.pl
index 116422d124..e35a965a7e 100644
--- a/challenge-165/paulo-custodio/perl/ch-1.pl
+++ b/challenge-165/paulo-custodio/perl/ch-1.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
# Challenge 165
#
@@ -7,13 +7,13 @@
#
# Scalable Vector Graphics (SVG) are not made of pixels, but lines, ellipses,
# and curves, that can be scaled to any size without any loss of quality. If you
-# have ever tried to resize a small JPG or PNG, you know what I mean by “loss of
-# quality”! What many people do not know about SVG files is, they are simply XML
+# have ever tried to resize a small JPG or PNG, you know what I mean by "loss of
+# quality"! What many people do not know about SVG files is, they are simply XML
# files, so they can easily be generated programmatically.
#
-# For this task, you may use external library, such as Perl’s SVG library,
+# For this task, you may use external library, such as Perl's SVG library,
# maintained in recent years by our very own Mohammad S Anwar. You can instead
-# generate the XML yourself; it’s actually quite simple. The source for the
+# generate the XML yourself; it's actually quite simple. The source for the
# example image for Task #2 might be instructive.
#
# Your task is to accept a series of points and lines in the following format,
diff --git a/challenge-165/paulo-custodio/perl/ch-2.pl b/challenge-165/paulo-custodio/perl/ch-2.pl
index df2d904645..160b7f1a77 100644
--- a/challenge-165/paulo-custodio/perl/ch-2.pl
+++ b/challenge-165/paulo-custodio/perl/ch-2.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
# Challenge 165
#
@@ -44,6 +44,7 @@ END
sub svg_circle {
my($cx, $cy, $r)=@_;
+ for($cx, $cy, $r) {$_=int($_);}
return <<END;
<circle cx="$cx" cy="$cy" r="$r" stroke="black" />
END
@@ -56,6 +57,7 @@ sub svg_point {
sub svg_line {
my($x1,$y1,$x2,$y2)=@_;
+ for($x1,$y1,$x2,$y2) {$_=int($_);}
return <<END;
<line x1="$x1" y1="$y1" x2="$x2" y2="$y2" stroke="black" />
END
diff --git a/challenge-165/paulo-custodio/python/ch-1.py b/challenge-165/paulo-custodio/python/ch-1.py
new file mode 100644
index 0000000000..523e15afe1
--- /dev/null
+++ b/challenge-165/paulo-custodio/python/ch-1.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python3
+
+# Challenge 165
+#
+# Task 1: Scalable Vector Graphics (SVG)
+# Submitted by: Ryan J Thompson
+#
+# Scalable Vector Graphics (SVG) are not made of pixels, but lines, ellipses,
+# and curves, that can be scaled to any size without any loss of quality. If you
+# have ever tried to resize a small JPG or PNG, you know what I mean by "loss of
+# quality"! What many people do not know about SVG files is, they are simply XML
+# files, so they can easily be generated programmatically.
+#
+# For this task, you may use external library, such as Perl's SVG library,
+# maintained in recent years by our very own Mohammad S Anwar. You can instead
+# generate the XML yourself; it's actually quite simple. The source for the
+# example image for Task #2 might be instructive.
+#
+# Your task is to accept a series of points and lines in the following format,
+# one per line, in arbitrary order:
+#
+# Point: x,y
+#
+# Line: x1,y1,x2,y2
+# Example:
+#
+# 53,10
+# 53,10,23,30
+# 23,30
+#
+# Then, generate an SVG file plotting all points, and all lines. If done
+# correctly, you can view the output .svg file in your browser.
+
+def svg_header(width, height):
+ return f'''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg height="{height}" width="{width}" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+'''
+
+def svg_footer():
+ return '''</svg>
+'''
+
+def svg_circle(cx, cy, r):
+ return f'<circle cx="{cx}" cy="{cy}" r="{r}" stroke="black" />\n'
+
+def svg_point(cx, cy):
+ return svg_circle(cx, cy, 1)
+
+def svg_line(x1, y1, x2, y2):
+ return f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" stroke="black" />\n'
+
+import sys
+
+file = sys.argv[1] if len(sys.argv) > 1 else None
+if file is None:
+ raise Exception("usage: ch-1.py file.svg")
+
+with open(file, "w") as f:
+ f.write(svg_header(100, 100))
+ for line in sys.stdin:
+ line = line.strip()
+ p = line.split(',')
+ p = [int(coord.strip()) for coord in p]
+ if len(p) == 2:
+ f.write(svg_point(*p))
+ elif len(p) == 4:
+ f.write(svg_line(*p))
+ else:
+ raise Exception(f"cannot parse: {line}")
+ f.write(svg_footer())
diff --git a/challenge-165/paulo-custodio/python/ch-2.py b/challenge-165/paulo-custodio/python/ch-2.py
new file mode 100644
index 0000000000..265da63b9f
--- /dev/null
+++ b/challenge-165/paulo-custodio/python/ch-2.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python3
+
+# Challenge 165
+#
+# Task 2: Line of Best Fit
+# Submitted by: Ryan J Thompson
+#
+# When you have a scatter plot of points, a line of best fit is the line that
+# best describes the relationship between the points, and is very useful in
+# statistics. Otherwise known as linear regression, here is an example of what
+# such a line might look like:
+#
+# Hull
+#
+# The method most often used is known as the least squares method, as it is
+# straightforward and efficient, but you may use any method that generates the
+# correct result.
+#
+# Calculate the line of best fit for the following 48 points:
+#
+# 333,129 39,189 140,156 292,134 393,52 160,166 362,122 13,193
+# 341,104 320,113 109,177 203,152 343,100 225,110 23,186 282,102
+# 284,98 205,133 297,114 292,126 339,112 327,79 253,136 61,169
+# 128,176 346,72 316,103 124,162 65,181 159,137 212,116 337,86
+# 215,136 153,137 390,104 100,180 76,188 77,181 69,195 92,186
+# 275,96 250,147 34,174 213,134 186,129 189,154 361,82 363,89
+
+import sys
+
+def svg_header(width, height):
+ return f'''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg height="{height}" width="{width}" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+'''
+
+def svg_footer():
+ return '''</svg>
+'''
+
+def svg_circle(cx, cy, r):
+ return f'<circle cx="{int(cx)}" cy="{int(cy)}" r="{int(r)}" stroke="black" />\n'
+
+def svg_point(cx, cy):
+ return svg_circle(cx, cy, 1)
+
+def svg_line(x1, y1, x2, y2):
+ return f'<line x1="{int(x1)}" y1="{int(y1)}" x2="{int(x2)}" y2="{int(y2)}" stroke="black" />\n'
+
+def least_squares(points):
+ N = len(points)
+ sum_x = sum_y = sum_x2 = sum_xy = 0
+ for x, y in points:
+ sum_x += x
+ sum_y += y
+ sum_x2 += x * x
+ sum_xy += x * y
+ m = (N * sum_xy - sum_x * sum_y) / (N * sum_x2 - sum_x * sum_x)
+ b = (sum_y - m * sum_x) / N
+ return m, b
+
+file = sys.argv[1] if len(sys.argv) > 1 else None
+if file is None:
+ raise Exception("usage: ch-1.py file.svg")
+
+with open(file, "w") as f:
+ f.write(svg_header(500, 500))
+ points = []
+ for line in sys.stdin:
+ for point in line.split():
+ x, y = map(int, point.split(','))
+ points.append((x, y))
+ f.write(svg_point(x, y))
+ m, b = least_squares(points)
+ f.write(svg_line(0, b, 500, m * 500 + b))
+ f.write(svg_footer())
diff --git a/challenge-166/paulo-custodio/perl/ch-1.pl b/challenge-166/paulo-custodio/perl/ch-1.pl
index 8e6f78001a..0764002300 100644
--- a/challenge-166/paulo-custodio/perl/ch-1.pl
+++ b/challenge-166/paulo-custodio/perl/ch-1.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
# Challenge 166
#
@@ -10,22 +10,22 @@
# 0xC0dedBad. I want more!
#
# Write a program that will read from a dictionary and find 2- to 8-letter
-# words that can be “spelled” in hexadecimal, with the addition of the following
+# words that can be "spelled" in hexadecimal, with the addition of the following
# letter substitutions:
#
-# o -> 0 (e.g., 0xf00d = “food”)
+# o -> 0 (e.g., 0xf00d = "food")
# l -> 1
# i -> 1
# s -> 5
# t -> 7
#
# You can use your own dictionary or you can simply open
-# ../../../data/dictionary.txt (relative to your script’s location in our GitHub
+# ../../../data/dictionary.txt (relative to your script's location in our GitHub
# repository) to access the dictionary of common words from Week #161.
#
# Optional Extras (for an 0xAddedFee, of course!)
#
-# Limit the number of “special” letter substitutions in any one result to
+# Limit the number of "special" letter substitutions in any one result to
# keep that result at least somewhat comprehensible. (0x51105010 is an
# actual example from my sample solution you may wish to avoid!)
#
diff --git a/challenge-166/paulo-custodio/perl/ch-2.pl b/challenge-166/paulo-custodio/perl/ch-2.pl
index f65656bcab..cb92177a74 100644
--- a/challenge-166/paulo-custodio/perl/ch-2.pl
+++ b/challenge-166/paulo-custodio/perl/ch-2.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
# Challenge 166
#
diff --git a/challenge-166/paulo-custodio/python/ch-1.py b/challenge-166/paulo-custodio/python/ch-1.py
new file mode 100644
index 0000000000..b64b0f1337
--- /dev/null
+++ b/challenge-166/paulo-custodio/python/ch-1.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+
+# Challenge 166
+#
+# Task 1: Hexadecimal Words
+# Submitted by: Ryan J Thompson
+#
+# As an old systems programmer, whenever I needed to come up with a 32-bit
+# number, I would reach for the tired old examples like 0xDeadBeef and
+# 0xC0dedBad. I want more!
+#
+# Write a program that will read from a dictionary and find 2- to 8-letter
+# words that can be "spelled" in hexadecimal, with the addition of the following
+# letter substitutions:
+#
+# o -> 0 (e.g., 0xf00d = "food")
+# l -> 1
+# i -> 1
+# s -> 5
+# t -> 7
+#
+# You can use your own dictionary or you can simply open
+# ../../../data/dictionary.txt (relative to your script's location in our GitHub
+# repository) to access the dictionary of common words from Week #161.
+#
+# Optional Extras (for an 0xAddedFee, of course!)
+#
+# Limit the number of "special" letter substitutions in any one result to
+# keep that result at least somewhat comprehensible. (0x51105010 is an
+# actual example from my sample solution you may wish to avoid!)
+#
+# Find phrases of words that total 8 characters in length
+# (e.g., 0xFee1Face), rather than just individual words.
+
+import sys
+
+if len(sys.argv) != 2:
+ sys.exit("usage: ch-1.py words.txt")
+
+f = open(sys.argv[1], "r")
+for line in f.readlines():
+ word = line.strip()
+ if len(word) >= 2 and len(word) <= 8 and all(c in 'abcdef0list' for c in word.lower()):
+ word = word.translate(str.maketrans('olist', '01157'))
+ print("0x" + word.upper())
diff --git a/challenge-166/paulo-custodio/python/ch-2.py b/challenge-166/paulo-custodio/python/ch-2.py
new file mode 100644
index 0000000000..a47b99586a
--- /dev/null
+++ b/challenge-166/paulo-custodio/python/ch-2.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+
+# Challenge 166
+#
+# Task 2: K-Directory Diff
+# Submitted by: Ryan J Thompson
+#
+# Given a few (three or more) directories (non-recursively), display a
+# side-by-side difference of files that are missing from at least one of the
+# directories. Do not display files that exist in every directory.
+#
+# Since the task is non-recursive, if you encounter a subdirectory, append a /,
+# but otherwise treat it the same as a regular file.
+# Example
+#
+# Given the following directory structure:
+#
+# dir_a:
+# Arial.ttf Comic_Sans.ttf Georgia.ttf Helvetica.ttf Impact.otf Verdana.ttf
+# Old_Fonts/
+#
+# dir_b:
+# Arial.ttf Comic_Sans.ttf Courier_New.ttf Helvetica.ttf Impact.otf
+# Tahoma.ttf Verdana.ttf
+#
+# dir_c:
+# Arial.ttf Courier_New.ttf Helvetica.ttf Impact.otf Monaco.ttf Verdana.ttf
+#
+# The output should look similar to the following:
+#
+# dir_a | dir_b | dir_c
+# -------------- | --------------- | ---------------
+# Comic_Sans.ttf | Comic_Sans.ttf |
+# | Courier_New.ttf | Courier_New.ttf
+# Georgia.ttf | |
+# | | Monaco.ttf
+# Old_Fonts/ | |
+# | Tahoma.ttf |
+
+import os
+import sys
+
+WIDTH = 16
+
+def read_dir(dir):
+ try:
+ with os.scandir(dir) as entries:
+ return sorted((entry.name + '/' if entry.is_dir() else entry.name) for entry in entries if entry.name not in {'.', '..'})
+ except OSError as e:
+ print(f"opendir {dir}: {e}", file=sys.stderr)
+ sys.exit(1)
+
+def read_dirs(*dirs):
+ return [read_dir(dir) for dir in dirs]
+
+def print_line(*cells):
+ for i in range(len(cells)):
+ print(f"{cells[i]:<{WIDTH}}", end=" | " if i != len(cells) - 1 else "")
+ print()
+
+def print_diff(dirs, contents):
+ # print header
+ print_line(*dirs)
+ print_line(*(["-" * WIDTH] * len(dirs)))
+
+ # collect files
+ files = {}
+ files_dir = {}
+ for i, dir in enumerate(dirs):
+ for file in contents[i]:
+ files[file] = True
+ if file not in files_dir:
+ files_dir[file] = {}
+ files_dir[file][dir] = True
+
+ # print rows
+ for file in sorted(files.keys()):
+ row = [file if dir in files_dir.get(file, {}) else "" for dir in dirs]
+ if any(cell == "" for cell in row):
+ print_line(*row)
+
+if len(sys.argv) > 2:
+ print_diff(sys.argv[1:], read_dirs(*sys.argv[1:]))
diff --git a/challenge-166/paulo-custodio/t/dir_a/Old_Fonts/.keep b/challenge-166/paulo-custodio/t/dir_a/Old_Fonts/.keep
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/challenge-166/paulo-custodio/t/dir_a/Old_Fonts/.keep