all stats

luatic's stats

guessed the most

namecorrect guessesgames togetherratio
kimapr10140.714
Palaiologos480.500
olus20007150.467
LyricLy8190.421
vspf250.400
Olivia4100.400
kotnen380.375
moshikoi270.286
Dolphy270.286
olive140.250
essaie140.250
soup girl160.167
taswelll2120.167
razetime1100.100
JJRubes050.000
IFcoltransG040.000
theqwertiest040.000

were guessed the most by

namecorrect guessesgames togetherratio
olive240.500
kotnen370.429
kimapr6140.429
moshikoi260.333
Palaiologos260.333
taswelll4120.333
LyricLy6190.316
Dolphy270.286
essaie140.250
razetime290.222
vspf150.200
JJRubes150.200
olus20003150.200
Olivia2100.200
soup girl040.000
theqwertiest040.000

entries

round #56

submitted at
0 likes

guesses
comments 0

post a comment


sus.zig ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
                                 const std=@import("std");const ArrayList                 
                                 =std.ArrayList;const Doer=struct{                        
                                 const State=enum{Normal,JustTainted                      
                        ,Tainted,TaintedGroup,Ignore,};const SyntaxError=error            
                        .InvalidSyntax;buf:ArrayList(u8),stk:ArrayList(usize              
                        ),stateStk:ArrayList(State),state:State,concatBegin               
                        :usize,pub                     fn init(alloc:anytype)Doer         
                        {return Doer                  {.buf=ArrayList(u8).init            
                        (alloc),.                     stk=ArrayList(usize).init           
                     (alloc),.         stateStk=ArrayList(State).init(alloc),.state       
                     =.Normal,         .concatBegin=0,};}pub fn startConcat(self:         
                     *Doer)void        {self.eraseConcat();self.state=.Normal;}pub        
                     fn eraseConcat (self:*Doer)void                    {self.buf.shrinkRetainingCapacity
                     (self.concatBegin);}pub fn pushState               (self:*Doer)!void 
                     {try self      .stk.append(self                    .concatBegin);try 
      self.stateStk.append(         self.state);self                             .concatBegin
      =self.buf.items.len;}         pub fn popState                              (self:   
      *Doer)!void{self.concatBegin  =self.stk.popOrNull                          () orelse 
   return SyntaxError;self.         state=self.stateStk.popOrNull() orelse unreachable;}   
   pub fn taint(self:*Doer)         void{self.eraseConcat();self.state=.Tainted;}pub fn   
   bufChar(self:*Doer,c:u8)         !void{try self.buf.append(c);}pub fn do(self:*Doer,   
   in:anytype     )![]const             u8{while(in.readByte())|c|{switch(self.state){.   
   Normal=>switch (c){'\\'=>           try self.bufChar(try in.readByte()),'|'=>self.state
   =.Ignore,      '*'=>{},'['          =>{if(try in.readByte()!=']')return SyntaxError;   
   self.state     =.JustTainted           ;},']'=>return SyntaxError,'('=>try self.pushState
   (),')'=>try     self.popState          (),else=>try self.bufChar(c),},.JustTainted     
   =>switch(      c){'\\'=>               {try in.skipBytes(1,.{});self.taint();},'*'     
   =>self.state   =.Normal,                                                '|'=>self      
   .startConcat   (),'('=>{                                                self.taint     
   ();try self    .pushState                                               ();},')'=>     
   {self.         eraseConcat                                              ();self.state  
   =.TaintedGroup ;},else=>                                                self.taint     
   (),},.         Tainted=>                                                switch(c)      
   {'\\'=>        try in.skipBytes                                         (1,.{}),'|'    
   =>self         .startConcat                                             (),'('=>try    
   self.pushState (),')'=>{                                                self.eraseConcat
   ();self.state  =.TaintedGroup                                           ;},else=>      
   {},},.TaintedGroup=>switch                                              (c){'*'=>      
   try self.      popState(                                                ),'|'=>{try    
   self.popState  ();self.startConcat                                      ();},'('=>     
   {try self.popState();self                                               .taint();      
   try self.pushState();},')'                                              =>{try self    
      .popState();self.state              =.TaintedGroup;},'\\'=>{try    in.skipBytes     
      (1,.{});try self.popState           ();self.taint();},else=>{try   self.popState    
      ();self.taint();}},.Ignore          =>switch(c){'\\','['=>try in  .skipBytes        
                     (1,.{}               ),']'=>return SyntaxError     ,'('=>try         
                     self.pushState       (),')'=>try  self.popState    (),else=>         
                     {},},}               }else|err   |{if(err!=error   .EndOfStream      
                     )return               err;}switch(self.state       ){.Normal         
                     ,.Ignore             =>return self.buf.toOwnedSlice(),else=>         
                     return                SyntaxError,}}};pub fn        main()!void      
                     {const stdout=std.io.getStdOut   ().writer();var bufout=std          
                     .io.bufferedWriter(stdout);const  stdin=std.io.getStdIn()            
                     ;var bufin=std.io.bufferedReader (stdin.reader());var arena          
                     =std.heap.ArenaAllocator.init                                        
                     (std.heap.page_allocator);defer                                      
                     arena.deinit();var doer=Doer                                         
.init(arena.allocator());try bufout.writer().writeAll(try doer.do(bufin.reader()));try bufout.flush();}

round #55

submitted at
0 likes

guesses
comments 0

post a comment


lyric.py ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from sys import stdin

M = {
    '+' : ((1, 0),
           (0, 1)),
    '/' : ((0,-1),
           (-1,0)),
    '\\': ((0, 1),
           (1, 0)),
}

L = tuple(map(str.rstrip, stdin.readlines()))

W, H = S = max(map(len, L)), len(L)

def I(p):
    x, y = p
    return y in range(H) and x in range(len(L[y])) and L[y][x] in M

def D(v, w):
    return sum(x * y for x, y in zip(v, w))

def F(p, v):
    x, y = p
    m = M[L[y][x]]
    w = tuple(map(lambda r: D(r, v), m))
    return (x + w[0], y + w[1]), w

def P(p, v):
    o = p
    while I(p):
        p, v = F(p, v)
    if abs(D(o, v) - D(p, v)) >= abs(D(S, v)) >= 8:
        exit(1)

for x in range(W):
    P((x, 0), (0, 1))
    P((x, H-1), (0, -1))

for y in range(H):
    P((0, y), (1, 0))
    P((W-1, y), (-1, 0))

def C(p):
    for v in ((0, 1), (0, -1), (1, 0), (-1, 0)):
        q = set()
        while I(p):
            q.add(p)
            p, v = F(p, v)
            if p in q:
                exit(1)

for y, l in enumerate(L):
    for x in range(len(l)):
        C((x, y))

round #54

submitted at
0 likes

guesses
comments 0

post a comment


bnuuy.tar.paq8px208fix1 data

round #53

submitted at
2 likes

guesses
comments 0

post a comment


.php Unicode text, UTF-8 text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/c/Program\ Files/PHP/php.exe
<?php
ini_set('evil_bit', 1);
$a=[];
while ($b=rtrim(fgets(STDIN), "\n\r"))
	{ $cs=array();
	  preg_match_all('/./u',$b,$cs);
	  $a[]=$cs[0];
	}
function d() {
global $a;
foreach ($a as $r)
{
	foreach ($r as $c)
		echo $c;
	echo "\n";
}
}
function ass($c) {
	if ($c) {
		return;
	}
	echo "invalid!!!";
	exit(69);
}
class RectAngle
{
	public readonly int $x1, $x2, $y1, $y2;
	public function __construct($x1, $x2, $y1, $y2) {
		$this->x1 = $x1;
		$this->x2 = $x2;
		$this->y1 = $y1;
		$this->y2 = $y2;
    }
    public function loop($f) {
		for ($x = $this->x1; $x <= $this->x2; $x++)
			for ($y = $this->y1; $y <= $this->y2; $y++)
				$f($x,$y);
    }
    public function cr() {
    	global $a;
    	$a[$this->y1][$this->x1]=$a[$this->y1][$this->x2]=$a[$this->y2][$this->x1]=$a[$this->y2][$this->x2]=' ';
    }
    public function inp($x,$y) {
    	return $x >= $this->x1 && $x <= $this->x2 && $y >= $this->y1 && $y <= $this->y2;
    }
}
if (!($h=count($a))) {
	exit;
}
$w=count($a[0]);
$rn=0;
$ls=[
	'│' => "UD",
	'─' => "LR",
	'┴' => "LRU",
	'┬' => "LRD",
	'┤' => "LUD",
	'├' => "RUD",
	'┌' => "DR",
	'┐' => "LD",
	'└' => "UR",
	'┘' => "LU",
];
$ds=[
	"L" => [-1,0],
	"R" => [1,0],
	"U" => [0,-1],
	"D" => [0,1],
];
$br=[];
foreach ($a as $y=>$r) {
	foreach ($r as $x=>$c) {
		switch ($c) {
			case '┌':
				$xn = $x;
				while (++$xn < $w && $r[$xn] != '┐');
				if ($xn==$w) continue 2;
				$yn = $y;
				while (++$yn < $h && $a[$yn][$x] != '└');
				if ($yn==$h) continue 2;
				if ($a[$yn][$xn] != '┘') continue 2;
				$re=new RectAngle($x,$xn,$y,$yn);
				$re->cr();
				$con=[++$rn=>true];
				$fl = function($x,$y) use ($re,&$br,$rn,$ds,$ls,$w,$h,&$con) {
					global $a;
					$br[$y][$x] = $rn;
					$in=0;
					$dv=null;
					ass(array_key_exists($a[$y][$x],$ls));
					foreach (str_split($ls[$a[$y][$x]]) as $dc) {
						$dw=$ds[$dc];$xm=$x+$dw[0];$ym=$y+$dw[1];
						if ($re->inp($xm,$ym)) $in++;
						else $dv = $dw;
					}
					ass($in==2);
					$a[$y][$x]=' ';
					if ($dv==null) return;
					$kill=[];
					while (1) {
						$x+=$dv[0];$y+=$dv[1];
						$kill[]=[$x,$y];
						ass((new RectAngle(0,$w-1,0,$h-1))->inp($x,$y));
						$re2 = null;
						if (array_key_exists($y,$br) && array_key_exists($x,$br[$y]))
							$re2 = $br[$y][$x];
						if ($re2!=null) {
							ass(!array_key_exists($re2,$con));
							$con[$re2]=true;
							foreach ($kill as $k)
								$a[$k[1]][$k[0]]=' ';
							break;
						}
						ass(array_key_exists($a[$y][$x],$ls));
						$sl = strlen($ls[$a[$y][$x]]);
						if ($sl==3) break;
						ass($sl==2);
						$dv2=null;
						foreach (str_split($ls[$a[$y][$x]]) as $dc) {
							$dvc=$ds[$dc];
							if ($dvc[0]!=-$dv[0] || $dvc[1]!=-$dv[1])
								$dv2=$dvc; #there is no going back
						}
						$dv=$dv2;
					}
				};
				(new RectAngle($x+1, $xn-1, $y+1, $yn-1))->loop(function($x,$y) {
					 global $a;
					ass($a[$y][$x] == ' ');
				});
				foreach ([
					new RectAngle($x+1, $xn-1, $y, $y),
					new RectAngle($x+1, $xn-1, $yn, $yn),
					new RectAngle($x, $x, $y+1, $yn-1),
					new RectAngle($xn, $xn, $y+1, $yn-1)
				] as $rl) $rl->loop($fl);
				break;
			case '│':
			case '─':
			case '┴':
			case '┬':
			case '┤':
			case '├':
			case '┐':
			case '└':
			case '┘':
			case ' ':
				break; # a ok
			default:
				ass(0);
		}
	}
}
foreach ($a as $r)
	foreach ($r as $c)
		ass($c==' ');
?>

round #52

submitted at
0 likes

guesses
comments 0

post a comment


thuemorseq.hs Unicode text, UTF-8 text
1
2
3
4
5
6
import Data.Bits (popCount, (.&.))
import Data.Function (on)
naive = [0] ++ go [0] where go seq = let inv = map (1-) seq in inv ++ go (seq ++ inv)
parity = go (0 :: Integer) where go i = popCount i .&. 1 : go (succ i)
main = if ((==) `on` take 1000) naive parity then putStrLn "Test passed" else error "Test failed"
-- 🥱

round #51

submitted at
1 like

guesses
comments 0

post a comment


tm.c ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#define mapass(v,f,...) v=f(v,##__VA_ARGS__)
enum C {Z,O,E};
const char L=-1,R=1;
typedef struct {char m;enum C w;int n;} T;
const T sts[7][3]={{
	{L,E,1},
	{L,E,1},
	{L,E,5},
},{
	{L,O,4},
	{L,Z,1},
	{R,E,2},
},{
	{R,O,3},
	{R,O,2},
	{R,O,0},
},{
	{R,Z,3},
	{R,Z,2},
	{R,Z,0},
},{
	{L,Z,4},
	{L,O,4},
	{R,E,6},
},{
	{L,Z,5},
	{L,O,5},
	{R,E,-1},
},{
	{R,E,2},
	{R,E,2},
	{R,E,2},
}};
char *dostuff(char *t)
{
	int s=0;
	++t;
	do {
		T tr=sts[s][*t];
		*t=tr.w; t+=tr.m; s=tr.n;
	} while (s!=-1);
	return t;
}
main()
{
	char c,*t=malloc(1);
	t[0]=E;
	int nt=1,ct=1;
	while (EOF!=(c=getchar())) {
		if (nt==ct) assert(mapass(t,realloc,ct<<=1));
		t[nt++]=Z;
	}
	if (nt+2>ct) assert(mapass(t,realloc,ct+2));
	t[nt++]=E;
	t[nt++]=E;
	assert(feof(stdin));
	mapass(t,dostuff);
	for(char *e=t+nt;t!=e&&*t!=E;++t)
		assert(EOF!=putchar('0'+*t));
}

round #50

submitted at
0 likes

guesses
comments 0

post a comment


thing.java ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.util.*;import java.util.regex.Pattern;import java.util.stream.*;import java.io.*;
// da spek sed "Your complete function may produce any amount of output, although the result should depend on text_so_far given some corpus."
// dis meks a infinte strem o'. do smth liek java thing.java "I like fish" <bible.txt | head -c 1000 o jst ctrl^C idk
class Thing{
public static void main(String... args){
final var corpus=new BufferedReader(new InputStreamReader(System.in)).lines().collect(Collectors.joining("\n"));
final var text_so_far=args[0];
final var n=3;
var next=new HashMap<String,ArrayList<String>>();
var p=Pattern.compile("\\w+");
var m=p.matcher(corpus);
var prevs=new ArrayList<String>();
prevs.add("");
while(m.find()){
var tok=m.group();
var ctx=prevs.get(prevs.size()-1);
for(var i=1;i<=Math.min(prevs.size()-1,n);i++){
var nexts=next.getOrDefault(ctx,new ArrayList<>());
nexts.add(tok);
next.put(ctx,nexts);
ctx=" "+prevs.get(prevs.size()-1-i)+" "+ctx;
}
prevs.add(tok);
}
var r=new Random();
m=p.matcher(text_so_far);
var ks=prevs;
prevs=new ArrayList<String>();
for (var i=0;i<n;i++)
prevs.add(ks.get(r.nextInt(ks.size())));
while (m.find())
prevs.add(m.group());
while(true){
var ctx = prevs.get(prevs.size()-1);
var choisez = new ArrayList<String>();
for(var j=1;j<=Math.min(prevs.size()-1,n);j++) {
choisez.addAll(next.getOrDefault(ctx, new ArrayList<>()));
ctx = prevs.get(prevs.size()-1-j)+" "+ctx;
}
if(choisez.isEmpty()){
for(var i=0;i<n;i++)
prevs.add(ks.get(r.nextInt(ks.size())));
}
var w = choisez.get(r.nextInt(choisez.size()));
System.out.print(" "+w);
prevs.add(w);
}
}
}

round #49

submitted at
0 likes

guesses
comments 0

post a comment


crisp.rkt ASCII text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
#lang racket
(define (proceed-parse in) (read-char in) (parse in))
(define (assert cond) (when (not cond) (raise "assertion failed")))
(define (expect in c) (assert (eqv? c (read-char in))))
(define (read-atom in)
  (let [(c (peek-char in))]
    (if (or (char-whitespace? c) (char=? #\) c)) '()
        (begin (read-char in) (cons c (read-atom in))))))
(define (skip-line in)
  (if (eqv? #\newline (read-char in)) (void) (skip-line in)))
(define (parse in)
  (let [(c (peek-char in))]
    (cond
      [(or (eof-object? c) (char=? #\) c)) '()]
      [(char=? #\# c) (begin (skip-line in) (parse in))]
      [(char-whitespace? c) (proceed-parse in)]
      [(char=? #\( c) (let [(r (proceed-parse in))]
                        (begin (expect in #\)) (cons r (parse in))))]
      [else (cons (let [(s (list->string (read-atom in)))]
                    (or (string->number s) (list 'name s)))
                  (parse in))])))
(define (fnify f)
  (lambda (args ctx) (f (eval-args args ctx))))
(define (thunk args ctx)
  (fnify (lambda (_) (last (eval-args args ctx)))))
(define (my-lambda args ctx)
  (letrec [(param (begin (assert (eqv? 'name (caar args))) (cadar args)))
           (body (cdr args))
           (f (lambda (xs)
                (if (null? xs) f
                    (let* [(new-ctx (hash-set ctx param (car xs)))
                           (res (last (eval-args body new-ctx)))]
                      (if (null? (cdr xs)) res
                          (res (cdr xs) ctx))))))]
    (fnify f)))
(define (my-quote args _) args)
(define (fnify-n n f)
  (letrec [(l (lambda (args ctx)     
                (if (null? args) l
                    (let [(arg (eval (car args) ctx))]
                      (if (= n 1)
                          (if (null? (cdr args))
                              (f arg)
                              ((f arg) (eval-args (cdr args) ctx)))
                          ((fnify-n (- n 1) (curry f arg)) (cdr args) ctx)))
                    )))] l))
(define my-t (fnify-n 2 (lambda (x y) x)))
(define my-f (fnify-n 2 (lambda (x y) y)))
(define (my-<= n m)
  (cond
    [(eq? n m) my-t]
    [(and (number? n) (number? m)) (if (<= n m) my-t my-f)]
    [(null? n) (if (pair? m) my-t my-f)]
    [(and (pair? n) (pair? m))
     (cond
       [(not (my-<= (car n) (car m))) my-f]
       [(not (my-<= (car m) (car n))) my-t]
       [else (my-<= (cdr n) (cdr m))])]
    [else my-f]))
(define (d args)
  (display args)
  (newline))
(define (my-macro margs mctx)
  (lambda (args ctx)
    (eval (last (eval-args margs (hash-set ctx "..." args))) ctx)))
(define predefs
  (hash
   ;; builtins (mostly inherited from racket)
   "d" (fnify d)
   "ib" (fnify (lambda (_) (char->integer (read-char))))
   "ob" (fnify-n 1 (lambda (c) (write-char (integer->char c))))
   "do" (fnify last)
   "car" (fnify-n 1 car)
   "cdr" (fnify-n 1 cdr)
   "cons" (fnify-n 2 cons)
   "list" (fnify identity)
   "-" (fnify-n 1 -)
   "+" (fnify-n 2 +)
   "*" (fnify-n 2 *)
   "<=" (fnify-n 2 my-<=)
   "t" my-t
   "f" my-f
   ;; special forms
   "\\\\" thunk
   "\\" my-lambda
   "'" my-quote
   "$" my-macro)) 
(define (eval-args args ctx)
  (map (lambda (arg) (eval arg ctx)) args))
(define (eval expr ctx)
  (if (pair? expr)
      (let [(f (car expr)) (args (cdr expr))]
        (if (eqv? f 'name) (hash-ref ctx (car args))
            ((eval f ctx) args ctx)))
      expr))
(define (get-file-name)
  (command-line
   #:program "crisp"
   #:args (filename)
   filename))
(define (maybe-display v)
  (when (not (eq? v (void))) (display v)))
(maybe-display (eval
                (cons (list 'name "do")
                      (call-with-input-file (get-file-name) parse))
                predefs))
stuff.crisp ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# she bangs
# (all lines starting with # actually) are ignored

# run this using "racket crisp.rkt stuff.crisp"

# d is a debug print for a list of arguments
(d 1 2 3)
# (ib) reads a byte, (ob b) writes a byte
(ob 65)
# (d (ib))
# basic math works; - is unary; +, * are strictly binary, fold them yourself
(d (+ (+ (* 4 5) (* 2 3)) (- 1)))
# lambdas (single parameter only)
(d ((\ x (\ y (+ x y))) 1 2))
# you can quote stuff, albeit unusually
(d (' + 1 2))
# automatic currying
(d (+ 1))
(d 42)
(d ((+ 1) 2))
(d 69)
# "thunks" (paramless lambdas)
(d ((\\ (+ 1 2))))
# we've got cons, car, cdr, list
(d (cons 1 2))
(d (car (cons 1 2)))
(d (cdr (cons 1 2)))
(d (')) # empty list
(d (cons 1 ('))) # list with one elem
(d (list 1 2 3))
# bools are just functions
(d (t 1 0))
(d (f 1 0))
(d (<= 1 2))
(d ((<= 1 2) 1 0))
# <= is special: it compares lexicographically and can be used to test for nil
(d ((<= (') (')) 1 0))
(d ((<= (') (' 1 2)) 1 0))
(d ((<= (' 1 2) (')) 1 0))
(d ((<= (' 1 2) (' 1 2)) 1 0))
# this is enough for a simple recursive fibonacci already
(d ((\ f (f f 10))
	(\ f (\ n (((<= n 1)
		(\\ n)
		(\\ (+ (f f (+ n (- 1))) (f f (+ n (- 2)))))))))))
# multiple things are awkward here:
# - nesting of lambdas
# - no let(rec)
# - thunks
# it's time to introduce "macros". macros are like functions,
# except they operate on the raw sexprs rather than the evaluated sexprs.
# $ is like \, but the parameter is always called ... and is implicit.
# "macro" "expansion" happens at runtime.
(d (($ (car ...)) 1 2 3))
(($ (d (list (car (' d)) ...)) (cons (car (' d)) ...)) 1 2 3)
(($ ...
	(list (list
		(car ...)
		(list (car (' \\)) (car (cdr ...)))
		(list (car (' \\)) (car (cdr (cdr ...)))))))
	t (d 1) (d 0))
# macros to solve the other problems are left as exercises to the reader

round #48

submitted at
0 likes

guesses
comments 0

post a comment


entry.ts ASCII text
1
export function entry(h:string,n:string):[number,number]|null{for(let g=1;n.length*g<=h.length;++g){const m=RegExp(n.split('').map(c=>(/[.*+?^${}()|[\]\\]/.test(c)?'\\':'')+c).join(`.{${g-1}}`)).exec(h);if(m)return[m.index,--g]}return null}// dis  onli wroks on WIDE CHARS because YES

round #47

submitted at
0 likes

guesses
comments 0

post a comment


LIS.groovy Unicode text, UTF-8 text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/*
    Efficient longest increasing subsequence finding.
    Written for Code Guessing Round 47 (https://cg.esolangs.gay/47/).
    Input: Sequence of integers delimited by spacing, ex.: 4 5 2 6 3 5
    Output: Subsequence in the same format, ex.: 4 5 6

    Code may contain minor inconsistencies;
    the author was initially trying to conceal their style (this was for code guessing, after all)
    but then effectively backpedaled on that too.

    The author recommends using at least a gigabyte of IDE bloat to have a half-decent Groovy experience.
 */

class BigIntTree implements Iterable<Iterable<Integer>> {
    class Node {
        List<Integer> is
        Node left, right
    }
    Node root

    void set(BigInteger k, int i) {
        Node node = root ?= new Node()
        for (int j = k.bitLength() - 1; j > -1; --j)
            node = k.testBit(j) ? (node.right ?= new Node()) : (node.left ?= new Node())
        (node.is ?= []).add(i)
    }
    // Breadth-first traversal of the tree gives lets us traverse the keys in sorted order
    // in linear time in the total number of digits in the input
    @Override
    Iterator<Iterable<Integer>> iterator() {
        List<Node> lvl = root == null ? [] : [root]
        int i = 0
        return new Iterator<Iterable<Integer>>() {
            @Override
            boolean hasNext() {
                return !lvl.isEmpty()
            }

            @Override
            Iterable<Integer> next() {
                List<Integer> vs
                do {
                    vs = lvl.get(i).is
                    if (++i >= lvl.size()) {
                        List<Node> nlvl = []
                        for (nd in lvl) {
                            if (nd.left != null) nlvl.add(nd.left)
                            if (nd.right != null) nlvl.add(nd.right)
                        }
                        lvl = nlvl
                        i = 0
                    }
                } while (vs == null)
                return vs
            }
        }
    }
}

class Subseq {
    class Node {
        int i
        Node prev

        Node(int i, Node prev) {
            this.i = i
            this.prev = prev
        }
    }
    int len
    Node root
    static Subseq EMPTY = new Subseq()

    Subseq() {}

    Subseq(Subseq p, int i) {
        len = (p == null ? 0 : p.len) + 1
        root = new Node(i, p.root)
    }

    BigInteger[] apply(BigInteger[] seq) {
        def res = new BigInteger[len]
        def node = this.root
        for (def i = len - 1; i > -1; i--) {
            res[i] = seq[node.i]
            node = node.prev
        }
        return res
    }
}

class SegmentTree {
    class Node {
        Subseq subseq = Subseq.EMPTY
        Node left, right

        Node(int n) {
            assert (n > 0)
            if (n == 1) return
            def mid = n >> 1
            left = new Node(mid)
            right = new Node(n - mid)
        }
        // Get best subseq s with max(s) <= n
        Subseq get(int w, int n) {
            assert n <= w
            if (w == n)
                return subseq
            def mid = w >> 1
            if (n <= mid)
                return left.get(mid, n)
            def ssl = left.subseq
            def ssr = right.get(w - mid, n - mid)
            return (ssr.len > ssl.len) ? ssr : ssl
        }
        // Set new best subseq s for max(s) <= n
        void set(int w, int n, Subseq ss) {
            assert n <= w
            if (w == n) {
                if (ss.len > subseq.len)
                    subseq = ss
                return
            }
            if (ss.len > subseq.len)
                subseq = ss
            def mid = w >> 1
            if (n <= mid) {
                left.set(mid, n, ss)
                return
            }
            // Note: We can't install this for left, since left has a stricter bound
            right.set(w - mid, n - mid, ss)
        }
    }
    Node root
    int n

    SegmentTree(int n) {
        root = new Node(this.n = n)
    }

    Subseq get(int n) {
        return root.get(this.n, n)
    }

    Subseq set(int n, Subseq ss) {
        return root.set(this.n, n, ss)
    }
}

static BigInteger[] solve(BigInteger[] seq) {
    if (seq.length == 0) return new BigInteger[0]
    def t = new BigIntTree()
    for (int i = 0; i < seq.length; ++i)
        t.set(seq[i], i)
    // Remove gaps in the ordering.
    // This is important for achieving good time complexity.
    int o = 0
    def ordinals = new int[seq.length]
    for (is in t) {
        ++o
        for (i in is)
            ordinals[i] = o
    }
    // Do the "greedy" / "dynamic programming" solving
    // using a segment tree of best subsequences for upper bounds of the last element.
    def st = new SegmentTree(o)
    for (int i = 0; i < ordinals.length; ++i) {
        def n = ordinals[i]
        def ss = n == 1 ? Subseq.EMPTY : st.get(n - 1)
        st.set(n, new Subseq(ss, i))
    }
    return st.get(o).apply(seq)
}

static BigInteger[] read() {
    def sc = new Scanner(System.in)
    List<BigInteger> s = []
    while (sc.hasNext())
        s << new BigInteger(sc.next())
    return s.toArray(new BigInteger[s.size()])
}

static void write(BigInteger[] subseq) {
    print(subseq[0])
    for (int i = 1; i < subseq.length; i++) {
        print(" ")
        print(subseq[i])
    }
    println()
}

static void main(String[] args) {
    write(solve(read()))
}

/*
    Runtime analysis:

    Let the input be a sequence of n numbers encoded in some base
    (say, binary, or decimal, with at least one digit per number), delimited by some delimiter.
    Then the length of the input is O(m), where m is the total count of digits in the input (in any fixed base).
    Constructing the prefix tree to sort the numbers is O(m) then,
    as is traversing the prefix tree in level-order (breadth-first, left to right);
    replacing numbers with their ordinals is O(m) as well
    (incrementing the ordinal o would be amortized constant time even if o were a bigint).

    For each distinct ordinal, there needs to be a distinct number in the input.
    To encode k distinct numbers, you need Θ(log(k)) bits (on average) for each number.
    This implies an input length of Θ(n log(k)) (in bits, bytes, characters, whatever, as long as it's fixed size).
    (This also imposes an upper bound of O(log n) on the length of each ordinal in bits,
    which is why this implementation elects to represent ordinals as "just integers":
    larger sequences couldn't be represented using Java data structures anyways.)

    The next step maintains a "segment tree" which maps maxima to longest subsequences
    using only elements encountered so far (a prefix of the sequence).
    Since the largest value is the largest ordinal, this segment tree has depth log(k).
    For each element in the sequence, one get and set operation are issued.
    Since these operations can both easily be seen (*) to be O(log(k)),
    we obtain O(n log(k)), which is true linear time in the input size (in bits, not in integer registers).

    (*) For a simplified analysis, assume a perfect binary segment tree (that is, k is a power of two).
    We presume big integers (which this implementation does not use for aforementioned reasons,
    but which are nevertheless relevant for runtime analysis).
    Then the comparison `w == n` would not be constant time,
    but for each bit it has to compare, it saves having to dive a layer deeper, so it is fine.
    Since we split perfectly in the middle, `n <= mid` would only have to look at the most significant bit.
    `w - mid` / `n - mid` effectively just removes that most significant bit, thus is also constant time.

    A proof of correctness will be supplied when the author finds the time and motivation.
    For now, you will have to take the author's "trust me bro" for it.

    Exercises left to the reader:

    * Test this thoroughly to convince yourself of the correctness.
    * Constant-factor optimization of the binary tree / prefix tree:
      "Compress" long paths of multiple bits (trie -> patricia tree)
    * Constant-factor optimization of the segment tree:
      Store it in an array, avoids many heap allocations, improves cache locality.
    * Rewrite this in a "better" programming language.
 */

round #46

submitted at
0 likes

guesses
comments 0

post a comment


README.rst ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
==========================
CG 46: Find Candidate Keys
==========================

Input
=====

**Tab-Separated Values** (TSV) on standard input as Olive intended.
The escape sequences ``\t``, ``\n``, ``\r`` and ``\\`` are supported.

Example
-------

Here is the example table in TSV format::

	contest	date held	winner	winner's second name
	dog fight	oct 17 2000	discarding sabot	sabot
	cat-off	jul 01 2001	palm tree oil	tree
	rat duel	oct 05 2001	cart of iron	of
	rat duel	mar 21 2006	cart of iron	of
	shark race	mar 21 2006	linguist	NULL

Output
======

For consistency, the output is also **pseudo-TSV** that is written to standard output.

Edge cases:

* The empty set of columns is represented by an empty line.
* The empty set of candidate keys is represented by no lines being printed.

Example
-------

Here is the output for the example table::

	date held	winner's second name
	date held	winner
	contest	date held
find_candidate_keys.clj Unicode text, UTF-8 text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
;; © 2042 Kim Apr
(ns find_candidate_keys
  (:require [clojure.string :as str]
            [clojure.set :as set]))
(def escs {"\\t" "\t" "\\n" "\n" "\\r" "\r" "\\\\" "\\"})
(defn rd-row [line]
  (map
   (fn [s] (str/replace s #"\\." (fn [c] (escs c c))))
   (str/split line #"\t")))
(defn rd-tsv []
  (let [ln (read-line)]
    (if (nil? ln) nil
           (cons (rd-row ln) (rd-tsv)))))
(defn transp [rws]
  (let [rst-rws (rest rws)]
    (if (empty? rst-rws)
         (map list (first rws))
        (map cons (first rws)
             (transp rst-rws)))))
(defn ntrvl [col]
  (filter
   ;; clj-kondo WILL lie to you!!!
   (fn [cl] (not (empty? (rest cl))))
   col))
(defn cl-add [cl i el] (assoc cl el (conj (cl el #{}) i)))
(defn eq-cls [col]
   (vals
    (reduce
     (fn [cl pair]
       (let [[i el] pair] (cl-add cl i el)))
      {}
     (map-indexed vector col))))
(defn mapify-eq-cls [cls]
  (reduce
   (fn [map cl]
     (reduce
      (fn [map i] (assoc map i cl))
      map
      cl))
   {}
   cls))
(defn merge-eq-cls [cls1 cls2]
  (let [m2 (mapify-eq-cls cls2)]
    (reduce
     (fn [cls cl1]
       (reduce
        (fn [cls cl2] (cons (set/intersection cl1 cl2) cls))
        cls
        (set (remove nil? (map m2 cl1)))))
     '()
     cls1)))
(defn map-subseq [f seq]
  (if (empty? seq) '()
      (cons (f seq) (map-subseq f (rest seq)))))
(defn cands [keys cnds]
  (if
   (empty? cnds) keys
   (reduce
    (fn [keys cnd]
      (if (empty? (cnd :eq))
        (cons (rest (reverse (map (comp first first) (cnd :cols)))) keys)
        (cands
         keys
         (remove nil? (map-subseq
          (fn [col]
            (let [mrgd (ntrvl (merge-eq-cls
                               (cnd :eq)
                               (ntrvl (eq-cls (rest (first col))))))]
              (if (= (cnd :eq) mrgd) nil
                  {:cols (cons col (cnd :cols)) :eq mrgd})))
          (rest (first (cnd :cols))))))))
    keys
    cnds)))
(defn cnd-empty [cols]
  (list {:cols (list (cons '() cols))
         :eq (ntrvl (list (set (range (count (rest (first cols)))))))}))
(def unescs (set/map-invert escs))
(defn wr-row [cnd]
  (println
   (str/join
    "\t"
    (map
     ;; It is with great disgust that I have to inform you that `.` in Java
     ;; matches "any character (may or may not match line terminators)"
     (fn [s] (str/replace s #".|\r|\n" (fn [c] (unescs c c)))) cnd))))
(defn wr-tsv [cnds]
  (run! wr-row cnds))
(wr-tsv (cands '() (cnd-empty (transp (rd-tsv)))))

round #45

submitted at
0 likes

guesses
comments 0

post a comment


bot.nim ASCII text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import std/bitops
import std/strutils
import std/options

type
    X = range[0'u8..6'u8]
    Y = range[0'u8..5'u8]
    Stack = set[Y]
    Mask = array[X, Stack]
    Board = tuple[ours: Mask, theirs: Mask]

type RowBitset = range[0'u8..127'u8]

proc winRowUtil (row: RowBitset): bool =
    (row and 0b0001111) == 0b0001111 or
    (row and 0b0011110) == 0b0011110 or
    (row and 0b0111100) == 0b0111100 or
    (row and 0b1111000) == 0b1111000

var winRows: set[RowBitset]
for i in RowBitset(0)..127'u8:
    if winRowUtil(i):
        winRows.incl i

proc winRow (row: RowBitset): bool =
    row in winRows

proc row (m: Mask, y: Y): RowBitset =
    for x in X(0)..6:
        if y in m[x]:
            result = result or (1'u8 shl x)

proc ascDiag (m: Mask, x: X, y: Y): RowBitset =
    var j = 0'u8
    for i in -int8(x.min(y))..int8((6-x).min(5-y)):
        if Y(int8(y) + i) in m[X(int8(x) + i)]:
            result = result or (1'u8 shl j)
        j += 1

proc descDiag (m: Mask, x: X, y: Y): RowBitset =
    var j = 0'u8
    for i in -int8((6-x).min(y))..int8(x.min(5-y)):
        if Y(int8(y) + i) in m[X(int8(x) - i)]:
            result = result or (1'u8 shl j)
        j += 1

proc winMove (m: Mask, x: X, y: Y): bool =
    winRow(cast[RowBitset](m[x])) or
    winRow(m.row(y)) or
    winRow(m.descDiag(x, y)) or
    winRow(m.ascDiag(x, y))

proc top (board: Board, x: X): Option[Y] =
    let used = cast[uint8](board.ours[x] + board.theirs[x])
    if used == 0:
        return Y(0).some
    let y = 8 - used.countLeadingZeroBits
    if y > 5:
        return Y.none
    return Y(y).some

#[
import std/unittest
suite "bot":
    test "winRow":
        check(winRow 0b1111000)
        check(winRow 0b0111100)
        check(winRow 0b0011110)
        check(winRow 0b0001111)
        check(not winRow 0b0001101)
    let m: Mask = [
        {1, 2, 3},
        {0, 3},
        {1, 2},
        {0, 1},
        {0, 4},
        {3, 4, 5},
        {1, 2, 3},
    ]
    test "row":
        check(m.row(0) == 0b0011010)
        check(m.row(1) == 0b1001101)
    test "ascDiag":
        check(m.ascDiag(1, 1) == 0b110100)
    test "descDiag":
        check(m.descDiag(1, 1) == 0b100)
    test "winMove":
        let m: Mask = [{1, 2, 3, 4}, {}, {}, {}, {}, {}, {}]
        check(m.winMove(0, 4))
    test "top":
        check((ours: m, theirs: m).top(5) == none(Y))
        check((ours: m, theirs: m).top(1) == some(Y(4)))
]#

proc applyMove (board: var Board, x: X, ours: bool) =
    let y = board.top(x).get
    if ours:
        board.ours[x].incl y
    else:
        board.theirs[x].incl y

proc maximize (board: Board, depth: uint8): tuple[score: float, move: X] =
    if depth > 7:
        return
    result.score = -1
    var foundValidMove = false
    for x in X(0)..6:
        let top = board.top(x)
        if top.isNone:
            continue
        let y = top.unsafeGet
        foundValidMove = true
        # Pick a valid move, even if it may seem futile.
        if result.score == -1:
            result.move = x
        var ours = board.ours
        ours[x].incl y
        if ours.winMove(x, y):
            return (score: 1, move: x)
        let min = -(ours: board.theirs, theirs: ours).maximize(depth + 1).score
        # Indirect win forcable?
        if min == 1:
            return (score: 1, move: x)
        if min > result.score:
            result.score = min
            result.move = x
    # Returns an invalid move value (0) but meh
    if not foundValidMove:
        result.score = 0
        

var board: Board

proc makeMove () =
    let move = board.maximize(0).move
    board.applyMove(move, true)
    echo $(move + 1)

let line = stdin.readLine
if line == "f":
    makeMove()
else:
    assert line == "s"

while true:
    let move = stdin.readLine.parseUInt()
    assert move >= 1 and move <= 7
    board.applyMove(X(move - 1), false)
    makeMove()
client.nim ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import os
import osproc
import std/strutils
import std/streams

type
    Spot = enum Free, Ours, Theirs
    Stack = array[6, Spot]
    Board = array[7, Stack]

var board: Board
var winner: Spot = Free

proc printBoard =
    for row in countdown(5, 0):
        for col in 0..6:
            const spotChar: array[Spot, char] = ['.', 'O', 'X']
            stdout.write spotChar[board[col][row]]
        stdout.write '\n'
    stdout.flushFile()

proc invalidMove (move: uint): bool =
    move < 1 or move > 7 or board[move - 1][^1] != Free

proc inBounds (x, y: int): bool =
    x >= 0 and x < 7 and y >= 0 and y < 6

proc countDir(x, y: uint, dx, dy: int): uint =
    var count: uint = 0
    var x = int(x)
    var y = int(y)
    let expected = board[x][y]
    while true:
        x += dx
        y += dy
        if not inBounds(x, y) or board[x][y] != expected:
            break
        count += 1
    return count

proc checkWinDir (x, y: uint, dx, dy: int): bool =
    return countDir(x, y, -dx, -dy) + 1 + countDir(x, y, dx, dy) >= 4

proc checkWin (x, y: uint): bool =
    checkWinDir(x, y, 0, 1) or checkWinDir(x, y, 1, 0) or checkWinDir(x, y, 1, 1)

var moves = 0
proc makeMove (move: uint, player: Spot) =
    assert player != Free
    for y, spot in board[move]:
        if spot == Free:
            board[move][y] = player
            if checkWin(move, uint(y)):
                winner = player
            moves += 1
            break

var bot = startProcess(paramStr(1), options = {})
var botIn = bot.inputStream
var botOut = bot.outputStream
proc sendCommand (command: string) =
    botIn.writeLine command
    botIn.flush
sendCommand "s" # hoomans go first!

while true:
    printBoard()
    if winner != Free or moves == 6*7:
        break
    block:
        echo "Make a move:"
        let move = stdin.readLine.parseUInt
        if invalidMove(move):
            echo "Invalid move"
            continue
        makeMove(move - 1, Ours)
        sendCommand $move
    if winner == Free:
        var line: string
        assert botOut.readLine line
        let move = line.parseUInt
        if invalidMove(move):
            echo "Invalid move from bot"
            break # can't resume with a broken bot
        makeMove(move - 1, Theirs)
bot.terminate
bot.close

const outcome: array[Spot, string] = ["Draw", "You win!", "They win!"]
echo outcome[winner]
help.txt ASCII text
1
2
Compile bot (or client): nim compile -d:release bot
Use client: ./client bot

round #44

submitted at
0 likes

guesses
comments 0

post a comment


countdown.py ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#programmer time (MY TIME) is worth MOAR than cpu time!!!!!!
import argparse
from collections import Counter
from itertools import permutations,product
class Param:
	n=1
	def eval(it): return next(it)
class Expr:
	def __init__(self,l,op,r):
		self.l,self.op,self.r,self.n=l,op,r,l.n+r.n
	def eval(self,it):
		l,r=self.l.eval(it),self.r.eval(it)
		match self.op:
			case '+': return l+r
			case '*': return l*r
			case '-': return float('nan') if l<r else l-r
			case '/': return float('nan') if not r or l%r else l/r
class Bag:
	def __init__(self,s):
		self.ops=Counter()
		self.digits=Counter()
		for c in s:
			if c in '+-*/':
				self.ops.update((c,))
			elif (d:=ord(c)-ord('0')) in range(10):
				self.digits.update((d,))
			else:
				raise ValueError('invalid string')
	def _exprs(ops):
		yield Param
		if not any(ops.values()): return
		nz=[o for o in ops if ops[o]]
		if sum(1 for _ in nz)==1 and (op:=nz[0]) in '+*':
			e=Param
			for _ in range(ops[op]):
				yield (e:=Expr(e,op,Param))
			return
		for op in ops:
			ops[op]-=1
			for splt in product(*(range(ops[o]+1) for o in ops)):
				for l,r in product(Bag._exprs({o:n for n,o in zip(splt,ops)}),Bag._exprs({o:ops[o]-n for n,o in zip(splt,ops)})):
					yield Expr(l,op,r)
			ops[op]+=1
	def exprs(self): return Bag._exprs(self.ops)
	def params(self,n): return permutations(self.digits,r=n)
	def solve(self,num): return min((expr.eval(iter(params)) for expr in self.exprs() for params in self.params(expr.n)),key=lambda x:abs(num-x))
if __name__=='__main__':
	parser=argparse.ArgumentParser()
	parser.add_argument('bag')
	parser.add_argument('num')
	args=parser.parse_args()
	print(Bag(args.bag).solve(int(args.num)))
ink.jpg JPEG image data, JFIF standard 1.01, resolution (DPI), density 300x300, segment length 16, progressive, precision 8, 4160x3120, components 3

round #43

submitted at
0 likes

guesses
comments 0

post a comment


dir spirou
main.lua Unicode text, UTF-8 text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
-- (c) 2021 🥺🥺🥺
-- this code was manualy cursed to meet the lowest standards ✅✅✅
-- "Inter-token spacing is the root of all evil." - Mahatma Gandhi
local splurped={}
do
	local ts={_G}
	local s={}
	repeat
		local ns={}
		local fr={}
		for _,t in pairs(ts) do
			s[t]=1
			for k,v in pairs(t) do
				if fr[k]==nil then
					fr[k]=v
				else
					fr[k]=fr
				end
				if type(v)=="table" and not s[v] then
					ns[#ns+1]=v
				end
			end
		end
		for k,v in pairs(fr) do
			if splurped[k]==nil and v~=fr then
				splurped[k]=v
			end
		end
		ts=ns
	until#ts==0
end
setfenv(1,setmetatable({},{__index=splurped}))
local function mapva(f,...)
	if select("#",...)==0 then return end
	return f((...)),mapva(f,select(2,...))
end
p,x,pts,stp=400,0,{},{} -- 400² is the HOLY RESOLUTION - DO NOT TOUCH!
function love.load(args)
	R,r,d=mapva(tonumber,unpack(args))
	m=p/(R-r+abs(d))*0.5*0.75
	R,r,d=R*m,r*m,d*m
	mdt = min(abs(1/(R-r)),abs(r/(R-r)/d))/10
	setTitle(((r<0)and"epi"or"hypo").."trochoid")
	setMode(p,p)
end
function love.update(fdt)
	n=ceil(fdt/mdt)
	dt=fdt/n
	for i=1,n do
		x=x-dt
		y=-x*(R-r)/r
		cx,cy=p/2,p/2
		rx,ry=cx+(R-r)*cos(x),cy+(R-r)*sin(x)
		px,py=floor(rx-d*cos(y)),floor(ry-d*sin(y))
		h=py*p+px
		if not stp[h] then
			stp[h]=1
			insert(pts,{px,py})
		end
	end
end
function love.draw()
	setColor(0,1,0,1)
	ellipse("line",cx,cy,R,R)
	ellipse("line",rx,ry,abs(r),abs(r))
	line(rx,ry,px,py)
	setColor(1,0,0,1)
	points(pts)
end
uhh.txt ASCII text
1
2
3
so uh i maded some sussy hax but they shoud work on
LOVE 11.3 (Mysterious Mysteries)
oh uh also run is "love . R r d" in foldr

round #42

submitted at
0 likes

guesses
comments 0

post a comment


dir 42
dir src
main.rs ASCII text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
// Simple 2048 game for the terminal

use crossterm::{
    self, cursor,
    event::{read, Event, KeyCode},
    execute, queue, terminal,
};
use rand::Rng;
use std::{
    fmt,
    io::{self, Stdout, Write},
};

#[derive(Copy, Clone, PartialEq)]
enum Move {
    Left,
    Right,
    Up,
    Down,
}

impl TryFrom<KeyCode> for Move {
    type Error = ();
    fn try_from(value: KeyCode) -> Result<Self, Self::Error> {
        match value {
            KeyCode::Left | KeyCode::Char('a') => Ok(Move::Left),
            KeyCode::Right | KeyCode::Char('d') => Ok(Move::Right),
            KeyCode::Up | KeyCode::Char('w') => Ok(Move::Up),
            KeyCode::Down | KeyCode::Char('s') => Ok(Move::Down),
            _ => Err(()),
        }
    }
}

#[derive(PartialEq, Clone)]
struct Board {
    tiles: [[u8; 4]; 4],
}

impl Board {
    fn random_tile() -> u8 {
        if rand::thread_rng().gen_range(1..=10) == 10 {
            2
        } else {
            1
        }
    }
    fn place_random_tile(&mut self) {
        loop {
            let y = rand::thread_rng().gen_range(0..4);
            let x = rand::thread_rng().gen_range(0..4);
            if self.tiles[y][x] == 0 {
                self.tiles[y][x] = Self::random_tile();
                break;
            }
        }
    }
    fn init() -> Self {
        let mut this = Self { tiles: [[0; 4]; 4] };
        this.place_random_tile();
        this.place_random_tile();
        this
    }
    fn transpose(&mut self) {
        let tiles = &mut self.tiles;
        for y in 0..tiles.len() {
            for x in 0..y {
                (tiles[y][x], tiles[x][y]) = (tiles[x][y], tiles[y][x]);
            }
        }
    }
    fn reverse_rows(&mut self) {
        for row in self.tiles.as_mut() {
            row.reverse()
        }
    }
    fn move_left(&mut self) {
        for row in self.tiles.as_mut() {
            for x in 1..4 {
                let mut nx = x;
                while nx > 0 && row[nx - 1] == 0 {
                    nx -= 1;
                }
                if nx > 0 && row[nx - 1] == row[x] {
                    row[nx - 1] += 1;
                    row[x] = 0;
                } else if nx < x {
                    row[nx] = row[x];
                    row[x] = 0;
                }
            }
        }
    }
    fn make_move(&mut self, mov: Move) {
        match mov {
            Move::Left => self.move_left(),
            Move::Right => {
                self.reverse_rows();
                self.move_left();
                self.reverse_rows();
            }
            Move::Up => {
                self.transpose();
                self.move_left();
                self.transpose();
            }
            Move::Down => {
                self.transpose();
                self.reverse_rows();
                self.move_left();
                self.reverse_rows();
                self.transpose();
            }
        }
    }
    fn valid_moves(&self) -> impl Iterator<Item = &Move> {
        [Move::Left, Move::Right, Move::Up, Move::Down]
            .iter()
            .filter(|&&mov| {
                let mut clone = self.clone();
                clone.make_move(mov);
                clone != *self
            })
    }
    fn won(&self) -> bool {
        const TILE_2048: u8 = 11;
        self.tiles.iter().flatten().any(|&t| t == TILE_2048)
    }
}

// TODO (...) the hardcoded carriage returns for raw terminal mode feel dirty.
impl fmt::Display for Board {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let sep: String = "+----".repeat(4) + "+\r\n";
        for row in self.tiles {
            f.write_str(&sep)?;
            f.write_str(
                &(String::from("|")
                    + &row
                        .map(|tile| {
                            if tile == 0 {
                                "    ".into()
                            } else {
                                format!("{:^4}", 1 << tile)
                            }
                        })
                        .join("|")
                    + "|\r\n"),
            )?;
        }
        f.write_str(&sep)?;
        Ok(())
    }
}

struct RawTerminal {
    stdout: Stdout,
}
impl RawTerminal {
    fn init() -> Result<Self, io::Error> {
        terminal::enable_raw_mode()?;
        let mut stdout = io::stdout();
        execute!(
            stdout,
            terminal::EnterAlternateScreen,
            crossterm::cursor::Hide
        )?;
        Ok(Self { stdout })
    }
    fn queue_reset(&mut self) -> Result<(), io::Error> {
        queue!(
            self.stdout,
            terminal::Clear(terminal::ClearType::FromCursorUp),
            cursor::MoveTo(0, 0)
        )
    }
    fn flush(&mut self) -> Result<(), io::Error> {
        self.stdout.flush()
    }
}
impl Drop for RawTerminal {
    fn drop(&mut self) {
        execute!(
            self.stdout,
            crossterm::cursor::Show,
            terminal::LeaveAlternateScreen
        )
        .unwrap();
        terminal::disable_raw_mode().unwrap();
    }
}

enum GameOutcome {
    Win,
    Loss,
    Quit,
}

fn play() -> Result<GameOutcome, io::Error> {
    let mut terminal = RawTerminal::init()?;
    let mut board = Board::init();
    'game: loop {
        terminal.queue_reset()?;
        print!("{board}");
        print!("arrow keys or WASD to play, q to quit");
        terminal.flush()?;
        if board.won() {
            return Ok(GameOutcome::Win);
        }
        let valid_moves: Vec<&Move> = board.valid_moves().collect();
        if valid_moves.is_empty() {
            return Ok(GameOutcome::Loss);
        }
        let mov = loop {
            match read()? {
                Event::Key(event) => {
                    if event.code == KeyCode::Char('q') {
                        return Ok(GameOutcome::Quit);
                    }
                    if let Ok(mov) = Move::try_from(event.code) {
                        if valid_moves.contains(&&mov) {
                            break mov;
                        }
                    }
                }
                Event::Resize(_, _) => {
                    continue 'game;
                }
                _ => (),
            }
        };
        board.make_move(mov);
        board.place_random_tile();
    }
}

fn main() {
    let outcome = play().unwrap();
    println!(
        "{}",
        match outcome {
            GameOutcome::Win => "You win!",
            GameOutcome::Loss => "You lose!",
            GameOutcome::Quit => "quit",
        }
    );
}
Cargo.lock ASCII text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3

[[package]]
name = "_2048"
version = "0.1.0"
dependencies = [
 "crossterm",
 "rand",
]

[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"

[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"

[[package]]
name = "bitflags"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"

[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"

[[package]]
name = "crossterm"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
dependencies = [
 "bitflags 2.4.0",
 "crossterm_winapi",
 "libc",
 "mio",
 "parking_lot",
 "signal-hook",
 "signal-hook-mio",
 "winapi",
]

[[package]]
name = "crossterm_winapi"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
dependencies = [
 "winapi",
]

[[package]]
name = "getrandom"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
 "cfg-if",
 "libc",
 "wasi",
]

[[package]]
name = "libc"
version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"

[[package]]
name = "lock_api"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
dependencies = [
 "autocfg",
 "scopeguard",
]

[[package]]
name = "log"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"

[[package]]
name = "mio"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [
 "libc",
 "log",
 "wasi",
 "windows-sys",
]

[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
 "lock_api",
 "parking_lot_core",
]

[[package]]
name = "parking_lot_core"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [
 "cfg-if",
 "libc",
 "redox_syscall",
 "smallvec",
 "windows-targets",
]

[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"

[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
 "libc",
 "rand_chacha",
 "rand_core",
]

[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
 "ppv-lite86",
 "rand_core",
]

[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
 "getrandom",
]

[[package]]
name = "redox_syscall"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
 "bitflags 1.3.2",
]

[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"

[[package]]
name = "signal-hook"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
dependencies = [
 "libc",
 "signal-hook-registry",
]

[[package]]
name = "signal-hook-mio"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
dependencies = [
 "libc",
 "mio",
 "signal-hook",
]

[[package]]
name = "signal-hook-registry"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
 "libc",
]

[[package]]
name = "smallvec"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"

[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"

[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
 "winapi-i686-pc-windows-gnu",
 "winapi-x86_64-pc-windows-gnu",
]

[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"

[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
 "windows-targets",
]

[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
 "windows_aarch64_gnullvm",
 "windows_aarch64_msvc",
 "windows_i686_gnu",
 "windows_i686_msvc",
 "windows_x86_64_gnu",
 "windows_x86_64_gnullvm",
 "windows_x86_64_msvc",
]

[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"

[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"

[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"

[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"

[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"

[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"

[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
Cargo.toml ASCII text
1
2
3
4
5
6
7
8
[package]
name = "_2048"
version = "0.1.0"
edition = "2021"

[dependencies]
rand = "0.8.5"
crossterm = "0.27.0"

round #41

submitted at
4 likes

guesses
comments 0

post a comment


41.zig Unicode text, UTF-8 text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
// FALSE bytecode compiler & VM for round 41 of code guessing (https://cg.esolangs.gay/41/).
// Written by Lars Müller. Licensed under the MIT license.
// Compile using `zig build-exe 41.zig -O ReleaseFast -fstrip -fsingle-threaded`.

const std = @import("std");

const Allocator = std.mem.Allocator;

const Op = enum(u32) {
	// 🥺
	Push,
	GetReg,
	SetReg,
	// Stack reordering
	Dup,
	Drop,
	Swap,
	Rot,
	Index,
	// Binops
	Add,
	Sub,
	Mul,
	Div,
	And,
	Or,
	Eq,
	Gt,
	// Unops
	Inv,
	Neg,
	// Control flow
	Jmp,
	Call,
	CallIf,
	Ret,
	LoopSetup,
	LoopTest,
	LoopBody,
	// I/O
	ReadByte,
	WriteByte,
	WriteInt, // technically redundant (like plenty of other instructions too) but I'm too laziggy and performance or something
	Flush,
};

// teknikhally this is a bytecode builder - 🤓
const Bytecode = struct {
	allocator: Allocator,
	words: std.ArrayList(u32),
	pub fn init(allocator: Allocator) Bytecode {
		return Bytecode{.allocator = allocator, .words = std.ArrayList(u32).init(allocator)};
	}
	pub fn deinit(self: *Bytecode) void {
		self.words.deinit();
	}
	pub fn getWords(self: *Bytecode) []u32 {
		return self.words.items;
	}
	fn emit(self: *Bytecode, op: Op) !void {
		try self.words.append(@intFromEnum(op));
	}
	fn emitToPatch(self: *Bytecode) !usize {
		try self.words.append(0xDEADBEEF);
		return self.words.items.len - 1;
	}
	fn patch(self: *Bytecode, i: usize, u: u32) void {
		self.words.items[i] = u;
	}
	fn emitPush(self: *Bytecode, u: u32) !void {
		try self.emit(.Push);
		try self.words.append(u);
	}
	fn append(self: *Bytecode, other: Bytecode) !u32 {
		const nextPos: u32 = @intCast(self.words.items.len);
		try self.words.appendSlice(other.words.items);
		return nextPos;
	}
};

// shot🔫 parser & bytecode emitter
fn Compiler(comptime R: type) type {
	return struct {
		const Self = @This();
		allocator: Allocator,
		in: R,
		b: ?u8 = null,
		bytecode: Bytecode,
		pub fn init(allocator: Allocator, in: R) Self {
			return Self{.allocator = allocator, .in = in, .bytecode = Bytecode.init(allocator)};
		}
		pub fn reset(self: *Self) void {
			self.b = null;
			self.bytecode = Bytecode.init(self.allocator);
		}
		pub fn deinit(self: *Self) void {
			self.bytecode.deinit();
		}

		fn readByte(self: *Self) !u8 {
			const b = self.b;
			if (b == null)
				return self.in.readByte();
			self.b = null;
			return b.?;
		}
		fn unreadByte(self: *Self, b: u8) void {
			self.b = b;
		}

		pub fn compileFn(self: *Self) !u32 {
			var bytecode = Bytecode.init(self.allocator);
			defer bytecode.deinit();
			while (true) {
				const b = self.readByte() catch |err| {
					if (err == error.EndOfStream) break;
					return err;
				};
				try switch (b) {
					'\t', ' ', '\n' => {},
					'{' => while (try self.readByte() != '}') {},
					'"' => while (true) {
						const quotedB = try self.readByte();
						if (quotedB == '"') break;
						try bytecode.emitPush(@as(u32, quotedB));
						try bytecode.emit(.WriteByte);
					},
					'\'' => {
						const quotedB = try self.readByte();
						try bytecode.emitPush(@as(u32, quotedB));
					},
					'0' ... '9' => {
						var u: u32 = b - '0';
						var nb: u8 = undefined;
						while (true) {
							nb = self.readByte() catch |err| {
								if (err == error.EndOfStream) break;
								return err;
							};
							if (nb < '0' or nb > '9') break;
							u = 10 * u + nb - '0';
						}
						self.unreadByte(nb);
						try bytecode.emitPush(u);
					},
					'a' ... 'z' => try bytecode.emitPush(@as(u32, b - 'a')),
					'[' => {
						try bytecode.emit(.Push);
						const i = try bytecode.emitToPatch();
						bytecode.patch(i, try self.compileFn());
						if (try self.readByte() != ']') return error.UnclosedQuote;
					},
					']' => {
						self.unreadByte(']');
						break;
					},
					'!' => bytecode.emit(.Call),
					'?' => bytecode.emit(.CallIf),
					'#' => {
						// too laziggy to relocate addresses for jumps so here you go, loops get three instructions
						for ([_]Op{.LoopSetup, .LoopTest, .LoopBody}) |op| try bytecode.emit(op);
					},
					else => try bytecode.emit(switch (b) {
						';' => .GetReg,
						':' => .SetReg,
						'$' => .Dup,
						'%' => .Drop,
						'\\' => .Swap,
						'@' => .Rot,
						'O' => .Index,
						'+' => .Add,
						'-' => .Sub,
						'/' => .Div,
						'*' => .Mul,
						'|' => .Or,
						'&' => .And,
						'=' => .Eq,
						'>' => .Gt,
						'~' => .Inv,
						'_' => .Neg,
						'^' => .ReadByte,
						',' => .WriteByte,
						'.' => .WriteInt,
						'B' => .Flush,
						else => return error.InvalidInstruction, // includes '`'
					}),
				};
			}
			try bytecode.emit(.Ret);
			return try self.bytecode.append(bytecode);
		}
		pub fn compile(self: *Self) !Bytecode {
			try self.bytecode.emit(.Push);
			const i = try self.bytecode.emitToPatch();
			try self.bytecode.emit(.Jmp);
			self.bytecode.patch(i, try self.compileFn());
			const bytecode = self.bytecode;
			self.reset();
			return bytecode;
		}
	};
}

// we skimp on error checking here (gotta go fast);
// FALSE programmers can be trusted to not ever make oopsies
// thus there is no typechecking (num/quote/char/reg etc.) here,
// no bounds checking, no stack overflow or underflow checking
// (Zig will trap the "unreachable" code though)
fn VM(comptime R: type, comptime W: type) type {
	return struct {
		const Self = @This();
		stack: std.ArrayList(u32),
		retstack: std.ArrayList(u32),
		regs: [32]u32 = undefined, // did you want zeroes? no zeroes for you.
		// i already gifted you a few registers, be grateful!
		in: R,
		out: W,
		pub fn init(allocator: Allocator, in: R, out: W) Self {
			return Self{
				.stack = std.ArrayList(u32).init(allocator),
				.retstack = std.ArrayList(u32).init(allocator),
				.in = in,
				.out = out,
			};
		}
		pub fn deinit(vm: *Self) void {
			vm.flush();
			vm.stack.deinit();
			vm.retstack.deinit();
		}
		fn pop(vm: *Self) u32 {
			return vm.stack.pop(); // what is an error?
		}
		fn push(vm: *Self, u: u32) void {
			vm.stack.append(u) catch unreachable; // gotta go fast
		}
		fn drop(vm: *Self) void {
			_ = vm.pop();
		}
		fn dup(vm: *Self) void {
			vm.push(vm.stack.getLast());
		}
		fn swap(vm: *Self) void {
			const top = vm.pop();
			const bot = vm.pop();
			vm.push(top);
			vm.push(bot);
		}
		fn rot(vm: *Self) void {
			const top = vm.pop();
			const mid = vm.pop();
			const bot = vm.pop();
			vm.push(mid);
			vm.push(top);
			vm.push(bot);
		}
		fn index(vm: *Self) void {
			const j = vm.pop();
			const i = vm.stack.items.len - j - 1;
			vm.push(vm.stack.items[i]); // what is an OOB
		}

		fn binop(vm: *Self, comptime op: fn(lhs: u32, rhs: u32) u32) void {
			const rhs = vm.pop();
			const lhs = vm.pop();
			vm.push(op(lhs, rhs));
		}
		// u32, i32, it's all the same (modular arithmetic says hi)
		fn add(lhs: u32, rhs: u32) u32 { return lhs +% rhs; }
		fn sub(lhs: u32, rhs: u32) u32 { return lhs -% rhs; }
		fn mul(lhs: u32, rhs: u32) u32 { return lhs *% rhs; }
		fn div(lhs: u32, rhs: u32) u32 { return @divTrunc(lhs, rhs); }
		fn band(lhs: u32, rhs: u32) u32 { return lhs & rhs; }
		fn bor(lhs: u32, rhs: u32) u32 { return lhs | rhs; }
		fn eq(lhs: u32, rhs: u32) u32 { return if (lhs == rhs) ~@as(u32, 0) else 0; }
		// okay *maybe* i lied and it's not quite as shrimple
		fn gt(lhs: u32, rhs: u32) u32 {
			// *portability* rules so let's write some inefficient branching code
			const sl = lhs >> 31;
			const sr = rhs >> 31;
			return if (if (sl == sr) lhs > rhs else sl < sr) ~@as(u32, 0) else 0;
		}

		fn unop(vm: *Self, comptime op: fn(i: u32) u32) void { vm.push(op(vm.pop())); }
		fn negate(i: u32) u32 { return 1 +% ~i; } // you should have recognized this!
		fn invert(i: u32) u32 { return ~i; }

		fn getReg(vm: *Self) void {
			const i = vm.pop();
			vm.push(vm.regs[@intCast(i)]); // OOBs don't happen, do they?
		}
		fn setReg(vm: *Self) void {
			const i = vm.pop();
			const v = vm.pop();
			vm.regs[@intCast(i)] = v;
		}

		fn readByte(vm: *Self) void {
			// no distinguishing EOF and other "errors" because yes
			vm.push(vm.in.readByte() catch ~@as(u32, 0));
		}
		fn _writeByte(vm: *Self, b: u8) void {
			const bs = [_]u8{b};
			// should we assert that it wrote exactly one character?
			_ = vm.out.write(bs[0..]) catch unreachable; // nah, nothing will go wrong.
		}
		fn writeByte(vm: *Self) void {
			vm._writeByte(@truncate(vm.pop()));
		}
		fn writeInt(vm: *Self) void {
			var i = vm.pop();
			const negative = i >> 31 == 1;
			if (negative) {
				vm._writeByte('-');
				i = 1 + ~i;
			}
			// maybe i should look up the library function for this
			var buf: [16]u8 = undefined;
			var j: u8 = 0;
			while (true) {
				buf[j] = @truncate(i % 10);
				j += 1;
				i = @divTrunc(i, 10);
				if (i == 0) break;
			}
			while (true) {
				j -= 1;
				vm._writeByte(buf[j] + '0');
				if (j == 0) break;
			}
		}
		fn flush(vm: *Self) void {
			vm.out.flush() catch unreachable;
		}
		
		pub fn run(vm: *Self, bytecode: []const u32) void {
			vm.retstack.append(@intCast(bytecode.len)) catch unreachable; // main func returning should end the program not pop an empty stack
			var ip: u32 = 0;
			while (ip < bytecode.len) {
				const op: Op = @enumFromInt(bytecode[ip]);
				switch (op) {
					// Control flow
					.Push => {
						vm.push(bytecode[ip + 1]); // surely this won't OOB
						ip += 2;
						continue;
					},
					.Jmp => {
						ip = vm.pop();
						continue;
					},
					.Call => {
						vm.retstack.append(ip + 1) catch unreachable;
						ip = vm.pop();
						continue;
					},
					.Ret => {
						ip = vm.retstack.pop();
						continue;
					},
					.CallIf => {
						const q = vm.pop();
						const v = vm.pop();
						if (v != 0) {
							vm.retstack.append(ip + 1) catch unreachable; // gotta go fast
							ip = q;
							continue;
						}
					},
					.LoopSetup => {
						const body = vm.pop();
						const cond = vm.pop();
						vm.retstack.append(body) catch unreachable;
						vm.retstack.append(cond) catch unreachable;
					},
					.LoopTest => {
						const cond = vm.retstack.getLast();
						vm.retstack.append(ip + 1) catch unreachable; // gotta go fast
						ip = cond;
						continue;
					},
					.LoopBody => {
						if (vm.pop() != 0) {
							const body = vm.retstack.items[vm.retstack.items.len - 2];
							vm.retstack.append(ip - 1) catch unreachable; // this is a sneaky one
							ip = body;
							continue;
						}
						// pop cond & body
						_ = vm.retstack.pop();
						_ = vm.retstack.pop();
					},
					// everything else
					.Dup => vm.dup(),
					.Drop => vm.drop(),
					.Swap => vm.swap(),
					.Rot => vm.rot(),
					.Index => vm.index(),
					.Add => vm.binop(add),
					.Sub => vm.binop(sub),
					.Mul => vm.binop(mul),
					.Div => vm.binop(div),
					.And => vm.binop(band),
					.Or => vm.binop(bor),
					.Eq => vm.binop(eq),
					.Gt => vm.binop(gt),
					.Neg => vm.unop(negate),
					.Inv => vm.unop(invert),
					.GetReg => vm.getReg(),
					.SetReg => vm.setReg(),
					.ReadByte => vm.readByte(),
					.WriteByte => vm.writeByte(),
					.WriteInt => vm.writeInt(),
					.Flush => vm.flush(),
				}
				ip += 1;
			}
		}
	};
}

pub fn main() !void {
	var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
	defer std.debug.assert(general_purpose_allocator.deinit() == .ok);
	const gpa = general_purpose_allocator.allocator();

	var args = try std.process.argsWithAllocator(gpa);
	defer args.deinit();
	if (!args.skip()) return error.InvalidUsage;
	const path = args.next();
	if (path == null) return error.InvalidUsage;
	var file = try std.fs.cwd().openFile(path.?, .{});
	defer file.close();
	var buf = std.io.bufferedReader(file.reader());
	var in = buf.reader();

	var compiler = Compiler(@TypeOf(in)).init(gpa, in);
	defer compiler.deinit();
	var bytecode = try compiler.compile();
	defer bytecode.deinit();

	var bufStdin = std.io.bufferedReader(std.io.getStdIn().reader());
	var stdinReader = bufStdin.reader();
	var bufStdout = std.io.bufferedWriter(std.io.getStdOut().writer());
	var vm = VM(@TypeOf(stdinReader), @TypeOf(bufStdout)).init(gpa, stdinReader, bufStdout);
	defer vm.deinit();
	vm.run(bytecode.getWords());
}
untrue.false Unicode text, UTF-8 text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
{
	FALSE self-interpreter.

	Takes a FALSE program as input, followed by `<` as a delimiter, followed by program input.
	If there is no program input, the `<` delimiter can be omitted.
	Expects ASCII: B rather than ß and O rather than ø.

	Written by Lars Müller (https://github.com/appgurueu)
	for round 41 of code guessing (https://cg.esolangs.gay/41/).
	Licensed under the MIT license.
	

	Heavily uses variables as to not interfere with what it's doing on the stack
	(splicing the stack, emitting bytecode on the stack or using the stack as the interpreter stack).

	Some FALSE operations will have linear time complexity in the size of the stack in this interpreter.
	That is, polynomial vs. superpolynomial time is preserved, but programs may get a linear time complexity factor.
}

{
	shove/splice (s):
	pop n elements,
	then call f to mutate the stack,
	then restore the popped elements

	invocation: [...]f: 42n: 32m: s;!
}
[
	n;0=
	$[% f;! 0~]?
	~[
		m;0=
		$[
			% {kill cond}
			% {kill a zero on stack}
			n; 1- n:
			32 m:
			s;!
			0 {this is to be left on the stack}
			0~ {this will be killed (cond)}
		]?
		~[
			m; 1- m:
			$ 1& {extract lowest bit}
			\ 2/ \ {>> 1 thing on stack}
			$[
				% s;! 2* 1| 0~
			]?
			~[
				s;! 2*
			]?
		]?
	]?
]s:

{
	Compiler.
	Leaves bytecode on stack.
	Uses`<` to delimit program and input.
}

0l: {bytecode length}
0t: 0n: {state t: 0 = default, 1 = number; n holds the numerical value of the number}
[^c: c;'<= c;1_= | ~] {loop until `<` or EOF is encountered}
[
	1h: {to handle? set to 0 if handled}
	'0c;> c;'9> | ~[
		c; '0- n; 10* + n: {add digit to numerical value}
		1t: {we have a number now}
		0h:
	]?
	h;[
		t;['P n; l;2+l:]? {emit a num push if necessary}
		0t: 0n: {reset state to "not a number, numerical value 0"}
	]?
	{variables}
	'ac;> c;'z> | ~[
		'P c;'a-
		l;2+l:
		0h:
	]?
	{character literals}
	c;''=[
		'P ^ {pls don't EOF here oki?}
		l;2+l:
		0h:	
	]?
	{whitespace}
	c;32{space}= c;9{tab}= c;10{newline}= ||[
		0h: {ignore whitespace; don't push it}	
	]?
	{comments}
	c;'{=[
		[^'}=~][]#
		0h:
	]?
	{string literals}
	c;'"=[
		[^$'"=~][
			{push char, then write char}
			'P \ ',
			l;3+l:
		]#
		% {murder the closing "}
		0h:
	]?
	{lambdas}
	c;'[=[
		'J 55555 {jump, address is to be replaced}
		l;2+l:
		{NOTE: we can reuse n here since it was already emitted}
		[l;]f: l;n: 32m: s;! {push start address of function on stack}
		0h:
	]?
	c;']=[
		{TODO (...) check balance}
		[q:]f: l;n: 32m: s;! {this should pop the top of the funcinfo stack, which starts right under the bytecode}
		'R l;1+l: {emit return}
		l;q; - n: {this is the length of the function - how many things to skip until we can edit the jump address before the function}
		[% l;]f: 32m: s;! {replace jump address}
		'P q; {return, push lambda}
		l;2+l:
		0h:
	]?
	c;'#=[
		'S 'T 'L
		l;3+l:
		0h:
	]?
	{TODO (...) reject invalid characters}
	h;[
		c;
		l;1+l:
	]?
]#

t;['P n; l;2+l:]? {deal with a trailing number (not that it would matter)}

'E {mark end of bytecode}

{
	Interpreter.
	Does everything on the stack.
	Stack layout: Bytecode, call stack, variables, working stack.
}

l; b: {base of the stack (start of bytecode) relative to the top}
l; c: {top of the call stack, relative to base}
{variables come after the call stack (c+x); push 26 var slots}
0 i:
[i;26=~][
	123456 {for easier debugging}
	i;1+i:
]#
b;26+b:
0 i: {program counter relative to b}
[b;i;-O 'E =~] {loop until sentinel is reached}
[
	b;i;-O {fetch instruction}
	$'P=[% i;1+i: b;i;-O b;1+b: 'E]? {push 'P <value>}
	{variables}
	$';=[%
		{take something from the stack as offset to add to c, then use as index}
		b;c;-\- 2-{1- for what we just popped, another 1- because it is in ':} O
		{-1+1=0}
	'E]?
	$':=[%
		{stack: val regno}
		\ v: {save val}
		b;2-b:
		b;c;- \ - 1- n: {n = b - c - regno - 1}
		[% v;]f: 32m: s;! {replace variable on stack}
	'E]?
	{control flow}
	{jump 'J <address>}
	$'J=[%
		i;1+i:
		b;i;-O
		1-{to undo later 1+}i: {set PC}
	'E]?
	{pop and call}
	$'!=[%
		g: {pop & remember function to call}
		[i;1+]f: b;c;- n: 32m: s;! {push next pc to call stack}
		c;1+c:
		g;1-{to undo later 1+}i: {set PC}
		{-1+1=0}
	'E]?
	{conditional call}
	$'?=[%
		b;2-b: {will pop two things}
		g: {remember func addr.}
		[
			{push to call stack}
			[i;1+]f: b;1+{pretend it was one larger (cmp with '! to see why)}c;- n: 32m: s;!
			c;1+c:
			g;1-{to undo later 1+}i: {set pc}
			b;1+b: {pushed one thing on call stack}
		]? {this pops!}
	'E]?
	{loop setup}
	$'S=[%
		g: o: {remember func addr.}
		{push condition & body lambdas on the call stack}
		[g;o;]f: b;2-c;- n:
		32m: s;!
		c;2+c:
		{no need to adjust base; all we did was move two things from stack to call stack}
	'E]?
	{loop test}
	$'T=[%
		b;c;- O
		{this is just the code for a call of `g`}
		g:
		[i;1+]f: b;1+c;- n: 32m: s;!
		c;1+c:
		g;1-i:
		b;1+b: {pushed addr to call stack, popped nothing (cond remains on call stack)}
	'E]?
	{loop looping}
	$'L=[%
		b;1-b: w:
		w;[
			b;c;-1+{body lies one deeper than cond} O
			{this is just the code for a call of `g`}
			g:
			[i;1-{sneaky one: go back to T instr}]f: b;1+c;- n: 32m: s;!
			c;1+c:
			g;1-i:
			b;1+b:
		]?
		w;0=[
			{clean up call stack: drop cond and body}
			[%%]f: b;c;- n: 32m: s;!
			c;2-c:
			b;2-b:
		]?
	'E]?
	{return}
	$'R=[%
		c;1-c:
		{pop from call stack}
		[
			1-{to undo later 1+}i:
		]f: b;c;-n: 32m: s;!
		b;1-b:
	'E]?
	{binops}
	$'+=[% + b;1-b: 'E]?
	$'-=[% - b;1-b: 'E]?
	$'*=[% * b;1-b: 'E]?
	$'/=[% / b;1-b: 'E]?
	$'&=[% & b;1-b: 'E]?
	$'|=[% | b;1-b: 'E]?
	$'>=[% > b;1-b: 'E]?
	$'==[% = b;1-b: 'E]?
	{unops}
	$'~=[% ~ 'E]?
	$'_=[% _ 'E]?
	{stack ops; these are funky}
	$'\=[% \ 'E]?
	$'@=[% @ 'E]?
	$'%=[% % b;1-b: 'E]?
	$'$=[% $ b;1+b: 'E]?
	$'O=[% O {+1-1} 'E]?
	{I/O; compiler needs to handle "..."}
	$'B=[% B 'E]?
	$'^=[% ^ b;1+b: 'E]?
	$',=[% , b;1-b: 'E]?
	'.=[. B b;1-b:]?
	i;1+i:
]#

round #40

submitted at
1 like

guesses
comments 0

post a comment


15.zip Zip archive data, at least v2.0 to extract, compression method=deflate
dir 15
dir android
dir app
dir src
dir debug
AndroidManifest.xml ASCII text
1
2
3
4
5
6
7
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- The INTERNET permission is required for development. Specifically,
         the Flutter tool needs it to communicate with the running application
         to allow setting breakpoints, to provide hot reload, etc.
    -->
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>
dir main
dir kotlin
dir com
dir example
dir fifteen
MainActivity.kt ASCII text
1
2
3
4
5
6
package com.example.fifteen

import io.flutter.embedding.android.FlutterActivity

class MainActivity: FlutterActivity() {
}
dir res
dir drawable
launch_background.xml ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@android:color/white" />

    <!-- You can insert your own image assets here -->
    <!-- <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/launch_image" />
    </item> -->
</layer-list>
dir drawable-v21
launch_background.xml ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="?android:colorBackground" />

    <!-- You can insert your own image assets here -->
    <!-- <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/launch_image" />
    </item> -->
</layer-list>
dir mipmap-hdpi
ic_launcher.png PNG image data, 72 x 72, 8-bit colormap, non-interlaced
launcher_icon.png PNG image data, 72 x 72, 8-bit/color RGBA, non-interlaced
dir mipmap-mdpi
ic_launcher.png PNG image data, 48 x 48, 8-bit colormap, non-interlaced
launcher_icon.png PNG image data, 48 x 48, 8-bit/color RGBA, non-interlaced
dir mipmap-xhdpi
ic_launcher.png PNG image data, 96 x 96, 8-bit colormap, non-interlaced
launcher_icon.png PNG image data, 96 x 96, 8-bit/color RGBA, non-interlaced
dir mipmap-xxhdpi
ic_launcher.png PNG image data, 144 x 144, 8-bit colormap, non-interlaced
launcher_icon.png PNG image data, 144 x 144, 8-bit/color RGBA, non-interlaced
dir mipmap-xxxhdpi
ic_launcher.png PNG image data, 192 x 192, 8-bit colormap, non-interlaced
launcher_icon.png PNG image data, 192 x 192, 8-bit/color RGBA, non-interlaced
dir values
styles.xml ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
    <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
        <!-- Show a splash screen on the activity. Automatically removed when
             the Flutter engine draws its first frame -->
        <item name="android:windowBackground">@drawable/launch_background</item>
    </style>
    <!-- Theme applied to the Android Window as soon as the process has started.
         This theme determines the color of the Android Window while your
         Flutter UI initializes, as well as behind your Flutter UI while its
         running.

         This Theme is only used starting with V2 of Flutter's Android embedding. -->
    <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
        <item name="android:windowBackground">?android:colorBackground</item>
    </style>
</resources>
dir values-night
styles.xml ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
        <!-- Show a splash screen on the activity. Automatically removed when
             the Flutter engine draws its first frame -->
        <item name="android:windowBackground">@drawable/launch_background</item>
    </style>
    <!-- Theme applied to the Android Window as soon as the process has started.
         This theme determines the color of the Android Window while your
         Flutter UI initializes, as well as behind your Flutter UI while its
         running.

         This Theme is only used starting with V2 of Flutter's Android embedding. -->
    <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
        <item name="android:windowBackground">?android:colorBackground</item>
    </style>
</resources>
AndroidManifest.xml ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        android:label="15"
        android:name="${applicationName}"
        android:icon="@mipmap/launcher_icon">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
	<queries>
		<intent>
			<action android:name="android.intent.action.VIEW" />
			<category android:name="android.intent.category.BROWSABLE" />
			<data android:scheme="https" />
		</intent>
	</queries>
</manifest>
dir profile
AndroidManifest.xml ASCII text
1
2
3
4
5
6
7
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- The INTERNET permission is required for development. Specifically,
         the Flutter tool needs it to communicate with the running application
         to allow setting breakpoints, to provide hot reload, etc.
    -->
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>
build.gradle ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') { reader ->
        localProperties.load(reader)
    }
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
    flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
    flutterVersionName = '1.0'
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
    namespace "com.example.fifteen"
    compileSdkVersion flutter.compileSdkVersion
    ndkVersion flutter.ndkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = '1.8'
    }

    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.example.fifteen"
        // You can update the following values to match your application needs.
        // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
        minSdkVersion flutter.minSdkVersion
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig signingConfigs.debug
        }
    }
}

flutter {
    source '../..'
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
dir gradle
dir wrapper
gradle-wrapper.properties ASCII text
1
2
3
4
5
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
build.gradle ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
buildscript {
    ext.kotlin_version = '1.7.10'
    repositories {
        google()
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:7.3.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

rootProject.buildDir = '../build'
subprojects {
    project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
    project.evaluationDependsOn(':app')
}

tasks.register("clean", Delete) {
    delete rootProject.buildDir
}
gradle.properties ASCII text
1
2
3
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
settings.gradle ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
include ':app'

def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()

assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }

def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
dir assets
icon.png PNG image data, 128 x 128, 8-bit/color RGBA, non-interlaced
icon.svg SVG Scalable Vector Graphics image
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   width="16"
   height="16"
   viewBox="0 0 4.2333332 4.2333333"
   version="1.1"
   id="svg5"
   inkscape:version="1.2.2 (732a01da63, 2022-12-09, custom)"
   sodipodi:docname="icon.svg"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:svg="http://www.w3.org/2000/svg">
  <sodipodi:namedview
     id="namedview7"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:showpageshadow="2"
     inkscape:pageopacity="0.0"
     inkscape:pagecheckerboard="0"
     inkscape:deskcolor="#d1d1d1"
     inkscape:document-units="px"
     showgrid="false"
     inkscape:zoom="1.4039843"
     inkscape:cx="14.601303"
     inkscape:cy="8.1909749"
     inkscape:window-width="1850"
     inkscape:window-height="1016"
     inkscape:window-x="0"
     inkscape:window-y="0"
     inkscape:window-maximized="1"
     inkscape:current-layer="layer1" />
  <defs
     id="defs2" />
  <g
     inkscape:label="Layer 1"
     inkscape:groupmode="layer"
     id="layer1">
    <rect
       style="fill:#ffffff;stroke:#000000;stroke-width:0.264583;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
       id="rect2269"
       width="3.96875"
       height="3.96875"
       x="0.14086828"
       y="0.14379625"
       ry="0.46099386" />
    <path
       style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       d="M 2.1166666,0.13229166 V 4.1010416"
       id="path3328"
       sodipodi:nodetypes="cc" />
    <path
       style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       d="M 4.1010417,2.1166665 H 0.13229166"
       id="path3328-3"
       sodipodi:nodetypes="cc" />
    <text
       xml:space="preserve"
       style="font-size:1.41111px;line-height:1.25;font-family:Comfortaa;-inkscape-font-specification:Comfortaa;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
       x="0.85640651"
       y="1.7070621"
       id="text3507"><tspan
         sodipodi:role="line"
         id="tspan3505"
         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Comfortaa;-inkscape-font-specification:'Comfortaa Bold';stroke-width:0.264583"
         x="0.85640651"
         y="1.7070621">1</tspan></text>
    <text
       xml:space="preserve"
       style="font-size:1.41111px;line-height:1.25;font-family:Comfortaa;-inkscape-font-specification:Comfortaa;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
       x="2.7050855"
       y="1.7001066"
       id="text3507-6"><tspan
         sodipodi:role="line"
         id="tspan3505-7"
         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Comfortaa;-inkscape-font-specification:'Comfortaa Bold';stroke-width:0.264583"
         x="2.7050855"
         y="1.7001066">2</tspan></text>
    <text
       xml:space="preserve"
       style="font-size:1.41111px;line-height:1.25;font-family:Comfortaa;-inkscape-font-specification:Comfortaa;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
       x="0.72468543"
       y="3.7001522"
       id="text3507-6-5"><tspan
         sodipodi:role="line"
         id="tspan3505-7-3"
         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Comfortaa;-inkscape-font-specification:'Comfortaa Bold';stroke-width:0.264583"
         x="0.72468543"
         y="3.7001522">3</tspan></text>
  </g>
</svg>
dir ios
dir Flutter
AppFrameworkInfo.plist ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>CFBundleDevelopmentRegion</key>
  <string>en</string>
  <key>CFBundleExecutable</key>
  <string>App</string>
  <key>CFBundleIdentifier</key>
  <string>io.flutter.flutter.app</string>
  <key>CFBundleInfoDictionaryVersion</key>
  <string>6.0</string>
  <key>CFBundleName</key>
  <string>App</string>
  <key>CFBundlePackageType</key>
  <string>FMWK</string>
  <key>CFBundleShortVersionString</key>
  <string>1.0</string>
  <key>CFBundleSignature</key>
  <string>????</string>
  <key>CFBundleVersion</key>
  <string>1.0</string>
  <key>MinimumOSVersion</key>
  <string>11.0</string>
</dict>
</plist>
Debug.xcconfig ASCII text
1
#include "Generated.xcconfig"
Release.xcconfig ASCII text
1
#include "Generated.xcconfig"
dir Runner
dir Assets.xcassets
dir AppIcon.appiconset
Contents.json JSON text data
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
{
  "images" : [
    {
      "size" : "20x20",
      "idiom" : "iphone",
      "filename" : "Icon-App-20x20@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "20x20",
      "idiom" : "iphone",
      "filename" : "Icon-App-20x20@3x.png",
      "scale" : "3x"
    },
    {
      "size" : "29x29",
      "idiom" : "iphone",
      "filename" : "Icon-App-29x29@1x.png",
      "scale" : "1x"
    },
    {
      "size" : "29x29",
      "idiom" : "iphone",
      "filename" : "Icon-App-29x29@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "29x29",
      "idiom" : "iphone",
      "filename" : "Icon-App-29x29@3x.png",
      "scale" : "3x"
    },
    {
      "size" : "40x40",
      "idiom" : "iphone",
      "filename" : "Icon-App-40x40@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "40x40",
      "idiom" : "iphone",
      "filename" : "Icon-App-40x40@3x.png",
      "scale" : "3x"
    },
    {
      "size" : "60x60",
      "idiom" : "iphone",
      "filename" : "Icon-App-60x60@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "60x60",
      "idiom" : "iphone",
      "filename" : "Icon-App-60x60@3x.png",
      "scale" : "3x"
    },
    {
      "size" : "20x20",
      "idiom" : "ipad",
      "filename" : "Icon-App-20x20@1x.png",
      "scale" : "1x"
    },
    {
      "size" : "20x20",
      "idiom" : "ipad",
      "filename" : "Icon-App-20x20@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "29x29",
      "idiom" : "ipad",
      "filename" : "Icon-App-29x29@1x.png",
      "scale" : "1x"
    },
    {
      "size" : "29x29",
      "idiom" : "ipad",
      "filename" : "Icon-App-29x29@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "40x40",
      "idiom" : "ipad",
      "filename" : "Icon-App-40x40@1x.png",
      "scale" : "1x"
    },
    {
      "size" : "40x40",
      "idiom" : "ipad",
      "filename" : "Icon-App-40x40@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "76x76",
      "idiom" : "ipad",
      "filename" : "Icon-App-76x76@1x.png",
      "scale" : "1x"
    },
    {
      "size" : "76x76",
      "idiom" : "ipad",
      "filename" : "Icon-App-76x76@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "83.5x83.5",
      "idiom" : "ipad",
      "filename" : "Icon-App-83.5x83.5@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "1024x1024",
      "idiom" : "ios-marketing",
      "filename" : "Icon-App-1024x1024@1x.png",
      "scale" : "1x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}
Icon-App-1024x1024@1x.png PNG image data, 1024 x 1024, 8-bit/color RGBA, non-interlaced
Icon-App-20x20@1x.png PNG image data, 20 x 20, 8-bit/color RGBA, non-interlaced
Icon-App-20x20@2x.png PNG image data, 40 x 40, 8-bit/color RGBA, non-interlaced
Icon-App-20x20@3x.png PNG image data, 60 x 60, 8-bit/color RGBA, non-interlaced
Icon-App-29x29@1x.png PNG image data, 29 x 29, 8-bit/color RGBA, non-interlaced
Icon-App-29x29@2x.png PNG image data, 58 x 58, 8-bit/color RGBA, non-interlaced
Icon-App-29x29@3x.png PNG image data, 87 x 87, 8-bit/color RGBA, non-interlaced
Icon-App-40x40@1x.png PNG image data, 40 x 40, 8-bit/color RGBA, non-interlaced
Icon-App-40x40@2x.png PNG image data, 80 x 80, 8-bit/color RGBA, non-interlaced
Icon-App-40x40@3x.png PNG image data, 120 x 120, 8-bit/color RGBA, non-interlaced
Icon-App-50x50@1x.png PNG image data, 50 x 50, 8-bit/color RGBA, non-interlaced
Icon-App-50x50@2x.png PNG image data, 100 x 100, 8-bit/color RGBA, non-interlaced
Icon-App-57x57@1x.png PNG image data, 57 x 57, 8-bit/color RGBA, non-interlaced
Icon-App-57x57@2x.png PNG image data, 114 x 114, 8-bit/color RGBA, non-interlaced
Icon-App-60x60@2x.png PNG image data, 120 x 120, 8-bit/color RGBA, non-interlaced
Icon-App-60x60@3x.png PNG image data, 180 x 180, 8-bit/color RGBA, non-interlaced
Icon-App-72x72@1x.png PNG image data, 72 x 72, 8-bit/color RGBA, non-interlaced
Icon-App-72x72@2x.png PNG image data, 144 x 144, 8-bit/color RGBA, non-interlaced
Icon-App-76x76@1x.png PNG image data, 76 x 76, 8-bit/color RGBA, non-interlaced
Icon-App-76x76@2x.png PNG image data, 152 x 152, 8-bit/color RGBA, non-interlaced
Icon-App-83.5x83.5@2x.png PNG image data, 167 x 167, 8-bit/color RGBA, non-interlaced
dir LaunchImage.imageset
Contents.json JSON text data
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "LaunchImage.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "LaunchImage@2x.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "filename" : "LaunchImage@3x.png",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}
LaunchImage.png PNG image data, 1 x 1, 8-bit gray+alpha, non-interlaced
LaunchImage@2x.png PNG image data, 1 x 1, 8-bit gray+alpha, non-interlaced
LaunchImage@3x.png PNG image data, 1 x 1, 8-bit gray+alpha, non-interlaced
README.md ASCII text
1
2
3
4
5
# Launch Screen Assets

You can customize the launch screen with your own desired assets by replacing the image files in this directory.

You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
dir Base.lproj
LaunchScreen.storyboard ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="EHf-IW-A2E">
            <objects>
                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
                        <viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
                            </imageView>
                        </subviews>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <constraints>
                            <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
                            <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
                        </constraints>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="53" y="375"/>
        </scene>
    </scenes>
    <resources>
        <image name="LaunchImage" width="168" height="185"/>
    </resources>
</document>
Main.storyboard ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
    </dependencies>
    <scenes>
        <!--Flutter View Controller-->
        <scene sceneID="tne-QT-ifu">
            <objects>
                <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
        </scene>
    </scenes>
</document>
AppDelegate.swift ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}
Info.plist ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleDisplayName</key>
	<string>15</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>15</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>$(FLUTTER_BUILD_NAME)</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>$(FLUTTER_BUILD_NUMBER)</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UIViewControllerBasedStatusBarAppearance</key>
	<false/>
	<key>CADisableMinimumFrameDurationOnPhone</key>
	<true/>
	<key>UIApplicationSupportsIndirectInputEvents</key>
	<true/>
</dict>
</plist>
Runner-Bridging-Header.h ASCII text
1
#import "GeneratedPluginRegistrant.h"
dir Runner.xcodeproj
dir project.xcworkspace
dir xcshareddata
IDEWorkspaceChecks.plist ASCII text
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>IDEDidComputeMac32BitWarning</key>
	<true/>
</dict>
</plist>
WorkspaceSettings.xcsettings ASCII text
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>PreviewsEnabled</key>
	<false/>
</dict>
</plist>
contents.xcworkspacedata ASCII text
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "self:">
   </FileRef>
</Workspace>
dir xcshareddata
dir xcschemes
Runner.xcscheme ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "1300"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "97C146ED1CF9000F007C117D"
               BuildableName = "Runner.app"
               BlueprintName = "Runner"
               ReferencedContainer = "container:Runner.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES">
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
            BuildableName = "Runner.app"
            BlueprintName = "Runner"
            ReferencedContainer = "container:Runner.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
      <Testables>
         <TestableReference
            skipped = "NO"
            parallelizable = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "331C8080294A63A400263BE5"
               BuildableName = "RunnerTests.xctest"
               BlueprintName = "RunnerTests"
               ReferencedContainer = "container:Runner.xcodeproj">
            </BuildableReference>
         </TestableReference>
      </Testables>
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
            BuildableName = "Runner.app"
            BlueprintName = "Runner"
            ReferencedContainer = "container:Runner.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Profile"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
            BuildableName = "Runner.app"
            BlueprintName = "Runner"
            ReferencedContainer = "container:Runner.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>
project.pbxproj ASCII text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 54;
	objects = {

/* Begin PBXBuildFile section */
		1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
		3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
		74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
		97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
		97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
		97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
		331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
		331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = 97C146E61CF9000F007C117D /* Project object */;
			proxyType = 1;
			remoteGlobalIDString = 97C146ED1CF9000F007C117D;
			remoteInfo = Runner;
		};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
		9705A1C41CF9048500538489 /* Embed Frameworks */ = {
			isa = PBXCopyFilesBuildPhase;
			buildActionMask = 2147483647;
			dstPath = "";
			dstSubfolderSpec = 10;
			files = (
			);
			name = "Embed Frameworks";
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
		1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
		1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
		3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
		74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
		74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
		7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
		9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
		9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
		97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
		97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
		97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
		97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
		97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
		331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		97C146EB1CF9000F007C117D /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		9740EEB11CF90186004384FC /* Flutter */ = {
			isa = PBXGroup;
			children = (
				3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
				9740EEB21CF90195004384FC /* Debug.xcconfig */,
				7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
				9740EEB31CF90195004384FC /* Generated.xcconfig */,
			);
			name = Flutter;
			sourceTree = "<group>";
		};
		331C8082294A63A400263BE5 /* RunnerTests */ = {
			isa = PBXGroup;
			children = (
				331C807B294A618700263BE5 /* RunnerTests.swift */,
			);
			path = RunnerTests;
			sourceTree = "<group>";
		};
		97C146E51CF9000F007C117D = {
			isa = PBXGroup;
			children = (
				9740EEB11CF90186004384FC /* Flutter */,
				97C146F01CF9000F007C117D /* Runner */,
				97C146EF1CF9000F007C117D /* Products */,
				331C8082294A63A400263BE5 /* RunnerTests */,
			);
			sourceTree = "<group>";
		};
		97C146EF1CF9000F007C117D /* Products */ = {
			isa = PBXGroup;
			children = (
				97C146EE1CF9000F007C117D /* Runner.app */,
				331C8081294A63A400263BE5 /* RunnerTests.xctest */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		97C146F01CF9000F007C117D /* Runner */ = {
			isa = PBXGroup;
			children = (
				97C146FA1CF9000F007C117D /* Main.storyboard */,
				97C146FD1CF9000F007C117D /* Assets.xcassets */,
				97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
				97C147021CF9000F007C117D /* Info.plist */,
				1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
				1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
				74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
				74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
			);
			path = Runner;
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		331C8080294A63A400263BE5 /* RunnerTests */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
			buildPhases = (
				331C807D294A63A400263BE5 /* Sources */,
				331C807E294A63A400263BE5 /* Frameworks */,
				331C807F294A63A400263BE5 /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
				331C8086294A63A400263BE5 /* PBXTargetDependency */,
			);
			name = RunnerTests;
			productName = RunnerTests;
			productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
			productType = "com.apple.product-type.bundle.unit-test";
		};
		97C146ED1CF9000F007C117D /* Runner */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
			buildPhases = (
				9740EEB61CF901F6004384FC /* Run Script */,
				97C146EA1CF9000F007C117D /* Sources */,
				97C146EB1CF9000F007C117D /* Frameworks */,
				97C146EC1CF9000F007C117D /* Resources */,
				9705A1C41CF9048500538489 /* Embed Frameworks */,
				3B06AD1E1E4923F5004D2608 /* Thin Binary */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = Runner;
			productName = Runner;
			productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
			productType = "com.apple.product-type.application";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		97C146E61CF9000F007C117D /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastUpgradeCheck = 1300;
				ORGANIZATIONNAME = "";
				TargetAttributes = {
					331C8080294A63A400263BE5 = {
						CreatedOnToolsVersion = 14.0;
						TestTargetID = 97C146ED1CF9000F007C117D;
					};
					97C146ED1CF9000F007C117D = {
						CreatedOnToolsVersion = 7.3.1;
						LastSwiftMigration = 1100;
					};
				};
			};
			buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
			compatibilityVersion = "Xcode 9.3";
			developmentRegion = en;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
				Base,
			);
			mainGroup = 97C146E51CF9000F007C117D;
			productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				97C146ED1CF9000F007C117D /* Runner */,
				331C8080294A63A400263BE5 /* RunnerTests */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		331C807F294A63A400263BE5 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		97C146EC1CF9000F007C117D /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
				3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
				97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
				97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
		3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
			isa = PBXShellScriptBuildPhase;
			alwaysOutOfDate = 1;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
				"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
			);
			name = "Thin Binary";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
		};
		9740EEB61CF901F6004384FC /* Run Script */ = {
			isa = PBXShellScriptBuildPhase;
			alwaysOutOfDate = 1;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "Run Script";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
		};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		331C807D294A63A400263BE5 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		97C146EA1CF9000F007C117D /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
				1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
		331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
			isa = PBXTargetDependency;
			target = 97C146ED1CF9000F007C117D /* Runner */;
			targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
		};
/* End PBXTargetDependency section */

/* Begin PBXVariantGroup section */
		97C146FA1CF9000F007C117D /* Main.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				97C146FB1CF9000F007C117D /* Base */,
			);
			name = Main.storyboard;
			sourceTree = "<group>";
		};
		97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				97C147001CF9000F007C117D /* Base */,
			);
			name = LaunchScreen.storyboard;
			sourceTree = "<group>";
		};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
		249021D3217E4FDB00AE95B9 /* Profile */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
				MTL_ENABLE_DEBUG_INFO = NO;
				SDKROOT = iphoneos;
				SUPPORTED_PLATFORMS = iphoneos;
				TARGETED_DEVICE_FAMILY = "1,2";
				VALIDATE_PRODUCT = YES;
			};
			name = Profile;
		};
		249021D4217E4FDB00AE95B9 /* Profile */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CLANG_ENABLE_MODULES = YES;
				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
				ENABLE_BITCODE = NO;
				INFOPLIST_FILE = Runner/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = (
					"$(inherited)",
					"@executable_path/Frameworks",
				);
				PRODUCT_BUNDLE_IDENTIFIER = com.example.fifteen;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
				SWIFT_VERSION = 5.0;
				VERSIONING_SYSTEM = "apple-generic";
			};
			name = Profile;
		};
		331C8088294A63A400263BE5 /* Debug */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = AE0B7B92F70575B8D7E0D07E /* Pods-RunnerTests.debug.xcconfig */;
			buildSettings = {
				BUNDLE_LOADER = "$(TEST_HOST)";
				CODE_SIGN_STYLE = Automatic;
				CURRENT_PROJECT_VERSION = 1;
				GENERATE_INFOPLIST_FILE = YES;
				MARKETING_VERSION = 1.0;
				PRODUCT_BUNDLE_IDENTIFIER = com.example.fifteen.RunnerTests;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
				SWIFT_VERSION = 5.0;
				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
			};
			name = Debug;
		};
		331C8089294A63A400263BE5 /* Release */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 89B67EB44CE7B6631473024E /* Pods-RunnerTests.release.xcconfig */;
			buildSettings = {
				BUNDLE_LOADER = "$(TEST_HOST)";
				CODE_SIGN_STYLE = Automatic;
				CURRENT_PROJECT_VERSION = 1;
				GENERATE_INFOPLIST_FILE = YES;
				MARKETING_VERSION = 1.0;
				PRODUCT_BUNDLE_IDENTIFIER = com.example.fifteen.RunnerTests;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_VERSION = 5.0;
				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
			};
			name = Release;
		};
		331C808A294A63A400263BE5 /* Profile */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 640959BDD8F10B91D80A66BE /* Pods-RunnerTests.profile.xcconfig */;
			buildSettings = {
				BUNDLE_LOADER = "$(TEST_HOST)";
				CODE_SIGN_STYLE = Automatic;
				CURRENT_PROJECT_VERSION = 1;
				GENERATE_INFOPLIST_FILE = YES;
				MARKETING_VERSION = 1.0;
				PRODUCT_BUNDLE_IDENTIFIER = com.example.fifteen.RunnerTests;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_VERSION = 5.0;
				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
			};
			name = Profile;
		};
		97C147031CF9000F007C117D /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = dwarf;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_TESTABILITY = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
				MTL_ENABLE_DEBUG_INFO = YES;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = iphoneos;
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Debug;
		};
		97C147041CF9000F007C117D /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
				MTL_ENABLE_DEBUG_INFO = NO;
				SDKROOT = iphoneos;
				SUPPORTED_PLATFORMS = iphoneos;
				SWIFT_COMPILATION_MODE = wholemodule;
				SWIFT_OPTIMIZATION_LEVEL = "-O";
				TARGETED_DEVICE_FAMILY = "1,2";
				VALIDATE_PRODUCT = YES;
			};
			name = Release;
		};
		97C147061CF9000F007C117D /* Debug */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CLANG_ENABLE_MODULES = YES;
				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
				ENABLE_BITCODE = NO;
				INFOPLIST_FILE = Runner/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = (
					"$(inherited)",
					"@executable_path/Frameworks",
				);
				PRODUCT_BUNDLE_IDENTIFIER = com.example.fifteen;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
				SWIFT_VERSION = 5.0;
				VERSIONING_SYSTEM = "apple-generic";
			};
			name = Debug;
		};
		97C147071CF9000F007C117D /* Release */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CLANG_ENABLE_MODULES = YES;
				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
				ENABLE_BITCODE = NO;
				INFOPLIST_FILE = Runner/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = (
					"$(inherited)",
					"@executable_path/Frameworks",
				);
				PRODUCT_BUNDLE_IDENTIFIER = com.example.fifteen;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
				SWIFT_VERSION = 5.0;
				VERSIONING_SYSTEM = "apple-generic";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				331C8088294A63A400263BE5 /* Debug */,
				331C8089294A63A400263BE5 /* Release */,
				331C808A294A63A400263BE5 /* Profile */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				97C147031CF9000F007C117D /* Debug */,
				97C147041CF9000F007C117D /* Release */,
				249021D3217E4FDB00AE95B9 /* Profile */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				97C147061CF9000F007C117D /* Debug */,
				97C147071CF9000F007C117D /* Release */,
				249021D4217E4FDB00AE95B9 /* Profile */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
dir Runner.xcworkspace
dir xcshareddata
IDEWorkspaceChecks.plist ASCII text
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>IDEDidComputeMac32BitWarning</key>
	<true/>
</dict>
</plist>
WorkspaceSettings.xcsettings ASCII text
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>PreviewsEnabled</key>
	<false/>
</dict>
</plist>
contents.xcworkspacedata ASCII text
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "group:Runner.xcodeproj">
   </FileRef>
</Workspace>
dir RunnerTests
RunnerTests.swift ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import Flutter
import UIKit
import XCTest

class RunnerTests: XCTestCase {

  func testExample() {
    // If you add code to the Runner application, consider adding tests here.
    // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
  }

}
dir lib
board.dart ASCII text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
library;

import "dart:math";

typedef Board = int;
typedef Tile = int;

const Board winningBoard = 0x0FEDCBA987654321;

Tile getTile(Board board, int i) {
  return (board >> (i << 2)) & 0xF;
}

Board setTile(Board board, int i, Tile tile) {
  final bitIdx = i << 2;
  return (board & ~(0xF << bitIdx)) | (tile << bitIdx);
}

Board swapTiles(Board board, int i, int j) {
  int a = getTile(board, i);
  int b = getTile(board, j);
  return setTile(setTile(board, i, b), j, a);
}

Board moveHoleTo(Board board, int newHolePos) {
  int bitPos = (flip(board) & 0xF) << 2;
  int newBitPos = newHolePos << 2;
  int val = (board >> newBitPos) & 0xF;
  return board ^ (val << bitPos) ^ (val << newBitPos);
}

/// Invert ("flip") the permutation of 0 - 15.
Board flip(Board board) {
  Board res = 0;
  for (int i = 0; i < 0x10; i++) {
    final tile = board & 0xF;
    res |= i << (tile << 2);
    board >>= 4;
  }
  return res;
}

bool isSolvable(Board board) {
  int inversions = 0;
  for (int i = 0; i < 0x10; i++) {
    for (int j = i + 1; j < 0x10; j++) {
      final a = getTile(board, i);
      final b = getTile(board, j);
      if (a != 0 && b != 0 && a > b) inversions++;
    }
  }
  final (_, hy) = idxToPos(getTile(flip(board), 0));
  return (inversions + hy).isOdd;
}

String toHex(Board board, [String rowsep = ""]) {
  return Iterable.generate(
      4,
      (y) => Iterable.generate(
              4, (x) => getTile(board, posToIdx(x, y)).toRadixString(0x10))
          .join()).join(rowsep);
}

Board _pack(Iterable<int> nums) {
  assert(nums.length == 0x10);
  return nums.fold(0, (board, tile) => (board << 4) | tile);
}

Board? fromHex(String hex) {
  if (!RegExp(r"^[\da-fA-F]{16}$").hasMatch(hex)) return null;
  return _pack(hex.codeUnits
      .map((c) => int.parse(String.fromCharCode(c), radix: 16))
      .toList()
      .reversed);
}

Board shuffle(Board board, int minMoves, int maxMoves) {
  var holePos = flip(board) & 0xF;
  final rand = Random();
  final moves = rand.nextInt(maxMoves) + minMoves;
  for (int i = 0; i <= moves; i++) {
    List<int> options = [];
    if (holePos > 3) options.add(-4);
    if (holePos < 12) options.add(4);
    int x = holePos & 3;
    if (x > 0) options.add(-1);
    if (x < 3) options.add(1);
    int delta = options[rand.nextInt(options.length)];
    int bitPos = holePos << 2;
    holePos += delta;
    int newBitPos = holePos << 2;
    int val = (board >> newBitPos) & 0xF;
    board ^= (val << bitPos) ^ (val << newBitPos);
  }
  return board;
}

Board randomSolvable() {
  return shuffle(winningBoard, 100, 1000);
}

int posToIdx(int x, int y) {
  return (y << 2) + x;
}

(int, int) idxToPos(int idx) {
  return (idx & 3, idx >> 2);
}

Iterable<Board> solveBFS(int solved, int toSolve, Board start) {
  int flippedMask = (toSolve << 4) | 0xF; // holes matter!
  bool predicate(Board board) => board & toSolve == winningBoard & toSolve;
  if (predicate(start)) return const Iterable.empty();
  List<(Board, Board)> level = [(start, flip(start))];
  Map<Board, Board> predecessor = {flip(start) & flippedMask: 0};
  while (level.isNotEmpty) {
    List<(Board, Board)> nextLevel = [];
    for (final tup in level) {
      final (board, flipped) = tup;
      final holePos = flipped & 0xF;
      Iterable<Board>? move(int dx, int dy) {
        int bitPos = holePos << 2;
        int newHolePos = holePos + posToIdx(dx, dy);
        int newBitPos = newHolePos << 2;
        if ((0xF << newBitPos) & solved != 0) return null;
        int val = (board >> newBitPos) & 0xF;
        final newBoard = board ^ (val << bitPos) ^ (val << newBitPos);
        int valPos = val << 2;
        final newFlipped =
            (((flipped & ~0xF) | newHolePos) & ~(0xF << valPos)) |
                (holePos << valPos);
        if (!predecessor.containsKey(newFlipped & flippedMask)) {
          predecessor[newFlipped & flippedMask] = board;
          if (predicate(newBoard)) {
            List<Board> solution = [newBoard];
            Board preBoard = board;
            while (preBoard != start) {
              solution.add(preBoard);
              preBoard = predecessor[flip(preBoard) & flippedMask]!;
            }
            return solution.reversed;
          }
          nextLevel.add((newBoard, newFlipped));
        }
        return null;
      }

      // Hot loop + no macros = ugly boilerplate (or error abuse or the like)
      final (hx, hy) = idxToPos(holePos);
      if (hx > 0) {
        final res = move(-1, 0);
        if (res != null) return res;
      }
      if (hx < 3) {
        final res = move(1, 0);
        if (res != null) return res;
      }
      if (hy > 0) {
        final res = move(0, -1);
        if (res != null) return res;
      }
      if (hy < 3) {
        final res = move(0, 1);
        if (res != null) return res;
      }
    }
    level = nextLevel;
  }
  throw "unsolvable";
}

Iterable<Board> solve(Board start) {
  const row1 = 0xFFFF;
  const row2 = row1 << 16;
  const upperHalf = row2 | row1;

  final row1Sol = solveBFS(0, row1, start);
  final row2Sol = solveBFS(row1, upperHalf, row1Sol.lastOrNull ?? start);
  final lowerSolution = solveBFS(
      upperHalf, ~0, row2Sol.lastOrNull ?? row1Sol.lastOrNull ?? start);

  return row1Sol.followedBy(row2Sol).followedBy(lowerSolution);
}
main.dart ASCII text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_launcher/url_launcher.dart';

import 'board.dart' as brd;

typedef Board = brd.Board;
typedef Tile = brd.Tile;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '15',
      theme: ThemeData(
        // Define the default brightness and colors.
        brightness: Brightness.light,
        colorSchemeSeed: Colors.lightBlueAccent,
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

class _TileWidget extends StatelessWidget {
  final Tile tile;
  final Function()? onPressed;
  final Color? disabledBackgroundColor;
  final bool showBlank;
  const _TileWidget(this.tile, this.onPressed,
      {this.disabledBackgroundColor = const Color.fromARGB(255, 134, 198, 238),
      this.showBlank = false});
  @override
  Widget build(BuildContext context) {
    if (tile == 0 && !showBlank) return Container();
    return Container(
        padding: const EdgeInsets.all(2),
        child: FilledButton(
          key: ValueKey<int>(tile),
          onPressed: onPressed,
          style: FilledButton.styleFrom(
              backgroundColor: const Color.fromARGB(255, 67, 170, 230),
              disabledBackgroundColor: disabledBackgroundColor),
          child: Text(tile == 0 ? "" : tile.toString(),
              style: DefaultTextStyle.of(context)
                  .style
                  .apply(fontSizeFactor: 2.0)),
        ));
  }
}

class _DraggableTileWidget extends StatelessWidget {
  final Tile tile;
  final int idx;
  final Function(Tile) onAccept;
  const _DraggableTileWidget(this.tile, this.idx, this.onAccept);
  @override
  Widget build(BuildContext context) {
    final Widget child = _TileWidget(tile, null, showBlank: true);
    return DragTarget<int>(
      builder: (context, candidateData, rejectedData) => LayoutBuilder(
          builder: (context, constraints) => Draggable<int>(
                data: idx,
                dragAnchorStrategy: pointerDragAnchorStrategy,
                feedback: SizedBox(
                    width: constraints.maxWidth,
                    height: constraints.maxHeight,
                    child: DefaultTextStyle.of(context).wrap(context, child)),
                childWhenDragging: _TileWidget(
                  tile,
                  null,
                  disabledBackgroundColor:
                      const Color.fromARGB(255, 190, 217, 233),
                  showBlank: true,
                ),
                child: child,
              )),
      onAccept: onAccept,
    );
  }
}

class _GameWidget extends StatefulWidget {
  final SharedPreferences? prefs;
  const _GameWidget(this.prefs);
  @override
  State<_GameWidget> createState() => _GameWidgetState();
}

class _GameWidgetState extends State<_GameWidget> {
  Board _board;
  Board get board => _board;
  bool get won => board == brd.winningBoard;
  set board(Board board) {
    _board = board;
    _persist();
  }

  bool _editing = false;
  bool get editing => _editing;
  set editing(bool editing) {
    _editing = editing;
    _persist();
  }

  // These two are deliberately not persisted
  Future<List<Board>>? _solving;
  Timer? _solutionStepper;

  _GameWidgetState() : _board = brd.randomSolvable();

  @override
  initState() {
    super.initState();
    if (widget.prefs == null) return;
    final SharedPreferences prefs = widget.prefs!;
    _editing = prefs.getBool('editing') ?? false;
    final boardHex = prefs.getString('board');
    if (boardHex != null) _board = brd.fromHex(boardHex) ?? _board;
    _persist();
  }

  _persist() {
    if (widget.prefs == null) return;
    final SharedPreferences prefs = widget.prefs!;
    prefs.setBool('editing', editing).then((success) {
      if (success) prefs.setString('board', brd.toHex(board));
      // TODO (...) log failure or notify user
    });
  }

  _move(int toIdx) {
    setState(() {
      board = brd.moveHoleTo(board, toIdx);
    });
  }

  _slide(int dx, int dy) {
    if (_solutionStepper != null || _solving != null || editing) return;
    var (hx, hy) = brd.idxToPos(brd.getTile(brd.flip(board), 0));
    // It is more intuitive to slide in the opposite direction of hole movement.
    hx -= dx;
    hy -= dy;
    if (hx < 0 || hx > 3 || hy < 0 || hy > 3) return;
    _move(brd.posToIdx(hx, hy));
  }

  _solve() {
    setState(() {
      _solving = compute((board) => brd.solve(board).toList(), board);
    });
  }

  _stop() {
    if (_solutionStepper == null) return;
    setState(() {
      _solutionStepper!.cancel();
      _solutionStepper = null;
    });
  }

  _shuffle() {
    setState(() {
      board = brd.randomSolvable();
      _solving = null;
      if (_solutionStepper != null) {
        _solutionStepper!.cancel();
        _solutionStepper = null;
      }
    });
  }

  _edit() {
    _stop();
    setState(() {
      editing = true;
    });
  }

  _done() {
    setState(() {
      editing = false;
    });
  }

  _copy() {
    Clipboard.setData(ClipboardData(text: brd.toHex(board)));
  }

  _paste() {
    Clipboard.getData(Clipboard.kTextPlain).then((value) {
      final text = value?.text;
      if (text == null) return;
      setState(() {
        final clippedboard = brd.fromHex(text);
        if (clippedboard != null) board = clippedboard;
      });
    });
  }

  _reset() {
    setState(() {
      board = brd.winningBoard;
    });
  }

  _swap(int i, j) {
    setState(() {
      board = brd.swapTiles(board, i, j);
    });
  }

  Widget _build() {
    final (hx, hy) = brd.idxToPos(brd.flip(board) & 0xF);
    final buttons = Iterable.generate(
        4,
        (y) => Iterable.generate(4, (x) {
              final idx = brd.posToIdx(x, y);
              Tile tile = brd.getTile(board, idx);
              if (editing) {
                return _DraggableTileWidget(
                  tile,
                  idx,
                  (int j) => _swap(idx, j),
                );
              }
              final neighbor = (x - hx).abs() + (y - hy).abs() == 1;
              return _TileWidget(
                tile,
                neighbor && _solutionStepper == null
                    ? () {
                        _move(idx);
                      }
                    : null,
              );
            }).toList()).toList();
    final grid = GridView.count(
      crossAxisCount: 4,
      shrinkWrap: true,
      physics: const NeverScrollableScrollPhysics(),
      children: buttons.expand((x) => x).toList(),
    );
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: editing
              ? [
                  TextButton(onPressed: _shuffle, child: const Text("Shuffle")),
                  TextButton(onPressed: _reset, child: const Text("Reset")),
                  TextButton(
                      // TODO (...?) disable if clipboard content is invalid
                      onPressed: _paste,
                      child: const Text("Paste")),
                  FilledButton(
                      onPressed: brd.isSolvable(board) ? _done : null,
                      child: const Text("Done")),
                ]
              : [
                  TextButton(onPressed: _shuffle, child: const Text("Shuffle")),
                  TextButton(onPressed: _edit, child: const Text("Edit")),
                  TextButton(
                      onPressed: brd.isSolvable(board) ? _copy : null,
                      child: const Text("Copy")),
                  _solutionStepper == null
                      ? FilledButton(
                          onPressed: won ? null : _solve,
                          child: const Text("Solve"))
                      : FilledButton(
                          onPressed: won ? null : _stop,
                          child: const Text("Stop")),
                ],
        ),
        Expanded(
            child: Center(
                child: Focus(
          autofocus: true,
          onKeyEvent: (_, keyEvent) {
            if (keyEvent is! KeyUpEvent) return KeyEventResult.ignored;
            switch (keyEvent.logicalKey) {
              case LogicalKeyboardKey.keyW:
                _slide(0, -1);
              case LogicalKeyboardKey.keyA:
                _slide(-1, 0);
              case LogicalKeyboardKey.keyS:
                _slide(0, 1);
              case LogicalKeyboardKey.keyD:
                _slide(1, 0);
              default:
                return KeyEventResult.ignored;
            }
            return KeyEventResult.handled;
          },
          child: GestureDetector(
              // TODO make sure that this fires only for the primary axis
              onHorizontalDragEnd: (DragEndDetails details) {
                if (details.primaryVelocity == null) return;
                _slide(details.primaryVelocity!.sign.toInt(), 0);
              },
              onVerticalDragEnd: (DragEndDetails details) {
                if (details.primaryVelocity == null) return;
                _slide(0, details.primaryVelocity!.sign.toInt());
              },
              child: grid),
        ))),
        TextButton(
            onPressed: () {
              launchUrl(Uri.parse("https://en.wikipedia.org/wiki/15_puzzle"),
                  mode: LaunchMode.externalApplication);
            },
            child: const Text("About")),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    if (_solving != null) {
      return FutureBuilder<List<Board>>(
        future: _solving,
        builder: (context, snapshot) {
          assert(!snapshot.hasError);
          if (snapshot.hasData) {
            _solving = null;
            final data = snapshot.data!;
            assert(data.isNotEmpty);
            int i = 0;
            _solutionStepper = Timer.periodic(
                const Duration(seconds: 1),
                (Timer t) => setState(() {
                      board = data[i];
                      i++;
                      if (i >= data.length) {
                        _solutionStepper!.cancel();
                        _solutionStepper = null;
                      }
                    }));
            return _build();
          }
          return const Center(child: CircularProgressIndicator());
        },
      );
    }
    return _build();
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  _MyHomePageState();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Container(
      padding:
          EdgeInsets.fromLTRB(0, MediaQuery.of(context).viewPadding.top, 0, 0),
      child: FutureBuilder<SharedPreferences>(
        future: SharedPreferences.getInstance(),
        builder: (context, snapshot) {
          // Behave gracefully if we don't have persistent storage.
          // TODO (...) log this or notify user about the issue
          if (snapshot.hasError) return const _GameWidget(null);
          if (snapshot.hasData) return _GameWidget(snapshot.data!);
          return const Center(child: CircularProgressIndicator());
        },
      ),
    ));
  }
}
dir linux
dir flutter
CMakeLists.txt ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# This file controls Flutter-level build steps. It should not be edited.
cmake_minimum_required(VERSION 3.10)

set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")

# Configuration provided via flutter tool.
include(${EPHEMERAL_DIR}/generated_config.cmake)

# TODO: Move the rest of this into files in ephemeral. See
# https://github.com/flutter/flutter/issues/57146.

# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
# which isn't available in 3.10.
function(list_prepend LIST_NAME PREFIX)
    set(NEW_LIST "")
    foreach(element ${${LIST_NAME}})
        list(APPEND NEW_LIST "${PREFIX}${element}")
    endforeach(element)
    set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
endfunction()

# === Flutter Library ===
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)

set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")

# Published to parent scope for install step.
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)

list(APPEND FLUTTER_LIBRARY_HEADERS
  "fl_basic_message_channel.h"
  "fl_binary_codec.h"
  "fl_binary_messenger.h"
  "fl_dart_project.h"
  "fl_engine.h"
  "fl_json_message_codec.h"
  "fl_json_method_codec.h"
  "fl_message_codec.h"
  "fl_method_call.h"
  "fl_method_channel.h"
  "fl_method_codec.h"
  "fl_method_response.h"
  "fl_plugin_registrar.h"
  "fl_plugin_registry.h"
  "fl_standard_message_codec.h"
  "fl_standard_method_codec.h"
  "fl_string_codec.h"
  "fl_value.h"
  "fl_view.h"
  "flutter_linux.h"
)
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
add_library(flutter INTERFACE)
target_include_directories(flutter INTERFACE
  "${EPHEMERAL_DIR}"
)
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
target_link_libraries(flutter INTERFACE
  PkgConfig::GTK
  PkgConfig::GLIB
  PkgConfig::GIO
)
add_dependencies(flutter flutter_assemble)

# === Flutter tool backend ===
# _phony_ is a non-existent file to force this command to run every time,
# since currently there's no way to get a full input/output list from the
# flutter tool.
add_custom_command(
  OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
    ${CMAKE_CURRENT_BINARY_DIR}/_phony_
  COMMAND ${CMAKE_COMMAND} -E env
    ${FLUTTER_TOOL_ENVIRONMENT}
    "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
      ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
  VERBATIM
)
add_custom_target(flutter_assemble DEPENDS
  "${FLUTTER_LIBRARY}"
  ${FLUTTER_LIBRARY_HEADERS}
)
generated_plugin_registrant.cc ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
//
//  Generated file. Do not edit.
//

// clang-format off

#include "generated_plugin_registrant.h"

#include <url_launcher_linux/url_launcher_plugin.h>

void fl_register_plugins(FlPluginRegistry* registry) {
  g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
      fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
  url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
}
generated_plugin_registrant.h ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
//
//  Generated file. Do not edit.
//

// clang-format off

#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_

#include <flutter_linux/flutter_linux.h>

// Registers Flutter plugins.
void fl_register_plugins(FlPluginRegistry* registry);

#endif  // GENERATED_PLUGIN_REGISTRANT_
generated_plugins.cmake ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#
# Generated file, do not edit.
#

list(APPEND FLUTTER_PLUGIN_LIST
  url_launcher_linux
)

list(APPEND FLUTTER_FFI_PLUGIN_LIST
)

set(PLUGIN_BUNDLED_LIBRARIES)

foreach(plugin ${FLUTTER_PLUGIN_LIST})
  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
  target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
  list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)

foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)
CMakeLists.txt ASCII text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# Project-level configuration.
cmake_minimum_required(VERSION 3.10)
project(runner LANGUAGES CXX)

# The name of the executable created for the application. Change this to change
# the on-disk name of your application.
set(BINARY_NAME "fifteen")
# The unique GTK application identifier for this application. See:
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
set(APPLICATION_ID "com.example.fifteen")

# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake.
cmake_policy(SET CMP0063 NEW)

# Load bundled libraries from the lib/ directory relative to the binary.
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")

# Root filesystem for cross-building.
if(FLUTTER_TARGET_PLATFORM_SYSROOT)
  set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
  set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
  set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
  set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
  set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
  set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()

# Define build configuration options.
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  set(CMAKE_BUILD_TYPE "Debug" CACHE
    STRING "Flutter build mode" FORCE)
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
    "Debug" "Profile" "Release")
endif()

# Compilation settings that should be applied to most targets.
#
# Be cautious about adding new options here, as plugins use this function by
# default. In most cases, you should add new options to specific targets instead
# of modifying this function.
function(APPLY_STANDARD_SETTINGS TARGET)
  target_compile_features(${TARGET} PUBLIC cxx_std_14)
  target_compile_options(${TARGET} PRIVATE -Wall -Werror)
  target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
  target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
endfunction()

# Flutter library and tool build rules.
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
add_subdirectory(${FLUTTER_MANAGED_DIR})

# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)

add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")

# Define the application target. To change its name, change BINARY_NAME above,
# not the value here, or `flutter run` will no longer work.
#
# Any new source files that you add to the application should be added here.
add_executable(${BINARY_NAME}
  "main.cc"
  "my_application.cc"
  "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
)

# Apply the standard set of build settings. This can be removed for applications
# that need different build settings.
apply_standard_settings(${BINARY_NAME})

# Add dependency libraries. Add any application-specific dependencies here.
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)

# Run the Flutter tool portions of the build. This must not be removed.
add_dependencies(${BINARY_NAME} flutter_assemble)

# Only the install-generated bundle's copy of the executable will launch
# correctly, since the resources must in the right relative locations. To avoid
# people trying to run the unbundled copy, put it in a subdirectory instead of
# the default top-level location.
set_target_properties(${BINARY_NAME}
  PROPERTIES
  RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
)


# Generated plugin build rules, which manage building the plugins and adding
# them to the application.
include(flutter/generated_plugins.cmake)


# === Installation ===
# By default, "installing" just makes a relocatable bundle in the build
# directory.
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
  set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
endif()

# Start with a clean build bundle directory every time.
install(CODE "
  file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
  " COMPONENT Runtime)

set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")

install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
  COMPONENT Runtime)

install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
  COMPONENT Runtime)

install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
  COMPONENT Runtime)

foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
  install(FILES "${bundled_library}"
    DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
    COMPONENT Runtime)
endforeach(bundled_library)

# Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install.
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
install(CODE "
  file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
  " COMPONENT Runtime)
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
  DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)

# Install the AOT library on non-Debug builds only.
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
  install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
    COMPONENT Runtime)
endif()
main.cc ASCII text
1
2
3
4
5
6
#include "my_application.h"

int main(int argc, char** argv) {
  g_autoptr(MyApplication) app = my_application_new();
  return g_application_run(G_APPLICATION(app), argc, argv);
}
my_application.cc ASCII text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
#include "my_application.h"

#include <flutter_linux/flutter_linux.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif

#include "flutter/generated_plugin_registrant.h"

struct _MyApplication {
  GtkApplication parent_instance;
  char** dart_entrypoint_arguments;
};

G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)

// Implements GApplication::activate.
static void my_application_activate(GApplication* application) {
  MyApplication* self = MY_APPLICATION(application);
  GtkWindow* window =
      GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));

  // Use a header bar when running in GNOME as this is the common style used
  // by applications and is the setup most users will be using (e.g. Ubuntu
  // desktop).
  // If running on X and not using GNOME then just use a traditional title bar
  // in case the window manager does more exotic layout, e.g. tiling.
  // If running on Wayland assume the header bar will work (may need changing
  // if future cases occur).
  gboolean use_header_bar = TRUE;
#ifdef GDK_WINDOWING_X11
  GdkScreen* screen = gtk_window_get_screen(window);
  if (GDK_IS_X11_SCREEN(screen)) {
    const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
    if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
      use_header_bar = FALSE;
    }
  }
#endif
  if (use_header_bar) {
    GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
    gtk_widget_show(GTK_WIDGET(header_bar));
    gtk_header_bar_set_title(header_bar, "15");
    gtk_header_bar_set_show_close_button(header_bar, TRUE);
    gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
  } else {
    gtk_window_set_title(window, "15");
  }

  gtk_window_set_default_size(window, 405, 720);
  gtk_widget_show(GTK_WIDGET(window));

  g_autoptr(FlDartProject) project = fl_dart_project_new();
  fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);

  FlView* view = fl_view_new(project);
  gtk_widget_show(GTK_WIDGET(view));
  gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));

  fl_register_plugins(FL_PLUGIN_REGISTRY(view));

  gtk_widget_grab_focus(GTK_WIDGET(view));
}

// Implements GApplication::local_command_line.
static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
  MyApplication* self = MY_APPLICATION(application);
  // Strip out the first argument as it is the binary name.
  self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);

  g_autoptr(GError) error = nullptr;
  if (!g_application_register(application, nullptr, &error)) {
     g_warning("Failed to register: %s", error->message);
     *exit_status = 1;
     return TRUE;
  }

  g_application_activate(application);
  *exit_status = 0;

  return TRUE;
}

// Implements GObject::dispose.
static void my_application_dispose(GObject* object) {
  MyApplication* self = MY_APPLICATION(object);
  g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
  G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
}

static void my_application_class_init(MyApplicationClass* klass) {
  G_APPLICATION_CLASS(klass)->activate = my_application_activate;
  G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
  G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
}

static void my_application_init(MyApplication* self) {}

MyApplication* my_application_new() {
  return MY_APPLICATION(g_object_new(my_application_get_type(),
                                     "application-id", APPLICATION_ID,
                                     "flags", G_APPLICATION_NON_UNIQUE,
                                     nullptr));
}
my_application.h ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#ifndef FLUTTER_MY_APPLICATION_H_
#define FLUTTER_MY_APPLICATION_H_

#include <gtk/gtk.h>

G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
                     GtkApplication)

/**
 * my_application_new:
 *
 * Creates a new Flutter-based application.
 *
 * Returns: a new #MyApplication.
 */
MyApplication* my_application_new();

#endif  // FLUTTER_MY_APPLICATION_H_
dir macos
dir Flutter
Flutter-Debug.xcconfig ASCII text
1
#include "ephemeral/Flutter-Generated.xcconfig"
Flutter-Release.xcconfig ASCII text
1
#include "ephemeral/Flutter-Generated.xcconfig"
GeneratedPluginRegistrant.swift ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
//
//  Generated file. Do not edit.
//

import FlutterMacOS
import Foundation

import shared_preferences_foundation
import url_launcher_macos

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
  SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
  UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
}
dir Runner
dir Assets.xcassets
dir AppIcon.appiconset
Contents.json JSON text data
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
{
    "info": {
        "version": 1,
        "author": "xcode"
    },
    "images": [
        {
            "size": "16x16",
            "idiom": "mac",
            "filename": "app_icon_16.png",
            "scale": "1x"
        },
        {
            "size": "16x16",
            "idiom": "mac",
            "filename": "app_icon_32.png",
            "scale": "2x"
        },
        {
            "size": "32x32",
            "idiom": "mac",
            "filename": "app_icon_32.png",
            "scale": "1x"
        },
        {
            "size": "32x32",
            "idiom": "mac",
            "filename": "app_icon_64.png",
            "scale": "2x"
        },
        {
            "size": "128x128",
            "idiom": "mac",
            "filename": "app_icon_128.png",
            "scale": "1x"
        },
        {
            "size": "128x128",
            "idiom": "mac",
            "filename": "app_icon_256.png",
            "scale": "2x"
        },
        {
            "size": "256x256",
            "idiom": "mac",
            "filename": "app_icon_256.png",
            "scale": "1x"
        },
        {
            "size": "256x256",
            "idiom": "mac",
            "filename": "app_icon_512.png",
            "scale": "2x"
        },
        {
            "size": "512x512",
            "idiom": "mac",
            "filename": "app_icon_512.png",
            "scale": "1x"
        },
        {
            "size": "512x512",
            "idiom": "mac",
            "filename": "app_icon_1024.png",
            "scale": "2x"
        }
    ]
}
app_icon_1024.png PNG image data, 1024 x 1024, 8-bit/color RGBA, non-interlaced
app_icon_128.png PNG image data, 128 x 128, 8-bit/color RGBA, non-interlaced
app_icon_16.png PNG image data, 16 x 16, 8-bit/color RGBA, non-interlaced
app_icon_256.png PNG image data, 256 x 256, 8-bit/color RGBA, non-interlaced
app_icon_32.png PNG image data, 32 x 32, 8-bit/color RGBA, non-interlaced
app_icon_512.png PNG image data, 512 x 512, 8-bit/color RGBA, non-interlaced
app_icon_64.png PNG image data, 64 x 64, 8-bit/color RGBA, non-interlaced
dir Base.lproj
MainMenu.xib Unicode text, UTF-8 text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
    <dependencies>
        <deployment identifier="macosx"/>
        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <objects>
        <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
            <connections>
                <outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
            </connections>
        </customObject>
        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
        <customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="Runner" customModuleProvider="target">
            <connections>
                <outlet property="applicationMenu" destination="uQy-DD-JDr" id="XBo-yE-nKs"/>
                <outlet property="mainFlutterWindow" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
            </connections>
        </customObject>
        <customObject id="YLy-65-1bz" customClass="NSFontManager"/>
        <menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
            <items>
                <menuItem title="APP_NAME" id="1Xt-HY-uBw">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <menu key="submenu" title="APP_NAME" systemMenu="apple" id="uQy-DD-JDr">
                        <items>
                            <menuItem title="About APP_NAME" id="5kV-Vb-QxS">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
                            <menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
                            <menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
                            <menuItem title="Services" id="NMo-om-nkz">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
                            <menuItem title="Hide APP_NAME" keyEquivalent="h" id="Olw-nP-bQN">
                                <connections>
                                    <action selector="hide:" target="-1" id="PnN-Uc-m68"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                <connections>
                                    <action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Show All" id="Kd2-mp-pUS">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
                            <menuItem title="Quit APP_NAME" keyEquivalent="q" id="4sb-4s-VLi">
                                <connections>
                                    <action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Edit" id="5QF-Oa-p0T">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <menu key="submenu" title="Edit" id="W48-6f-4Dl">
                        <items>
                            <menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
                                <connections>
                                    <action selector="undo:" target="-1" id="M6e-cu-g7V"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
                                <connections>
                                    <action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
                            <menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
                                <connections>
                                    <action selector="cut:" target="-1" id="YJe-68-I9s"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
                                <connections>
                                    <action selector="copy:" target="-1" id="G1f-GL-Joy"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
                                <connections>
                                    <action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                <connections>
                                    <action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Delete" id="pa3-QI-u2k">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
                                <connections>
                                    <action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
                            <menuItem title="Find" id="4EN-yA-p0u">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <menu key="submenu" title="Find" id="1b7-l0-nxx">
                                    <items>
                                        <menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
                                            <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
                                            <connections>
                                                <action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
                                    <items>
                                        <menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
                                            <connections>
                                                <action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
                                            <connections>
                                                <action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
                                        <menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem title="Substitutions" id="9ic-FL-obx">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
                                    <items>
                                        <menuItem title="Show Substitutions" id="z6F-FW-3nz">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
                                        <menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Smart Quotes" id="hQb-2v-fYv">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Smart Dashes" id="rgM-f4-ycn">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Smart Links" id="cwL-P1-jid">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Data Detectors" id="tRr-pd-1PS">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Text Replacement" id="HFQ-gK-NFA">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem title="Transformations" id="2oI-Rn-ZJC">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <menu key="submenu" title="Transformations" id="c8a-y6-VQd">
                                    <items>
                                        <menuItem title="Make Upper Case" id="vmV-6d-7jI">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Make Lower Case" id="d9M-CD-aMd">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Capitalize" id="UEZ-Bs-lqG">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem title="Speech" id="xrE-MZ-jX0">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <menu key="submenu" title="Speech" id="3rS-ZA-NoH">
                                    <items>
                                        <menuItem title="Start Speaking" id="Ynk-f8-cLZ">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Stop Speaking" id="Oyz-dy-DGm">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="View" id="H8h-7b-M4v">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <menu key="submenu" title="View" id="HyV-fh-RgO">
                        <items>
                            <menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
                                <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
                                <connections>
                                    <action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Window" id="aUF-d1-5bR">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
                        <items>
                            <menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
                                <connections>
                                    <action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Zoom" id="R4o-n2-Eq4">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
                            <menuItem title="Bring All to Front" id="LE2-aR-0XJ">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Help" id="EPT-qC-fAb">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <menu key="submenu" title="Help" systemMenu="help" id="rJ0-wn-3NY"/>
                </menuItem>
            </items>
            <point key="canvasLocation" x="142" y="-258"/>
        </menu>
        <window title="APP_NAME" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g" customClass="MainFlutterWindow" customModule="Runner" customModuleProvider="target">
            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
            <rect key="contentRect" x="335" y="390" width="405" height="720"/>
            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1577"/>
            <view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
                <rect key="frame" x="0.0" y="0.0" width="405" height="720"/>
                <autoresizingMask key="autoresizingMask"/>
            </view>
        </window>
    </objects>
</document>
dir Configs
AppInfo.xcconfig Unicode text, UTF-8 text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// Application-level settings for the Runner target.
//
// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
// future. If not, the values below would default to using the project name when this becomes a
// 'flutter create' template.

// The application's name. By default this is also the title of the Flutter window.
PRODUCT_NAME = 15

// The application's bundle identifier
PRODUCT_BUNDLE_IDENTIFIER = com.example.fifteen

// The copyright displayed in application information
// TODO update this
PRODUCT_COPYRIGHT = Copyright © 2023
Debug.xcconfig ASCII text
1
2
#include "../../Flutter/Flutter-Debug.xcconfig"
#include "Warnings.xcconfig"
Release.xcconfig ASCII text
1
2
#include "../../Flutter/Flutter-Release.xcconfig"
#include "Warnings.xcconfig"
Warnings.xcconfig ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
GCC_WARN_UNDECLARED_SELECTOR = YES
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
CLANG_WARN_PRAGMA_PACK = YES
CLANG_WARN_STRICT_PROTOTYPES = YES
CLANG_WARN_COMMA = YES
GCC_WARN_STRICT_SELECTOR_MATCH = YES
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
GCC_WARN_SHADOW = YES
CLANG_WARN_UNREACHABLE_CODE = YES
AppDelegate.swift ASCII text
1
2
3
4
5
6
7
8
9
import Cocoa
import FlutterMacOS

@NSApplicationMain
class AppDelegate: FlutterAppDelegate {
  override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
    return true
  }
}
DebugProfile.entitlements ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.app-sandbox</key>
	<true/>
	<key>com.apple.security.cs.allow-jit</key>
	<true/>
	<key>com.apple.security.network.server</key>
	<true/>
</dict>
</plist>
Info.plist ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIconFile</key>
	<string></string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>$(FLUTTER_BUILD_NAME)</string>
	<key>CFBundleVersion</key>
	<string>$(FLUTTER_BUILD_NUMBER)</string>
	<key>LSMinimumSystemVersion</key>
	<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
	<key>NSHumanReadableCopyright</key>
	<string>$(PRODUCT_COPYRIGHT)</string>
	<key>NSMainNibFile</key>
	<string>MainMenu</string>
	<key>NSPrincipalClass</key>
	<string>NSApplication</string>
</dict>
</plist>
MainFlutterWindow.swift ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import Cocoa
import FlutterMacOS

class MainFlutterWindow: NSWindow {
  override func awakeFromNib() {
    let flutterViewController = FlutterViewController()
    let windowFrame = self.frame
    self.contentViewController = flutterViewController
    self.setFrame(windowFrame, display: true)

    RegisterGeneratedPlugins(registry: flutterViewController)

    super.awakeFromNib()
  }
}
Release.entitlements ASCII text
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.app-sandbox</key>
	<true/>
</dict>
</plist>
dir Runner.xcodeproj
dir project.xcworkspace
dir xcshareddata
IDEWorkspaceChecks.plist ASCII text
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>IDEDidComputeMac32BitWarning</key>
	<true/>
</dict>
</plist>
dir xcshareddata
dir xcschemes
Runner.xcscheme ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "1300"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "33CC10EC2044A3C60003C045"
               BuildableName = "fifteen.app"
               BlueprintName = "Runner"
               ReferencedContainer = "container:Runner.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES">
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "33CC10EC2044A3C60003C045"
            BuildableName = "fifteen.app"
            BlueprintName = "Runner"
            ReferencedContainer = "container:Runner.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
      <Testables>
         <TestableReference
            skipped = "NO"
            parallelizable = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "331C80D4294CF70F00263BE5"
               BuildableName = "RunnerTests.xctest"
               BlueprintName = "RunnerTests"
               ReferencedContainer = "container:Runner.xcodeproj">
            </BuildableReference>
         </TestableReference>
      </Testables>
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "33CC10EC2044A3C60003C045"
            BuildableName = "fifteen.app"
            BlueprintName = "Runner"
            ReferencedContainer = "container:Runner.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Profile"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "33CC10EC2044A3C60003C045"
            BuildableName = "fifteen.app"
            BlueprintName = "Runner"
            ReferencedContainer = "container:Runner.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>
project.pbxproj ASCII text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 54;
	objects = {

/* Begin PBXAggregateTarget section */
		33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
			isa = PBXAggregateTarget;
			buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
			buildPhases = (
				33CC111E2044C6BF0003C045 /* ShellScript */,
			);
			dependencies = (
			);
			name = "Flutter Assemble";
			productName = FLX;
		};
/* End PBXAggregateTarget section */

/* Begin PBXBuildFile section */
		331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
		335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
		33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
		33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
		33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
		33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
		331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
			proxyType = 1;
			remoteGlobalIDString = 33CC10EC2044A3C60003C045;
			remoteInfo = Runner;
		};
		33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
			proxyType = 1;
			remoteGlobalIDString = 33CC111A2044C6BA0003C045;
			remoteInfo = FLX;
		};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
		33CC110E2044A8840003C045 /* Bundle Framework */ = {
			isa = PBXCopyFilesBuildPhase;
			buildActionMask = 2147483647;
			dstPath = "";
			dstSubfolderSpec = 10;
			files = (
			);
			name = "Bundle Framework";
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
		331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
		331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
		333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
		335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
		33CC10ED2044A3C60003C045 /* fifteen.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "fifteen.app"; sourceTree = BUILT_PRODUCTS_DIR; };
		33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
		33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
		33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
		33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = "<group>"; };
		33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = "<group>"; };
		33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = "<group>"; };
		33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = "<group>"; };
		33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = "<group>"; };
		33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
		33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
		33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
		7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
		9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		331C80D2294CF70F00263BE5 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		33CC10EA2044A3C60003C045 /* Frameworks */ = {
			isa = PBXFra