aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Schneider <atschneider@temple.edu>2024-06-07 20:23:39 -0400
committerAndrew Schneider <atschneider@temple.edu>2024-06-07 20:23:39 -0400
commit8c5b886b9ea1d2a223b6acb6012fbb58e68505f4 (patch)
treeace62cca152077c43a3a815c43b8c7c5ebeb586b
parentfed96c997e23ec9b3ed4bd40e26b07a061d73dfe (diff)
downloadperlweeklychallenge-club-8c5b886b9ea1d2a223b6acb6012fbb58e68505f4.tar.gz
perlweeklychallenge-club-8c5b886b9ea1d2a223b6acb6012fbb58e68505f4.tar.bz2
perlweeklychallenge-club-8c5b886b9ea1d2a223b6acb6012fbb58e68505f4.zip
README editing
-rw-r--r--challenge-272/atschneid/README.md35
-rw-r--r--challenge-272/atschneid/blog.txt2
2 files changed, 26 insertions, 11 deletions
diff --git a/challenge-272/atschneid/README.md b/challenge-272/atschneid/README.md
index 9fe531f2ed..4bdaab9dac 100644
--- a/challenge-272/atschneid/README.md
+++ b/challenge-272/atschneid/README.md
@@ -73,7 +73,7 @@ void defang(char * input, char * output) {
}
```
-It handles the example cases just fine, but based on a strict reading of the specification, every '.' should be replaced by '[.]', this implementation fails on basically all edge cases: leading, multiple, and trailing '.'s all get dropped. I thought about how to handle these cases in general, and decided 'every' means *every* so in case like "..." we'd expect to get "[.][.][.]". In keeping consistency across all of my implementations I decided on this one
+It handles the example cases just fine, but based on a strict reading of the specification, every '.' should be replaced by '[.]', this implementation fails on basically all edge cases: leading, multiple, and trailing '.'s all get dropped. Although I'm really overthinking this here, because, again, on a strict reading of the instructions, we are given a *valid IP address* so it shouldn't really come up. Still, I thought about how to handle these cases in general, and decided 'every' means *every* (and outweighs *valid*) so in case like "..." we'd expect to get "[.][.][.]". In keeping consistency across all of my implementations I decided on this one
```c
void defang(char * input, char * output) {
@@ -94,11 +94,11 @@ void defang(char * input, char * output) {
}
```
-Here I'm crawling along the string one character at a time. If the char is '.' then add the chars '[', '.', ']' to the output string, otherwise just add the char itself. Interesting that my crude solution here is about as long as the one using `strtok`. If this problem had been *slightly* more complicated I might have had to use a library.
+Here I'm crawling along the string one character at a time. If the char is `'.'` then add the chars `'[', '.', ']'` to the output string, otherwise just add the char itself. Interesting that my crude solution here is about as long as the one using `strtok`. If this problem had been *slightly* more complicated I might have had to use a library.
Next up, Prolog. Getting anything done in Prolog is always a trip for me. It takes a little while to adjust, in particular, I always forget I have to pass the output variable to the function. With Prolog, at very high level, you're not really saying "compute this function and store the return value in X" as much as "give me an X that is a solution to this function." What's really cool is that often you can flip that to be "here is an X that is the solution to this function, give its input Y that yields X" or something like that. Besides all that, the syntax turns out to be very similar to a functional language like Haskell or Lisp. Anyway, I digress.
-I decided to write this in a way that could be run using GNU Prolog. I don't remember why I decided that, maybe I wanted a challenge. Because once I started running into issues and started Googling (DuckDuckGoing really) for answers I got a lot of results telling me how to do the thing I wanted very easily in SWI Prolog, which is a much more fully-featured, batteries included Prolog implementation. In particular, handling strings is not easy to do in Prolog in general, but SWI has adding a lot of functionality around this. If my understanding is correct, in Prolog a string is just a list of chars, except that it's not. For instance, you can't pattern match on it. But if you print a string you get a list of char codes, so it's kind of a lose-lose. The solution, or rather *a* solution, or better yet *my* solution is to convert strings to atoms. Prolog loves atoms and there are functions to convert a list of chars into an atom, and by the Prolog reflexive property, vice versa. Printing an atom gives it's name as you would expect, so that is what I use for output too. So in my roundabout Prolog solution, I start by converting a string to a list of chars
+I decided to write this in a way that could be run using GNU Prolog. I don't remember why I decided that, maybe I wanted a challenge. Because once I started running into issues and started Googling (DuckDuckGoing really) for answers I got a lot of results telling me how to do the thing I wanted very easily in SWI Prolog, which is a much more fully-featured, batteries included Prolog implementation. In particular, handling strings is not easy to do in Prolog in general, but SWI has adding a lot of functionality around this. If my understanding is correct, in Prolog a string is just a list of chars, except that it's not. For instance, you can't pattern match on it. But if you print a string you get a list of char codes, so it's kind of a lose-lose. The solution, or rather *a* solution, or better still *my* solution is to convert strings to atoms. Prolog loves atoms and there are functions to convert a list of chars into an atom, and by the Prolog reflexive property, vice versa. Printing an atom gives it's name as you would expect, so that is what I use for output too. So in my roundabout Prolog solution, I start by converting a string to a list of chars
```prolog
str_to_chars(S, Cs) :- atom_codes(X, S), atom_chars(X, Cs).
@@ -106,7 +106,7 @@ str_to_chars(S, Cs) :- atom_codes(X, S), atom_chars(X, Cs).
If we initialize this function as `str_to_chars("hello", Cs).` it first looks for a solution to `atom_codes(X, "hello")` which is, it looks for an atom whose characters match the list of char codes (recall the string is represented as a list of char codes) of "hello" (explicitly `[104,101,108,108,111]`). This is exactly the atom `hello` which is bound to the variable `X`. Next it tries `atom_chars(X, Cs)` which is now `atom_chars(hello, Cs)` which attempts to find a list of chars (not char codes here) which make up the characters of `hello`, obviously giving `['h', 'e', 'l', 'l', 'o']` which gets bound to the variable `Cs`. Phew. There's got to be a better way to do this, but this works.
-Now that we have a list of chars, the rest is pretty easy. The easy part was the hard part. What we'll do is walk through the list of chars. If the list is empty, return an empty list. If the first char is '.' return the list `['[', '.', ']']` appended to the defanged list minus its head, and otherwise append the head to the defanged list minus its head. Like so
+Now that we have a list of chars, the rest is pretty easy. The easy part was the hard part. What we'll do is walk through the list of chars. If the list is empty, return an empty list. If the first char is `'.'` return the list `['[', '.', ']']` appended to the defanged list minus its head, and otherwise append the head to the defanged list minus its head. Like so
```prolog
defang_chars([], []).
@@ -114,7 +114,7 @@ defang_chars(['.'|Xs], ['[', '.', ']'|Y]) :- defang_chars(Xs, Y), !.
defang_chars([X|Xs], [X|Y]) :- defang_chars(Xs, Y).
```
-You know I really abused terminology there. Prolog doesn't return anything! It just shows how hard it is to get my mind into logic programming mode. Really it's (constructive) matching. One thing to point out is the cut `!` operator in line 2. What I want here is that if we match a '.' then commit to it. Don't backtrack on to line 3, since that won't give us the correct output.
+You know I really abused terminology there. Prolog doesn't return anything! It just shows how hard it is to get my mind into logic programming mode. Really it's (constructive) matching. One thing to point out is the cut `!` operator in line 2. What I want here is that if we match a `'.'` then commit to it. Don't backtrack and end up on line 3, since that won't give us the correct output.
I'll mention briefly my Racket solution. After struggling through my Prolog implementation, this one was a breeze. The logic is basically the same, convert strings to lists, then recursively operate on the head of the list.
@@ -129,9 +129,9 @@ I'll mention briefly my Racket solution. After struggling through my Prolog impl
[else (cons first (loop rest))])))))
```
-One cool thing I dug up was `raco fmt` which is a code formatter for Racket. I used to think, "I'm a freewheelin' guy, don't fence me in, I'll format my code however I feel," but now I know that guy was a jerk! Find a style and stick with it, it will make your life easier. It doesn't matter so much what format you use as that you use a format. I read somewhere, and I agree.
+One cool thing I dug up was `raco fmt` which is a code formatter for Racket. I used to think, "I'm a freewheelin' guy, don't fence me in, I'll format my code however I feel," but now I know that guy was a jerk! Find a style and stick with it, it will make your life easier. It doesn't matter so much what format you use as that you use a format. I read that somewhere once, and I now agree.
-Funny side note, I had mentally converted 'defang' to 'defrang', and coded up all my solutions using 'defrang' in the function names somewhere, then had to do a substitution to get things back to normal. Maybe that's an idea for a future PWC - fix all the function names in some C code or something like that. Also, defrang ... I like that word. I'll have to rememebr to try to use that somewhere.
+Funny side note, I had mentally converted 'defang' to 'defrang', and coded up all my solutions using 'defrang' in the function names somewhere, then had to do a substitution to get things back to normal. Maybe that's an idea for a future PWC - fix all the function names in some C code or something like that. Also, defrang ... I like that word. I'll have to remember to try to use that somewhere.
## Task 2: String Score
@@ -186,6 +186,8 @@ Submitted by: Mohammad Sajid Anwar
What I like most about this challenge is it finally gives us a way to directly compare programming languages. Now if someone asks if Raku is better than Perl I can say 37 > 30 so yes!
+This is a cool one. I could imagine some variation of this being used to encrypt messages somehow. Maybe if we kept is as list.
+
Let's see some code
```perl
@@ -199,7 +201,11 @@ sub sum_char_abs_diff ($s) {
}
```
-Steps
+Here is the Perl function that does basically all the work. It takes a string, splits it on `''` which gives a list of characters. Then we map each value in that list of chars to its ascii value using `ord`. Next we initialize our sum value to 0. Now the for loop runs from index 1 until the end of the char-int list. This has the nice effect of handling strings of size 0 and size 1, the loop will never run and the value of 0 will be returned, which seems like a logically acceptable result in these cases. Within the loop we add to the sum the absolute value of the difference of element at the index and the element before it. That's a lot of words but it should be pretty clear by looking at the code.
+
+It looks like a pretty clean solution to me this time. I wonder if I could one-line it.
+
+The C code is very similar to the Perl solution
```c
int sum_abs_char_diffs(const char * s) {
@@ -214,7 +220,9 @@ int sum_abs_char_diffs(const char * s) {
}
```
-Plays to C's strengths, a char is basically an int! I wonder if I can do this in perl?
+The main thing to point out here is that it plays to C's strengths, a char is basically an int! I though about trying some implicit casting in Perl, but it is to eager to do some `atoi` magic. Here we can simply do the arithmetic on the chars and the results come out right.
+
+Prolog next
```prolog
sum_char_diffs([], 0).
@@ -227,7 +235,9 @@ sum_char_diffs([A, B|Xs], S) :-
sum_char_diffs([B|Xs], S2), S is S2 + B - A.
```
-The trickiest bit here is that I didn't know if there's an absolute value function so I just treat `A > B` and `B >= A` separately. The fact that Prolog thinks of strings as a list of char codes works well for me here, no conversion necessary!
+Here we match explicitly on an empty string or a string of length 1 and bind the value 0, otherwise we bind the sum of the difference of the first two elements plus the value from the same function called recursively on the list minus its head. The trickiest bit here is that I didn't know if there's an absolute value function so I just treat `A > B` and `B >= A` separately. The fact that Prolog thinks of strings as a list of char codes works well for me here, no conversion necessary! Take that!
+
+Finally some Racket. Despite the looks of this one it was easy again to write.
```racket
(define (sum-abs-char-diffs s)
@@ -238,5 +248,8 @@ The trickiest bit here is that I didn't know if there's an absolute value functi
(loop (cdr num-list) (+ diff-sum (abs (- (car num-list) (cadr num-list)))))))))
```
+The logic here is basically the same as for Prolog, in a functional form (returns a value). I wasn't sure what to do about the stack of closing parens that built up at the end, but `raco fmt` just bunched them all together on the last line, so I'll accept that.
+
+Ok. This concludes my long, rambling description of my various solutions to this week's challenge. I'm looking forward to seeing what comes up next week, and maybe soon I'll sending in some of the challenge ideas I've been tinkering with.
-#### **Thanks!**
+#### **Take care**
diff --git a/challenge-272/atschneid/blog.txt b/challenge-272/atschneid/blog.txt
new file mode 100644
index 0000000000..ee6a47af39
--- /dev/null
+++ b/challenge-272/atschneid/blog.txt
@@ -0,0 +1,2 @@
+https://github.com/atschneid/perlweeklychallenge-club/blob/master/challenge-272/atschneid/README.md
+