aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaulo Custodio <pauloscustodio@gmail.com>2023-03-22 19:34:38 +0000
committerPaulo Custodio <pauloscustodio@gmail.com>2023-03-22 19:34:38 +0000
commitf036ddd90eca9f7472fed1034d5e223e46a7543f (patch)
tree986503caa0a9db21c7d2a0622f3feb402cc53948
parentda3731bfb028253180da6118717957b1d1226c44 (diff)
downloadperlweeklychallenge-club-f036ddd90eca9f7472fed1034d5e223e46a7543f.tar.gz
perlweeklychallenge-club-f036ddd90eca9f7472fed1034d5e223e46a7543f.tar.bz2
perlweeklychallenge-club-f036ddd90eca9f7472fed1034d5e223e46a7543f.zip
Add C and C++ solutions
-rw-r--r--challenge-209/paulo-custodio/basic/ch-1.bas34
-rw-r--r--challenge-209/paulo-custodio/basic/ch-2.bas144
-rw-r--r--challenge-209/paulo-custodio/c/ch-1.c69
-rw-r--r--challenge-209/paulo-custodio/c/ch-2.c216
-rw-r--r--challenge-209/paulo-custodio/cpp/ch-1.cpp66
-rw-r--r--challenge-209/paulo-custodio/cpp/ch-2.cpp101
6 files changed, 561 insertions, 69 deletions
diff --git a/challenge-209/paulo-custodio/basic/ch-1.bas b/challenge-209/paulo-custodio/basic/ch-1.bas
index fb9a6300d9..f3b1c1013f 100644
--- a/challenge-209/paulo-custodio/basic/ch-1.bas
+++ b/challenge-209/paulo-custodio/basic/ch-1.bas
@@ -29,23 +29,23 @@
' (10) i.e. the last character is not 1-bit character.
function decode(in as string) as string
- dim result as string
- do while in<>""
- if left(in,1)="0" then
- result=result+"a"
- in=mid(in,2)
- elseif left(in,2)="10" then
- result=result+"b"
- in=mid(in,3)
- elseif left(in,2)="11" then
- result=result+"c"
- in=mid(in,3)
- else
- print "Error: cannot parse: "; in
- end
- end if
- loop
- decode=result
+ dim result as string
+ do while in<>""
+ if left(in,1)="0" then
+ result=result+"a"
+ in=mid(in,2)
+ elseif left(in,2)="10" then
+ result=result+"b"
+ in=mid(in,3)
+ elseif left(in,2)="11" then
+ result=result+"c"
+ in=mid(in,3)
+ else
+ print "Error: cannot parse: "; in
+ end
+ end if
+ loop
+ decode=result
end function
dim in as string, result as string
diff --git a/challenge-209/paulo-custodio/basic/ch-2.bas b/challenge-209/paulo-custodio/basic/ch-2.bas
index 96447e2b53..02e2fb621f 100644
--- a/challenge-209/paulo-custodio/basic/ch-2.bas
+++ b/challenge-209/paulo-custodio/basic/ch-2.bas
@@ -33,68 +33,108 @@ dim shared names() as string
dim shared emails() as string
sub collect_args()
- dim i as integer, j as integer, row as integer
- row=1
- i=1
- do while command(i)<>""
- redim preserve names(row) as string
- redim preserve emails(row) as string
- names(row)=command(i)
- i=i+1
- do while command(i)<>"" and command(i)<>","
- emails(row)=emails(row)+command(i)+" "
- i=i+1
- loop
- if command(i)="," then i=i+1: row=row+1
- loop
+ dim i as integer, j as integer, row as integer
+ row=1
+ i=1
+ do while command(i)<>""
+ redim preserve names(row) as string
+ redim preserve emails(row) as string
+ names(row)=command(i)
+ i=i+1
+ do while command(i)<>"" and command(i)<>","
+ emails(row)=emails(row)+command(i)+" "
+ i=i+1
+ loop
+ if command(i)="," then i=i+1: row=row+1
+ loop
end sub
sub split(byval text as string, delim as string = " ", ret() as string)
- dim p as integer, count as integer
- count=0
- do
- do while left(text,1)=delim: text=mid(text,2): loop ' eat front delimiters
- if text="" then exit do
- redim preserve ret(count) as string
- p=instr(text,delim)
- if p<1 then
- ret(count)=text
- exit do
- else
- ret(count)=left(text,p-1)
- text=mid(text,p+1)
- count=count+1
- end if
- loop
+ dim p as integer, count as integer
+ count=0
+ do
+ do while left(text,1)=delim: text=mid(text,2): loop ' eat front delimiters
+ if text="" then exit do
+ redim preserve ret(count) as string
+ p=instr(text,delim)
+ if p<1 then
+ ret(count)=text
+ exit do
+ else
+ ret(count)=left(text,p-1)
+ text=mid(text,p+1)
+ count=count+1
+ end if
+ loop
end sub
function common_email(byref aa as integer, byref bb as integer) as boolean
- dim emails_a() as string, emails_b() as string
- dim a as integer, i as integer, b as integer, j as integer
- for a=0 to ubound(names)
- split(emails(a),,emails_a())
- for i=0 to ubound(emails_a)
- for b=0 to ubound(names)
- if a<>b then
- split(emails(b),,emails_b())
- for j=0 to ubound(emails_b)
- if mails_a(i)=mails_b(j) then
- aa=a: bb=b: common_email=true
- exit function
- end if
- next
- end if
- next
- next
- next
- common_email=false
+ dim emails_a() as string, emails_b() as string
+ dim a as integer, i as integer, b as integer, j as integer
+ for a=0 to ubound(names)
+ split(emails(a),,emails_a())
+ for i=0 to ubound(emails_a)
+ for b=0 to ubound(names)
+ if a<>b then
+ split(emails(b),,emails_b())
+ for j=0 to ubound(emails_b)
+ if emails_a(i)=emails_b(j) then
+ aa=a: bb=b: common_email=true
+ exit function
+ end if
+ next
+ end if
+ next
+ next
+ next
+ common_email=false
end function
+sub sort(s() as string)
+ dim i as integer, j as integer, tmp as string
+ for i=0 to ubound(s)-1
+ for j=i+1 to ubound(s)
+ if s(i)>s(j) then tmp=s(i): s(i)=s(j): s(j)=tmp
+ next
+ next
+end sub
+
+function sort_uniq_emails(emails as string) as string
+ dim s() as string, i as integer, last as string, ret as string
+ split emails,,s()
+ sort s()
+ ret=""
+ for i=0 to ubound(s)
+ if s(i)<>last then
+ ret=ret+s(i)+" "
+ last=s(i)
+ end if
+ next
+ sort_uniq_emails=ret
+end function
-dim i as integer, a as integer, b as integer
+sub merge_account(a as integer, b as integer)
+ dim all_emails as string, i as integer
+ all_emails=sort_uniq_emails(emails(a)+" "+emails(b))
+ emails(a)=all_emails
+ for i=b to ubound(names)-1
+ names(i)=names(i+1)
+ emails(i)=emails(i+1)
+ next
+ redim preserve names(ubound(names)-1)
+ redim preserve emails(ubound(emails)-1)
+end sub
+
+sub merge_accounts()
+ dim a as integer, b as integer
+ do while common_email(a, b)
+ merge_account(a, b)
+ loop
+end sub
+dim i as integer
collect_args
-if common_email(a, b) then print a, b
+merge_accounts
for i=0 to ubound(names)
- print i;names(i) ',emails(i)
+ print names(i);" ";emails(i)
next
diff --git a/challenge-209/paulo-custodio/c/ch-1.c b/challenge-209/paulo-custodio/c/ch-1.c
new file mode 100644
index 0000000000..370f5f0399
--- /dev/null
+++ b/challenge-209/paulo-custodio/c/ch-1.c
@@ -0,0 +1,69 @@
+/*
+Challenge 209
+
+Task 1: Special Bit Characters
+Submitted by: Mohammad S Anwar
+
+You are given an array of binary bits that ends with 0.
+
+Valid sequences in the bit string are:
+
+[0] -decodes-to-> "a"
+[1, 0] -> "b"
+[1, 1] -> "c"
+
+Write a script to print 1 if the last character is an “a” otherwise print 0.
+Example 1
+
+Input: @bits = (1, 0, 0)
+Output: 1
+
+The given array bits can be decoded as 2-bits character (10) followed by
+1-bit character (0).
+
+Example 2
+
+Input: @bits = (1, 1, 1, 0)
+Output: 0
+
+Possible decode can be 2-bits character (11) followed by 2-bits character
+(10) i.e. the last character is not 1-bit character.
+*/
+
+#define MAX_STRING 256
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void decode(char* out, const char* in) {
+ const char* p = in;
+ char* q = out;
+ while (*p) {
+ switch (*p) {
+ case '0': *q++ = 'a'; p++; break;
+ case '1':
+ p++;
+ switch (*p) {
+ case '0': *q++ = 'b'; p++; break;
+ case '1': *q++ = 'c'; p++; break;
+ default: fputs("invalid input", stderr); exit(EXIT_FAILURE);
+ }
+ break;
+ default: fputs("invalid input", stderr); exit(EXIT_FAILURE);
+ }
+ }
+ *q++ = '\0';
+}
+
+int main(int argc, char* argv[]) {
+ argv++; argc--;
+ if (argc != 1) {
+ fputs("usage: ch-2 str\n", stderr);
+ return EXIT_FAILURE;
+ }
+
+ char out[MAX_STRING];
+ decode(out, argv[0]);
+ printf("%d\n", out[strlen(out)-1] == 'a' ? 1 : 0);
+}
diff --git a/challenge-209/paulo-custodio/c/ch-2.c b/challenge-209/paulo-custodio/c/ch-2.c
new file mode 100644
index 0000000000..a5349dac18
--- /dev/null
+++ b/challenge-209/paulo-custodio/c/ch-2.c
@@ -0,0 +1,216 @@
+/*
+Challenge 209
+
+Task 2: Merge Account
+Submitted by: Mohammad S Anwar
+
+You are given an array of accounts i.e. name with list of email addresses.
+
+Write a script to merge the accounts where possible. The accounts can only
+be merged if they have at least one email address in common.
+
+Example 1:
+
+Input: @accounts = [ ["A", "a1@a.com", "a2@a.com"],
+ ["B", "b1@b.com"],
+ ["A", "a3@a.com", "a1@a.com"] ]
+ ]
+
+Output: [ ["A", "a1@a.com", "a2@a.com", "a3@a.com"],
+ ["B", "b1@b.com"] ]
+
+Example 2:
+
+Input: @accounts = [ ["A", "a1@a.com", "a2@a.com"],
+ ["B", "b1@b.com"],
+ ["A", "a3@a.com"],
+ ["B", "b2@b.com", "b1@b.com"] ]
+
+Output: [ ["A", "a1@a.com", "a2@a.com"],
+ ["A", "a3@a.com"],
+ ["B", "b1@b.com", "b2@b.com"] ]
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+typedef struct ArrayStr {
+ int count;
+ char** items;
+} ArrayStr;
+
+typedef struct Account {
+ char* name;
+ ArrayStr* emails;
+} Account;
+
+typedef struct Accounts {
+ int count;
+ Account** items;
+} Accounts;
+
+void* check_mem(void* p) {
+ if (!p) {
+ fputs("Out of memory", stderr);
+ exit(EXIT_FAILURE);
+ }
+ return p;
+}
+
+ArrayStr* arrstr_new() {
+ return check_mem(calloc(1, sizeof(ArrayStr)));
+}
+
+void arrstr_clear(ArrayStr* as) {
+ for (int i = 0; i < as->count; i++)
+ free(as->items[i]);
+ as->count = 0;
+}
+
+void arrstr_free(ArrayStr* as) {
+ arrstr_clear(as);
+ free(as);
+}
+
+void arrstr_push(ArrayStr* as, const char* s) {
+ as->items = check_mem(realloc(as->items, (as->count + 1) * sizeof(char**)));
+ as->items[as->count++] = check_mem(strdup(s));
+}
+
+void arrstr_remove(ArrayStr* as, int idx) {
+ if (idx < as->count) {
+ free(as->items[idx]);
+ memmove(&as->items[idx], &as->items[idx + 1], (as->count - idx - 1) * sizeof(char**));
+ as->count--;
+ }
+}
+
+int compare(const void* a, const void* b) {
+ return strcmp(*(const char**)a, *(const char**)b);
+}
+
+void arrstr_sort(ArrayStr* as) {
+ qsort(as->items, as->count, sizeof(char**), compare);
+}
+
+void arrstr_uniq(ArrayStr* as) {
+ arrstr_sort(as);
+ for (int i = 0; i < as->count - 1; i++) {
+ if (strcmp(as->items[i], as->items[i + 1]) == 0) {
+ arrstr_remove(as, i + 1);
+ i--;
+ }
+ }
+}
+
+int arrstr_find(ArrayStr* as, const char* name) {
+ for (int i = 0; i < as->count; i++)
+ if (strcmp(as->items[i], name) == 0)
+ return i;
+ return -1;
+}
+
+Account* acc_new(const char* name) {
+ Account* acc = check_mem(calloc(1, sizeof(Account)));
+ acc->name = check_mem(strdup(name));
+ acc->emails = arrstr_new();
+ return acc;
+}
+
+void acc_free(Account* acc) {
+ free(acc->name);
+ arrstr_free(acc->emails);
+ free(acc);
+}
+
+void acc_push_email(Account* acc, const char* email) {
+ arrstr_push(acc->emails, email);
+}
+
+void acc_merge(Account* acc, Account* other) {
+ for (int i = 0; i < other->emails->count; i++)
+ acc_push_email(acc, other->emails->items[i]);
+ arrstr_uniq(acc->emails);
+}
+
+Accounts* accs_new() {
+ return check_mem(calloc(1, sizeof(Accounts)));
+}
+
+void accs_clear(Accounts* accs) {
+ for (int i = 0; i < accs->count; i++)
+ acc_free(accs->items[i]);
+ accs->count = 0;
+}
+
+void accs_free(Accounts* accs) {
+ accs_clear(accs);
+ free(accs);
+}
+
+void accs_push(Accounts* accs, const char* name) {
+ accs->items = check_mem(realloc(accs->items, (accs->count + 1) * sizeof(Account**)));
+ accs->items[accs->count++] = acc_new(name);
+}
+
+void accs_remove(Accounts* accs, int idx) {
+ if (idx < accs->count) {
+ acc_free(accs->items[idx]);
+ memmove(&accs->items[idx], &accs->items[idx + 1], (accs->count - idx - 1) * sizeof(Account**));
+ accs->count--;
+ }
+}
+
+bool accs_find_common(Accounts* accs, int* pa, int* pb) {
+ for (*pa = 0; *pa < accs->count - 1; (*pa)++) {
+ for (int i = 0; i < accs->items[*pa]->emails->count; i++) {
+ const char* email = accs->items[*pa]->emails->items[i];
+ for (*pb = *pa + 1; *pb < accs->count; (*pb)++) {
+ if (arrstr_find(accs->items[*pb]->emails, email) >= 0) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+void accs_merge(Accounts* accs) {
+ int a, b;
+ while (accs_find_common(accs, &a, &b)) {
+ acc_merge(accs->items[a], accs->items[b]);
+ accs_remove(accs, b);
+ }
+}
+
+int main(int argc, char* argv[]) {
+ argv++; argc--;
+ if (argc == 0) {
+ fputs("usage: name emails... name emails...\n", stderr);
+ return EXIT_FAILURE;
+ }
+
+ Accounts* accs = accs_new();
+
+ for (int i = 0; i < argc; i++) {
+ const char* name = argv[i++];
+ accs_push(accs, name);
+ for (; i < argc && strcmp(argv[i], ",") != 0; i++) {
+ const char* email = argv[i];
+ acc_push_email(accs->items[accs->count - 1], email);
+ }
+ }
+
+ accs_merge(accs);
+
+ for (int i = 0; i < accs->count; i++) {
+ printf("%s ", accs->items[i]->name);
+ for (int j = 0; j < accs->items[i]->emails->count; j++)
+ printf("%s ", accs->items[i]->emails->items[j]);
+ printf("\n");
+ }
+
+ accs_free(accs);
+}
diff --git a/challenge-209/paulo-custodio/cpp/ch-1.cpp b/challenge-209/paulo-custodio/cpp/ch-1.cpp
new file mode 100644
index 0000000000..af0e604c5e
--- /dev/null
+++ b/challenge-209/paulo-custodio/cpp/ch-1.cpp
@@ -0,0 +1,66 @@
+/*
+Challenge 209
+
+Task 1: Special Bit Characters
+Submitted by: Mohammad S Anwar
+
+You are given an array of binary bits that ends with 0.
+
+Valid sequences in the bit string are:
+
+[0] -decodes-to-> "a"
+[1, 0] -> "b"
+[1, 1] -> "c"
+
+Write a script to print 1 if the last character is an “a” otherwise print 0.
+Example 1
+
+Input: @bits = (1, 0, 0)
+Output: 1
+
+The given array bits can be decoded as 2-bits character (10) followed by
+1-bit character (0).
+
+Example 2
+
+Input: @bits = (1, 1, 1, 0)
+Output: 0
+
+Possible decode can be 2-bits character (11) followed by 2-bits character
+(10) i.e. the last character is not 1-bit character.
+*/
+
+#include <iostream>
+#include <string>
+
+std::string decode(const std::string& in) {
+ std::string out;
+ const char* p = in.c_str();
+ while (*p) {
+ switch (*p) {
+ case '0': out.push_back('a'); p++; break;
+ case '1':
+ p++;
+ switch (*p) {
+ case '0': out.push_back('b'); p++; break;
+ case '1': out.push_back('c'); p++; break;
+ default: std::cerr << "invalid input" << std::endl; exit(EXIT_FAILURE);
+ }
+ break;
+ default: std::cerr << "invalid input" << std::endl; exit(EXIT_FAILURE);
+ }
+ }
+ return out;
+}
+
+int main(int argc, char* argv[]) {
+ argv++; argc--;
+ if (argc != 1) {
+ std::cerr << "usage: ch-2 str" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ std::string out = decode(argv[0]);
+ int result = (!out.empty() && out.back()=='a') ? 1 : 0;
+ std::cout << result << std::endl;
+}
diff --git a/challenge-209/paulo-custodio/cpp/ch-2.cpp b/challenge-209/paulo-custodio/cpp/ch-2.cpp
new file mode 100644
index 0000000000..0767787b2d
--- /dev/null
+++ b/challenge-209/paulo-custodio/cpp/ch-2.cpp
@@ -0,0 +1,101 @@
+/*
+Challenge 209
+
+Task 2: Merge Account
+Submitted by: Mohammad S Anwar
+
+You are given an array of accounts i.e. name with list of email addresses.
+
+Write a script to merge the accounts where possible. The accounts can only
+be merged if they have at least one email address in common.
+
+Example 1:
+
+Input: @accounts = [ ["A", "a1@a.com", "a2@a.com"],
+ ["B", "b1@b.com"],
+ ["A", "a3@a.com", "a1@a.com"] ]
+ ]
+
+Output: [ ["A", "a1@a.com", "a2@a.com", "a3@a.com"],
+ ["B", "b1@b.com"] ]
+
+Example 2:
+
+Input: @accounts = [ ["A", "a1@a.com", "a2@a.com"],
+ ["B", "b1@b.com"],
+ ["A", "a3@a.com"],
+ ["B", "b2@b.com", "b1@b.com"] ]
+
+Output: [ ["A", "a1@a.com", "a2@a.com"],
+ ["A", "a3@a.com"],
+ ["B", "b1@b.com", "b2@b.com"] ]
+*/
+
+#include <algorithm>
+#include <iostream>
+#include <string>
+#include <vector>
+
+struct Account {
+ std::string name;
+ std::vector<std::string> emails;
+
+ Account(const std::string& name_) : name(name_) {}
+
+ void merge(const Account& other) {
+ emails.insert(emails.end(), other.emails.begin(), other.emails.end()); // concatenate
+ std::sort(emails.begin(), emails.end()); // sort
+ auto it = std::unique(emails.begin(), emails.end()); // uniq
+ emails.resize(std::distance(emails.begin(), it));
+ }
+};
+
+bool find_common(std::vector<Account>& accs, size_t& a, size_t& b) {
+ for (a = 0; a < accs.size() - 1; a++) {
+ for (size_t i = 0; i < accs[a].emails.size(); i++) {
+ std::string& email = accs[a].emails[i];
+ for (b = a + 1; b < accs.size(); b++) {
+ auto it = std::find(accs[b].emails.begin(), accs[b].emails.end(), email);
+ if (it != accs[b].emails.end())
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void merge_accounts(std::vector<Account>& accs) {
+ size_t a, b;
+ while (find_common(accs, a, b)) {
+ accs[a].merge(accs[b]);
+ accs.erase(accs.begin() + b);
+ }
+}
+
+int main(int argc, char* argv[]) {
+ argv++; argc--;
+ if (argc == 0) {
+ std::cerr << "usage: name emails... name emails..." << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ std::vector<Account> accs;
+
+ for (int i = 0; i < argc; i++) {
+ std::string name = argv[i++];
+ accs.emplace_back(name);
+ for (; i < argc && std::string(argv[i])!= ","; i++) {
+ std::string email = argv[i];
+ accs.back().emails.push_back(email);
+ }
+ }
+
+ merge_accounts(accs);
+
+ for (size_t i = 0; i < accs.size(); i++) {
+ std::cout << accs[i].name << " ";
+ for (size_t j = 0; j < accs[i].emails.size(); j++)
+ std::cout << accs[i].emails[j] << " ";
+ std::cout << std::endl;
+ }
+}