diff options
| author | Paulo Custodio <pauloscustodio@gmail.com> | 2023-03-22 19:34:38 +0000 |
|---|---|---|
| committer | Paulo Custodio <pauloscustodio@gmail.com> | 2023-03-22 19:34:38 +0000 |
| commit | f036ddd90eca9f7472fed1034d5e223e46a7543f (patch) | |
| tree | 986503caa0a9db21c7d2a0622f3feb402cc53948 | |
| parent | da3731bfb028253180da6118717957b1d1226c44 (diff) | |
| download | perlweeklychallenge-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.bas | 34 | ||||
| -rw-r--r-- | challenge-209/paulo-custodio/basic/ch-2.bas | 144 | ||||
| -rw-r--r-- | challenge-209/paulo-custodio/c/ch-1.c | 69 | ||||
| -rw-r--r-- | challenge-209/paulo-custodio/c/ch-2.c | 216 | ||||
| -rw-r--r-- | challenge-209/paulo-custodio/cpp/ch-1.cpp | 66 | ||||
| -rw-r--r-- | challenge-209/paulo-custodio/cpp/ch-2.cpp | 101 |
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; + } +} |
