commit 051865dc8bfdc3090372ac45d2d8d0cb476feafe
parent be8e5b114b7cb5eff6e49c5381db163e1aa66761
Author: Jack Sangdahl <jack@pngu.org>
Date: Fri, 12 Dec 2025 19:10:25 -0700
3606. coupon code validator
Diffstat:
2 files changed, 142 insertions(+), 0 deletions(-)
diff --git a/coupon_code_validator.c b/coupon_code_validator.c
@@ -0,0 +1,90 @@
+// 3606. Coupon Code Validator
+#include "leetcode.h"
+
+/*
+ * you are given three arrays of length 'n' that describe the properties of 'n'
+ * coupons 'code', 'businessLine', and 'isActive'. the i'th coupon has a string
+ * representing the coupon identifier, a string denoting the business category
+ * of the coupon, a boolean indicating if the coupon is currently active. a
+ * coupon is considered valid if all of the following conditions hold: 'code[i]'
+ * is non-empty and consists of only alphanumeric characters and underscores,
+ * 'businessLine[i]' is one of the categories electronics, grocery, pharmacy, or
+ * restaurant, and 'isActive[i]' is true. return an array of the codes of all
+ * valid coupons sorted first by their 'businessLine' order.
+ */
+
+void swap_str(char **s, int i, int j) {
+ char *tmp = s[i];
+ s[i] = s[j];
+ s[j] = tmp;
+}
+
+void swap_bool(bool *arr, int i, int j) {
+ bool tmp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = tmp;
+}
+
+bool alphanumeric(char *s) {
+ while (*s) {
+ if (!isalnum(*s) && *s != '_')
+ return false;
+ s++;
+ }
+ return true;
+}
+
+bool valid_category(char *s) {
+ if (strcmp(s, "electronics") && strcmp(s, "grocery") &&
+ strcmp(s, "pharmacy") && strcmp(s, "restaurant"))
+ return false;
+ return true;
+}
+
+char **validateCoupons(char **code, int codeSize, char **businessLine,
+ int businessLineSize, bool *isActive, int isActiveSize,
+ int *returnSize) {
+ char **ans = (char **)malloc(codeSize * sizeof(char *));
+ *returnSize = 0;
+ for (int i = 0; i < businessLineSize; i++)
+ for (int j = i + 1; j < businessLineSize; j++) {
+ int cmp = strcmp(businessLine[i], businessLine[j]);
+ if (cmp) {
+ swap_str(businessLine, i, j);
+ swap_str(code, i, j);
+ swap_bool(isActive, i, j);
+ } else if (!cmp && strcmp(code[i], code[j])) {
+ swap_str(code, i, j);
+ swap_bool(isActive, i, j);
+ }
+ }
+ for (int i = 0; i < codeSize; i++)
+ if (isActive[i] && alphanumeric(code[i]) && valid_category(businessLine[i]))
+ ans[(*returnSize)++] = strdup(code[i]);
+ return ans;
+}
+
+int main() {
+ char *c1[] = {"SAVE20", "", "PHARMA5", "SAVE@20"},
+ *b1[] = {"restaurant", "grocery", "pharmacy", "restaurant"};
+ char *c2[] = {"GROCERY15", "ELECTRONICS_50", "DISCOUNT10"},
+ *b2[] = {"grocery", "electronics", "invalid"};
+ bool ia1[] = {true, true, true, true}, ia2[] = {false, true, true};
+ int rs1, rs2;
+ char **vc1 = validateCoupons(c1, ARRAY_SIZE(c1), b1, ARRAY_SIZE(b1), ia1,
+ ARRAY_SIZE(ia1), &rs1);
+ char **vc2 = validateCoupons(c2, ARRAY_SIZE(c2), b2, ARRAY_SIZE(b2), ia2,
+ ARRAY_SIZE(ia2), &rs2);
+ for (int i = 0; i < rs1; i++)
+ printf("%s ", vc1[i]); // expect: PHARMA5 SAVE20
+ printf("\n");
+ for (int i = 0; i < rs2; i++)
+ printf("%s ", vc2[i]); // expect: ELECTRONICS_50
+ printf("\n");
+ for (int i = 0; i < rs1; i++)
+ free(vc1[i]);
+ free(vc1);
+ for (int i = 0; i < rs2; i++)
+ free(vc2[i]);
+ free(vc2);
+}
diff --git a/coupon_code_validator.py b/coupon_code_validator.py
@@ -0,0 +1,52 @@
+# 3606. Coupon Code Validator
+
+"""
+you are given three arrays of length 'n' that describe the properties of 'n'
+coupons 'code', 'businessLine', and 'isActive'. the i'th coupon has a string
+representing the coupon identifier, a string denoting the business category
+of the coupon, a boolean indicating if the coupon is currently active. a
+coupon is considered valid if all of the following conditions hold: 'code[i]'
+is non-empty and consists of only alphanumeric characters and underscores,
+'businessLine[i]' is one of the categories electronics, grocery, pharmacy, or
+restaurant, and 'isActive[i]' is True. return an array of the codes of all
+valid coupons sorted first by their 'businessLine' order.
+"""
+
+
+class Solution(object):
+ def validateCoupons(self, code, businessLine, isActive):
+ """
+ :type code: List[str]
+ :type businessLine: List[str]
+ :type isActive: List[bool]
+ :rtype: List[str]
+ """
+
+ def valid(record):
+ return (
+ record[0] in valid_business
+ and record[2]
+ and record[1].replace("_", "a").isalnum()
+ )
+
+ valid_business = {"electronics", "grocery", "restaurant", "pharmacy"}
+ ans = sorted(filter(valid, zip(businessLine, code, isActive)))
+ return [id for _, id, _ in ans]
+
+
+if __name__ == "__main__":
+ obj = Solution()
+ print(
+ obj.validateCoupons(
+ code=["SAVE20", "", "PHARMA5", "SAVE@20"],
+ businessLine=["restaurant", "grocery", "pharmacy", "restaurant"],
+ isActive=[True, True, True, True],
+ )
+ )
+ print(
+ obj.validateCoupons(
+ code=["GROCERY15", "ELECTRONICS_50", "DISCOUNT10"],
+ businessLine=["grocery", "electronics", "invalid"],
+ isActive=[False, True, True],
+ )
+ )