Problem:
Boolean Expression Compressor
You are asked to build a compressor for Boolean expressions
that transforms expressions to the shortest form keeping their meaning.
The grammar of the Boolean expressions has terminals
0
1
a
b
c
d
-
^
*
(
)
, start symbol <E> and the following production rule:
<E>  ::=
0
|
1
|
a
|
b
|
c
|
d
|
-
<E>  |
(
<E>
^
<E>
)
|
(
<E>
*
<E>
)
Letters
a
,
b
,
c
and
d
represent Boolean
variables that have values of either
0
or
1
.
Operators are evaluated as shown in the Table below.
In other words,
-
means negation (NOT),
^
means exclusive disjunction (XOR), and
*
means logical conjunction (AND).
Table: Evaluations of operators
Write a program that calculates the length of the shortest expression that
evaluates equal to the given expression with whatever values of the four variables.
For example,
0
, that is the first expression in the sample input,
cannot be shortened further.
Therefore the shortest length for this expression is 1.
For another example,
(a*(1*b))
, the second in the sample input,
always evaluates equal to
(a*b)
and
(b*a)
,
which are the shortest.   The output for this expression, thus, should be
5
.
Input
The input consists of multiple datasets.
A dataset consists of one line, containing an expression
conforming to the grammar described above.
The length of the expression is less than or equal to 16 characters.
The end of the input is indicated by a line containing one

.
 (period).
The number of datasets in the input is at most 200.
Output
For each dataset, 
output a single line containing an integer which is the length of the
shortest expression that has the same value as the given expression for 
all combinations of values in the variables.
Sample Input
0
(a*(1*b))
(1^a)
(-(-a*-b)*a)
(a^(b^(c^d)))
.
Output for the Sample Input
1
5
2
1
13

Submitted solutions:

code_snippet: #include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<cstring>
using namespace std;

const int N = 16;

char S[N + 2];
int T[N + 2], p;
map<char, int> M;
const char *al = "abcd";
const char *nu = "01";
const char *st = "^*";

vector<vector<char>> V[N + 2];

int get(vector<char> &s)
{
	if (strchr(nu, s[p]))
		return s[p++] - '0';
	if (strchr(al, s[p]))
		return M[s[p++]];
	if (s[p] == '-')
	{
		p++;
		return 1 ^ get(s);
	}
	p++;
	int l = get(s);
	int t = p++;
	int r = get(s);
	p++;
	if (s[t] == '^')
		return l^r;
	else
		return l&r;
}

int get(char *s)
{
	if (strchr(nu, s[p]))
		return s[p++] - '0';
	if (strchr(al, s[p]))
		return M[s[p++]];
	if (s[p] == '-')
	{
		p++;
		return 1 ^ get(s);
	}
	p++;
	int l = get(s);
	int t = p++;
	int r = get(s);
	p++;
	if (s[t] == '^')
		return l^r;
	else
		return l&r;
}

void init(int k)
{
	if (k == 1)
	{
		for (int i = 0; i < 4; i++)
			V[k].push_back({ al[i] });
		for (int i = 0; i < 2; i++)
			V[k].push_back({ nu[i] });
	}
	if (k >= 2)
	{
		for (auto &t : V[k - 1])
		{
			V[k].push_back({ '-' });
			vector<char> &v = V[k].back();
			v.insert(v.end(), t.begin(), t.end());
		}
	}
	if (k >= 3)
	{
		for (int i = 1, j = k - 3 - 1; i < k - 3; i++, j--)
		{
			for (auto &t : V[i])
				for (auto &t2 : V[j])
				{
					for (int l = 0; l < 2; l++)
					{
						V[k].push_back({ '(' });
						vector<char> &v = V[k].back();
						v.insert(v.end(), t.begin(), t.end());
						v.push_back(st[l]);
						v.insert(v.end(), t2.begin(), t2.end());
						v.push_back(')');
					}
				}
		}
	}
	//for (auto &v : V[k])
	//{
	//	for (auto &c : v)
	//		printf("%c", c);
	//	printf("\n");
	//	printf("k=%d\n", k);
	//}
}

int main()
{
	for (int i = 1; i < N; i++)
	{
		init(i);
		//printf("i=%d\n", i);
	}
	for (; scanf("%s", S) && S[0] != '.'; )
	{
		for (int t = 0; t < 1 << 4; t++)
		{
			for (int l = 0; l < 4; l++)
				M[al[l]] = t >> l & 1;
			p = 0;
			T[t] = get(S);
			//printf("t=%d\n", t);
		}
		//printf("A\n");
		int ans = 1;
		for (; ans < 16; ans++)
		{
			bool ok = false;
			for (auto &v : V[ans])
			{
				bool all = true;
				for (int t = 0; t < 1 << 4; t++)
				{
					for (int l = 0; l < 4; l++)
						M[al[l]] = t >> l & 1;
					p = 0;
					all &= T[t] == get(v);
					if (!all)
						break;
				}
				if (all)
				{
					ok = true;
					break;
				}
			}
			if (ok)
				break;
			//printf("nowans=%d\n", ans);
		}
		printf("%d\n", ans);
	}
}

/*


*/
accuracy: 1
time_ms: 2900
memory_kb: 166396
final_rank: 20

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

// #ifndef ONLINE_JUDGE
// #define _GLIBCXX_DEBUG // 配列外参照のエラー
// #endif

// スタンダードライブラリ
#include <bits/stdc++.h>
using namespace std;

// 型関連
using ll = long long;
using lint = long long;
using pll = pair<ll, ll>;
using plll = tuple<ll, ll, ll>;
using pii = pair<int, int>;
using piii = tuple<ll, ll, ll>;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vvvvi = vector<vector<vector<vector<int>>>>;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
using vvvl = vector<vector<vector<ll>>>;
using vvvvl = vector<vector<vector<vector<ll>>>>;

template <class T> using prique = priority_queue<T>;

// 型定数
constexpr ll mod = 998244353;
constexpr ll MOD = 1000000007;
int INF32 = 2e9;
ll INF64 = 9e18;
#define endl '\n';

int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

/////////////////////////// print関連
template <typename T> void print(vector<T> A);
void print();
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail);
void print(string S);
template <typename T> void print(vector<vector<T>> &F);

inline void Yes(bool f);


int get_val(string &S, vi &V) {
    int idx=0;
    auto E = [&](auto E) -> int {
        if (S[idx] == '0' || S[idx] == '1') {
            idx++;
            return S[idx-1] - '0';
        }
        if (S[idx] == 'a' || S[idx] == 'b' || S[idx] == 'c' || S[idx] == 'd') {
            idx++;
            return V[S[idx-1]-'a'];
        }
        if (S[idx] == '-') {
            idx++;
            int nval = E(E);
            return (1^nval);
        }
        idx++;
        int left = E(E);
        char op = S[idx];
        idx++;
        int right = E(E);
        idx++;
        if (op == '*') {
            return (left & right);
        }
        return (left ^ right);
    };

    return E(E);
}

bool is_sameST(string S, string T) {

    

    for (int B = 0; B < (1 << 4); B++) {
        vi V(4);
        for (int i = 0; i < 4; i++) {
            if (B & (1 << i)) {
                V[i]=1;
            }
        }
        if (get_val(S, V) != get_val(T, V)) {
            return false;
        }
    }
    return true;
}

///////////////////ここから//////////////////////
bool solve(vector<vector<string>> &Logical) {
    string S;
    cin >> S;
    if (S == ".")
        return false;
    int N = S.size();

    
    for (int i = 1; i < N; i++) {
        for (auto l : Logical[i]) {
            if (is_sameST(S, l)) {
                print(i);
                return true;
            }
        }
    }
    print(N);

    return true;
}

int main() {
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int N=15;
    vector<vector<string>> Logical(N + 1);
    Logical[1] = {"a", "b", "c", "d", "0", "1"};

    for (int i = 2; i < N + 1; i++) {
        for (auto l : Logical[i - 1]) {
            Logical[i].push_back("-" + l);
        }
        for (int j = 1; j < i - 3; j++) {
            for (auto l1 : Logical[j]) {
                for (auto l2 : Logical[i - 3 - j]) {
                    Logical[i].push_back("(" + l1 + "*" + l2 + ")");
                    Logical[i].push_back("(" + l1 + "^" + l2 + ")");
                }
            }
        }
    }
    while (solve(Logical))
        ;
}

////////////////////print/////////////////////////
// 1次元ベクトルを出力する
template <typename T> void print(vector<T> A) {
    if (A.size() == 0) {
        return;
    }
    for (size_t i = 0; i < A.size() - 1; i++) {
        cout << A[i] << ' ';
    }
    cout << A[A.size() - 1] << endl;
    return;
}

// 2次元ベクトルを出力する
template <typename T> void print(vector<vector<T>> &F) {
    for (size_t i = 0; i < F.size(); i++) {
        for (size_t j = 0; j < F[i].size(); j++) {
            cout << F[i][j];
            if (j < F[i].size() - 1) {
                cout << ' ';
            }
        }
        cout << endl;
    }
}

// 空白行を出力するprint
void print() { cout << endl; }

// 数値・文字列を空白区切りで出力する. print(a,b)など
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    cout << head;
    if (sizeof...(tail) != 0)
        cout << " ";
    print(forward<Tail>(tail)...);
}

void print(string S) { cout << S << endl; }

//////////////出力関連

inline void Yes(bool f) {
    if (f) {
        cout << "Yes" << endl;
    } else {
        cout << "No" << endl;
    }
}
accuracy: 1
time_ms: 1370
memory_kb: 98536
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;

using ll =long long;


ll a=0,b=0,c=0,d=0;
ll eval(string S){
    if(S=="a"){
        return a;
    }
    else if(S=="b"){
        return b;
    }
    else if(S=="c"){
        return c;
    }
    else if(S=="d"){
        return d;
    }
    else if(S=="0"){
        return 0;
    }
    else if(S=="1"){
        return (1<<16)-1;
    }
    else if(S[0]=='-'){
        return (1<<16)-1-eval(S.substr(1,S.size()-1));
    }
    else{
        ll k=0;
        for(ll i=1;i<S.size();i++){
            if(S[i]=='(')k++;
            else if(S[i]==')')k--;
            else if(S[i]=='*'&&k==0){
                return eval(S.substr(1,i-1))&eval(S.substr(i+1,S.size()-i-2));
            }
            else if(S[i]=='^'&&k==0){
                return eval(S.substr(1,i-1))^eval(S.substr(i+1,S.size()-i-2));
            }
        }
    }
    return 0;
}

map<ll,ll> AN;


void init(){
    for(int i=0;i<16;i++){
        a*=2;
        b*=2;
        c*=2;
        d*=2;
        if(i%16<8)a++;
        if(i%8<4)b++;
        if(i%4<2)c++;
        if(i%2<1)d++;
    }

    priority_queue<pair<ll,string>,vector<pair<ll,string>>,greater<pair<ll,string>>> Q;
    Q.push({1,"0"});
    Q.push({1,"1"});
    Q.push({1,"a"});
    Q.push({1,"b"});
    Q.push({1,"c"});
    Q.push({1,"d"});
    // AN[eval("0")]=1;
    // AN[eval("1")]=1;
    // AN[eval("a")]=1;
    // AN[eval("b")]=1;
    // AN[eval("c")]=1;
    // AN[eval("d")]=1;
    set<string> seen;
    ll MX=15;
    while(!Q.empty()){
        auto [n,s]=Q.top();
        Q.pop();
        // cout<<AN.size()<<endl;
        if(seen.count(s))continue;
        seen.insert(s);
        if(AN.count(eval(s)))continue;
        AN[eval(s)]=n;
        string ns="-"+s;
        if(!AN.count(eval(ns))&&ns.size()<15){
            Q.push({ns.size(),ns});
        }
        for(auto ss:seen){
            ns="("+ss+"^"+s+")";
            if(!AN.count(eval(ns))&&ns.size()<15){
                Q.push({ns.size(),ns});
            }
            ns="("+ss+"*"+s+")";
            if(!AN.count(eval(ns))&&ns.size()<15){
                Q.push({ns.size(),ns});
            }
            ns="("+s+"^"+ss+")";
            if(!AN.count(eval(ns))&&ns.size()<15){
                Q.push({ns.size(),ns});
            }
            ns="("+s+"*"+ss+")";
            if(!AN.count(eval(ns))&&ns.size()<15){
                Q.push({ns.size(),ns});
            }
        }
    }
}


void solve(string S){
    if(!AN.count(eval(S))){
        AN[eval(S)]=S.size();
    }
    cout<<AN[eval(S)]<<"\n";
}


int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    init();

    string S;
    while(cin>>S,S!=".")solve(S);
}
accuracy: 1
time_ms: 3730
memory_kb: 4264
final_rank: 19

code_snippet: #pragma region Macros
#include <bits/stdc++.h>

#include <atcoder/all>
using namespace std;
using namespace atcoder;
using lint = long long;
using mint = modint998244353;
using ull = unsigned long long;
using ld = long double;
using int128 = __int128_t;
#define all(x) (x).begin(), (x).end()
#define EPS 1e-8
#define uniqv(v) v.erase(unique(all(v)), v.end())
#define OVERLOAD_REP(_1, _2, _3, name, ...) name
#define REP1(i, n) for (auto i = std::decay_t<decltype(n)>{}; (i) != (n); ++(i))
#define REP2(i, l, r) for (auto i = (l); (i) != (r); ++(i))
#define rep(...) OVERLOAD_REP(__VA_ARGS__, REP2, REP1)(__VA_ARGS__)
#define log(x) cout << x << endl
#define logfixed(x) cout << fixed << setprecision(10) << x << endl;
#define logy(bool)         \
  if (bool) {              \
    cout << "Yes" << endl; \
  } else {                 \
    cout << "No" << endl;  \
  }

ostream &operator<<(ostream &dest, __int128_t value) {
  ostream::sentry s(dest);
  if (s) {
    __uint128_t tmp = value < 0 ? -value : value;
    char buffer[128];
    char *d = end(buffer);
    do {
      --d;
      *d = "0123456789"[tmp % 10];
      tmp /= 10;
    } while (tmp != 0);
    if (value < 0) {
      --d;
      *d = '-';
    }
    int len = end(buffer) - d;
    if (dest.rdbuf()->sputn(d, len) != len) {
      dest.setstate(ios_base::badbit);
    }
  }
  return dest;
}

template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (int i = 0; i < (int)v.size(); i++) {
    os << v[i] << (i + 1 != (int)v.size() ? " " : "");
  }
  return os;
}

template <typename T>
ostream &operator<<(ostream &os, const set<T> &set_var) {
  for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
    os << *itr;
    ++itr;
    if (itr != set_var.end()) os << " ";
    itr--;
  }
  return os;
}

template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
  for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
    os << itr->first << " -> " << itr->second << "\n";
  }
  return os;
}

template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &pair_var) {
  os << "(" << pair_var.first << ", " << pair_var.second << ")";
  return os;
}

void out() { cout << '\n'; }
template <class T, class... Ts>
void out(const T &a, const Ts &...b) {
  cout << a;
  (cout << ... << (cout << ' ', b));
  cout << '\n';
}

template <typename T>
istream &operator>>(istream &is, vector<T> &v) {
  for (T &in : v) is >> in;
  return is;
}

inline void in(void) { return; }
template <typename First, typename... Rest>
void in(First &first, Rest &...rest) {
  cin >> first;
  in(rest...);
  return;
}

template <typename T>
bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T>
bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

vector<lint> dx8 = {1, 1, 0, -1, -1, -1, 0, 1};
vector<lint> dy8 = {0, 1, 1, 1, 0, -1, -1, -1};
vector<lint> dx4 = {1, 0, -1, 0};
vector<lint> dy4 = {0, 1, 0, -1};

#pragma endregion

bool operate(bool A, char c, bool B) {
  if (c == '^') return A ^ B;
  if (c == '*') return A & B;
  return 1;
}

bool eval(string s, bool a, bool b, bool c, bool d) {
  // cout << s << endl;
  int l = s.size();
  if (s == "0") return 0;
  if (s == "1") return 1;
  if (s == "a") return a;
  if (s == "b") return b;
  if (s == "c") return c;
  if (s == "d") return d;

  // is (E*F) or 1 or 0
  if (s[0] == '(' && s[l - 1] == ')') {
    int x = 0;
    int op;
    bool L, R;
    for (int p = 1; p < l; ++p) {
      if (s[p] == '(') x++;
      if (s[p] == ')') x--;
      if (x == 0 && s[p] != '-') {
        L = eval(s.substr(1, p), a, b, c, d);
        op = s[p + 1];
        R = eval(s.substr(p + 2, l - p - 3), a, b, c, d);
        return operate(L, op, R);
      }
    }
    assert(false);

  } else if (s[0] == '-') {
    return !eval(s.substr(1, l - 1), a, b, c, d);
  } else {
    assert(false);
  }
}

int main() {
  cin.tie(0)->sync_with_stdio(0);
  string s;

  vector<vector<string>> create(17, vector<string>());
  queue<string> que;

  create[1] = {"a", "b", "c", "d", "1", "0"};
  for (auto v : create[1]) {
    que.push(v);
  }

  auto hash = [&](string s) -> int {
    int h = 0;
    for (int bit = 0; bit < (1 << 4); ++bit) {
      int a = bit & 1, b = (bit >> 1) & 1;
      int c = (bit >> 2) & 1, d = (bit >> 3) & 1;
      h += (1 << bit) * (int)eval(s, a, b, c, d);
    }
    return h;
  };

  map<int, int> smallest;
  map<int, string> ans;
  for (auto v : create[1]) {
    smallest[hash(v)] = 1;
    ans[hash(v)] = v;
  }

  for (int size = 1; size <= 16; ++size)
    for (int pos = 0; pos < create[size].size(); ++pos) {
      string E = create[size][pos];
      // cout << E << endl;
      // -E
      if (1 + size <= 16) {
        string onew = "-" + E;
        if (!smallest.contains(hash(onew)) || smallest[hash(onew)] > 1 + size) {
          create[1 + size].push_back(onew);
          smallest[hash(onew)] = 1 + size;
          ans[hash(onew)] = onew;
        }
      }
      // (E op F)
      for (int i = 1; i <= size; ++i) {
        if (3 + size + i > 16) break;
        int new_size = 3 + size + i;
        for (auto F : create[i]) {
          string new1 = '(' + E + '^' + F + ')';
          string new2 = '(' + E + '*' + F + ')';
          if (!smallest.contains(hash(new1)) || smallest[hash(new1)] > new_size) {
            create[new_size].push_back(new1);
            smallest[hash(new1)] = new_size;
            ans[hash(new1)] = new1;
          }
          if (!smallest.contains(hash(new2)) || smallest[hash(new2)] > new_size) {
            create[new_size].push_back(new2);
            smallest[hash(new2)] = new_size;
            ans[hash(new2)] = new2;
          }
        }
      }
    }

  while (1) {
    in(s);
    if (s == ".") break;

    cout << smallest[hash(s)] << endl;
    // cout << ans[hash(s)] << endl;
  }
}
accuracy: 1
time_ms: 120
memory_kb: 4096
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef int ll;
typedef unsigned long long ull;
typedef long double ld;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rrep(i,start,end) for (ll i = start;i >= (ll)(end);i--)
#define repn(i,end) for(ll i = 0; i <= (ll)(end); i++)
#define reps(i,start,end) for(ll i = start; i < (ll)(end); i++)
#define repsn(i,start,end) for(ll i = start; i <= (ll)(end); i++)
#define each(p,a) for(auto &p:a)
typedef vector<ll> vll;
typedef vector<pair<ll ,ll>> vpll;
typedef vector<vector<ll>> vvll;
typedef set<ll> sll;
typedef map<ll , ll> mpll;
typedef pair<ll ,ll> pll;
typedef tuple<ll , ll , ll> tpl3;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
#define sz(x) (ll)x.size()
// << std::fixed << std::setprecision(10)
const ll INF = 1LL << 30;
const ld EPS = 1e-9;
 
ll lceil(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b)+1;}else{return -((-a)/b);}}
ll lfloor(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b);}else{return -((-a)/b)-1;}}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
//0indexed
inline ll topbit(ll a){assert(a != 0);return 63 - __builtin_clzll(a);}
inline ll smlbit(ll a){assert(a != 0);return __builtin_ctzll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T> std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<typename T1, typename T2>std::ostream &operator<< (std::ostream &os, std::pair<T1,T2> p){os << "{" << p.first << "," << p.second << "}";return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
template <class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v) e++;return v;}
template <class T> vector<T> operator++(vector<T> &v, signed) {auto res = v;for(auto &e : v) e++;return res;}
template <class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v) e--;return v;}
template <class T> vector<T> operator--(vector<T> &v, signed) {auto res = v;for(auto &e : v) e--;return res;}
//grid探索用
vector<ll> _ta = {0,0,1,-1,1,1,-1,-1};
vector<ll> _yo = {1,-1,0,0,1,-1,1,-1};
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
  
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;

typedef string::const_iterator State;

class ParseError {};
//プロトタイプ宣言
ll expression(State &begin);

struct node{
	char ch; // charがいいときもある
	vector<ll> to;
};
vector<node>nodes;

set<char> variable = {'0','1','a','b','c','d'};
//四則演算の式を構文解析し評価結果を返す。
ll expression(State &begin){
  if(variable.count(*begin)){
    ll ret = nodes.size();
    nodes.push_back({*begin,{}});
    begin++;
    return ret;
  }
  if(*begin== '-'){
    ll ret = nodes.size();
    nodes.push_back({'-',{}});
    begin++;
    ll nxt = expression(begin);
    nodes[ret].to.push_back(nxt);
    nodes[nxt].to.push_back(ret);
    return ret;
  }else if(*begin == '('){
    begin++;
    ll before = expression(begin);
    ll ret = nodes.size();
    assert(*begin == '^' or *begin == '*');
    nodes.push_back({*begin,{}});
    begin++;
    ll after = expression(begin);
    nodes[ret].to.push_back(before);
    nodes[ret].to.push_back(after);
    nodes[before].to.push_back(ret);
    nodes[after].to.push_back(ret);
    assert(*begin == ')');
    begin++;
    return ret;
  }
  return -1;
}

// map<string,pair<ll,vector<node>>>mp;

vector<ll>states(1LL<<16,INF);


ll dfs(vll&val,ll v,ll par){
  char c = nodes[v].ch;
  if(variable.count(c)){
    if(c== '0' or c == '1'){
      return c-'0';
    }else{
      return val[c-'a'];
    }
  }else if(c == '-'){
    vll tmp;
    each(p,nodes[v].to)if(p != par){
      tmp.push_back(dfs(val,p,v));
    }
    assert(sz(tmp) ==1);
    return !tmp[0];
  }else {
    assert(c == '*' or c == '^');
    vll tmp;
    each(p,nodes[v].to)if(p != par){
      tmp.push_back(dfs(val,p,v));
    }
    assert(sz(tmp) ==2);
    if(c == '*'){
      return tmp[0]&tmp[1];
    }else{
      return tmp[0]^tmp[1];
    }
  }
}

void solve(string s){
  nodes.clear();
  State begin = s.begin();
  ll root = expression(begin);
  assert(begin== s.end());
  vll val(4);
  // vector<ll> found(n,0);//n頂点

  ll nowstate = 0;
  rep(i,1<<4){
    rep(j,4){
      if(i >> j &1){
        val[j] = 1;
      }else{
        val[j] = 0;
      }
    }
    nowstate+=dfs(val,root,-1) << i;
  }

  // assert(states.count(nowstate));
  cout << min(states[nowstate],sz(s)) << endl;

}
 
int main(){
  ios::sync_with_stdio(false);cin.tie(nullptr);
  vector<vector<string>> sable(15);
  sable[0].push_back("a");
  sable[0].push_back("b");
  sable[0].push_back("c");
  sable[0].push_back("d");
  sable[0].push_back("0");
  sable[0].push_back("1");

  ll sablesiz = sz(sable[0]);
  ll rem = 1LL << 16;
  rep(i,15){
    // cerr << i << endl;
    if(rem == 0)break;
    if(i != 0){
      // - をつけるだけ
      each(p,sable[i-1])if(p[0] != '-' && p != "0" && p != "1"){
        sable[i].push_back(string('-'+p));
      }
      //演算
      // (u * v)
      // (u ^ v)
  
      if(i >=3){
        for(ll j = 1;i+1-j-3 >=1;j++){
          ll k = i+1 -3-j;
          // assert(k >= 1);
          each(p,sable[j-1]){
            each(q,sable[k-1]){
              if((p == "0" or p == "1") && (q== "0" or q == "1"))continue;
              sable[i].push_back('('+p+'*'+q+')');
              sable[i].push_back('('+p+'^'+q+')');
            }
          }
        }
      }
      sablesiz += sz(sable[i]);
    }

    vll val(4);
    each(s,sable[i]){
      // assert(sz(s) == i+1);
      State begin = s.begin();
      ll root = expression(begin);
      // mp[s] = {root,nodes};
      // assert(begin== s.end());

      ll state = 0;

      rep(i,1<<4){
        rep(j,4){
          if(i >> j &1){
            val[j] = 1;
          }else{
            val[j] = 0;
          }
        }
        state += dfs(val,root,-1) << i;
      }
      if(states[state] == INF){
        rem--;
      }
      chmin(states[state],i+1);
      nodes.clear();
    }
    
  }

  //   rep(i,6){
  //   each(p,sable[i]){
  //     cout << p << endl;
  //   }
  // }


  // cerr << sablesiz << endl;




  while(true){
    Str(s);
    if(s ==".")break;
    solve(s);
  }
}
accuracy: 1
time_ms: 2470
memory_kb: 50368
final_rank: 18

code_snippet: #line 1 "AOJ/ICPC2017/e.cpp"
#include <bits/stdc++.h>
using namespace std;

#line 2 "/opt/ei1333_s_library/math/combinatorics/montgomery-mod-int.hpp"

template <uint32_t mod_, bool fast = false>
struct MontgomeryModInt {
 private:
  using mint = MontgomeryModInt;
  using i32 = int32_t;
  using i64 = int64_t;
  using u32 = uint32_t;
  using u64 = uint64_t;

  static constexpr u32 get_r() {
    u32 ret = mod_;
    for (i32 i = 0; i < 4; i++) ret *= 2 - mod_ * ret;
    return ret;
  }

  static constexpr u32 r = get_r();

  static constexpr u32 n2 = -u64(mod_) % mod_;

  static_assert(r * mod_ == 1, "invalid, r * mod != 1");
  static_assert(mod_ < (1 << 30), "invalid, mod >= 2 ^ 30");
  static_assert((mod_ & 1) == 1, "invalid, mod % 2 == 0");

  u32 x;

 public:
  MontgomeryModInt() : x{} {}

  MontgomeryModInt(const i64 &a)
      : x(reduce(u64(fast ? a : (a % mod() + mod())) * n2)) {}

  static constexpr u32 reduce(const u64 &b) {
    return u32(b >> 32) + mod() - u32((u64(u32(b) * r) * mod()) >> 32);
  }

  mint &operator+=(const mint &p) {
    if (i32(x += p.x - 2 * mod()) < 0) x += 2 * mod();
    return *this;
  }

  mint &operator-=(const mint &p) {
    if (i32(x -= p.x) < 0) x += 2 * mod();
    return *this;
  }

  mint &operator*=(const mint &p) {
    x = reduce(u64(x) * p.x);
    return *this;
  }

  mint &operator/=(const mint &p) {
    *this *= p.inv();
    return *this;
  }

  mint operator-() const { return mint() - *this; }

  mint operator+(const mint &p) const { return mint(*this) += p; }

  mint operator-(const mint &p) const { return mint(*this) -= p; }

  mint operator*(const mint &p) const { return mint(*this) *= p; }

  mint operator/(const mint &p) const { return mint(*this) /= p; }

  bool operator==(const mint &p) const {
    return (x >= mod() ? x - mod() : x) == (p.x >= mod() ? p.x - mod() : p.x);
  }

  bool operator!=(const mint &p) const {
    return (x >= mod() ? x - mod() : x) != (p.x >= mod() ? p.x - mod() : p.x);
  }

  u32 val() const {
    u32 ret = reduce(x);
    return ret >= mod() ? ret - mod() : ret;
  }

  mint pow(u64 n) const {
    mint ret(1), mul(*this);
    while (n > 0) {
      if (n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  mint inv() const { return pow(mod() - 2); }

  friend ostream &operator<<(ostream &os, const mint &p) {
    return os << p.val();
  }

  friend istream &operator>>(istream &is, mint &a) {
    i64 t;
    is >> t;
    a = mint(t);
    return is;
  }

  static constexpr u32 mod() { return mod_; }
};

template <uint32_t mod>
using modint = MontgomeryModInt<mod>;
using modint998244353 = modint<998244353>;
using modint1000000007 = modint<1000000007>;
#line 1 "/opt/ei1333_s_library/math/fft/superset-zeta-moebius-transform.hpp"
/**
 * @brief Superset Zeta/Moebius Transform (上位集合のゼータ/メビウス変換)
 */
template <typename T>
void superset_zeta_transform(vector<T> &f) {
  const int n = (int)f.size();
  assert((n & (n - 1)) == 0);
  for (int i = 1; i < n; i <<= 1) {
    for (int j = 0; j < n; j += i << 1) {
      for (int k = 0; k < i; k++) {
        f[j + k] += f[j + k + i];
      }
    }
  }
}

template <typename T>
void superset_moebius_transform(vector<T> &f) {
  const int n = (int)f.size();
  assert((n & (n - 1)) == 0);
  for (int i = 1; i < n; i <<= 1) {
    for (int j = 0; j < n; j += i << 1) {
      for (int k = 0; k < i; k++) {
        f[j + k] -= f[j + k + i];
      }
    }
  }
}
#line 2 "/opt/ei1333_s_library/math/fft/bitwise-and-convolution.hpp"

/**
 * @brief Bitwise And Convolution (Bitwise-AND畳み込み)
 */
template <typename T>
vector<T> bitwise_and_convolution(vector<T> f, vector<T> g) {
  const int n = (int)f.size();
  assert(f.size() == g.size());
  assert((n & (n - 1)) == 0);
  superset_zeta_transform(f);
  superset_zeta_transform(g);
  for (int i = 0; i < n; i++) f[i] *= g[i];
  superset_moebius_transform(f);
  return f;
}
#line 1 "/opt/ei1333_s_library/math/fft/fast-walsh-hadamard-transform.hpp"
/**
 * @brief Fast Walsh Hadamard Transform (高速ウォルシュアダマール変換)
 */
template <typename T>
void fast_walsh_hadamard_transform(vector<T> &f, bool inv = false) {
  const int n = (int)f.size();
  assert((n & (n - 1)) == 0);
  for (int i = 1; i < n; i <<= 1) {
    for (int j = 0; j < n; j += i << 1) {
      for (int k = 0; k < i; k++) {
        T s = f[j + k], t = f[j + k + i];
        f[j + k] = s + t;
        f[j + k + i] = s - t;
      }
    }
  }
  if (inv) {
    T inv_n = T(1) / n;
    for (auto &x : f) x *= inv_n;
  }
}
#line 2 "/opt/ei1333_s_library/math/fft/bitwise-xor-convolution.hpp"

/**
 * @brief Bitwise Xor Convolution (Bitwise-XOR畳み込み)
 */
template <typename T>
vector<T> bitwise_xor_convolution(vector<T> f, vector<T> g) {
  const int n = (int)f.size();
  assert(f.size() == g.size());
  assert((n & (n - 1)) == 0);
  fast_walsh_hadamard_transform(f, false);
  fast_walsh_hadamard_transform(g, false);
  for (int i = 0; i < n; i++) f[i] *= g[i];
  fast_walsh_hadamard_transform(f, true);
  return f;
}
#line 7 "AOJ/ICPC2017/e.cpp"
using mint = modint998244353;

int parse(string s) {
    if (s == "0") {
        return 0;
    }
    if (s == "1") {
        return (1 << 16) - 1;
    }
    if (s == "a") {
        int res = 0;
        for (int d = 0; d < 16; ++d) {
            if (d >> 3 & 1) {
                res += 1 << d;
            }
        }
        return res;
    }
    if (s == "b") {
        int res = 0;
        for (int d = 0; d < 16; ++d) {
            if (d >> 2 & 1) {
                res += 1 << d;
            }
        }
        return res;
    }
    if (s == "c") {
        int res = 0;
        for (int d = 0; d < 16; ++d) {
            if (d >> 1 & 1) {
                res += 1 << d;
            }
        }
        return res;
    }
    if (s == "d") {
        int res = 0;
        for (int d = 0; d < 16; ++d) {
            if (d >> 0 & 1) {
                res += 1 << d;
            }
        }
        return res;
    }
    if (s[0] == '-') {
        return (1 << 16) - 1 - parse(string(s.begin() + 1, s.end()));
    }
    int stack = 0;
    for (int i = 0; i < s.size(); ++i) {
        if (s[i] == '(') {
            ++stack;
        }
        if (s[i] == ')') {
            --stack;
        }
        if (stack == 1 && s[i] == '^') {
            return parse(string(s.begin() + 1, s.begin() + i)) ^
                   parse(string(s.begin() + i + 1, s.end() - 1));
        }
        if (stack == 1 && s[i] == '*') {
            return parse(string(s.begin() + 1, s.begin() + i)) &
                   parse(string(s.begin() + i + 1, s.end() - 1));
        }
    }
    exit(1);
}

bool solve(vector<vector<mint>> &table) {
    string s;
    cin >> s;
    if (s == ".") {
        return false;
    }
    int n = parse(s);
    int ans = 1;
    while (table[ans][n] == 0) {
        ++ans;
    }
    cout << ans << endl;
    return true;
}

vector<vector<mint>> precalc() {
    vector<vector<mint>> res(17, vector<mint>(1 << 16));
    res[1][parse(string("0"))] = 1;
    res[1][parse(string("1"))] = 1;
    res[1][parse(string("a"))] = 1;
    res[1][parse(string("b"))] = 1;
    res[1][parse(string("c"))] = 1;
    res[1][parse(string("d"))] = 1;
    for (int i = 2; i < 17; ++i) {
        for (int n = 0; n < (1 << 16); ++n) {
            if (res[i - 1][n] != 0) {
                res[i][n] = 1;
                res[i][(1 << 16) - 1 - n] = 1;
            }
        }
        if (i < 5) {
            continue;
        }
        for (int j = 1; j < i - 3; ++j) {
            auto tmp = bitwise_xor_convolution(res[j], res[i - 3 - j]);
            for (int n = 0; n < (1 << 16); ++n) {
                if (tmp[n] != 0) {
                    res[i][n] = 1;
                }
            }
        }
        for (int j = 1; j < i - 3; ++j) {
            auto tmp = bitwise_and_convolution(res[j], res[i - 3 - j]);
            for (int n = 0; n < (1 << 16); ++n) {
                if (tmp[n] != 0) {
                    res[i][n] = 1;
                }
            }
        }
    }
    return res;
}

int main(void) {
    auto table = precalc();
    while (solve(table))
        ;
    return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 8204
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef pair<ll,ll> pi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define ALL(A) A.begin(),A.end()
#define LB(A,x) (lower_bound(ALL(A),x)-A.begin())
template<typename T>bool chmax(T&a,T b){if(a<b){a=b;return true;}return false;}
template<typename T>bool chmin(T&a,T b){if(a>b){a=b;return true;}return false;}
int main(){
    vi ans(65536,1e18);
    ans[0]=ans[43690]=ans[52428]=ans[61680]=ans[65280]=ans[65535]=1;
    priority_queue<pi>Q;
    Q.emplace(pi(-1,0));
    Q.emplace(pi(-1,43690));
    Q.emplace(pi(-1,52428));
    Q.emplace(pi(-1,61680));
    Q.emplace(pi(-1,65280));
    Q.emplace(pi(-1,65535));
    set<ll>S;
    while(Q.size()){
        ll d=-Q.top().first;
        ll v=Q.top().second;
        Q.pop();
        if(d!=ans[v]||d>16)continue;
        S.insert(v);
        if(chmin(ans[65535-v],d+1))Q.emplace(pi(-d-1,65535-v));
        for(auto u:S){
            if(chmin(ans[u^v],d+ans[u]+3))Q.emplace(pi(-ans[u^v],u^v));
            if(chmin(ans[u&v],d+ans[u]+3))Q.emplace(pi(-ans[u&v],u&v));
        }
    }
    while(1){
        string S;cin>>S;
        if(S==".")return 0;
        ll N=S.size();
        vi par(N);
        {
            stack<ll>st;
            REP(i,N){
                if(S[i]=='(')st.emplace(i);
                if(S[i]==')')par[st.top()]=i,st.pop();
            }
        }
        ll a=0;
        function<ll(ll,ll,ll)>f=[&](ll l,ll r,ll i){
            if(r-l==1){
                if(S[l]=='1')return 1LL;
                if(S[l]=='0')return 0LL;
                return (i>>(S[l]-'a'))%2;
            }
            if(S[l]=='-')return 1-f(l+1,r,i);
            assert(S[l]=='('&&par[l]==r-1);
            ll lev=0,t=l+1;
            while(lev||(S[t]!='*'&&S[t]!='^')){
                if(S[t]=='(')lev++;
                if(S[t]==')')lev--;
                t++;
            }
            ll x=f(l+1,t,i),y=f(t+1,r-1,i);
            if(S[t]=='^')return x^y;
            return x&y;
        };
        REP(i,16)if(f(0,N,i))a+=1<<i;
        cout<<ans[a]<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 6872
final_rank: 5

code_snippet: #ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif
// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <type_traits>
#include <typeindex>
#include <unordered_map>
#include <unordered_set>

#endif
using namespace std;
using ll = long long;
#define rep(i, n) for (int i = 0; i < n; i++)
#define all(v) v.begin(), v.end()
template <class T, class U>
inline bool chmax(T &a, U b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template <class T, class U>
inline bool chmin(T &a, U b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
constexpr int INF = 1001001001;
constexpr int64_t llINF = 3000000000000000000;
const double pi = acos(-1);
struct linear_sieve {
    vector<int> least_factor, prime_list;
    linear_sieve(int n) : least_factor(n + 1, 0) {
        for (int i = 2; i <= n; i++) {
            if (least_factor[i] == 0) {
                least_factor[i] = i;
                prime_list.push_back(i);
            }
            for (int p : prime_list) {
                if (ll(i) * p > n || p > least_factor[i]) break;
                least_factor[i * p] = p;
            }
        }
    }
};

ll extgcd(ll a, ll b, ll &x, ll &y) {
    // ax+by=gcd(|a|,|b|)
    if (a < 0 || b < 0) {
        ll d = extgcd(abs(a), abs(b), x, y);
        if (a < 0) x = -x;
        if (b < 0) y = -y;
        return d;
    }
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    ll d = extgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}
ll modpow(ll a, ll b, ll m) {
    a %= m;
    ll res = 1 % m;
    while (b) {
        if (b & 1) {
            res *= a;
            res %= m;
        }
        a *= a;
        a %= m;
        b >>= 1;
    }
    return res;
}
ll modinv(ll x, ll modulo) {
    ll a = x, b = modulo, u = 1, v = 0, t;
    while (b > 0) {
        t = a / b;
        swap(a -= t * b, b);
        swap(u -= t * v, v);
    }
    return (u >= 0 ? u % modulo : (modulo - (-u) % modulo) % modulo);
}
template <int modulo>
struct modint {
    int x;
    modint() : x(0) {}
    modint(int64_t y) : x(y >= 0 ? y % modulo : (modulo - (-y) % modulo) % modulo) {}
    modint &operator+=(const modint &p) {
        if ((x += p.x) >= modulo) x -= modulo;
        return *this;
    }
    modint &operator-=(const modint &p) {
        if ((x += modulo - p.x) >= modulo) x -= modulo;
        return *this;
    }
    modint &operator*=(const modint &p) {
        x = (int)(1LL * x * p.x % modulo);
        return *this;
    }
    modint &operator/=(const modint &p) {
        *this *= p.inv();
        return *this;
    }
    modint operator-() const { return modint(-x); }
    modint operator+(const modint &p) const { return modint(*this) += p; }
    modint operator-(const modint &p) const { return modint(*this) -= p; }
    modint operator*(const modint &p) const { return modint(*this) *= p; }
    modint operator/(const modint &p) const { return modint(*this) /= p; }
    bool operator==(const modint &p) const { return x == p.x; }
    bool operator!=(const modint &p) const { return x != p.x; }
    modint inv() const {
        int a = x, b = modulo, u = 1, v = 0, t;
        while (b > 0) {
            t = a / b;
            swap(a -= t * b, b);
            swap(u -= t * v, v);
        }
        return modint(u);
    }
    modint pow(int64_t n) const {
        modint ret(1), mul(x);
        while (n > 0) {
            if (n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }
    friend ostream &operator<<(ostream &os, const modint &p) { return os << p.x; }
    friend istream &operator>>(istream &is, modint &a) {
        int64_t t;
        is >> t;
        a = modint<modulo>(t);
        return (is);
    }
    int val() const { return x; }
    static constexpr int mod() { return modulo; }
    static constexpr int half() { return (modulo + 1) >> 1; }
};
template <typename T>
struct Binomial {
    vector<T> inv, fact, factinv;
    Binomial(int n) {
        inv.resize(n + 1);
        fact.resize(n + 1);
        factinv.resize(n + 1);
        inv[0] = fact[0] = factinv[0] = 1;
        for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * i;
        factinv[n] = fact[n].inv();
        inv[n] = fact[n - 1] * factinv[n];
        for (int i = n - 1; i >= 1; i--) {
            factinv[i] = factinv[i + 1] * (i + 1);
            inv[i] = fact[i - 1] * factinv[i];
        }
    }
    T C(int n, int r) {
        if (n < 0 || n < r || r < 0) return 0;
        return fact[n] * factinv[n - r] * factinv[r];
    }
    T P(int n, int r) {
        if (n < 0 || n < r || r < 0) return 0;
        return fact[n] * factinv[n - r];
    }
    T H(int n, int r) {
        if (n == 0 && r == 0) return 1;
        if (n < 0 || r < 0) return 0;
        return r == 0 ? 1 : C(n + r - 1, r);
    }
};
template <class T>
struct Matrix {
    int n;
    vector<vector<T>> m;
    Matrix() : Matrix(0) {}
    Matrix(int x) : Matrix(vector<vector<T>>(x, vector<T>(x, 0))) {}
    Matrix(const vector<vector<T>> &a) {
        n = a.size();
        m = a;
    }
    vector<T> &operator[](int i) { return m[i]; }
    const vector<T> &operator[](int i) const { return m[i]; }
    static Matrix identity(int x) {
        Matrix res(x);
        for (int i = 0; i < x; i++) res[i][i] = 1;
        return res;
    }
    Matrix operator+(const Matrix &a) const {
        Matrix x = (*this);
        return x += a;
    }
    Matrix operator*(const Matrix &a) const {
        Matrix x = (*this);
        return x *= a;
    }
    Matrix &operator+=(const Matrix &a) {
        Matrix res(n);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                res[i][j] = m[i][j] + a[i][j];
            }
        }
        m = res.m;
        return *this;
    }
    Matrix &operator*=(const Matrix &a) {
        Matrix res(n);
        for (int i = 0; i < n; i++) {
            for (int k = 0; k < n; k++) {
                for (int j = 0; j < n; j++) {
                    res[i][j] += m[i][k] * a[k][j];
                }
            }
        }
        m = res.m;
        return *this;
    }
    Matrix pow(ll b) const {
        Matrix x = *this, res = identity(n);
        while (b) {
            if (b & 1) {
                res *= x;
            }
            x *= x;
            b >>= 1;
        }
        return res;
    }
};
struct UnionFind {
    vector<int> par, siz, es;
    UnionFind(int x) {
        par.resize(x);
        siz.resize(x);
        es.resize(x);
        for (int i = 0; i < x; i++) {
            par[i] = i;
            siz[i] = 1;
            es[i] = 0;
        }
    }
    int find(int x) {
        if (par[x] == x) return x;
        return par[x] = find(par[x]);
    }
    bool unite(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) {
            es[x]++;
            return false;
        }
        if (siz[x] < siz[y]) swap(x, y);
        par[y] = x;
        siz[x] += siz[y];
        es[x] += es[y] + 1;
        return true;
    }
    bool same(int x, int y) { return find(x) == find(y); }
    int size(int x) { return siz[find(x)]; }
    int edges(int x) { return es[find(x)]; }
};
template <class S, S (*op)(S, S), S (*e)()>
struct segtree {
    int siz = 1;
    vector<S> dat;
    segtree(int n) : segtree(vector<S>(n, e())) {}
    segtree(const vector<S> &a) {
        while (siz < a.size()) siz <<= 1;
        dat = vector<S>(siz << 1, e());
        for (int i = 0; i < a.size(); i++) dat[siz + i] = a[i];
        for (int i = siz - 1; i >= 1; i--) dat[i] = op(dat[2 * i], dat[2 * i + 1]);
    }
    void set(int p, S x) {
        p += siz;
        dat[p] = x;
        while (p > 0) {
            p >>= 1;
            dat[p] = op(dat[2 * p], dat[2 * p + 1]);
        }
    }
    void add(int p, S x) { set(p, get(p) + x); }
    S get(int p) { return dat[p + siz]; }
    S prod(int l, int r) {
        S vl = e(), vr = e();
        l += siz, r += siz;
        while (l < r) {
            if (l & 1) vl = op(vl, dat[l++]);
            if (r & 1) vr = op(dat[--r], vr);
            l >>= 1, r >>= 1;
        }
        return op(vl, vr);
    }
    S all_prod() { return dat[1]; }
};
template <class T>
struct BIT {
    // 1-indexed
    int n, beki = 1;
    vector<T> bit;
    BIT(int x) {
        bit.resize(x + 1, 0);
        n = x;
        while (beki * 2 <= n) beki *= 2;
    }
    T sum(int i) {
        T res = 0;
        while (i > 0) {
            res += bit[i];
            i -= i & -i;
        }
        return res;
    }
    T sum(int l, int r) {
        //[l,r]
        return sum(r) - (l == 0 ? 0 : sum(l - 1));
    }
    void add(int i, T x) {
        while (i <= n) {
            bit[i] += x;
            i += i & -i;
        }
    }
    int lowerbound(T w) {
        if (w <= 0) return 0;
        int x = 0;
        for (int k = beki; k > 0; k >>= 1) {
            if (x + k <= n && bit[x + k] < w) {
                w -= bit[x + k];
                x += k;
            }
        }
        return x + 1;
    }
};
template <class T, T (*op)(T, T), T (*e)()>
struct sparsetable {
    vector<vector<T>> table;
    vector<int> logtable;
    sparsetable() = default;
    sparsetable(vector<T> v) {
        int len = 0;
        while ((1 << len) <= v.size()) len++;
        table.assign(len, vector<T>(1 << len));
        for (int i = 0; i < (int)v.size(); i++) table[0][i] = v[i];
        for (int i = 1; i < len; i++) {
            for (int j = 0; j + (1 << i) <= (1 << len); j++) {
                table[i][j] = op(table[i - 1][j], table[i - 1][j + (1 << (i - 1))]);
            }
        }
        logtable.resize(v.size() + 1);
        for (int i = 2; i < logtable.size(); i++) {
            logtable[i] = logtable[(i >> 1)] + 1;
        }
    }
    T query(int l, int r) {
        assert(l <= r);
        if (l == r) return e();
        int len = logtable[r - l];
        return op(table[len][l], table[len][r - (1 << len)]);
    }
};
template <class T, T (*op)(T, T), T (*e)()>
struct disjointsparsetable {
    vector<vector<T>> table;
    vector<int> logtable;
    disjointsparsetable() = default;
    disjointsparsetable(vector<T> v) {
        int len = 0;
        while ((1 << len) <= v.size()) len++;
        table.assign(len, vector<T>(1 << len, e()));
        for (int i = 0; i < (int)v.size(); i++) table[0][i] = v[i];
        for (int i = 1; i < len; i++) {
            int shift = 1 << i;
            for (int j = 0; j < (int)v.size(); j += shift << 1) {
                int t = min(j + shift, (int)v.size());
                table[i][t - 1] = v[t - 1];
                for (int k = t - 2; k >= j; k--) table[i][k] = op(v[k], table[i][k + 1]);
                if (v.size() <= t) break;
                table[i][t] = v[t];
                int r = min(t + shift, (int)v.size());
                for (int k = t + 1; k < r; k++) table[i][k] = op(table[i][k - 1], v[k]);
            }
        }
        logtable.resize(1 << len);
        for (int i = 2; i < logtable.size(); i++) {
            logtable[i] = logtable[(i >> 1)] + 1;
        }
    }
    T query(int l, int r) {
        if (l == r) return e();
        if (l >= --r) return table[0][l];
        int len = logtable[l ^ r];
        return op(table[len][l], table[len][r]);
    };
};
pair<int, int> lcatree_op(pair<int, int> a, pair<int, int> b) { return min(a, b); }
pair<int, int> lcatree_e() { return {1000000000, -1}; }
struct lca_tree {
    int n, size;
    vector<int> in, ord, depth;
    sparsetable<pair<int, int>, lcatree_op, lcatree_e> st;
    lca_tree(vector<vector<int>> g, int root = 0) : n((int)g.size()), size(log2(n) + 2), in(n), depth(n, n) {
        depth[root] = 0;
        function<void(int, int)> dfs = [&](int v, int p) {
            in[v] = (int)ord.size();
            ord.push_back(v);
            for (int u : g[v]) {
                if (u == p) continue;
                if (depth[u] > depth[v] + 1) {
                    depth[u] = depth[v] + 1;
                    dfs(u, v);
                    ord.push_back(v);
                }
            }
        };
        dfs(root, -1);
        vector<pair<int, int>> vec((int)ord.size());
        for (int i = 0; i < (int)ord.size(); i++) {
            vec[i] = make_pair(depth[ord[i]], ord[i]);
        }
        st = vec;
    }
    int lca(int u, int v) {
        if (in[u] > in[v]) swap(u, v);
        if (u == v) return u;
        return st.query(in[u], in[v]).second;
    }
    int dist(int u, int v) {
        int l = lca(u, v);
        return depth[u] + depth[v] - 2 * depth[l];
    }
};
struct auxiliary_tree : lca_tree {
    vector<vector<int>> G;
    auxiliary_tree(vector<vector<int>> &g) : lca_tree(g), G(n) {}
    pair<int, vector<int>> query(vector<int> vs, bool decending = false) {
        // decending:親から子の方向のみ辺を貼る
        assert(!vs.empty());
        sort(vs.begin(), vs.end(), [&](int a, int b) { return in[a] < in[b]; });
        int m = vs.size();
        stack<int> st;
        st.push(vs[0]);
        for (int i = 0; i < m - 1; i++) {
            int w = lca(vs[i], vs[i + 1]);
            if (w != vs[i]) {
                int l = st.top();
                st.pop();
                while (!st.empty() && depth[w] < depth[st.top()]) {
                    if (!decending) G[l].push_back(st.top());
                    G[st.top()].push_back(l);
                    l = st.top();
                    st.pop();
                }
                if (st.empty() || st.top() != w) {
                    st.push(w);
                    vs.push_back(w);
                }
                if (!decending) G[l].push_back(w);
                G[w].push_back(l);
            }
            st.push(vs[i + 1]);
        }
        while (st.size() > 1) {
            int x = st.top();
            st.pop();
            if (!decending) G[x].push_back(st.top());
            G[st.top()].push_back(x);
        }
        // {root,vertex_list}
        return make_pair(st.top(), vs);
    }
    void clear(vector<int> vs) {
        for (int v : vs) G[v].clear();
    }
};
struct Mo {
    int n;
    vector<pair<int, int>> lr;

    explicit Mo(int n) : n(n) {}

    void add(int l, int r) { /* [l, r) */
        lr.emplace_back(l, r);
    }

    template <typename AL, typename AR, typename EL, typename ER, typename O>
    void build(const AL &add_left, const AR &add_right, const EL &erase_left, const ER &erase_right, const O &out) {
        int q = (int)lr.size();
        int bs = n / min<int>(n, sqrt(q));
        vector<int> ord(q);
        iota(begin(ord), end(ord), 0);
        sort(begin(ord), end(ord), [&](int a, int b) {
            int ablock = lr[a].first / bs, bblock = lr[b].first / bs;
            if (ablock != bblock) return ablock < bblock;
            return (ablock & 1) ? lr[a].second > lr[b].second : lr[a].second < lr[b].second;
        });
        int l = 0, r = 0;
        for (auto idx : ord) {
            while (l > lr[idx].first) add_left(--l);
            while (r < lr[idx].second) add_right(r++);
            while (l < lr[idx].first) erase_left(l++);
            while (r > lr[idx].second) erase_right(--r);
            out(idx);
        }
    }

    template <typename A, typename E, typename O>
    void build(const A &add, const E &erase, const O &out) {
        build(add, add, erase, erase, out);
    }
};
template <class S, S (*op)(S, S), S (*e)(), class F, S (*mapping)(F, S), F (*composition)(F, F), F (*id)()>
struct lazy_segtree {
    int _n, sz = 1;
    vector<S> dat;
    vector<F> lazy;
    lazy_segtree(vector<S> a) : _n(int(a.size())) {
        while (sz < _n) sz <<= 1;
        dat.resize(sz * 2, e());
        lazy.resize(sz * 2, id());
        rep(i, _n) dat[sz + i] = a[i];
        for (int i = sz - 1; i >= 1; i--) dat[i] = op(dat[2 * i], dat[2 * i + 1]);
    }
    void eval(int k) {
        dat[k] = mapping(lazy[k], dat[k]);
        if (k < sz) {
            lazy[k * 2] = composition(lazy[k], lazy[k * 2]);
            lazy[k * 2 + 1] = composition(lazy[k], lazy[k * 2 + 1]);
        }
        lazy[k] = id();
    }
    void apply(int a, int b, F f, int k = 1, int l = 0, int r = -1) {
        eval(k);
        if (r == -1) r = sz;
        if (r <= a || b <= l) return;
        if (a <= l && r <= b) {
            lazy[k] = composition(f, lazy[k]);
            eval(k);
            return;
        }
        int m = (l + r) >> 1;
        apply(a, b, f, 2 * k, l, m);
        apply(a, b, f, 2 * k + 1, m, r);
        dat[k] = op(dat[2 * k], dat[2 * k + 1]);
    }
    S prod(int a, int b, int k = 1, int l = 0, int r = -1) {
        eval(k);
        if (r == -1) r = sz;
        if (r <= a || b <= l) return e();
        if (a <= l && r <= b) return dat[k];
        int m = (l + r) >> 1;
        S vl = prod(a, b, 2 * k, l, m);
        S vr = prod(a, b, 2 * k + 1, m, r);
        return op(vl, vr);
    }
};

template <class S, S (*op)(S, S), S (*e)()>
struct dual_segtree {
    int sz = 1, log = 0;
    vector<S> lz;
    dual_segtree(vector<S> a) {
        int n = a.size();
        while (sz < n) {
            sz <<= 1;
            log++;
        }
        lz.assign(sz << 1, e());
        for (int i = 0; i < n; i++) lz[i + sz] = a[i];
    }
    void push(int k) {
        int b = __builtin_ctz(k);
        for (int d = log; d > b; d--) {
            lz[k >> d << 1] = op(lz[k >> d << 1], lz[k >> d]);
            lz[k >> d << 1 | 1] = op(lz[k >> d << 1 | 1], lz[k >> d]);
            lz[k >> d] = e();
        }
    }
    void apply(int l, int r, S x) {
        l += sz, r += sz;
        push(l);
        push(r);
        while (l < r) {
            if (l & 1) {
                lz[l] = op(lz[l], x);
                l++;
            }
            if (r & 1) {
                r--;
                lz[r] = op(lz[r], x);
            }
            l >>= 1, r >>= 1;
        }
    }
    S get(int k) {
        k += sz;
        S res = e();
        while (k) {
            res = op(res, lz[k]);
            k >>= 1;
        }
        return res;
    }
};

/*
#include <atcoder/string>
int string_period(string s) {
    int n = s.size();
    auto z = atcoder::z_algorithm(s);
    for (int i = 1; i < n; i++) {
        if (n % i == 0 && z[i] == n - i) return i;
    }
    return n;
}
*/
struct LowLink {
    vector<vector<int>> g;
    vector<int> ord, low, out;
    vector<bool> used;
    vector<pair<int, int>> bridge;
    vector<pair<int, int>> articulation;
    int unions;
    LowLink(vector<vector<int>> g) : g(g) {
        int n = (int)g.size();
        ord.resize(n);
        low.resize(n);
        out.resize(n);
        used.resize(n);
        unions = 0;
        int t = 0;
        for (int i = 0; i < n; i++) {
            if (!used[i]) {
                dfs(i, t, -1);
                unions++;
            }
        }
    }
    void dfs(int v, int &t, int par) {
        used[v] = true;
        ord[v] = t++, low[v] = ord[v];
        int cnt = 0;
        bool par_back = false;
        for (int to : g[v]) {
            if (!used[to]) {
                dfs(to, t, v);
                low[v] = min(low[v], low[to]);
                if (ord[v] < low[to]) bridge.push_back(minmax(v, to));
                if (ord[v] <= low[to]) cnt++;
            } else if (to != par || par_back) {
                low[v] = min(low[v], ord[to]);
            } else
                par_back = true;
        }
        if (par != -1) cnt++;
        if (cnt >= 2) articulation.push_back({v, cnt});
        out[v] = t;
    }
};
template <typename T>
T rand(T l, T r) {
    static mt19937 mt(random_device{}());
    if constexpr (is_integral_v<T>) {
        uniform_int_distribution<T> dist(l, r);
        return dist(mt);
    } else if constexpr (is_floating_point_v<T>) {
        uniform_real_distribution<T> dist(l, r);
        return dist(mt);
    }
}
int res[1 << 16];
char Minus(char c) {
    if (c == '0') return '1';
    return '0';
}
char Xor(char a, char b) {
    if (a == b) return '0';
    return '1';
}
char And(char a, char b) {
    if (a == '1' && b == '1') return '1';
    return '0';
}
int calc_formula(string s) {
    string t;
    for (char c : s) {
        t += c;
        while (1) {
            if (t.size() >= 2 && t.end()[-2] == '-' && isdigit(t.back())) {
                char d = Minus(t.back());
                t.pop_back();
                t.pop_back();
                t += d;
                continue;
            }
            if (t.back() == ')') {
                char d = '.';
                if (t.end()[-3] == '^')
                    d = Xor(t.end()[-4], t.end()[-2]);
                else
                    d = And(t.end()[-4], t.end()[-2]);
                t.pop_back();
                t.pop_back();
                t.pop_back();
                t.pop_back();
                t.pop_back();
                t.push_back(d);
                continue;
            }
            break;
        }
    }
    return (t[0] - '0');
}
int calc_charFormula(string &s) {
    int ans = 0;
    rep(i, 16) {
        string t = s;
        for (char &c : t) {
            rep(j, 4) {
                if (c == 'a' + j) c = '0' + ((i >> j) & 1);
            }
        }
        ans |= calc_formula(t) << i;
    }
    return ans;
}
void precalc() {
    fill(res, res + 65536, INF);
    vector<vector<string>> E(17);
    E[1] = {"0", "1", "a", "b", "c", "d"};
    for (auto s : E[1]) {
        res[calc_charFormula(s)] = 1;
    }
    for (int i = 2; i <= 16; i++) {
        vector<string> tmp;
        for (auto s : E[i - 1]) {
            tmp.push_back('-' + s);
        }
        for (int j = 1; j + 3 < i; j++) {
            int k = i - 3 - j;
            for (auto s : E[j]) {
                for (auto t : E[k]) {
                    tmp.push_back('(' + s + '^' + t + ')');
                    tmp.push_back('(' + s + '*' + t + ')');
                }
            }
        }
        for (auto s : tmp) {
            int ans = calc_charFormula(s);
            if (chmin(res[ans], s.size())) E[i].push_back(s);
        }
    }
}
void solve() {
    string s;
    cin >> s;
    if (s == ".") exit(0);
    cout << res[calc_charFormula(s)] << endl;
    // calc for 2^4 patterns
    // generate all possible string and calc for 2^4 patterns
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    /*int t;
    cin >> t;
    while (t--) */
    precalc();
    while (1) solve();
}
accuracy: 1
time_ms: 50
memory_kb: 4372
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vc<vc<T>>;
void solve();
int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    ll t = 1;
    // cin >> t;
    for (int i = 1; i <= t; i++) solve();
    return 0;
}
#define rep(i, a, b) for (ll i = (a); i < (b); i++)
ll dy[4] = {0, 1, 0, -1}, dx[4] = {1, 0, -1, 0};
// ll dy[8] = {1, 1, 0, -1, -1, -1, 0, 1}, dx[8] = {0, 1, 1, 1, 0, -1, -1, -1};
string s, t;
ll pos;
void solve() {
    ll ABCD[4];
    auto get = [&](char c) -> ll {
        if (c == 'a') return ABCD[0];
        if (c == 'b') return ABCD[1];
        if (c == 'c') return ABCD[2];
        if (c == 'd') return ABCD[3];
        return 0;
    };
    vc<ll> min_op(1 << 16, 1e9);
    auto E = [&](auto &&E, string &S) -> ll {
        if (S[pos] == '(') {
            pos++;
            ll v1 = E(E, S);
            char op = S[pos++];
            ll v2 = E(E, S);
            pos++;
            if (op == '^') return v1 ^ v2;
            return v1 & v2;
        }
        if (S[pos] == '0' || S[pos] == '1') {
            pos++;
            return S[pos - 1] - '0';
        }
        if ('a' <= S[pos] && S[pos] <= 'd') {
            ll v = get(S[pos]);
            pos++;
            return v;
        }
        pos++;
        ll v1 = E(E, S);
        return 1 - v1;
    };
    auto check2 = [&]() -> void {
        ll num = 0;
        rep(a, 0, 2) {
            rep(b, 0, 2) {
                rep(c, 0, 2) {
                    rep(d, 0, 2) {
                        ABCD[0] = a, ABCD[1] = b, ABCD[2] = c, ABCD[3] = d;
                        pos = 0;
                        ll val = a * 8 + b * 4 + c * 2 + d;
                        num |= (1 << val) * E(E, t);
                    }
                }
            }
        }
        min_op[num] = min(min_op[num], (ll)t.size());
    };
    auto check = [&](vc<char> &C) -> void {
        ll nC = C.size();
        if (nC >= 5) return;
        if (nC == 0) return;
        auto add1 = [&](bool f) -> void {
            if (f) t += "-";
            t += "(";
        };
        auto add2 = [&](bool f, int idx) -> void {
            if (f) t += "-";
            t += C[idx];
        };
        auto add_op = [&](bool f) -> void {
            if (f)
                t += "^";
            else
                t += "*";
        };
        if (nC == 1) {
            rep(m2, 0, 2) {
                t = "";
                add2(m2, 0);
                check2();
            }
            return;
        }
        if (nC == 2) {
            rep(m1, 0, 2) {
                rep(m2, 0, 4) {
                    rep(op, 0, 2) {
                        t = "";
                        add1(m1);
                        add2(m2 & 1, 0);
                        add_op(op);
                        add2(m2 & 2, 1);
                        t += ")";
                        check2();
                    }
                }
            }
            return;
        }
        if (nC == 3) {
            rep(m1, 0, 4) {
                rep(m2, 0, 8) {
                    rep(op, 0, 4) {
                        t = "";
                        add1(m1 & 1);
                        add1(m1 & 2);
                        add2(m2 & 1, 0);
                        add_op(op & 1);
                        add2(m2 & 2, 1);
                        t += ")";
                        add_op(op & 2);
                        add2(m2 & 4, 2);
                        t += ")";
                        check2();
                    }
                }
            }
            return;
        }
        rep(m1, 0, 8) {
            rep(m2, 0, 16) {
                rep(op, 0, 8) {
                    t = "";
                    add1(m1 & 1);
                    add1(m1 & 2);
                    add1(m1 & 4);
                    add2(m2 & 1, 0);
                    add_op(op & 1);
                    add2(m2 & 2, 1);
                    t += ")";
                    add_op(op & 2);
                    add2(m2 & 4, 2);
                    t += ")";
                    add_op(op & 4);
                    add2(m2 & 8, 3);
                    t += ")";
                    check2();
                }
            }
        }
        rep(m1, 0, 8) {
            rep(m2, 0, 16) {
                rep(op, 0, 8) {
                    t = "";
                    add1(m1 & 1);
                    add1(m1 & 2);
                    add2(m2 & 1, 0);
                    add_op(op & 1);
                    add2(m2 & 2, 1);
                    t += ")";
                    add_op(op & 2);
                    add1(m1 & 4);
                    add2(m2 & 4, 2);
                    add_op(op & 4);
                    add2(m2 & 8, 3);
                    t += ")";
                    t += ")";
                    check2();
                }
            }
        }
        return;
    };
    auto dfs = [&](auto &&dfs, vc<char> &C) -> void {
        if (C.size() >= 5) return;
        check(C);
        for (char c = 'a'; c <= 'd'; c++) {
            C.push_back(c);
            dfs(dfs, C);
            C.pop_back();
        }
    };
    vc<char> C;
    dfs(dfs, C);
    min_op[0] = 1, min_op[65535] = 1;
    while (true) {
        string s;
        cin >> s;
        if (s == ".") break;
        ll num = 0;
        rep(a, 0, 2) rep(b, 0, 2) rep(c, 0, 2) rep(d, 0, 2) {
            ABCD[0] = a, ABCD[1] = b, ABCD[2] = c, ABCD[3] = d;
            pos = 0;
            ll val = a * 8 + b * 4 + c * 2 + d;
            num |= (1 << val) * E(E, s);
        }
        cout << min_op[num] << endl;
    }
}
accuracy: 1
time_ms: 210
memory_kb: 3484
final_rank: 9

code_snippet: #include <bits/stdc++.h>

const int N{1 << 16};
int dist[N];

void init() {
    const int INF{(int)2e9};
    std::fill(dist, dist + N, INF);
    using qt = std::pair<int, int>;
    std::priority_queue<qt, std::vector<qt>, std::greater<qt>> que;
    dist[0] = 1; // 0
    que.emplace(dist[0], 0);
    dist[N - 1] = 1; // 1
    que.emplace(dist[1], N - 1);
    for (int i{} ; i < 4 ; i++) { // a, b, c, d
        int val{};
        for (int bit{} ; bit < (1 << 4) ; bit++) {
            if (bit & (1 << i)) val |= (1 << bit);
        }
        dist[val] = 1;
        que.emplace(dist[val], val);
    }
    while (que.size()) {
        auto [d, v]{que.top()};
        que.pop();
        if (dist[v] < d) continue;
        {// -
            int x{(N - 1) ^ v};
            if (dist[x] > dist[v] + 1) {
                dist[x] = dist[v] + 1;
                que.emplace(dist[x], x);
            }
        }
        for (int i{} ; i < N ; i++) {
            if (dist[i] + dist[v] + 3 > 16) continue;
            {
                int x{i ^ v};
                if (dist[x] > dist[i] + dist[v] + 3) {
                    dist[x] = dist[i] + dist[v] + 3;
                    que.emplace(dist[x], x);
                }
            }
            {
                int x{i & v};
                if (dist[x] > dist[i] + dist[v] + 3) {
                    dist[x] = dist[i] + dist[v] + 3;
                    que.emplace(dist[x], x);
                }
            }
        }
    }
}

int parse(const std::string& S) {
    int res{};
    for (int bit{} ; bit < (1 << 4) ; bit++) {
        int it{};
        auto f{[&](auto f) -> int {
            if (S[it] == '(') {
                it++;
                int front{f(f)};
                assert(S[it] == '*' or S[it] == '^');
                char op{S[it]};
                it++;
                int back{f(f)};
                assert(S[it] == ')');
                it++;
                return op == '*' ? (front & back) : (front ^ back);
            }
            else if (S[it] == '-') {
                it++;
                int val{f(f)};
                return 1 - val;
            }
            else {
                char c{S[it]};
                it++;
                if (c == '0') return 0;
                if (c == '1') return 1;
                if (c == 'a') return (bool)(bit & (1 << 0));
                if (c == 'b') return (bool)(bit & (1 << 1));
                if (c == 'c') return (bool)(bit & (1 << 2));
                if (c == 'd') return (bool)(bit & (1 << 3));
                assert(false);
                return -1;
            }
        }};
        if (f(f)) res |= (1 << bit);
    }
    return res;
}

bool solve() {
    std::string S;
    std::cin >> S;
    if (S == ".") return false;
    std::cout << dist[parse(S)] << '\n';
    return true;
}

int main() {
    init();
    std::cin.tie(nullptr)->sync_with_stdio(false);
    while (solve()) ;
}
accuracy: 1
time_ms: 100
memory_kb: 3584
final_rank: 6

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

} // namespace macro

using namespace macro;
#line 3 "A.cpp"

bool solve(const string& s, int& i, int x) {
    if(s[i] == '0') { i++; return 0; }
    if(s[i] == '1') { i++; return 1; }
    if(s[i] == 'a') { i++; return x & (1 << 0); }
    if(s[i] == 'b') { i++; return x & (1 << 1); }
    if(s[i] == 'c') { i++; return x & (1 << 2); }
    if(s[i] == 'd') { i++; return x & (1 << 3); }
    if(s[i] == '-') { i++; return !solve(s, i, x); }
    if(s[i] == '(') {
        i++;
        bool L = solve(s, i, x);
        assert(s[i] == '^' or s[i] == '*');
        char op = s[i];
        i++;
        bool R = solve(s, i, x);
        assert(s[i] == ')');
        i++;
        if(op == '^') {
            return L ^ R;
        } else {
            return L & R;
        }
    }
    assert(0);
}

set<string> st;
map<vector<int>, int> mp;
void dfs(string s) {
    if(s.size() <= 16 and !st.count(s)) {

        vector<int> f(1 << 4, 0);
        for(int x : rep(1 << 4)) {
            int i = 0;
            f[x] = solve(s, i, x);
        }
        if(!mp.count(f) or mp[f] > s.size()) {
            mp[f] = s.size();
            st.insert(s);
            dfs("-" + s);
            for(string t : st) {
                if(1 + s.size() + 1 + t.size() + 1 <= 16) {
                    dfs("(" + s + "^" + t + ")");
                    dfs("(" + t + "^" + s + ")");
                    dfs("(" + s + "*" + t + ")");
                    dfs("(" + t + "*" + s + ")");
                }
            }
        }
    }
}

int main() {
    dfs("0");
    dfs("1");
    dfs("a");
    dfs("b");
    dfs("c");
    dfs("d");

    for(string s : st) {
        vector<int> f(1 << 4, 0);
        for(int x : rep(1 << 4)) {
            int i = 0;
            f[x] = solve(s, i, x);
        }
        if(!mp.count(f)) {
            mp[f] = s.size();
        } else {
            chmin(mp[f], (int)s.size());
        }
    }

    while(true) {
        string s = in();
        if(s == ".") return 0;

        vector<int> f(1 << 4, 0);
        for(int x : rep(1 << 4)) {
            int i = 0;
            f[x] = solve(s, i, x);
        }
        print(mp[f]);
    }
}
accuracy: 1
time_ms: 140
memory_kb: 4120
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;

const vector<int> base = { 0x0000, 0xffff, 0xaaaa, 0xcccc, 0xf0f0, 0xff00 };

int parse(const string& s, int &pos) {
	if (s[pos] == '0' || s[pos] == '1' || s[pos] == 'a' || s[pos] == 'b' || s[pos] == 'c' || s[pos] == 'd') {
		int res = base[s[pos] == '0' ? 0 : s[pos] == '1' ? 1 : s[pos] == 'a' ? 2 : s[pos] == 'b' ? 3 : s[pos] == 'c' ? 4 : 5];
		pos += 1;
		return res;
	}
	if (s[pos] == '-') {
		pos += 1;
		return 65535 - parse(s, pos);
	}
	pos += 1;
	int lc = parse(s, pos);
	char ch = s[pos];
	pos += 1;
	int rc = parse(s, pos);
	pos += 1;
	return (ch == '^' ? lc ^ rc : lc & rc);
}

int main() {
	// step #1. precompute distances
	vector<int> dist(65536, -1);
	vector<vector<int> > group(2);
	int cnt = base.size();
	group[1] = base;
	for (int i : base) {
		dist[i] = 1;
	}
	int d = 1, x = 0;
	while (cnt < 65536) {
		d += 1;
		group.push_back(vector<int>());
		for (int i : group[d - 1]) {
			if (dist[65535 - i] == -1) {
				dist[65535 - i] = d;
				group[d].push_back(65535 - i);
				cnt += 1;
			}
		}
		if (d >= 5) {
			for (int i = 1; i <= d - 4; i++) {
				for (int j : group[i]) {
					for (int k : group[(d - 3) - i]) {
						x += 1;
						if (dist[j ^ k] == -1) {
							dist[j ^ k] = d;
							group[d].push_back(j ^ k);
							cnt += 1;
						}
						if (dist[j & k] == -1) {
							dist[j & k] = d;
							group[d].push_back(j & k);
							cnt += 1;
						}
					}
				}
			}
		}
	}
	
	// step #2. solve
	cin.tie(0);
	ios::sync_with_stdio(false);
	while (true) {
		string s;
		cin >> s;
		if (s == ".") {
			break;
		}
		int pos = 0;
		int bit = parse(s, pos);
		cout << dist[bit] << '\n';
	}

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3756
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
#define rep(i, n) for (ll i = 0; i < (n); i++)

struct Parser {
    string S;
    int idx;
    int val;
    Parser(string s) : S(s), idx(0){};

    char peek() { return S[idx]; }
    char read() { return S[idx++]; }
    bool consume(char c) {
        if (peek() == c) {
            read();
            return true;
        }
        return false;
    }
    bool eos() { return idx == (int)S.size(); }

    int solve(int v) {
        val = v;
        idx = 0;
        return E();
    }

    int E() {
        if (consume('-')) {
            return 1 - E();
        }
        if (consume('(')) {
            int a = E();
            char op = read();
            int b = E();
            consume(')');
            if (op == '^') {
                if (a != b) return 1;
                return 0;
            } else {
                if (a == 1 && b == 1) return 1;
                return 0;
            }
        }
        char a = read();
        if (a == '0') return 0;
        if (a == '1') return 1;
        if (a == 'a') return ((val >> 0) & 1);
        if (a == 'b') return ((val >> 1) & 1);
        if (a == 'c') return ((val >> 2) & 1);
        if (a == 'd') return ((val >> 3) & 1);
        exit(1);
    }
};

int res(string s) {
    int re = 0;
    Parser ps(s);
    rep(v, 1 << 4) {
        re *= 2;
        ll a = ps.solve(v);
        re += a;
        if (!(a == 0 || a == 1)) {
            cout << "WA" << endl;
        }
    }
    return re;
}

struct Pre {
    vector<int> dp;

    Pre() {
        int inf = 10000;
        dp.resize(1 << 16, inf);
        vector<int> update(1 << 16, inf);
        set<int> ok;
        auto add = [&](int key, int val) {
            if (dp[key] != inf) return;
            update[key] = min(update[key], val);
        };
        // 更新するとき気を付ける

        auto nxtmns = [&]() {
            for (auto key : ok) {
                // add(((1 << 16) - 1) ^ key, dp[key] + 1);
                int u = 0;
                rep(i, 16) {
                    if (!((key >> i) & 1)) {
                        u += (1 << i);
                    }
                }
                add(u, dp[key] + 1);
            }
        };

        auto nxt = [&]() {
            for (auto k1 : ok) {
                for (auto k2 : ok) {
                    if (3 + dp[k1] + dp[k2] > 18) continue;
                    add(k1 ^ k2, 3 + dp[k1] + dp[k2]);
                    add(k1 & k2, 3 + dp[k1] + dp[k2]);
                }
            }
        };

        auto ud = [&](int v) {
            rep(i, 1 << 16) if (update[i] == v) {
                dp[i] = update[i];
                ok.insert(i);
                update[i] = inf;
            }
        };

        add(res("0"), 1);
        add(res("1"), 1);
        add(res("a"), 1);
        add(res("b"), 1);
        add(res("c"), 1);
        add(res("d"), 1);

        for (int v = 1; v <= 16; v++) {
            ud(v);
            nxtmns();
            ud(v);
            nxt();
        }
        ud(17);

        // cout << "=====" << endl;
        // rep(i, 1 << 16) cout << i << " " << dp[i] << endl;
        // cout << "=====" << endl;
    }
} pre;

bool solve() {
    string S;
    cin >> S;
    if (S == ".") return false;

    int ans = min((int)S.size(), pre.dp[res(S)]);
    if ((int)S.size() < pre.dp[res(S)]) {
        cout << "WA!! " << S << " " << pre.dp[res(S)] << endl;
        exit(1);
    }
    cout << ans << endl;

    return true;
}

int main() {
    auto st = [&](int s) {
        string res;
        while (s > 0) {
            res += '0' + s % 2;
            s /= 2;
        }
        return res;
    };
    auto nxtmns = [&](int key) {
        int u = 0;
        rep(i, 16) {
            if (!((key >> i) & 1)) {
                u += (1 << i);
            }
        }
        return u;
    };

    // cout << "a : " << pre.dp[res("a")] << endl;
    // cout << "-a : " << pre.dp[res("-a")] << endl;
    // cout << "nxtmnsval " << st(nxtmns(res("a"))) << endl;
    // cout << "res( a) : " << st(res("a")) << endl;
    // cout << "res(-a) : " << st(res("-a")) << endl;
    auto out = [&](string s) { cout << s << " " << pre.dp[res(s)] << endl; };
    // out("(c*d)");
    // out("((c*d)*a)");
    // out("-((c*d)*a)");
    // out("--a");
    // out("(-((c*d)*a)^a)");
    // out("(a^b)");
    while (solve())
        ;
}
accuracy: 1
time_ms: 50
memory_kb: 3496
final_rank: 3

code_snippet: #include<bits/stdc++.h>
#define rng(i,a,b) for(int i=(a);i<(b);i++)
#define rep(i,n) rng(i,0,(n))
#define vec vector
#define pb emplace_back
#define all(a) (a).begin(),(a).end()
using ll = long long;
using ld = long double;
using namespace std;

signed main() {

    struct st {
        string s;
        int val;
    };

    //1
    vec<st>e;
    int one = 0, two = 0, thr = 0;
    rep(z, 4) {
        st tmp;
        tmp.s = 'a' + z;
        tmp.val = 0;
        rep(i, 2)rep(j, 2)rep(x, 2)rep(y, 2) {
            if (z == 0 && i == 1 || z == 1 && j == 1 || z == 2 && x == 1 || z == 3 && y == 1) {
                int keta = (i << 3) | (j << 2) | (x << 1) | y;
                tmp.val |= (1 << keta);
            }
        }
        e.pb(tmp);
        tmp.s = "-";
        tmp.s += 'a' + z;
        tmp.val = 0;
        rep(i, 2)rep(j, 2)rep(x, 2)rep(y, 2) {
            if (z == 0 && i == 0 || z == 1 && j == 0 || z == 2 && x == 0 || z == 3 && y == 0) {
                int keta = (i << 3) | (j << 2) | (x << 1) | y;
                tmp.val |= (1 << keta);
            }
        }
        e.pb(tmp);
        one += 2;
    }

    //2 = 1*1
    rep(i, one)rng(j, i + 1, one) {
        rep(k, 2)rep(r, 2) {
            st tmp;
            tmp.s = "(";
            tmp.s += ((k == 0) ? "" : "-") + e[i].s + "^" + ((r == 0) ? "" : "-") + e[j].s + ")";
            tmp.val = (k == 0 ? e[i].val : (((1 << 16) - 1) ^ e[i].val)) ^ (r == 0 ? e[j].val : (((1 << 16) - 1) ^ e[j].val));
            e.pb(tmp);
            tmp;
            tmp.s = "(";
            tmp.s += ((k == 0) ? "" : "-") + e[i].s + "*" + ((r == 0) ? "" : "-") + e[j].s + ")";
            tmp.val = (k == 0 ? e[i].val : (((1 << 16) - 1) ^ e[i].val)) & (r == 0 ? e[j].val : (((1 << 16) - 1) ^ e[j].val));
            e.pb(tmp);
            two += 2;
        }
    }

    //3=1*2
    rep(i, one)rng(j, one, one + two) {
        rep(k, 2)rep(r, 2) {
            st tmp;
            tmp.s = "(";
            tmp.s += ((k == 0) ? "" : "-") + e[i].s + "^" + ((r == 0) ? "" : "-") + e[j].s + ")";
            tmp.val = (k == 0 ? e[i].val : (((1 << 16) - 1) ^ e[i].val)) ^ (r == 0 ? e[j].val : (((1 << 16) - 1) ^ e[j].val));
            e.pb(tmp);
            tmp.s = "(";
            tmp.s += ((k == 0) ? "" : "-") + e[i].s + "*" + ((r == 0) ? "" : "-") + e[j].s + ")";
            tmp.val = (k == 0 ? e[i].val : (((1 << 16) - 1) ^ e[i].val)) & (r == 0 ? e[j].val : (((1 << 16) - 1) ^ e[j].val));
            e.pb(tmp);
            thr += 2;
        }
    }

    //3=2*2
    rng(i, one, one + two)rng(j, i + 1, one + two) {
        rep(k, 2)rep(r, 2) {
            st tmp;
            tmp.s = "(";
            tmp.s += ((k == 0) ? "" : "-") + e[i].s + "^" + ((r == 0) ? "" : "-") + e[j].s + ")";
            tmp.val = (k == 0 ? e[i].val : (((1 << 16) - 1) ^ e[i].val)) ^ (r == 0 ? e[j].val : (((1 << 16) - 1) ^ e[j].val));
            if (tmp.s.size() <= 16)e.pb(tmp);
            tmp.s = "(";
            tmp.s += ((k == 0) ? "" : "-") + e[i].s + "*" + ((r == 0) ? "" : "-") + e[j].s + ")";
            tmp.val = (k == 0 ? e[i].val : (((1 << 16) - 1) ^ e[i].val)) & (r == 0 ? e[j].val : (((1 << 16) - 1) ^ e[j].val));
            if (tmp.s.size() <= 16)e.pb(tmp);
        }
    }

    //4=(1,2)*3
    rep(i, one + two)rng(j, one + two, one + two + thr) {
        rep(k, 2)rep(r, 2) {
            st tmp;
            tmp.s = "(";
            tmp.s += ((k == 0) ? "" : "-") + e[i].s + "^" + ((r == 0) ? "" : "-") + e[j].s + ")";
            tmp.val = (k == 0 ? e[i].val : (((1 << 16) - 1) ^ e[i].val)) ^ (r == 0 ? e[j].val : (((1 << 16) - 1) ^ e[j].val));
            if (tmp.s.size() <= 16)e.pb(tmp);
            tmp.s = "(";
            tmp.s += ((k == 0) ? "" : "-") + e[i].s + "*" + ((r == 0) ? "" : "-") + e[j].s + ")";
            tmp.val = (k == 0 ? e[i].val : (((1 << 16) - 1) ^ e[i].val)) & (r == 0 ? e[j].val : (((1 << 16) - 1) ^ e[j].val));
            if (tmp.s.size() <= 16)e.pb(tmp);
        }
    }
    string s;
    while (cin >> s && s != ".") {
        int val = 0;
        vec<int>kakko(s.size(), -1);
        stack<int>stc;
        rep(i, s.size()) {
            if (s[i] == '(') {
                stc.push(i);
            }
            else if (s[i] == ')') {
                int t = stc.top();stc.pop();
                kakko[t] = i;
            }
        }
        rep(i, 2)rep(j, 2)rep(x, 2)rep(y, 2) {
            auto dfs = [&](int l, int r, auto& dfs) ->bool {
                int cnt = 0;
                vec<bool>v;
                int op = -1;
                for (int z = l;z < r;z++) {
                    if (s[z] == '(') {
                        bool ret = dfs(z + 1, kakko[z], dfs);
                        if (cnt % 2 == 1) ret = !ret;
                        cnt = 0;
                        v.pb(ret);
                        z = kakko[z];
                    }
                    else if ('a' <= s[z] && s[z] <= 'd' || s[z] == '0' || s[z] == '1') {
                        if (s[z] == 'a') v.pb((cnt % 2 == 0) ? i : 1 - i);
                        if (s[z] == 'b') v.pb((cnt % 2 == 0) ? j : 1 - j);
                        if (s[z] == 'c') v.pb((cnt % 2 == 0) ? x : 1 - x);
                        if (s[z] == 'd') v.pb((cnt % 2 == 0) ? y : 1 - y);
                        if (s[z] == '0') v.pb((cnt % 2 == 0) ? 0 : 1);
                        if (s[z] == '1') v.pb((cnt % 2 == 0) ? 1 : 0);
                        cnt = 0;
                    }
                    else if (s[z] == '*') op = 0;
                    else if (s[z] == '^') op = 1;
                    else cnt++;
                }
                if (op < 0) return v[0];
                if (op == 0) return v[0] & v[1];
                return v[0] ^ v[1];
                };
            int keta = (i << 3) | (j << 2) | (x << 1) | y;
            val |= (dfs(0, s.size(), dfs) << keta);
        }

        //0か1は例外処理
        bool flag = true;
        rep(i, 2)rep(j, 2)rep(x, 2)rep(y, 2) {
            int keta = (i << 3) | (j << 2) | (x << 1) | y;
            if ((val >> keta) & 1) flag = false;
        }
        if (flag) {
            cout << "1\n";
            continue;
        }
        flag = true;
        rep(i, 2)rep(j, 2)rep(x, 2)rep(y, 2) {
            int keta = (i << 3) | (j << 2) | (x << 1) | y;
            if (!((val >> keta) & 1)) flag = false;
        }
        if (flag) {
            cout << "1\n";
            continue;
        }

        int ans = s.size();
        for (const auto& g : e) {
            if (g.s.size() > ans) continue;
            if (val == g.val) ans = min(ans, int(g.s.size()));
            if (val == (((1 << 16) - 1) ^ g.val)) ans = min(ans, int(g.s.size()) + 1);
        }
        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 2180
memory_kb: 16604
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
int NOT(int x) {
  return x^1;
}
int XOR(int x, int y) {
  return x^y;
}
int AND(int x, int y) {
  return x&y;
}
int expression(string &s, int &l, int &r, vector<int> &f) {
  if( '0' <= s[l] && s[l] <= '1' ) {
    return s[l]-'0';
  }else if( 'a' <= s[l] && s[l] <= 'd' ) {
    return f[s[l]-'a'];
  }else if( s[l] == '-' ) {
    l++;
    return NOT(expression(s, l, r, f));
  }else {
    int p, q;
    char c;
    for( int i = l+1, d = 0; i <= r-1; i++ ) {
      if( s[i] == '(' ) d++;
      if( s[i] == ')' ) d--;
      if( ( s[i] == '*' || s[i] == '^' ) && d == 0 ) c = s[i], p = i-1, q = i+1;
    }
    if( c == '*' ) {
      l++, r--;
      return AND(expression(s, l, p, f), expression(s, q, r, f));
    }
    if( c == '^' ) {
      l++, r--;
      return XOR(expression(s, l, p, f), expression(s, q, r, f));
    }
  }
  return -1;
}
int main() {
  int L = 16, rem = 1<<L;
  vector<int> ans(1<<L, -1);
  vector<vector<string>> E(L+1, vector<string>());
  vector<vector<int>> f_all(1<<4, vector<int>(4));
  for( int i = 0; i < 1<<4; i++ ) {
    for( int j = 0; j < 4; j++ ) {
      f_all[i][j] = (i>>j)&1;
    }
  }
  auto get_key = [&](string s) -> int {
    int ret = 0;
    for( int i = 0; i < 1<<4; i++ ) {
      int _l = 0, _r = (int)s.size()-1;
      ret |= expression(s, _l, _r, f_all[i])<<i;
    }
    return ret;
  };
  auto operate = [&](string s) -> void {
    int ret = get_key(s);
    if( ans[ret] == -1 ) {
      rem--;
      ans[ret] = (int)s.size();
    }
  };
  E[1] = {"0", "1", "a", "b", "c", "d"};
  for( string &s : E[1] ) {
    operate(s);
  }
  for( int l = 2; l <= L; l++ ) {
    for( string &s : E[l-1] ) {
      if( s.front() != '-' ) E[l].push_back("-"+s);
    }
    if( l >= 5 ) {
      for( int x = 1; x <= (l-3)/2; x++ ) {
        for( string &s : E[x] ) {
          for( string &t : E[l-3-x] ) {
            E[l].push_back("("+s+"*"+t+")");
            E[l].push_back("("+s+"^"+t+")");
          }
        }
      }
    }
    for( string &s : E[l] ) {
      if( rem == 0 ) break;
      operate(s);
    }
  }
  string e;
  while( true ) {
    cin >> e;
    if( e == "." ) break;
    cout << ans[get_key(e)] << endl;
  }
}
accuracy: 1
time_ms: 610
memory_kb: 45816
final_rank: 14

code_snippet: #include <bits/stdc++.h>

#define rep(i,s,n) for(int i = int(s); i < int(n); i++)
#define rrep(i,s,n) for(int i = int(n) - 1; i >= s; i--)
#define all(v) v.begin(), v.end()

using ll = long long;
using ull = unsigned long long;
using ld = long double;

template<class T>
bool chmin(T &a, T b) {
    if(a <= b) return false;
    a = b;
    return true;
}

template<class T>
bool chmax(T &a, T b) {
    if(a >= b) return false;
    a = b;
    return true;
}

int main() {
    const int INF = std::numeric_limits<int>::max() / 4;
    const int sz = 4;
    const int m = 1<<sz;
    const int mask = (1<<m) - 1;
    const int max = 16;
    std::vector<int> table(4, 0);
    rep(i,0,4) {
        rep(bit,0,1<<sz) {
            if((bit >> i) & 1) {
                table[i] |= (1<<bit);
            }
        }
    }
    std::vector<int> dp(1<<m, INF);
    {
        dp[0] = 1;
        dp[mask] = 1;
        std::vector<std::pair<int,int>> p;
        p.emplace_back(1, 0);
        p.emplace_back(1, mask);
        rep(i,0,4) {
            p.emplace_back(1, table[i]);
            dp[table[i]] = 1;
        }
        int idx = 0;
        while(idx < (int)p.size()) {
            auto [lenS, S] = p[idx];
            if(dp[S] < lenS || dp[S] > max) {
                idx++;
                continue;
            }
            if(dp[mask ^ S] > lenS + 1) {
                dp[mask ^ S] = lenS + 1;
                p.emplace_back(lenS + 1, mask ^ S);
            }
            rep(i,0,idx) {
                auto [lenT, T] = p[i];
                if(dp[T] < lenT) continue;
                if(dp[S^T] > lenS + lenT + 3) {
                    dp[S^T] = lenS + lenT + 3;
                    p.emplace_back(lenS + lenT + 3, S^T);
                }
                if(dp[S&T] > lenS + lenT + 3) {
                    dp[S&T] = lenS + lenT + 3;
                    p.emplace_back(lenS + lenT + 3, S & T);
                }
            }
            idx++;
        }
    }
    std::string s;
    while(std::cin >> s, s != ".") {
        int idx = 0;
        auto f = [&]() -> int {
            char c = s[idx++];
            if(c == '0') return 0;
            else if(c == '1') return (1<<m) - 1;
            else if('a' <= c && c <= 'd') {
                return table[c-'a'];
            }
            else {
                assert(0);
            }
        };
        auto expect = [&](char c) -> bool {
            return s[idx] == c;
        };
        auto consume = [&](char c) -> void {
            if(s[idx] == c) {
                idx++;
            }
            else {
                assert(0);
            }
        };
        auto E = [&](auto &&self) -> int {
            if(expect('-')) {
                consume('-');
                int e = self(self);
                return mask ^ e;
            }
            else if(expect('(')) {
                consume('(');
                int lhs = self(self);
                char c = s[idx];
                consume(c);
                int rhs = self(self);
                consume(')');
                if(c == '*') {
                    return lhs & rhs;
                }
                else if(c == '^') {
                    return lhs ^ rhs;
                }
                else {
                    assert(0);
                }
            }
            else {
                return f();
            }
        };
        int res = E(E);
        assert(idx == (int)s.size());
        std::cout << dp[res] << '\n';
    }
}
accuracy: 1
time_ms: 310
memory_kb: 5224
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vvvvll = vector<vvvll>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vvvb = vector<vvb>;
using vd = vector<double>;
using vvd = vector<vd>;
using vvvd = vector<vvd>;
#define all(A) A.begin(),A.end()
#define ALL(A) A.begin(),A.end()
#define rep(i, n) for (ll i = 0; i < (ll) (n); i++)
using pqr = priority_queue<pair<ll, ll>, vector<pair<ll, ll>>, greater<pair<ll, ll>>>;

template<class T>
bool chmax(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p < q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

template<class T>
bool chmin(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p > q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

ll gcd(ll(a), ll(b)) {
    if (b == 0)return a;
    ll c = a;
    while (a % b != 0) {
        c = a % b;
        a = b;
        b = c;
    }
    return b;
}

vll M((1 << 16), 1e18);

bool dev(string S, bool a, bool b, bool c, bool d) {
    bool res = 0;
    ll N = S.size();
    if (S[0] == '(') {
        ll kakko = 0;
        for (ll i = 1; i < N; i++) {
            if (S[i] == '(')kakko++;
            else if (S[i] == ')')kakko--;
            else if (S[i] == '^' && kakko == 0) {
                string S1 = S.substr(1, i - 1);
                string S2 = S.substr(i + 1, N - i - 2);
                return dev(S1, a, b, c, d) ^ dev(S2, a, b, c, d);
                break;
            }
            else if (S[i] == '*' && kakko == 0) {
                string S1 = S.substr(1, i - 1);
                string S2 = S.substr(i + 1, N - i - 2);
                return dev(S1, a, b, c, d) & dev(S2, a, b, c, d);
                break;
            }
        }
    }
    else if (S[0] == '-') {
        return !dev(S.substr(1, N - 1), a, b, c, d);
    }
    else if (S[0] == 'a')return a;
    else if (S[0] == 'b')return b;
    else if (S[0] == 'c')return c;
    else if (S[0] == 'd')return d;
    else if (S[0] == '0')return 0;
    else if (S[0] == '1')return 1;
    return res;
}

ll solve(string S) {
    ll res = 0;
    rep(bit, (1 << 4)) {
        bool a = (bit & 1);
        bool b = (bit & 2);
        bool c = (bit & 4);
        bool d = (bit & 8);
        if (dev(S, a, b, c, d))res += (1 << bit);
    }
    return res;
}
set<string> maked;
vector<string> V;

void make(string S) {
    if (maked.count(S))return;
    maked.insert(S);
    if(chmin(M[solve(S)], ll(S.size()))){
    
        V.push_back(S);
        make("-" + S);
        rep(i,V.size()){
            string p = V[i];
            if (p != "") {
                if (p.size() + S.size() > 10)continue;
                make("(" + p + "*" + S + ")");
                make("(" + p + "^" + S + ")");
                make("(" + S + "*" + p + ")");
                make("(" + S + "^" + p + ")");
            }
        }
    }

}



int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    maked.insert("");
    make("0");
    make("1");
    make("a");
    make("b");
    make("c");
    make("d");
    string S;
    while (cin >> S) {
        if (S == ".")return 0;
        cout << min(ll(S.size()),M[solve(S)]) << endl;
    }

}
accuracy: 1
time_ms: 10
memory_kb: 3972
final_rank: 1

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"
using namespace std;
// #include <atcoder/lazysegtree>
// using namespace atcoder;

typedef long long int ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<vvll> vvvll;
typedef vector<pll> vpll;
typedef vector<vpll> vvpll;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef priority_queue<pll, vpll, function<bool(pll, pll)> > pqpll;
typedef priority_queue<ll, vll, function<bool(pll, pll)> > pqll;

//struct edge{ ll from,to,cost; edge(ll e_from,ll e_to,ll e_cost): from(e_from), to(e_to), cost(e_cost){} };
//typedef vector<vector<edge>> Graph;

#define rep(i,a,n) for(ll i = a;i < n;i++)
#define rrep(i,a,n) for(ll i = n-1; i >= a;i--)
#define LINF (1LL << 60)
#define INF (1 << 30)
#define fs first
#define sc second
#define EPS 1e-10
#define ALL(a) a.begin(), a.end()
#define tcheck(a) if((clock() - start)/(ld)CLOCKS_PER_SEC >= a) break
#define debug(s) cout << #s << endl
#define debugval(x) cout << #x" = " << x << endl

template<typename T> ll sz(vector<T>& pos) { return (ll)pos.size(); }
template<typename T> ll sz(priority_queue<T, vector<T> >& pq) { return (ll)pq.size(); }
template<typename T> ll sz(priority_queue<T, vector<T>, greater<T> >& pq) { return (ll)pq.size(); }
ll sz(string& s) { return (ll)s.size(); }

template<typename T> void chmin(T& a, T b) { if (a > b) a = b; }
template<typename T> void chmax(T& a, T b) { if (a < b) a = b; }

ll gcd(ll a, ll b) { return ((!b) ? a : gcd(b, a % b)); }
ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }
ll dx[4] = { 0,-1,0,1 }, dy[4] = { -1,0,1,0 };
inline bool isinside(ll i, ll n) { return (i < n&& i >= 0); }

typedef string::const_iterator State;
class ParseError {};

const ll A = 0xFF00, B = 0xF0F0, C = 0xCCCC, D = 0xAAAA;

ll expr(State& begin) {
    if (*begin == '1') {
        begin++;
        return 0xFFFF;
    }
    else if (*begin == '0') {
        begin++;
        return 0;
    }
    else if ('a' <= *begin && *begin <= 'd') {
        ll res = 0;
        if (*begin == 'a') res = A;
        else if (*begin == 'b') res = B;
        else if (*begin == 'c') res = C;
        else if (*begin == 'd') res = D;
        begin++;
        return res;
    }
    else if (*begin == '-') {
        begin++;
        ll res = expr(begin);
        res ^= 0xFFFF;
        return res;
    }
    else if (*begin == '(') {
        begin++;
        ll res = expr(begin);
        char op = *begin; begin++;
        ll res2 = expr(begin);
        if (op == '^') res ^= res2;
        else if (op == '*') res &= res2;
        else {
            cout << "parseerror0 : " << *begin << endl;
            throw ParseError();
        }
        begin++;
        return res;
    }
    else {
        cout << "parseerror1 : " << *begin << endl;
        throw ParseError();
    }
    return 0;
}


string t = "01abcd";
vector<string> tvec = vector<string>({ "-E","(E^E)","(E*E)" });
int main() {
    string s;
    while (1) {
        cin >> s;
        if (s == ".") break;

        State begin = s.begin();
        ll res = expr(begin);

        ll ans = 16;
        queue<string> que;
        que.emplace("E");
        while (que.size()) {
            string str = que.front();
            que.pop();
            if (ans <= str.size())continue;
            ll ecnt = 0;
            rep(i, 0, sz(str)) if (str[i] == 'E') ecnt++;
            rep(i, 0, sz(str)) {
                if (str[i] == 'E') {
                    rep(j, 0, sz(t)) {
                        str[i] = t[j];
                        begin = str.begin();
                        if (ecnt == 1 && expr(begin) == res) chmin(ans, sz(str));
                        else if (ecnt >= 2) que.push(str);
                    }

                    rep(j, 0, sz(tvec)) {
                        string newstr = str.substr(0, i) + tvec[j] + str.substr(i + 1, sz(str) - i - 1);
                        if (sz(newstr) <= 15) que.push(newstr);
                    }
                }
            }
        }
        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 1390
memory_kb: 19432
final_rank: 15

code_snippet: #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
#include <chrono>
#include <random>
#include <queue>
#include <bitset>
#include <stack>
#include <functional>

// AtCoder
// #include <atcoder/all>
// using namespace atcoder;

#ifdef LOCAL
    #define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
    #define eprintf(...)
#endif

#define rep_(i, a_, b_, a, b, ...) for (int i = (a), i##_len = (b); i < i##_len; ++i)
#define rep(i, ...) rep_(i, __VA_ARGS__, __VA_ARGS__, 0, __VA_ARGS__)
#define reprev_(i, a_, b_, a, b, ...) for (int i = (b)-1, i##_min = (a); i >= i##_min; --i)
#define reprev(i, ...) reprev_(i, __VA_ARGS__, __VA_ARGS__, 0, __VA_ARGS__)
#define all(x) (x).begin(), (x).end()
template <class T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return 1; } return 0; }
template <class T> bool chmin(T &a, const T &b) { if (b < a) { a = b; return 1; } return 0; }
#define fls(x) (64 - __builtin_clzll(x))
#define pcnt(x) __builtin_popcountll(x)
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair <int,int> P;
typedef long double ld;

int var(char c) {
    if (c == '0') return 0b0000'0000'0000'0000;
    if (c == '1') return 0b1111'1111'1111'1111;
    if (c == 'a') return 0b1111'1111'0000'0000;
    if (c == 'b') return 0b1111'0000'1111'0000;
    if (c == 'c') return 0b1100'1100'1100'1100;
    if (c == 'd') return 0b1010'1010'1010'1010;
    // cerr << "[debug] c=" << c << endl;
    assert(false);
}
int parse(const string &s, int &cur) {
    // cerr << "[debug] cur=" << cur << " s[cur]=" << s[cur] << endl;

    int res = 0;
    if (s[cur] == '(') {
        int l = parse(s, ++cur);
        char op = s[cur++];
        int r = parse(s, cur);
        ++cur;
        if (op == '*') return l & r;
        else return l ^ r;
    } else if (s[cur] == '-') {
        int tmp = parse(s, ++cur);
        return ~tmp & 0b1111'1111'1111'1111;
    } else {
        return var(s[cur++]);
    }
    // cerr << "[debug] cur=" << cur << endl;
    assert(false);
}
int parse(const string &s) {
    int cur = 0;
    return parse(s, cur);
}
void debug_out(int res) {
    cerr << "[debug] ";
    reprev (i, 16) cerr << (res >> i & 1);
    cerr << endl;
}

vector<int> make_table(void) {
    vector<int> res(1 << 16, 1e9);
    map<int, int> mp, mp_;
    mp[var('0')] = 1;
    mp[var('1')] = 1;
    mp[var('a')] = 1;
    mp[var('b')] = 1;
    mp[var('c')] = 1;
    mp[var('d')] = 1;
    rep (_, 4) {
        for (auto [k, v] : mp) {
            // -
            int minus = ~k & 0b1111'1111'1111'1111;
            if (mp.find(minus) == mp.end()) mp[minus] = v + 1;
            else chmin(mp[minus], v + 1);
        }

        if (_ == 3) break;

        mp_ = mp;
        for (auto [k, v] : mp) {
            for (auto [k_, v_] : mp) {
                int res = k & k_;
                if (mp_.find(res) == mp_.end()) mp_[res] = v + v_ + 3;
                else chmin(mp_[res], v + v_ + 3);
            }

            // ^
            for (auto [k_, v_] : mp) {
                int res = k ^ k_;
                if (mp_.find(res) == mp_.end()) mp_[res] = v + v_ + 3;
                else chmin(mp_[res], v + v_ + 3);
            }
        }
        swap(mp, mp_);
    }
    for (auto [k, v] : mp) res[k] = v;
    return res;
}

int main (void)
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    auto table = make_table();
    string s;
    while (true) {
        cin >> s;
        if (s == ".") break;
        int parsed = parse(s);
        // debug_out(parsed);
        cout << table[parsed] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 510
memory_kb: 6288
final_rank: 12

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <climits>
#include <string>
#include <cmath>
#include <bitset>
#include <complex>
#include <functional>
#include <ctime>
#include <cassert>
#include <fstream>
#include <stack>
#include <random>
#include <iomanip>
#include <time.h>
#include <list>
#include <unordered_map>

#include <algorithm>
#include <array>

using namespace std;
typedef long long ll;
typedef long double dd;
typedef vector<ll> vl;
typedef vector<dd> vd;
typedef vector<vector<ll>> vvl;
#define i_7 (ll)(1E9+7)
//#define i_7 998244353
#define i_5 i_7-2
ll mod(ll a){
    ll c=a%i_7;
    if(c>=0)return c;
    return c+i_7;
}
typedef pair<ll,ll> l_l;
typedef pair<dd,dd> d_d;
ll inf=(ll)1E18;
#define rep(i,l,r) for(ll i=l;i<=r;i++)
#define pb push_back
ll max(ll a,ll b){if(a<b)return b;else return a;}
ll min(ll a,ll b){if(a>b)return b;else return a;}
dd EPS=1E-6;
dd PI=acos(-1);
#define endl "\n"
#define fastio ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);




ll exp(const string &s, ll &cur, const bitset<4> cha){
    if(s[cur] == '-'){
        cur++;
        ll tmp = exp(s, cur, cha);
        return 1-tmp;
    }else if(s[cur] == '('){
        cur++;
        ll t1 = exp(s, cur, cha);
        char op = s[cur];
        cur++;
        ll t2 = exp(s, cur, cha);
        cur++;
        if(op == '*'){
            return t1&t2;
        }else if(op == '^'){
            return t1^t2;
        }
        assert(0);
        return 0;
    }else if(s[cur] == '0' || s[cur] == '1'){
        ll tmp = s[cur] - '0';
        cur++;
        return tmp;
    }else{
        ll index = s[cur] - 'a';
        ll tmp = cha[index];
        cur++;
        return tmp;
    }
}

bitset<16> exp_all(const string &s){
    bitset<16> res;
    rep(i,0,15){
        bitset<4> cha(i);
        ll cur=0;
        ll exp_res = exp(s, cur, cha);
        res[i] = exp_res;
    }
    return res;
}

struct Hoge{
    ll time;
    bitset<16> value;
    Hoge(ll time, bitset<16> value){
        this->time = time;
        this->value = value;
    }
    bool operator < ( const Hoge &b ) const{
        if(this->time == b.time){
            return this->value.to_ulong() < b.value.to_ulong();
        }else{
            return this->time < b.time;
        }
    }
    
};

signed main(){fastio
    ll N=(1<<16);
    ll dp[N];
    rep(i,0,N-1)dp[i] = inf;
    
    bitset<16> bit_0("0000000000000000");
    bitset<16> bit_1("1111111111111111");
    bitset<16> bit_a("1111111100000000");
    bitset<16> bit_b("1111000011110000");
    bitset<16> bit_c("1100110011001100");
    bitset<16> bit_d("1010101010101010");
    dp[bit_0.to_ulong()] = 1;
    dp[bit_1.to_ulong()] = 1;
    dp[bit_a.to_ulong()] = 1;
    dp[bit_b.to_ulong()] = 1;
    dp[bit_c.to_ulong()] = 1;
    dp[bit_d.to_ulong()] = 1;
    set<Hoge> que;
    que.insert(Hoge(1, bit_0));
    que.insert(Hoge(1, bit_1));
    que.insert(Hoge(1, bit_a));
    que.insert(Hoge(1, bit_b));
    que.insert(Hoge(1, bit_c));
    que.insert(Hoge(1, bit_d));
    
    while(!que.empty()){
        Hoge que_tmp=*que.begin(); que.erase(que.begin());
        ll d=que_tmp.time;
        bitset<16> value = que_tmp.value;
        if(dp[value.to_ulong()] < d)continue;
        //'-'
        //cout<<value<<' '<<dp[value.to_ulong()]<<' '<<que.size()<<endl;
        if(d > 16)continue;
        
        bitset<16> not_ = ~value;
        if(dp[not_.to_ulong()] > dp[value.to_ulong()] + 1){
            dp[not_.to_ulong()] = dp[value.to_ulong()] + 1;
            que.insert(Hoge(dp[not_.to_ulong()], not_));
        }
        rep(i,0,(1<<16)-1){
            if(dp[i]==inf)continue;
            bitset<16> bi(i);
            bitset<16> and_ = value&bi;
            bitset<16> xor_ = value^bi;
            if(dp[and_.to_ulong()] > dp[value.to_ulong()] + dp[i] +3){
                dp[and_.to_ulong()] = dp[value.to_ulong()] + dp[i] +3;
                que.insert(Hoge(dp[and_.to_ulong()], and_));
            }
            if(dp[xor_.to_ulong()] > dp[value.to_ulong()] + dp[i] +3){
                dp[xor_.to_ulong()] = dp[value.to_ulong()] + dp[i] +3;
                que.insert(Hoge(dp[xor_.to_ulong()], xor_));
            }
        }
    }
    
    //cout<<"Hoge"<<endl;
    
    while(true){
        string s;cin>>s;
        if(s=="."){
            return 0;
        }
        bitset<16> res = exp_all(s);
        cout<<dp[res.to_ulong()]<<endl;
    }
    
    return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 25784
final_rank: 13