linear algebra – Sparse PCA vs Orthogonal Matching Pursuit

can’t wrap my head around the difference between Sparse PCA and OMP.
Both try to find a sparse linear combination.

Of course, the optimization criteria is different.

In Sparse PCA we have:
begin{aligned} max & v^{T} Sigma v \ text { subject to } &|v|_{2}=1 \ &|v|_{0} leq k end{aligned}

In OMP we have:
$$
min _{x}|f-D x|_{2}^{2} text { subject to }|x|_{0} leq N
$$

Even though these are different, they resemble one another in my eyes.
I’ll explain: In PCA we wish to take the projection that counts for the most variance.
If we add the “sparsity” constraint, than we regularize and get some projection which is sparser, but does not account for the most variance possible (without the constraint).

In OMP (the algorithm procedure here), we pretty much do the same thing, iteratively – we find the “atom” that gives the largest inner product – which is the most correlative.

Differences I see:

  1. Different optimization problem (already said) – however the “applicative” view look very similar, therefore I ask this question
  2. OMP is an iterative procedure, while in Sparce PCA, there are direct solutions?

Thanks!

Why b regex is not matching correctly?

As per re docs, b matches an empty string both at start and end of a word, with the word being a combination of characters of the w class.

So basically b represents a sort of boundary between separated words. And in fact the following matches as expected:

re.match(b"bfoob", "foo bar")

But surprisingly this doesn’t:

re.match(r"bfoob", "bar foo baz")

Why is the left boundary behaving differently? I’m sure I’m missing something here, or maybe I’m not fully understanding how b works.

python – Kuberhealthy Check – check NodeGroup labels are matching

This is quite a specific script I have written, for Kubernetes Cluster monitoring purposes (specifically the Nodes). Essentially, I need to ensure that the Nodes within a NodeGroup all have the same labels and label values, or else they will not be scaled out evenly for Node Scale out in the version of Kubernetes we are using (Cluster Auto Scaler wants the values to be the same in order to treat the Nodes equally).

The env var IN_CLUSTER is used so I can set whether the script is run from my local machine (which can read kubectl config) or whether it’s running as a container within the cluster (leverage RBAC permissions).

The script I have written works and does what I need – get a list of Nodes in the cluster, iterate through each NodeGroup (there are four Node Groups – core, general, observability, pci). We group the Nodes into their relevant NodeGroup. We then check each Node within the NodeGroup, and do a comparison to ensure the labels match.

The script implements the Kubernetes client for retrieving list of Nodes. The script also implements the Kuberhealthy client, which is simply to report the check results (success or failure) to the Kuberhealthy master.

I do not like the fact that the four NodeGroups are hardcoded in the script but can’t think how to achieve what I want with an array stored as an env var.

The script is intended to simply run top to bottom and be simple. I’m not sure it makes sense to have the if __name__ == '__main__' directive as it’s never going to be imported as a module.

from kubernetes import client, config
from kh_client import *
import os

# requires cluster role with permissions list, get nodes!
# needs refactoring, for time being have kept it as a 'top to bottom' script

def main():
    if os.getenv('IN_CLUSTER') == "TRUE":
        config.load_incluster_config()
    else:
        config.load_kube_config()
    
    try:
        api_instance = client.CoreV1Api()
        node_list = api_instance.list_node()
    except client.exceptions.ApiException:
        print("401 Unauthorised. Please check you are authenticated for the target cluster / have set the IN_CLUSTER env var.")
        exit(2)

    node_group_core = ()
    node_group_general = ()
    node_group_observability = ()
    node_group_pci = ()

    # print("%stt%s" % ("NAME", "LABELS"))
    # this needs changing but difficult to do with an env_var
    for node in node_list.items:
        if node.metadata.labels.get('nodegroup-name') == "core":
            node_group_core.append(node)
        if node.metadata.labels.get('nodegroup-name') == "general":
            node_group_general.append(node)
        if node.metadata.labels.get('nodegroup-name') == "observability":
            node_group_observability.append(node)
        if node.metadata.labels.get('nodegroup-name') == "pci":
            node_group_pci.append(node)

    check_node_group_labels(node_group_core)
    check_node_group_labels(node_group_general)
    check_node_group_labels(node_group_observability)
    check_node_group_labels(node_group_pci)

    # everything has checked successfully, report success. 
    print("Reporting Success.")
    try:
        report_success()
    except Exception as e:
        print(f"Error when reporting success: {e}")

def check_node_group_labels(node_group):
    # ignored labels taken from https://github.com/kubernetes/autoscaler/blob/3a69f118d95cd653bf101aecc0ea5e00bf7ba370/cluster-autoscaler/processors/nodegroupset/aws_nodegroups.go#L26
    # this can be refactored
    ignored_labels = ( "alpha.eksctl.io/instance-id", 
                       "alpha.eksctl.io/nodegroup-name", 
                       "eks.amazonaws.com/nodegroup", 
                       "k8s.amazonaws.com/eniConfig",
                       "lifecycle",
                       # labels i've added
                       "topology.kubernetes.io/zone",
                       "kubernetes.io/hostname",
                       "failure-domain.beta.kubernetes.io/zone" )

    node_group_labels = ()
    for l in node_group(0).metadata.labels:
        if l not in ignored_labels:
            node_group_labels.append(l)

    print(f"There are {len(node_group)} nodes in {node_group(0).metadata.labels.get('nodegroup-name')}")

    for label in node_group_labels:
        # compare against the 'benchmark' label, any difference means a mismatch as far as CAS is concerned
        # print(label)
        benchmark_label = node_group(0).metadata.labels.get(label)
        # print("benchmark label: ", benchmark_label)
        for node in node_group(1:):
            # print("node label", node.metadata.labels.get(label))
            if node.metadata.labels.get(label) != benchmark_label:
                print("Reporting Failure.")
                try:
                    report_failure((f"Warning! label mismatch detected, for nodegroup and node {node.metadata.name}, benchmark value: {benchmark_label}, this node value: {node.metadata.labels.get(label)}"))
                except Exception as e:
                    print(f"Error when reporting failure: {e}")

if __name__ == '__main__':
    main()
```

string matching – understanding the algorithm for building the KMP failure function

I am struggling to completely grasp the algorithm for building the KMP failure function. The bulk of what is making my understanding incomplete concerns the line length=PI(length-1) in the psuedo code below. Here are my questions:

1.) How do we know that in the event s(i) != s(length), the best possible option for our candidate prefix suffix is in fact PI(length-1)?

2.) If the candidate PI(length-1) fails, and on the next iteration of the while loop, we must go to PI(PI(length-1)-1), how do we know that the best possible candidate is actually BETWEEN PI(length-1) and PI(PI(length-1)-1)?

3.) When s(i)!=s(length) how do we know there does not exist a suffix(that matches a prefix) that ends at s(i) and that begins at a point in the string PRIOR to i-length?

I think my confusion could best be cleared by short informal proofs.

function f(string s): 

PI = an array of integers with size equal to length of s

length=0
i=1

while i < the length of the s:
    if s(length) == s(i):
        length+=1
        s(i)=length
        i+=1
    else:
        if length!=0:
            length=PI(length-1)
        else:
            PI(i)=0
            i+=1
return PI

Thank you!

pattern matching – Issues in expanding expressions with formal sums

I have a very long expression involving formal sums to infinity, unfixed functions and several variables.

In this very long expression, I need a typical term, like

$frac{6 A sigma sum _{n=0}^{infty } left(frac{2 A (n+1)^2 e^{-frac{A (n+1)}{w^2}} left(sum _{m=0}^{infty } (m+1) (m+2) w^m sigma ^n a(n+1,m+2)right)}{w^3}+(n+1) e^{-frac{A (n+1)}{w^2}} left(sum _{m=0}^{infty } m (m+1) (m+2) w^{m-1} sigma ^n a(n+1,m+2)right)right)}{w^3}$,

to be given like,

$frac{6 A sigma sum _{n=0}^{infty } (n+1) e^{-frac{A (n+1)}{w^2}} sum _{m=0}^{infty } m (m+1) (m+2) w^{m-1} sigma ^n a(n+1,m+2)}{w^3}+frac{2 A sum _{n=0}^{infty } (n+1)^2 e^{-frac{A (n+1)}{w^2}} sum _{m=0}^{infty } (m+1) (m+2) w^m sigma ^n a(n+1,m+2)}{w^6}$,

i.e to be expanded.

I need to do this for quite a lot of terms, and Mathematica’s Expand or ExpandAll doesn’t work.

composer – Magento2 – Getting error Could not find a matching version of package After submitting in packagist.org

I have Created New Module and uploaded in github.

Module Name : vrajeshpatel4u/helloworld

Url : https://github.com/vrajeshpatel4u/helloworld/

Packagist Url : https://packagist.org/packages/vrajeshpatel4u/helloworld

Below command I have tried still getting error : Could not find a matching version of package vrajeshpatel4u/helloworld. Check the package spelling, your version constraint and that the package is available in a stability which matches your minimum-stability (stable).

git add .
git commit -m 'initial commit'
git push origin master
git tag 1.0.0
git push origin --tags

Here is the composer.json

{
    "name": "vrajeshpatel4u/helloworld",
    "description": "Simple Hello World Module for Magento 2",
    "type": "magento2-module",
    "version": "1.0.0",
    "license": (
        "OSL-3.0",
        "AFL-3.0"
    ),
    "authors": (
        {
            "name": "Vrajesh Patel"
        }
    ),
    "minimum-stability": "dev",
    "require": {
        "php": "~7.1.3||~7.2.0||~7.3.0"
    },
    "autoload": {
        "files": (
            "registration.php"
        ),
        "psr-4": {
            "V4U\Helloworld\": ""
        }
    }
}

For installing Modules I have tried below commands :

composer require vrajeshpatel4u/helloworld

composer require vrajeshpatel4u/helloworld:dev-main

Any one help me to fix the issue?

Thank you.

A special perfect matching in a complete edge-colored graph

This question is related to an edge-monochromatic version of this question, originated from recent advances in quantum physics.

Given an even number $nge 6$ and a non-negative integer $kll n$, let $G=(V,E)=K_n$ be a complete graph on $n$ vertices, $(V,E_1), dots, (V,E_{n-1-k}) $ be spanning pairwise edge-disjoint subgraphs of $G$, and $R=Esetminusbigcup_{i=1}^{n-k} E_i$ be the set of remaining edges of $G$. I want to show the following

Claim. There exists a perfect matching $Msubseteq Esetminus R$ of $G$ such that for any $i=1,dots n-k$, $Mnotsubseteq E_i$ and a graph $(V_i, E’_i)$ has no cycles of even length. Here $V_i$ is the set of vertices of $G$ incident to edges in $Mcap E_i$ and $E’_i=(Mcap E_i)cup R_i$, where $R_i$ is the set of edges of $R$ with both endvertices in $V_i$.

In order to feel Claim, let us consider its simple cases.

For $k=0$ Claim is easy to show. Indeed, in this case $E_1,dots, E_{n-1-k}$ is a partition of $E$ into perfect matchings, so the set $R$ is empty. It is easy to show that $G$ has $(n-1)!!>n-k$ perfect matchings, so $G$ has a perfect matching $M$ distinct from any of $E_i$. Let $i=1,dots n-k$ be any number. The set $E’_i$ is contained in $M$, so it is a matching and the graph $(V_i, E’_i)$ has no cycles.

But Claim looks non-trivial already for $k=1$. In this case each graph $(V,E_i)$ has maximum vertex degree at most two, so it is a union of pairwise vertex-disjoint paths or cycles and $R$ is a matching, which follows that $E’_i$ is a union of at most two matchings.

Concerning the general case, given $n$, I want to prove Claim for the biggest possible $k$, which, I guess, is nevertheless $o(n)$.

Thanks.

How can I optimize matching a string against a bunch of regular expressions?

Here is some working code for converting an input string to an output string:

const list = (
  { text: "i~&__", code: "u14f0", name: 'Nasal German i with extra low tone' },
  { text: "i~&_", code: "u14e2", name: 'Nasal German i with low tone' },
  { text: "i~&^^", code: "u14ee", name: 'Nasal German i with extra high tone' },
  { text: "i~&^", code: "u14ea", name: 'Nasal German i with high tone' },
  { text: "i~&", code: "u14e6", name: 'Nasal German i' },
  { text: "(i~&__)", code: "u14f1", name: 'Nasal German i with extra low tone and stress' },
  { text: "(i~&_)", code: "u14e3", name: 'Nasal German i with low tone and stress' },
  { text: "(i~&^^)", code: "u14ef", name: 'Nasal German i with extra high tone and stress' },
  { text: "(i~&^)", code: "u14eb", name: 'Nasal German i with high tone and stress' },
  { text: "(i~&)", code: "u14e7", name: 'Nasal German i with stress' },

  { text: "i~__", code: "u14fa", name: 'German i with extra low tone' },
  { text: "i~_", code: "u0434", name: 'German i with low tone' },
  { text: "i~^^", code: "u14fe", name: 'German i with extra high tone' },
  { text: "i~^", code: "u0438", name: 'German i with high tone' },
  { text: "i~", code: "u0430", name: 'German i' },
  { text: "(i~__)", code: "u14fb", name: 'German i with extra low tone and stress' },
  { text: "(i~_)", code: "u0435", name: 'German i with low tone and stress' },
  { text: "(i~^^)", code: "u14ff", name: 'German i with extra high tone and stress' },
  { text: "(i~^)", code: "u0439", name: 'German i with high tone and stress' },
  { text: "(i~)", code: "u0432", name: 'German i with stress' },

  { text: "i+&__", code: "u1470", name: 'Nasal short i with extra low tone' },
  { text: "i+&_", code: "u1462", name: 'Nasal short i with low tone' },
  { text: "i+&^^", code: "u146e", name: 'Nasal short i with extra high tone' },
  { text: "i+&^", code: "u146a", name: 'Nasal short i with high tone' },
  { text: "i+&", code: "u1466", name: 'Nasal short i' },
  { text: "(i+&__)", code: "u1471", name: 'Nasal short i with extra low tone and stress' },
  { text: "(i+&_)", code: "u1463", name: 'Nasal short i with low tone and stress' },
  { text: "(i+&^^)", code: "u146f", name: 'Nasal short i with extra high tone and stress' },
  { text: "(i+&^)", code: "u146b", name: 'Nasal short i with high tone and stress' },
  { text: "(i+&)", code: "u1467", name: 'Nasal short i with stress' },

  { text: "i+__", code: "u147a", name: 'Short i with extra low tone' },
  { text: "i+_", code: "u03d4", name: 'Short i with low tone' },
  { text: "i+^^", code: "u147e", name: 'Short i with extra high tone' },
  { text: "i+^", code: "u03d8", name: 'Short i with high tone' },
  { text: "i+", code: "u03d0", name: 'Short i' },
  { text: "(i+__)", code: "u147b", name: 'Short i with extra low tone and stress' },
  { text: "(i+_)", code: "u03d5", name: 'Short i with low tone and stress' },
  { text: "(i+^^)", code: "u147f", name: 'Short i with extra high tone and stress' },
  { text: "(i+^)", code: "u03d9", name: 'Short i with high tone and stress' },
  { text: "(i+)", code: "u03d2", name: 'Short i with stress' },

  { text: "i&__", code: "u1530", name: 'Nasal i sound with extra low tone' },
  { text: "i&_", code: "u1522", name: 'Nasal i sound with low tone' },
  { text: "i&^^", code: "u152e", name: 'Nasal i sound with extra high tone' },
  { text: "i&^", code: "u152a", name: 'Nasal i sound with high tone' },
  { text: "i&", code: "u1526", name: 'Nasal i sound' },
  { text: "(i&__)", code: "u1531", name: 'Nasal i sound with extra low tone and stress' },
  { text: "(i&_)", code: "u1523", name: 'Nasal i sound with low tone and stress' },
  { text: "(i&^^)", code: "u152f", name: 'Nasal i sound with extra high tone and stress' },
  { text: "(i&^)", code: "u152b", name: 'Nasal i sound with high tone and stress' },
  { text: "(i&)", code: "u1527", name: 'Nasal i sound with stress' },

  { text: "i__", code: "u153a", name: 'I sound with extra low tone' },
  { text: "i_", code: "u0474", name: 'I sound with low tone' },
  { text: "i^^", code: "u153e", name: 'I sound with extra high tone' },
  { text: "i^", code: "u0478", name: 'I sound with high tone' },
  { text: "i", code: "u0470", name: 'I sound' },
  { text: "(i__)", code: "u153b", name: 'I sound with extra low tone and stress' },
  { text: "(i_)", code: "u0475", name: 'I sound with low tone and stress' },
  { text: "(i^^)", code: "u153f", name: 'I sound with extra high tone and stress' },
  { text: "(i^)", code: "u0479", name: 'I sound with high tone and stress' },
  { text: "(i)", code: "u0472", name: 'I sound with stress' },

  { text: "e~&__", code: "u1512", name: 'Nasal Danish oe with extra low tone' },
  { text: "e~&_", code: "u1504", name: 'Nasal Danish oe with low tone' },
  { text: "e~&^^", code: "u1500", name: 'Nasal Danish oe with extra high tone' },
  { text: "e~&^", code: "u150c", name: 'Nasal Danish oe with high tone' },
  { text: "e~&", code: "u1508", name: 'Nasal Danish oe' },
  { text: "(e~&__)", code: "u1513", name: 'Nasal Danish oe with extra low tone and stress' },
  { text: "(e~&_)", code: "u1505", name: 'Nasal Danish oe with low tone and stress' },
  { text: "(e~&^^)", code: "u1501", name: 'Nasal Danish oe with extra high tone and stress' },
  { text: "(e~&^)", code: "u150d", name: 'Nasal Danish oe with high tone and stress' },
  { text: "(e~&)", code: "u1509", name: 'Nasal Danish oe with stress' },

  { text: "e~__", code: "u1518", name: 'Danish oe with extra low tone' },
  { text: "e~_", code: "u0456", name: 'Danish oe with low tone' },
  { text: "e~^^", code: "u151c", name: 'Danish oe with extra high tone' },
  { text: "e~^", code: "u045a", name: 'Danish oe with high tone' },
  { text: "e~", code: "u0451", name: 'Danish oe' },
  { text: "(e~__)", code: "u1519", name: 'Danish oe with extra low tone and stress' },
  { text: "(e~_)", code: "u0457", name: 'Danish oe with low tone and stress' },
  { text: "(e~^^)", code: "u151d", name: 'Danish oe with extra high tone and stress' },
  { text: "(e~^)", code: "u045b", name: 'Danish oe with high tone and stress' },
  { text: "(e~)", code: "u0453", name: 'Danish oe with stress' },

  { text: "e+&__", code: "u1510", name: 'Nasal short e with extra low tone' },
  { text: "e+&_", code: "u1502", name: 'Nasal short e with low tone' },
  { text: "e+&^^", code: "u150e", name: 'Nasal short e with extra high tone' },
  { text: "e+&^", code: "u150a", name: 'Nasal short e with high tone' },
  { text: "e+&", code: "u1506", name: 'Nasal short e' },
  { text: "(e+&__)", code: "u1511", name: 'Nasal short e with extra low tone and stress' },
  { text: "(e+&_)", code: "u1503", name: 'Nasal short e with low tone and stress' },
  { text: "(e+&^^)", code: "u150f", name: 'Nasal short e with extra high tone and stress' },
  { text: "(e+&^)", code: "u150b", name: 'Nasal short e with high tone and stress' },
  { text: "(e+&)", code: "u1507", name: 'Nasal short e with stress' },

  { text: "e+__", code: "u151a", name: 'Short e with extra low tone' },
  { text: "e+_", code: "u0454", name: 'Short e with low tone' },
  { text: "e+^^", code: "u151e", name: 'Short e with extra high tone' },
  { text: "e+^", code: "u0458", name: 'Short e with high tone' },
  { text: "e+", code: "u0450", name: 'Short e' },
  { text: "(e+__)", code: "u151b", name: 'Short e with extra low tone and stress' },
  { text: "(e+_)", code: "u0455", name: 'Short e with low tone and stress' },
  { text: "(e+^^)", code: "u151f", name: 'Short e with extra high tone and stress' },
  { text: "(e+^)", code: "u0459", name: 'Short e with high tone and stress' },
  { text: "(e+)", code: "u0452", name: 'Short e with stress' },

  { text: "e&__", code: "u14d0", name: 'Nasal e sound with extra low tone' },
  { text: "e&_", code: "u14c2", name: 'Nasal e sound with low tone' },
  { text: "e&^^", code: "u14ce", name: 'Nasal e sound with extra high tone' },
  { text: "e&^", code: "u14ca", name: 'Nasal e sound with high tone' },
  { text: "e&", code: "u14c6", name: 'Nasal e sound' },
  { text: "(e&__)", code: "u14d1", name: 'Nasal e sound with extra low tone and stress' },
  { text: "(e&_)", code: "u14c3", name: 'Nasal e sound with low tone and stress' },
  { text: "(e&^^)", code: "u14cf", name: 'Nasal e sound with extra high tone and stress' },
  { text: "(e&^)", code: "u14cb", name: 'Nasal e sound with high tone and stress' },
  { text: "(e&)", code: "u14c7", name: 'Nasal e sound with stress' },

  { text: "e__", code: "u14da", name: 'E sound with extra low tone' },
  { text: "e_", code: "u0414", name: 'E sound with low tone' },
  { text: "e^^", code: "u14de", name: 'E sound with extra high tone' },
  { text: "e^", code: "u0418", name: 'E sound with high tone' },
  { text: "e", code: "u0410", name: 'E sound' },
  { text: "(e__)", code: "u14db", name: 'E sound with extra low tone and stress' },
  { text: "(e_)", code: "u0415", name: 'E sound with low tone and stress' },
  { text: "(e^^)", code: "u14df", name: 'E sound with extra high tone and stress' },
  { text: "(e^)", code: "u0419", name: 'E sound with high tone and stress' },
  { text: "(e)", code: "u0412", name: 'E sound with stress' },

  { text: "a+~&__", code: "u1492", name: 'Nasal Danish æ with extra low tone' },
  { text: "a+~&_", code: "u148e", name: 'Nasal Danish æ with low tone' },
  { text: "a+~&^^", code: "u148a", name: 'Nasal Danish æ with extra high tone' },
  { text: "a+~&^", code: "u1486", name: 'Nasal Danish æ with high tone' },
  { text: "a+~&", code: "u1482", name: 'Nasal Danish æ' },
  { text: "(a+~&__)", code: "u1493", name: 'Nasal Danish æ with extra low tone and stress' },
  { text: "(a+~&_)", code: "u148f", name: 'Nasal Danish æ with low tone and stress' },
  { text: "(a+~&^^)", code: "u148b", name: 'Nasal Danish æ with extra high tone and stress' },
  { text: "(a+~&^)", code: "u1487", name: 'Nasal Danish æ with high tone and stress' },
  { text: "(a+~&)", code: "u1483", name: 'Nasal Danish æ with stress' },

  { text: "a+~__", code: "u1498", name: 'Danish æ with extra low tone' },
  { text: "a+~_", code: "u03b6", name: 'Danish æ with low tone' },
  { text: "a+~^^", code: "u149c", name: 'Danish æ with extra high tone' },
  { text: "a+~^", code: "u03ba", name: 'Danish æ with high tone' },
  { text: "a+~", code: "u03b1", name: 'Danish æ' },
  { text: "(a+~__)", code: "u1499", name: 'Danish æ with extra low tone and stress' },
  { text: "(a+~_)", code: "u03b7", name: 'Danish æ with low tone and stress' },
  { text: "(a+~^^)", code: "u149d", name: 'Danish æ with extra high tone and stress' },
  { text: "(a+~^)", code: "u03bb", name: 'Danish æ with high tone and stress' },
  { text: "(a+~)", code: "u03b3", name: 'Danish æ with stress' },

  { text: "a~&__", code: "u1592", name: 'Nasal German e sound with extra low tone' },
  { text: "a~&_", code: "u1584", name: 'Nasal German e sound with low tone' },
  { text: "a~&^^", code: "u1580", name: 'Nasal German e sound with extra high tone' },
  { text: "a~&^", code: "u158c", name: 'Nasal German e sound with high tone' },
  { text: "a~&", code: "u1588", name: 'Nasal German e sound' },
  { text: "(a~&__)", code: "u1593", name: 'Nasal German e sound with extra low tone and stress' },
  { text: "(a~&_)", code: "u1585", name: 'Nasal German e sound with low tone and stress' },
  { text: "(a~&^^)", code: "u1581", name: 'Nasal German e sound with extra high tone and stress' },
  { text: "(a~&^)", code: "u158d", name: 'Nasal German e sound with high tone and stress' },
  { text: "(a~&)", code: "u1589", name: 'Nasal German e sound with stress' },

  { text: "a~__", code: "u1598", name: 'German e sound with extra low tone' },
  { text: "a~_", code: "u0506", name: 'German e sound with low tone' },
  { text: "a~^^", code: "u159c", name: 'German e sound with extra high tone' },
  { text: "a~^", code: "u050a", name: 'German e sound with high tone' },
  { text: "a~", code: "u0501", name: 'German e sound' },
  { text: "(a~__)", code: "u1599", name: 'German e sound with extra low tone and stress' },
  { text: "(a~_)", code: "u0507", name: 'German e sound with low tone and stress' },
  { text: "(a~^^)", code: "u159d", name: 'German e sound with extra high tone and stress' },
  { text: "(a~^)", code: "u050b", name: 'German e sound with high tone and stress' },
  { text: "(a~)", code: "u0503", name: 'German e sound with stress' },

  { text: "a+&__", code: "u1490", name: 'Nasal short a with extra low tone' },
  { text: "a+&_", code: "u148c", name: 'Nasal short a with low tone' },
  { text: "a+&^^", code: "u1488", name: 'Nasal short a with extra high tone' },
  { text: "a+&^", code: "u1484", name: 'Nasal short a with high tone' },
  { text: "a+&", code: "u1480", name: 'Nasal short a' },
  { text: "(a+&__)", code: "u1491", name: 'Nasal short a with extra low tone and stress' },
  { text: "(a+&_)", code: "u148d", name: 'Nasal short a with low tone and stress' },
  { text: "(a+&^^)", code: "u1489", name: 'Nasal short a with extra high tone and stress' },
  { text: "(a+&^)", code: "u1485", name: 'Nasal short a with high tone and stress' },
  { text: "(a+&)", code: "u1481", name: 'Nasal short a with stress' },

  { text: "a+__", code: "u149a", name: 'Short a with extra low tone' },
  { text: "a+_", code: "u03b4", name: 'Short a with low tone' },
  { text: "a+^^", code: "u149e", name: 'Short a with extra high tone' },
  { text: "a+^", code: "u03b8", name: 'Short a with high tone' },
  { text: "a+", code: "u03b0", name: 'Short a' },
  { text: "(a+__)", code: "u149b", name: 'Short a with extra low tone and stress' },
  { text: "(a+_)", code: "u03b5", name: 'Short a with low tone and stress' },
  { text: "(a+^^)", code: "u149f", name: 'Short a with extra high tone and stress' },
  { text: "(a+^)", code: "u03b9", name: 'Short a with high tone and stress' },
  { text: "(a+)", code: "u03b2", name: 'Short a with stress' },

  { text: "a&__", code: "u1590", name: 'Nasal a sound with extra low tone' },
  { text: "a&_", code: "u1582", name: 'Nasal a sound with low tone' },
  { text: "a&^^", code: "u158e", name: 'Nasal a sound with extra high tone' },
  { text: "a&^", code: "u158a", name: 'Nasal a sound with high tone' },
  { text: "a&", code: "u1586", name: 'Nasal a sound' },
  { text: "(a&__)", code: "u1591", name: 'Nasal a sound with extra low tone and stress' },
  { text: "(a&_)", code: "u1583", name: 'Nasal a sound with low tone and stress' },
  { text: "(a&^^)", code: "u158f", name: 'Nasal a sound with extra high tone and stress' },
  { text: "(a&^)", code: "u158b", name: 'Nasal a sound with high tone and stress' },
  { text: "(a&)", code: "u1587", name: 'Nasal a sound with stress' },

  { text: "a__", code: "u159a", name: 'A sound with extra low tone' },
  { text: "a_", code: "u0504", name: 'A sound with low tone' },
  { text: "a^^", code: "u159e", name: 'A sound with extra high tone' },
  { text: "a^", code: "u0508", name: 'A sound with high tone' },
  { text: "a", code: "u0500", name: 'A sound' },
  { text: "(a__)", code: "u159b", name: 'A sound with extra low tone and stress' },
  { text: "(a_)", code: "u0505", name: 'A sound with low tone and stress' },
  { text: "(a^^)", code: "u159f", name: 'A sound with extra high tone and stress' },
  { text: "(a^)", code: "u0509", name: 'A sound with high tone and stress' },
  { text: "(a)", code: "u0502", name: 'A sound with stress' },

  { text: "o~&__", code: "u1450", name: 'Nasal German o with extra low tone' },
  { text: "o~&_", code: "u1442", name: 'Nasal German o with low tone' },
  { text: "o~&^^", code: "u144e", name: 'Nasal German o with extra high tone' },
  { text: "o~&^", code: "u144a", name: 'Nasal German o with high tone' },
  { text: "o~&", code: "u1446", name: 'Nasal German o' },
  { text: "(o~&__)", code: "u1451", name: 'Nasal German o with extra low tone and stress' },
  { text: "(o~&_)", code: "u1443", name: 'Nasal German o with low tone and stress' },
  { text: "(o~&^^)", code: "u144f", name: 'Nasal German o with extra high tone and stress' },
  { text: "(o~&^)", code: "u144b", name: 'Nasal German o with high tone and stress' },
  { text: "(o~&)", code: "u1447", name: 'Nasal German o with stress' },

  { text: "o~__", code: "u145a", name: 'German o with extra low tone' },
  { text: "o~_", code: "u0394", name: 'German o with low tone' },
  { text: "o~^^", code: "u145e", name: 'German o with extra high tone' },
  { text: "o~^", code: "u0398", name: 'German o with high tone' },
  { text: "o~", code: "u0390", name: 'German o' },
  { text: "(o~__)", code: "u145b", name: 'German o with extra low tone and stress' },
  { text: "(o~_)", code: "u0395", name: 'German o with low tone and stress' },
  { text: "(o~^^)", code: "u145f", name: 'German o with extra high tone and stress' },
  { text: "(o~^)", code: "u0399", name: 'German o with high tone and stress' },
  { text: "(o~)", code: "u0392", name: 'German o with stress' },

  { text: "o+&__", code: "u1550", name: 'Nasal short o with extra low tone' },
  { text: "o+&_", code: "u1542", name: 'Nasal short o with low tone' },
  { text: "o+&^^", code: "u154e", name: 'Nasal short o with extra high tone' },
  { text: "o+&^", code: "u154a", name: 'Nasal short o with high tone' },
  { text: "o+&", code: "u1546", name: 'Nasal short o' },
  { text: "(o+&__)", code: "u1551", name: 'Nasal short o with extra low tone and stress' },
  { text: "(o+&_)", code: "u1543", name: 'Nasal short o with low tone and stress' },
  { text: "(o+&^^)", code: "u154f", name: 'Nasal short o with extra high tone and stress' },
  { text: "(o+&^)", code: "u154b", name: 'Nasal short o with high tone and stress' },
  { text: "(o+&)", code: "u1547", name: 'Nasal short o stress' },

  { text: "o+__", code: "u155a", name: 'Short o with extra low tone' },
  { text: "o+_", code: "u04c4", name: 'Short o with low tone' },
  { text: "o+^^", code: "u155e", name: 'Short o with extra high tone' },
  { text: "o+^", code: "u04c8", name: 'Short o with high tone' },
  { text: "o+", code: "u04c0", name: 'Short o' },
  { text: "(o+__)", code: "u155b", name: 'Short o with extra low tone and stress' },
  { text: "(o+_)", code: "u04c5", name: 'Short o with low tone and stress' },
  { text: "(o+^^)", code: "u155f", name: 'Short o with extra high tone and stress' },
  { text: "(o+^)", code: "u04c9", name: 'Short o with high tone and stress' },
  { text: "(o+)", code: "u04c2", name: 'Short o stress' },

  { text: "o&__", code: "u1570", name: 'Nasal o sound with extra low tone' },
  { text: "o&_", code: "u1562", name: 'Nasal o sound with low tone' },
  { text: "o&^^", code: "u156e", name: 'Nasal o sound with extra high tone' },
  { text: "o&^", code: "u156a", name: 'Nasal o sound with high tone' },
  { text: "o&", code: "u1566", name: 'Nasal o sound' },
  { text: "(o&__)", code: "u1571", name: 'Nasal o sound with extra low tone and stress' },
  { text: "(o&_)", code: "u1563", name: 'Nasal o sound with low tone and stress' },
  { text: "(o&^^)", code: "u156f", name: 'Nasal o sound with extra high tone and stress' },
  { text: "(o&^)", code: "u156b", name: 'Nasal o sound with high tone and stress' },
  { text: "(o&)", code: "u1567", name: 'Nasal o sound with stress' },

  { text: "o__", code: "u157a", name: 'O sound with extra low tone' },
  { text: "o_", code: "u04e4", name: 'O sound with low tone' },
  { text: "o^^", code: "u157e", name: 'O sound with extra high tone' },
  { text: "o^", code: "u04e8", name: 'O sound with high tone' },
  { text: "o", code: "u04e0", name: 'O sound' },
  { text: "(o__)", code: "u157b", name: 'O sound with extra low tone and stress' },
  { text: "(o_)", code: "u04e5", name: 'O sound with low tone and stress' },
  { text: "(o^^)", code: "u157f", name: 'O sound with extra high tone and stress' },
  { text: "(o^)", code: "u04e9", name: 'O sound with high tone and stress' },
  { text: "(o)", code: "u04e2", name: 'O sound with stress' },

  { text: "u+&__", code: "u15b0", name: 'Nasal short u with extra low tone' },
  { text: "u+&_", code: "u15a2", name: 'Nasal short u with low tone' },
  { text: "u+&^^", code: "u15ae", name: 'Nasal short u with extra high tone' },
  { text: "u+&^", code: "u15aa", name: 'Nasal short u with high tone' },
  { text: "u+&", code: "u15a6", name: 'Nasal short u' },
  { text: "(u+&__)", code: "u15b1", name: 'Nasal short u with extra low tone and stress' },
  { text: "(u+&_)", code: "u15a3", name: 'Nasal short u with low tone and stress' },
  { text: "(u+&^^)", code: "u15af", name: 'Nasal short u with extra high tone and stress' },
  { text: "(u+&^)", code: "u15ab", name: 'Nasal short u with high tone and stress' },
  { text: "(u+&)", code: "u15a7", name: 'Nasal short u with stress' },

  { text: "u+__", code: "u15ba", name: 'Short u with extra low tone' },
  { text: "u+_", code: "u04a4", name: 'Short u with low tone' },
  { text: "u+^^", code: "u15be", name: 'Short u with extra high tone' },
  { text: "u+^", code: "u04a8", name: 'Short u with high tone' },
  { text: "u+", code: "u04a0", name: 'Short u' },
  { text: "(u+__)", code: "u15bb", name: 'Short u with extra low tone and stress' },
  { text: "(u+_)", code: "u04a5", name: 'Short u with low tone and stress' },
  { text: "(u+^^)", code: "u15bf", name: 'Short u with extra high tone and stress' },
  { text: "(u+^)", code: "u04a9", name: 'Short u with high tone and stress' },
  { text: "(u+)", code: "u04a2", name: 'Short u with stress' },

  { text: "u&__", code: "u14b0", name: 'Nasal u sound with extra low tone' },
  { text: "u&_", code: "u14a2", name: 'Nasal u sound with low tone' },
  { text: "u&^^", code: "u14ae", name: 'Nasal u sound with extra high tone' },
  { text: "u&^", code: "u14aa", name: 'Nasal u sound with high tone' },
  { text: "u&", code: "u14a6", name: 'Nasal u sound' },
  { text: "(u&__)", code: "u14b1", name: 'Nasal u sound with extra low tone and stress' },
  { text: "(u&_)", code: "u14a3", name: 'Nasal u sound with low tone and stress' },
  { text: "(u&^^)", code: "u14af", name: 'Nasal u sound with extra high tone and stress' },
  { text: "(u&^)", code: "u14ab", name: 'Nasal u sound with high tone and stress' },
  { text: "(u&)", code: "u14a7", name: 'Nasal u sound with stress' },

  { text: "u__", code: "u14ba", name: 'U sound with extra low tone' },
  { text: "u_", code: "u03f4", name: 'U sound with low tone' },
  { text: "u^^", code: "u14be", name: 'U sound with extra high tone' },
  { text: "u^", code: "u03f8", name: 'U sound with high tone' },
  { text: "u", code: "u03f0", name: 'U sound' },
  { text: "(u__)", code: "u14bb", name: 'U sound with extra low tone and stress' },
  { text: "(u_)", code: "u03f5", name: 'U sound with low tone and stress' },
  { text: "(u^^)", code: "u14bf", name: 'U sound with extra high tone and stress' },
  { text: "(u^)", code: "u03f9", name: 'U sound with high tone and stress' },
  { text: "(u)", code: "u03f2", name: 'U sound with stress' },

  { text: "m+", code: "u0102", name: 'M sound with nasal quality' },
  { text: "m", code: "u0100", name: 'M sound' },
  { text: "n+", code: "u0142", name: 'Indian n sound' },
  { text: "n", code: "u0140", name: 'N sound' },
  { text: "q", code: "u0160", name: 'Ng sound' },
  { text: "g?", code: "u0138", name: 'Implosive g sound' },
  { text: "g.", code: "u135a", name: 'Stop g sound' },
  { text: "g@", code: "u1357", name: 'Tense g sound' },
  { text: "g", code: "u0130", name: 'G sound' },
  { text: "'", code: "u01b0", name: 'Lack of sound, glottal stop' },
  { text: """, code: "u01b2", name: 'Arabic voiced pharyngeal fricative' },
  { text: "d~", code: "u00d1", name: 'Arabic d sound' },
  { text: "d!", code: "u006c", name: 'Ejective d sound' },
  { text: "d?", code: "u0068", name: 'Implosive d sound' },
  { text: "d*", code: "u0064", name: 'Click d sound' },
  { text: "d+", code: "u0062", name: 'Indian d sound' },
  { text: "d.", code: "u123a", name: 'Stop d sound' },
  { text: "d@", code: "u1237", name: 'Tense d sound' },
  { text: "d", code: "u0060", name: 'D sound' },
  { text: "b?", code: "u0048", name: 'Implosive b sound' },
  { text: "b!", code: "u004c", name: 'Ejective b sound' },
  { text: "b.", code: "u121a", name: 'Stop b sound' },
  { text: "b@", code: "u1217", name: 'Tense b sound' },
  { text: "b", code: "u0040", name: 'B sound' },
  { text: "p!", code: "u0038", name: 'Ejective p sound' },
  { text: "p*", code: "u0034", name: 'Click p sound' },
  { text: "p.", code: "u120a", name: 'Stop p sound' },
  { text: "p@", code: "u1207", name: 'Tense p sound' },
  { text: "p", code: "u0030", name: 'P sound' },
  { text: "t+", code: "u00d2", name: 'Indian t sound' },
  { text: "t!", code: "u00dc", name: 'Ejective t sound' },
  { text: "t~", code: "u00d1", name: 'Arabic t sound' },
  { text: "t*", code: "u00d4", name: 'Click t sound' },
  { text: "t.", code: "u129a", name: 'Stop t sound' },
  { text: "t@", code: "u1297", name: 'Tense t sound' },
  { text: "t", code: "u00d0", name: 'T sound' },
  { text: "k!", code: "u0058", name: 'Ejective k sound' },
  { text: "k*", code: "u0054", name: 'Click k sound' },
  { text: "k+", code: "u0052", name: 'Arabic Q sound' },
  { text: "k+!", code: "u0059", name: 'Arabic ejective Q sound' },
  { text: "k.", code: "u122a", name: 'Stop k sound' },
  { text: "k@", code: "u1227", name: 'Tense k sound' },
  { text: "k", code: "u0050", name: 'K sound' },
  { text: "h+", code: "u0122", name: 'Hebrew harsh h sound' },
  { text: "h~", code: "u0121", name: 'Arabic h sound' },
  { text: "h", code: "u0120", name: 'H sound' },
  { text: "j+", code: "u0152", name: 'Indian j sound' },
  { text: "j", code: "u0150", name: 'J sound' },
  { text: "s+", code: "u0072", name: 'Navajo s sound' },
  { text: "s~", code: "u0071", name: 'Arabic s sound' },
  { text: "s.", code: "u124a", name: 'Stop s sound' },
  { text: "s@", code: "u1247", name: 'Tense s sound' },
  { text: "s", code: "u0070", name: 'S sound' },
  { text: "f+", code: "u00c2", name: 'Labial f sound' },
  { text: "f", code: "u00c0", name: 'f sound' },
  { text: "v+", code: "u00f2", name: 'Labial v sound' },
  { text: "v~", code: "u00f1", name: 'Other v sound' },
  { text: "v", code: "u00f0", name: 'V sound' },
  { text: "z+", code: "u0092", name: 'Zulu dl sound' },
  { text: "z", code: "u0090", name: 'Z sound' },
  { text: "c+~", code: "u00b2", name: 'Arabic voiced th sound' },
  { text: "c+", code: "u00b0", name: 'Voiced th sound' },
  { text: "c", code: "u0080", name: 'Unvoiced th sound' },
  { text: "l+", code: "u0172", name: 'Indian l sound' },
  { text: "l*", code: "u0174", name: 'Click l sound' },
  { text: "l~", code: "u0171", name: 'Arabic l sound' },
  { text: "l", code: "u0170", name: 'L sound' },
  { text: "r~", code: "u01a2", name: 'French r sound' },
  { text: "r+", code: "u00e2", name: 'Indian r sound' },
  { text: "r!", code: "u00e0", name: 'Single rolling r sound' },
  { text: "r", code: "u01a0", name: 'English r sound' },
  { text: "x+", code: "u0192", name: 'Indian sh sound' },
  { text: "x.", code: "u141a", name: 'Stop sh sound' },
  { text: "x@", code: "u1417", name: 'Tense sh sound' },
  { text: "x", code: "u0190", name: 'Sh sound' },
  { text: "w", code: "u0110", name: 'W sound' },
  { text: "y", code: "u0180", name: 'Y sound' },
  { text: "y+", code: "u0182", name: 'Slight y sound' },
  { text: " ", code: "u0020", name: 'Hanakana Space' },
  { text: ".", code: "u0021", name: 'Hanakana Period' },
  { text: ",", code: "u0024", name: 'Hanakana comma' },
  { text: "(", code: "u0023", name: 'Hanakana opening parenthesis' },
  { text: ")", code: "u002b", name: 'Hanakana closing parenthesis' },
  { text: "(", code: "u0026", name: 'Hanakana opening bracket' },
  { text: ")", code: "u0027", name: 'Hanakana closing bracket' },
  { text: "|", code: "u0025", name: 'Hanakana pipe' },
  { text: "#", code: "u0028", name: 'Hanakana at sign' },
  { text: "/", code: "u0029", name: 'Hanakana forward slash' },
  { text: "\", code: "u002a", name: 'Hanakana backward slash' },
  { text: ":", code: "u0022", name: 'Hanakana colon' }
)

const look = {}
list.forEach(({ text }) => {
  look(text) = '^' + text.replace(/(()*!?^+_.()|\/)/g, _ => `\${_}`)
})

const form = text => {
  let remaining = text.replace(/((A-Z))/g, (_, $1) => `${$1.toLowerCase()}+`)
  let output = ()
  a:
  while (remaining.length) {
    for (let node of list) {
      const pattern = look(node.text)
      const regex = new RegExp(pattern)
      const match = remaining.match(regex)
      if (match) {
        const val = node.code
        output.push(val)
        remaining = remaining.substr(match(0).length)
        continue a
      }
    }
    throw new Error(`${remaining}:${text}`)
  }
  return output.join('')
}

console.log(form('asdf'))
console.log(form('helloworld'))

Given I would like to specify the patterns in this list object, how can I perhaps compile them and/or optimize the main form function which converts input to output?

pattern matching – What sorts of expressions can be Solve’d for?

We can Solve for expressions that match _Symbol, as in Solve(x^2+1 == 0, x)—but we can also solve for more general expressions, such as x(1) (Solve(x(1)^2+1 == 0, x(1))) and Subscripts (Solve(Subscript(x, 1)^2+1 == 0, Subscript(x, 1))). However, not every expression can be a variable for Solve: Solve("a"^2+1 == 0, "a") returns the Solve::ivar error message, saying that "a" is not a valid variable.

So, what makes an expression a “valid variable” in the sense of Solve internally?

Is it related to what expressions can hold definitions, or is that a separate question?

A workaround can be obtained, in a similar manner to this question, by testing a simple Solve for the error message directly:

VariableQ(expr_) := 
 Quiet(Check(Solve(True, expr); True, False, {Solve::ivar}), {Solve::ivar})

but I’d like to understand the logic behind what is or isn’t a valid variable.

haskell – State monad and pattern matching on data constructors

I am writing a Settlers of Catan server in Haskell for fun. Currently I am passing around state manually. I want to learn more about the State monad and want to incorporate it into my project.

However, my GameState has multiple data constructors that I pattern match on to yield different functionality. Three of such data constructors are for the WaitingLobby (when people can still join over the internet), the SetupPhase (before the game has really started and people have to build their initial settlements), and one for the RunningGame (when you can play the game turn by turn normally). Code:

data GameState = WaitingLobby ... | SetupPhase ... | RunningGame ...

Lots of functions pattern match on the type of data constructor used. For example the function that handles building a settlement after it has been decided that the player is indeed allowed to do so:

doConstructBuilding :: GameState -> Building -> VertexCoordinate -> GameState 
doConstructBuilding gs@(SetupPhase _ _ board _ _ _) building coord          = gs { board = placeBuilding building coord board,
                                                                                   _placedSettlement = True }
doConstructBuilding gs@(RunningGame playerList cur board _) building coord  = gs { board = placeBuilding building coord board, 
                                                                                   playerList = map payIfCur playerList}
                                    where payIfCur p | cur == playerId p = playerPays p $ constructionCost building
                                                     | otherwise         = p

So the different GameState dataconstructors have different implementations: In the SetupPhase the building is placed and it is noted that the player has placed a settlement in the state, while in the RunningGame the building is also placed, but here the player also pays resources for it.

The question: My understanding is that with the state monad you only pull out the state once you’re in the monadic context on the right side of the =. So How would I implement something like this?

Note: Maybe there are other solutions for this particular method, but I have a lot of these data constructor pattern match cases.